summaryrefslogtreecommitdiffstats
path: root/src/libs/xpcom18a4/xpcom
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
commitf215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch)
tree6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/libs/xpcom18a4/xpcom
parentInitial commit. (diff)
downloadvirtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.tar.xz
virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.zip
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--src/libs/xpcom18a4/xpcom-config.h69
-rw-r--r--src/libs/xpcom18a4/xpcom-namespace-cleanup.map34
-rw-r--r--src/libs/xpcom18a4/xpcom-private.h32
-rw-r--r--src/libs/xpcom18a4/xpcom/.cvsignore3
-rw-r--r--src/libs/xpcom18a4/xpcom/Makefile.in84
-rw-r--r--src/libs/xpcom18a4/xpcom/Makefile.kup0
-rw-r--r--src/libs/xpcom18a4/xpcom/MoreFiles/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/MoreFiles/Makefile.in70
-rw-r--r--src/libs/xpcom18a4/xpcom/MoreFiles/MoreFilesX.c2765
-rw-r--r--src/libs/xpcom18a4/xpcom/MoreFiles/MoreFilesX.h1800
-rw-r--r--src/libs/xpcom18a4/xpcom/base/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/xpcom/base/Makefile.in133
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsAgg.h155
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsAllocator.cpp41
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsAllocator.h50
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsAutoPtr.h1353
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsCom.h43
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsConsoleMessage.cpp69
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsConsoleMessage.h58
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsConsoleService.cpp321
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsConsoleService.h89
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsDebugImpl.cpp477
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsDebugImpl.h61
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsError.h317
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsErrorService.cpp153
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsErrorService.h76
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsExceptionService.cpp383
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsExceptionService.h94
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsGarbageCollector.c127
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIAllocator.h56
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIConsoleListener.idl49
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIConsoleMessage.idl56
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIConsoleService.idl85
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsID.cpp152
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsID.h166
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIDebug.idl67
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIErrorService.idl100
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIException.idl101
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIExceptionService.idl97
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIID.h41
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIInterfaceRequestor.idl72
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsILeakDetector.idl54
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIMemory.idl126
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIProgrammingLanguage.idl70
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsISupports.idl80
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsISupportsBase.h119
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsISupportsObsolete.h243
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsISystemInfo.idl62
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsITraceRefcnt.idl72
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsIWeakReference.idl102
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsLeakDetector.cpp248
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsLeakDetector.h60
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsMemoryImpl.cpp548
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsMemoryImpl.h91
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsStackFrameUnix.cpp375
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsStackFrameUnix.h46
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsStackFrameWin.cpp351
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsStackFrameWin.h126
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsTraceRefcntImpl.cpp1444
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsTraceRefcntImpl.h109
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsWeakPtr.h48
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nscore.h468
-rw-r--r--src/libs/xpcom18a4/xpcom/base/nsrootidl.idl128
-rw-r--r--src/libs/xpcom18a4/xpcom/base/pure.h135
-rw-r--r--src/libs/xpcom18a4/xpcom/base/pure_api.c126
-rw-r--r--src/libs/xpcom18a4/xpcom/build/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/build/Makefile.in165
-rw-r--r--src/libs/xpcom18a4/xpcom/build/dlldeps.cpp202
-rw-r--r--src/libs/xpcom18a4/xpcom/build/malloc.c5126
-rw-r--r--src/libs/xpcom18a4/xpcom/build/nsOS2VACLegacy.cpp753
-rw-r--r--src/libs/xpcom18a4/xpcom/build/nsStringAPI.cpp261
-rw-r--r--src/libs/xpcom18a4/xpcom/build/nsXPCOM.h217
-rw-r--r--src/libs/xpcom18a4/xpcom/build/nsXPCOMCID.h174
-rw-r--r--src/libs/xpcom18a4/xpcom/build/nsXPCOMPrivate.h228
-rw-r--r--src/libs/xpcom18a4/xpcom/build/nsXPComInit.cpp1079
-rw-r--r--src/libs/xpcom18a4/xpcom/build/win32.order1514
-rw-r--r--src/libs/xpcom18a4/xpcom/build/xpcom-tests.pkg47
-rw-r--r--src/libs/xpcom18a4/xpcom/build/xpcom.pkg106
-rw-r--r--src/libs/xpcom18a4/xpcom/build/xpcom_alpha.def252
-rw-r--r--src/libs/xpcom18a4/xpcom/components/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/components/Makefile.in107
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsCategoryManager.cpp799
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsCategoryManager.h159
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsCategoryManagerUtils.h88
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsComponentManager.cpp3794
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsComponentManager.h339
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsComponentManagerObsolete.cpp271
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsComponentManagerObsolete.h185
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsComponentManagerUtils.h196
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsICategoryManager.idl101
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIClassInfo.idl132
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIComponentLoader.idl109
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIComponentLoaderManager.idl72
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIComponentManager.idl111
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIComponentManagerObsolete.idl351
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIComponentManagerUtils.h43
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIComponentRegistrar.idl243
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIFactory.idl79
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIModule.idl115
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsINativeComponentLoader.idl70
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIServiceManager.idl119
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIServiceManagerObsolete.h250
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsIServiceManagerUtils.h185
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsModule.h58
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.cpp1150
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.h84
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsObsoleteModuleLoading.h27
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsServiceManagerObsolete.cpp155
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsStaticComponent.h52
-rw-r--r--src/libs/xpcom18a4/xpcom/components/nsStaticComponentLoader.cpp317
-rw-r--r--src/libs/xpcom18a4/xpcom/components/xcDll.cpp457
-rw-r--r--src/libs/xpcom18a4/xpcom/components/xcDll.h121
-rw-r--r--src/libs/xpcom18a4/xpcom/doc/README8
-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
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/Makefile.in86
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsCOMPtr.cpp124
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsCOMPtr.h1405
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsComponentManagerUtils.cpp133
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsDebug.cpp119
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsDebug.h276
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsGenericFactory.cpp547
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsGenericFactory.h129
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsIGenericFactory.h480
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsIInterfaceRequestorUtils.cpp64
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsIInterfaceRequestorUtils.h83
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsISupportsImpl.h1246
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsISupportsUtils.h230
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsIWeakReferenceUtils.h162
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsMemory.cpp151
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsMemory.h154
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsServiceManagerUtils.h183
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsTraceRefcnt.cpp125
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsTraceRefcnt.h135
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsWeakReference.cpp169
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/nsWeakReference.h150
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/objs.mk60
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/standalone/.cvsignore8
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/standalone/Makefile.in88
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/standalone/nsGREDirServiceProvider.cpp596
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/standalone/nsGREDirServiceProvider.h68
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/standalone/nsXPCOMGlue.cpp524
-rw-r--r--src/libs/xpcom18a4/xpcom/glue/standalone/nsXPCOMGlue.h109
-rw-r--r--src/libs/xpcom18a4/xpcom/io/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/io/Makefile.in175
-rw-r--r--src/libs/xpcom18a4/xpcom/io/SpecialSystemDirectory.cpp770
-rw-r--r--src/libs/xpcom18a4/xpcom/io/SpecialSystemDirectory.h136
-rw-r--r--src/libs/xpcom18a4/xpcom/io/macDirectoryCopy.c784
-rw-r--r--src/libs/xpcom18a4/xpcom/io/macDirectoryCopy.h158
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsAppDirectoryServiceDefs.h120
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsAppFileLocationProvider.cpp608
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsAppFileLocationProvider.h67
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsBinaryStream.cpp663
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsBinaryStream.h125
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsByteArrayInputStream.cpp164
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsByteArrayInputStream.h59
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsDirectoryService.cpp1241
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsDirectoryService.h177
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsDirectoryServiceDefs.h197
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsDirectoryServiceUtils.h61
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsEscape.cpp491
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsEscape.h196
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsFastLoadFile.cpp2581
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsFastLoadFile.h566
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsFastLoadPtr.h112
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsFastLoadService.cpp571
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsFastLoadService.h71
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIAsyncInputStream.idl136
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIAsyncOutputStream.idl136
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIBaseStream.idl45
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIBinaryInputStream.idl121
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIBinaryOutputStream.idl119
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIByteArrayInputStream.idl48
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIDirectoryEnumerator.idl68
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIDirectoryService.idl138
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIFastLoadFileControl.idl123
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIFastLoadService.idl155
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIFile.idl343
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIInputStream.idl139
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIInputStreamTee.idl61
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsILineInputStream.idl54
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsILocalFile.idl180
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsILocalFileMac.idl262
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsILocalFileOS2.idl90
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIMultiplexInputStream.idl88
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIObjectInputStream.idl87
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIObjectOutputStream.idl131
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIObservableInputStream.idl67
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIObservableOutputStream.idl67
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIOutputStream.idl167
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIPipe.idl211
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIScriptableInputStream.idl73
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsISeekableStream.idl102
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIStorageStream.idl107
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIStreamBufferAccess.idl191
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIStringStream.idl138
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsIUnicharInputStream.h94
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsInputStreamTee.cpp224
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLinebreakConverter.cpp495
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLinebreakConverter.h156
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFile.h118
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFileCommon.cpp278
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFileMac.cpp3554
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFileMac.h137
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFileOS2.cpp1742
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFileOS2.h113
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFileOSX.cpp2542
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFileOSX.h119
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFileUnicode.h47
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFileUnix.cpp1724
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFileUnix.h132
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFileWin.cpp2440
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsLocalFileWin.h113
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsMultiplexInputStream.cpp389
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsMultiplexInputStream.h63
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsNativeCharsetUtils.cpp1280
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsNativeCharsetUtils.h66
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsPipe3.cpp1276
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsScriptableInputStream.cpp102
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsScriptableInputStream.h71
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsSegmentedBuffer.cpp207
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsSegmentedBuffer.h125
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsStorageStream.cpp563
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsStorageStream.h98
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsStreamUtils.cpp583
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsStreamUtils.h111
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsStringIO.h86
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsStringStream.cpp457
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsStringStream.h84
-rw-r--r--src/libs/xpcom18a4/xpcom/io/nsUnicharInputStream.cpp415
-rw-r--r--src/libs/xpcom18a4/xpcom/libxpt/xptcall/porting.html13
-rw-r--r--src/libs/xpcom18a4/xpcom/libxpt/xptcall/status.html13
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/Makefile.in130
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/component/Makefile.in81
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/component/nsFileSpecImpl.cpp857
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/component/nsFileSpecImpl.h116
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/component/nsIRegistry.idl186
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/component/nsIRegistryUtils.h63
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/component/nsRegistry.cpp2019
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/component/nsRegistry.h77
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/component/nsXPCOMObsolete.cpp57
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/component/regExport.cpp357
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/component/xpcomobsoletec.pkg6
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/dlldeps.cpp50
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsFileSpec.cpp1367
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsFileSpec.h782
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecBeOS.cpp547
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecImpl.cpp879
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecImpl.h116
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecMac.cpp1471
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecOS2.cpp840
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecUnix.cpp703
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecWin.cpp766
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsFileStream.cpp392
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsFileStream.h772
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsIFileSpec.idl204
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsIFileStream.cpp727
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsIFileStream.h157
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsIRegistry.idl186
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsIRegistryUtils.h63
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsSpecialSystemDirectory.cpp1189
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsSpecialSystemDirectory.h167
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/nsXPCOMObsolete.cpp54
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/xpcomobsolete.h50
-rw-r--r--src/libs/xpcom18a4/xpcom/obsolete/xpcomobsolete.pkg7
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/Makefile.in49
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/public/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/public/Makefile.in63
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/public/nsIProxyCreateInstance.idl53
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/public/nsIProxyObjectManager.idl87
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/public/nsProxiedService.h164
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/public/nsProxyEvent.h183
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/public/nsProxyRelease.h112
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/Makefile.in67
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/nsIProxyCreateInstance.h39
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEvent.cpp613
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventClass.cpp367
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventObject.cpp555
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventPrivate.h201
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/nsProxyObjectManager.cpp322
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/nsProxyRelease.cpp55
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/tests/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/tests/Makefile.in60
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/tests/nsITestProxy.idl9
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/tests/proxytests.cpp553
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/Makefile.in49
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/Makefile.kup0
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/.cvsignore4
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/Makefile.in49
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/Makefile.kup0
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/README6
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/porting.html212
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/public/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/public/Makefile.in54
-rwxr-xr-xsrc/libs/xpcom18a4/xpcom/reflect/xptcall/public/genstubs.pl78
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/public/xptcall.h271
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/public/xptcstubsdecl.inc761
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/public/xptcstubsdef.inc256
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/Makefile.in62
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/Makefile.kup0
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/Makefile.in56
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/Makefile.kup0
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcinvoke_mac.cpp148
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcinvoke_mac.s128
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcstubs_mac.cpp265
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcstubs_mac.s78
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/Makefile.in72
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcinvoke_emx.cpp185
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcinvoke_gcc_x86_os2.cpp159
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcinvoke_vacpp.asm268
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_emx.cpp153
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_gcc_x86_os2.cpp180
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_os2.cpp195
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_vacpp.asm1563
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/Makefile.in50
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/README6
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/clean.bat5
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/invoke_test.cpp239
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/mk_invoke.bat9
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/mk_stub.bat9
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/stub_test.cpp210
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/Makefile.in416
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/Makefile.kup0
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/vtable_layout_x86.cpp62
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptc_gcc_x86_unix.h92
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptc_platforms_unixish_x86.h161
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_amd64_darwin.cpp218
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_amd64_vbox.asm403
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm.cpp220
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm64_vbox.cpp296
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm_netbsd.cpp213
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ipf32.s145
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ipf64.s145
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_irix.s149
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_mips.s166
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_openvms_alpha.s99
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_osf1_alpha.s83
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_pa32.s131
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_aix.s146
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_aix64.s161
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s140
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_linux.s113
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_netbsd.s114
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_rhapsody.s162
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_bsdos.s121
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_linux.s67
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s84
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_netbsd.s71
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris.s71
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_GCC.s71
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_GCC3.s70
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_SUNW.s72
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparcv9_solaris_SUNW.s103
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_gcc_x86_unix.cpp215
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ipf32.cpp164
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ipf64.cpp133
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_irix.cpp173
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_alpha.cpp181
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_m68k.cpp170
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_s390.cpp254
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_s390x.cpp250
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_mips.cpp122
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_netbsd_m68k.cpp175
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_openvms_alpha.cpp107
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_osf1_alpha.cpp93
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_pa32.cpp181
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_aix.cpp106
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_aix64.cpp95
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_linux.cpp141
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_netbsd.cpp147
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_rhapsody.cpp145
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_sparc_netbsd.cpp156
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_sparc_solaris.cpp156
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_sparcv9_solaris.cpp107
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_unixish_x86.cpp187
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_unsupported.cpp48
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_64_linux.cpp227
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_solaris.cpp285
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_amd64_darwin.cpp243
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm.cpp244
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm64_vbox.cpp272
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm_netbsd.cpp145
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ipf32.s124
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ipf64.s124
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_irix.s97
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_mips.s.m4109
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_openvms_alpha.s115
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_osf1_alpha.s75
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_pa32.s68
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_aix.s117
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_aix64.s137
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_darwin.s.m4126
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_linux.s89
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_netbsd.s89
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_sparc_netbsd.s65
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_sparc_solaris.s65
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_sparcv9_solaris.s67
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_gcc_x86_unix.cpp202
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ipf32.cpp185
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ipf64.cpp186
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_irix.cpp226
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_alpha.cpp236
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_m68k.cpp146
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_s390.cpp220
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_s390x.cpp224
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_mips.cpp131
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_netbsd_m68k.cpp147
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_openvms_alpha.cpp147
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_osf1_alpha.cpp149
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_pa32.cpp176
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_aix.cpp228
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_aix64.cpp215
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_linux.cpp253
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_netbsd.cpp217
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_rhapsody.cpp254
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_sparc_netbsd.cpp146
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_sparc_solaris.cpp146
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_sparcv9_solaris.cpp139
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_unixish_x86.cpp188
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_unsupported.cpp56
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_linux.cpp242
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_solaris.cpp271
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_solaris.cpp165
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/Makefile.in82
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcinvoke.cpp107
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_alpha.cpp171
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_asm_alpha.s128
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcstubs.cpp202
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcstubs_alpha.cpp228
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcstubs_asm_alpha.s120
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/xptcall.cpp62
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/src/xptcprivate.h45
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/status.html404
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/tests/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/tests/Makefile.in64
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptcall/tests/TestXPTCInvoke.cpp1464
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/Makefile.in49
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/Makefile.in66
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIInterfaceInfo.idl137
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIInterfaceInfoManager.idl85
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIXPTLoader.idl100
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/xptinfo.h281
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/Makefile.in75
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/TODO20
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiFile.cpp113
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiInterfaceInfo.cpp819
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp2126
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiManifest.cpp710
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiMisc.cpp164
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiTypelibGuts.cpp63
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiWorkingSet.cpp432
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiZipItem.cpp102
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiZipLoader.cpp113
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiprivate.h981
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/Makefile.in58
-rw-r--r--src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/TestInterfaceInfo.cpp146
-rw-r--r--src/libs/xpcom18a4/xpcom/sample/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/xpcom/sample/Makefile.in113
-rw-r--r--src/libs/xpcom18a4/xpcom/sample/nsISample.idl66
-rw-r--r--src/libs/xpcom18a4/xpcom/sample/nsSample.cpp181
-rw-r--r--src/libs/xpcom18a4/xpcom/sample/nsSample.h129
-rw-r--r--src/libs/xpcom18a4/xpcom/sample/nsSample.js130
-rw-r--r--src/libs/xpcom18a4/xpcom/sample/nsSampleModule.cpp131
-rw-r--r--src/libs/xpcom18a4/xpcom/sample/nsTestSample.cpp158
-rw-r--r--src/libs/xpcom18a4/xpcom/sample/win32.order1
-rw-r--r--src/libs/xpcom18a4/xpcom/sample/xpconnect-sample.html220
-rw-r--r--src/libs/xpcom18a4/xpcom/string/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/string/Makefile.in54
-rw-r--r--src/libs/xpcom18a4/xpcom/string/README.html44
-rw-r--r--src/libs/xpcom18a4/xpcom/string/doc/README.html44
-rw-r--r--src/libs/xpcom18a4/xpcom/string/doc/string-guide.html2508
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/Makefile.in86
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsAString.h96
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsAlgorithm.h131
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsCharTraits.h784
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsDependentString.h60
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsDependentSubstring.h56
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsEmbedString.h158
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsLiteralString.h116
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsObsoleteAString.h102
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsPrintfCString.h87
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsPromiseFlatString.h56
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsReadableUtils.h370
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsString.h237
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsStringAPI.h853
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsStringFwd.h96
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsStringIterator.h373
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsSubstring.h74
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsSubstringTuple.h56
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsTAString.h618
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsTDependentString.h137
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsTDependentSubstring.h143
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsTObsoleteAString.h165
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsTPromiseFlatString.h158
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsTString.h721
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsTSubstring.h575
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsTSubstringTuple.h113
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsUTF8Utils.h462
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/nsXPIDLString.h46
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/string-template-def-char.h58
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/string-template-def-unichar.h58
-rw-r--r--src/libs/xpcom18a4/xpcom/string/public/string-template-undef.h59
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/Makefile.in77
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsAString.cpp51
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsDependentSubstring.cpp50
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsObsoleteAStringThunk.cpp52
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsPrintfCString.cpp83
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsPromiseFlatString.cpp49
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsReadableUtils.cpp1122
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsString.cpp49
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsStringComparator.cpp75
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsStringObsolete.cpp1327
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsSubstring.cpp250
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsSubstringTuple.cpp64
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsTAString.cpp509
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsTDependentSubstring.cpp65
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsTObsoleteAStringThunk.cpp235
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsTPromiseFlatString.cpp66
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsTString.cpp63
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsTStringComparator.cpp79
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsTStringObsolete.cpp518
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsTSubstring.cpp656
-rw-r--r--src/libs/xpcom18a4/xpcom/string/src/nsTSubstringTuple.cpp127
-rw-r--r--src/libs/xpcom18a4/xpcom/stub/nsStringAPI.cpp261
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/.cvsignore31
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/CvtURL.cpp126
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/Makefile.in116
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/RegFactory.cpp162
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/SizeTest01.cpp107
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/SizeTest02.cpp93
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/SizeTest03.cpp101
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/SizeTest04.cpp72
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/SizeTest05.cpp78
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/SizeTest06.cpp231
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/Makefile.in76
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTest.Prefix4
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTest.mcpbin0 -> 245184 bytes
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestDebug.Prefix4
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestNo_wchar_t.Prefix5
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileNew.Prefix3
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileOld.Prefix6
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileStd.Prefix7
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/ToDo.doc41
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/nsStdStringWrapper.h234
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/profile_main.cpp497
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/test_main.cpp651
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestArray.cpp230
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestAtoms.cpp132
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestAutoLock.cpp91
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestAutoPtr.cpp566
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestCOMPtr.cpp651
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestCOMPtrEq.cpp200
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestCRT.cpp112
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestCallTemplates.cpp129
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestDeque.cpp155
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestFactory.cpp160
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestFactory.h69
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestHashtables.cpp939
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestID.cpp77
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestMinStringAPI.cpp333
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestObserverService.cpp250
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestPermanentAtoms.cpp88
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestPipes.cpp655
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestServMgr.cpp173
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestShutdown.cpp78
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestStackCrawl.cpp11
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestStrings.cpp643
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestThreads.cpp280
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestVoidBTree.cpp302
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/TestXPIDLString.cpp18
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/dynamic/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/dynamic/Makefile.in61
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/dynamic/TestDynamic.cpp76
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/dynamic/win32.order1
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/nsIFileEnumerator.cpp95
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/nsIFileTest.cpp475
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/resources.h52
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/services/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/services/Makefile.in58
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/services/MyService.cpp93
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/services/MyService.h69
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/services/win32.order1
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/test.properties46
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/utils/WhatError.cpp61
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/utils/cp.js111
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/utils/dirs.js155
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/utils/ls.js64
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/windows/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/windows/Makefile.in60
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/windows/TestCOM.cpp181
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/windows/TestHelloXPLoop.cpp177
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/windows/nsStringTest.cpp33
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/windows/nsStringTest.h2277
-rw-r--r--src/libs/xpcom18a4/xpcom/tests/windows/nsStringTest2.h444
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/Makefile.in105
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/TimerThread.cpp462
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/TimerThread.h122
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsAutoLock.cpp435
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsAutoLock.h383
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsEnvironment.cpp202
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsEnvironment.h67
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsEventQueue.cpp632
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsEventQueue.h89
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsEventQueueService.cpp450
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsEventQueueService.h77
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsEventQueueUtils.h78
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsIEnvironment.idl89
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsIEventQueue.idl107
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsIEventQueueService.idl151
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsIEventTarget.idl67
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsIProcess.idl32
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsIRunnable.idl44
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsIThread.idl144
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsITimer.idl191
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsITimerInternal.idl48
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsITimerManager.idl61
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsPIEventQueueChain.h93
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsProcess.h71
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsProcessCommon.cpp363
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsProcessMac.cpp188
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsThread.cpp457
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsThread.h92
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsTimerImpl.cpp642
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/nsTimerImpl.h195
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/plevent.c1774
-rw-r--r--src/libs/xpcom18a4/xpcom/threads/plevent.h690
-rw-r--r--src/libs/xpcom18a4/xpcom/tools/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/tools/Makefile.in53
-rwxr-xr-xsrc/libs/xpcom18a4/xpcom/tools/analyze-xpcom-log.pl177
-rw-r--r--src/libs/xpcom18a4/xpcom/tools/registry/.cvsignore3
-rw-r--r--src/libs/xpcom18a4/xpcom/tools/registry/Makefile.in77
-rw-r--r--src/libs/xpcom18a4/xpcom/tools/registry/regxpcom.cpp404
-rw-r--r--src/libs/xpcom18a4/xpcom/tools/windows/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/tools/windows/Makefile.in52
-rw-r--r--src/libs/xpcom18a4/xpcom/tools/windows/rebasedlls.cpp104
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/Makefile.in49
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/Makefile.in88
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/README16
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/compiler.rsrcbin0 -> 915 bytes
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/linker.rsrcbin0 -> 984 bytes
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_console.c139
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_console.h49
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_memory.cpp146
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_stdlib.cpp58
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_strings.cpp38
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_strings.h47
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl.cpp417
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl.h25
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl_panel.cpp695
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl_panel.h106
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpt_linker.cpp546
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/panel.rsrcbin0 -> 16238 bytes
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/version.rsrcbin0 -> 755 bytes
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.c275
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.h278
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_doc.c312
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_header.c1196
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_idl.c836
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_java.c1053
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_typelib.c1237
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_util.c851
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/Makefile.in50
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/public/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/public/Makefile.in51
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_arena.h145
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_struct.h562
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_xdr.h240
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/src/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/src/Makefile.in76
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_arena.c358
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_struct.c956
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_xdr.c665
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/tests/.cvsignore3
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/tests/Makefile.in59
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/tests/PrimitiveTest.c157
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/tests/SimpleTypeLib.c192
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/tools/.cvsignore3
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/tools/Makefile.in90
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/tools/xpt_dump.c941
-rw-r--r--src/libs/xpcom18a4/xpcom/typelib/xpt/tools/xpt_link.c883
-rw-r--r--src/libs/xpcom18a4/xpcom/windbgdlg/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/windbgdlg/Makefile.in50
-rw-r--r--src/libs/xpcom18a4/xpcom/windbgdlg/windbgdlg.cpp60
-rw-r--r--src/libs/xpcom18a4/xpcom/xpcom-config.h.in65
-rw-r--r--src/libs/xpcom18a4/xpcom/xpcom-private.h.in31
808 files changed, 208496 insertions, 0 deletions
diff --git a/src/libs/xpcom18a4/xpcom-config.h b/src/libs/xpcom18a4/xpcom-config.h
new file mode 100644
index 00000000..ee34a6d6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom-config.h
@@ -0,0 +1,69 @@
+/* xpcom/xpcom-config.h. Generated automatically by configure. */
+/* Global defines needed by xpcom clients */
+
+#ifndef _XPCOM_CONFIG_H_
+#define _XPCOM_CONFIG_H_
+
+/* Define this to throw() if the compiler complains about
+ * constructors returning NULL
+ */
+#define CPP_THROW_NEW throw()
+
+/* Define if the c++ compiler supports a 2-byte wchar_t */
+#define HAVE_CPP_2BYTE_WCHAR_T 1
+
+/* Define if the c++ compiler supports changing access with |using| */
+#define HAVE_CPP_ACCESS_CHANGING_USING 1
+
+/* Define if the c++ compiler can resolve ambiguity with |using| */
+#define HAVE_CPP_AMBIGUITY_RESOLVING_USING 1
+
+/* Define if the c++ compiler has builtin Bool type */
+/* #undef HAVE_CPP_BOOL */
+
+/* Define if a dyanmic_cast to void* gives the most derived object */
+#define HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR 1
+
+/* Define if the c++ compiler supports the |explicit| keyword */
+#define HAVE_CPP_EXPLICIT 1
+
+/* Define if the c++ compiler supports the modern template
+ * specialization syntax
+ */
+#define HAVE_CPP_MODERN_SPECIALIZE_TEMPLATE_SYNTAX 1
+
+/* Define if the c++ compiler supports the |std| namespace */
+#define HAVE_CPP_NAMESPACE_STD 1
+
+/* Define if the c++ compiler supports reinterpret_cast */
+#define HAVE_CPP_NEW_CASTS 1
+
+/* Define if the c++ compiler supports partial template specialization */
+#define HAVE_CPP_PARTIAL_SPECIALIZATION 1
+
+/* Define if the c++ compiler has trouble comparing a constant
+ * reference to a templatized class to zero
+ */
+/* #undef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO */
+
+/* Define if the c++ compiler supports the |typename| keyword */
+#define HAVE_CPP_TYPENAME 1
+
+/* Define if the stanard template operator!=() is ambiguous */
+#define HAVE_CPP_UNAMBIGUOUS_STD_NOTEQUAL 1
+
+/* Define if statvfs() is available */
+#define HAVE_STATVFS 1
+
+/* Define if the c++ compiler requires implementations of
+ * unused virtual methods
+ */
+#define NEED_CPP_UNUSED_IMPLEMENTATIONS 1
+
+/* Define to either <new> or <new.h> */
+#define NEW_H <new>
+
+/* Define if binary compatibility with Mozilla 1.x string code is desired */
+#define MOZ_V1_STRING_ABI 1
+
+#endif /* _XPCOM_CONFIG_H_ */
diff --git a/src/libs/xpcom18a4/xpcom-namespace-cleanup.map b/src/libs/xpcom18a4/xpcom-namespace-cleanup.map
new file mode 100644
index 00000000..2488ca1a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom-namespace-cleanup.map
@@ -0,0 +1,34 @@
+# GNU ld version script, for linux
+# Gets rid of all non-prefixed non-C++ global symbols. They cause problem if
+# VirtualBox drags in the system-provided nspr library or some other code from
+# the Mozilla project. VirtualBox shouldn't pollute the namespace.
+
+#
+# Copyright (C) 2008-2023 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# SPDX-License-Identifier: GPL-3.0-only
+#
+
+{
+ global:
+ _Z*; VBoxNs*;
+ __bss_start; _edata; _end; _fini; _init;
+ local:
+ *;
+};
diff --git a/src/libs/xpcom18a4/xpcom-private.h b/src/libs/xpcom18a4/xpcom-private.h
new file mode 100644
index 00000000..e0721fae
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom-private.h
@@ -0,0 +1,32 @@
+/* xpcom/xpcom-private.h. Generated automatically by configure. */
+/* The following defines are only used by the xpcom implementation */
+
+#ifndef _XPCOM_PRIVATE_H_
+#define _XPCOM_PRIVATE_H_
+
+/* Define to build the static component loader */
+#define ENABLE_STATIC_COMPONENT_LOADER 1
+
+/* Define if getpagesize() is available */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if iconv() is available */
+#define HAVE_ICONV 1
+
+/* Define if iconv() supports const input */
+/* #undef HAVE_ICONV_WITH_CONST_INPUT */
+
+/* Define if mbrtowc() is available */
+#define HAVE_MBRTOWC 1
+
+/* Define if <sys/mount.h> is present */
+#define HAVE_SYS_MOUNT_H 1
+
+/* Define if <sys/vfs.h> is present */
+#define HAVE_SYS_VFS_H 1
+
+/* Define if wcrtomb() is available */
+#define HAVE_WCRTOMB 1
+
+#endif /* _XPCOM_PRIVATE_H_ */
+
diff --git a/src/libs/xpcom18a4/xpcom/.cvsignore b/src/libs/xpcom18a4/xpcom/.cvsignore
new file mode 100644
index 00000000..34b091a9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/.cvsignore
@@ -0,0 +1,3 @@
+Makefile
+xpcom-config.h
+xpcom-private.h
diff --git a/src/libs/xpcom18a4/xpcom/Makefile.in b/src/libs/xpcom18a4/xpcom/Makefile.in
new file mode 100644
index 00000000..8bfe9abe
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/Makefile.in
@@ -0,0 +1,84 @@
+#
+# ***** 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
+GRE_MODULE = 1
+
+DIRS = \
+ MoreFiles \
+ typelib \
+ string \
+ glue \
+ base \
+ ds \
+ io \
+ components \
+ threads \
+ reflect \
+ proxy \
+ build \
+ tools \
+ $(NULL)
+
+ifeq ($(OS_ARCH),WINNT)
+ifdef MOZ_DEBUG
+DIRS += windbgdlg
+endif
+endif
+
+ifdef ENABLE_TESTS
+DIRS += \
+ tests \
+ sample \
+ typelib/xpt/tests \
+ reflect/xptinfo/tests \
+ reflect/xptcall/tests \
+ proxy/tests
+endif
+
+# xpcom-config.h is generated by configure
+SDK_HEADERS = xpcom-config.h
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/Makefile.kup b/src/libs/xpcom18a4/xpcom/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/Makefile.kup
diff --git a/src/libs/xpcom18a4/xpcom/MoreFiles/.cvsignore b/src/libs/xpcom18a4/xpcom/MoreFiles/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/MoreFiles/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/MoreFiles/Makefile.in b/src/libs/xpcom18a4/xpcom/MoreFiles/Makefile.in
new file mode 100644
index 00000000..56d89456
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/MoreFiles/Makefile.in
@@ -0,0 +1,70 @@
+#
+# ***** 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.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications.
+# Portions created by the Initial Developer are Copyright (C) 2001
+# 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 = macmorefiles
+REQUIRES =
+
+# ifeq for standalone builds
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+
+LIBRARY_NAME = macmorefiles_s
+
+CSRCS = \
+ MoreFilesX.c \
+ FSCopyObject.c \
+ $(NULL)
+
+EXPORTS += \
+ MoreFilesX.h \
+ FSCopyObject.h \
+ $(NULL)
+
+# we don't want the shared lib, but we want to force the creation of a
+# static lib.
+FORCE_STATIC_LIB=1
+FORCE_USE_PIC=1
+
+endif
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/xpcom/MoreFiles/MoreFilesX.c b/src/libs/xpcom18a4/xpcom/MoreFiles/MoreFilesX.c
new file mode 100644
index 00000000..d1b7af9e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/MoreFiles/MoreFilesX.c
@@ -0,0 +1,2765 @@
+/*
+ File: MoreFilesX.c
+
+ Contains: A collection of useful high-level File Manager routines
+ which use the HFS Plus APIs wherever possible.
+
+ Version: MoreFilesX 1.0.1
+
+
+*/
+
+/* ***** 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) 2000
+ * 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 ***** */
+
+
+// Modified 2006-01-23 - added this comment.
+
+#if defined(__MACH__)
+ #include <Carbon/Carbon.h>
+ #include <string.h>
+#else
+ #include <Carbon.h>
+ #include <string.h>
+#endif
+
+#include "MoreFilesX.h"
+
+/* Set BuildingMoreFilesXForMacOS9 to 1 if building for Mac OS 9 */
+#ifndef BuildingMoreFilesXForMacOS9
+ #define BuildingMoreFilesXForMacOS9 0
+#endif
+
+/*****************************************************************************/
+
+#pragma mark ----- Local type definitions -----
+
+struct FSIterateContainerGlobals
+{
+ IterateContainerFilterProcPtr iterateFilter; /* pointer to IterateFilterProc */
+ FSCatalogInfoBitmap whichInfo; /* fields of the CatalogInfo to get */
+ FSCatalogInfo catalogInfo; /* FSCatalogInfo */
+ FSRef ref; /* FSRef */
+ FSSpec spec; /* FSSpec */
+ FSSpec *specPtr; /* pointer to spec field, or NULL */
+ HFSUniStr255 name; /* HFSUniStr255 */
+ HFSUniStr255 *namePtr; /* pointer to name field, or NULL */
+ void *yourDataPtr; /* a pointer to caller supplied data the filter may need to access */
+ ItemCount maxLevels; /* maximum levels to iterate through */
+ ItemCount currentLevel; /* the current level FSIterateContainerLevel is on */
+ Boolean quitFlag; /* set to true if filter wants to kill interation */
+ Boolean containerChanged; /* temporary - set to true if the current container changed during iteration */
+ OSErr result; /* result */
+ ItemCount actualObjects; /* number of objects returned */
+};
+typedef struct FSIterateContainerGlobals FSIterateContainerGlobals;
+
+struct FSDeleteContainerGlobals
+{
+ OSErr result; /* result */
+ ItemCount actualObjects; /* number of objects returned */
+ FSCatalogInfo catalogInfo; /* FSCatalogInfo */
+};
+typedef struct FSDeleteContainerGlobals FSDeleteContainerGlobals;
+
+/*****************************************************************************/
+
+#pragma mark ----- Local prototypes -----
+
+static
+void
+FSDeleteContainerLevel(
+ const FSRef *container,
+ FSDeleteContainerGlobals *theGlobals);
+
+static
+void
+FSIterateContainerLevel(
+ FSIterateContainerGlobals *theGlobals);
+
+static
+OSErr
+GenerateUniqueHFSUniStr(
+ long *startSeed,
+ const FSRef *dir1,
+ const FSRef *dir2,
+ HFSUniStr255 *uniqueName);
+
+/*****************************************************************************/
+
+#pragma mark ----- File Access Routines -----
+
+/*****************************************************************************/
+
+OSErr
+FSCopyFork(
+ SInt16 srcRefNum,
+ SInt16 dstRefNum,
+ void *copyBufferPtr,
+ ByteCount copyBufferSize)
+{
+ OSErr srcResult;
+ OSErr dstResult;
+ OSErr result;
+ SInt64 forkSize;
+ ByteCount readActualCount;
+
+ /* check input parameters */
+ require_action((NULL != copyBufferPtr) && (0 != copyBufferSize), BadParameter, result = paramErr);
+
+ /* get source fork size */
+ result = FSGetForkSize(srcRefNum, &forkSize);
+ require_noerr(result, SourceFSGetForkSizeFailed);
+
+ /* allocate disk space for destination fork */
+ result = FSSetForkSize(dstRefNum, fsFromStart, forkSize);
+ require_noerr(result, DestinationFSSetForkSizeFailed);
+
+ /* reset source fork's position to 0 */
+ result = FSSetForkPosition(srcRefNum, fsFromStart, 0);
+ require_noerr(result, SourceFSSetForkPositionFailed);
+
+ /* reset destination fork's position to 0 */
+ result = FSSetForkPosition(dstRefNum, fsFromStart, 0);
+ require_noerr(result, DestinationFSSetForkPositionFailed);
+
+ /* If copyBufferSize is greater than 4K bytes, make it a multiple of 4k bytes */
+ /* This will make writes on local volumes faster */
+ if ( (copyBufferSize >= 0x00001000) && ((copyBufferSize & 0x00000fff) != 0) )
+ {
+ copyBufferSize &= ~(0x00001000 - 1);
+ }
+
+ /* copy source to destination */
+ srcResult = dstResult = noErr;
+ while ( (noErr == srcResult) && (noErr == dstResult) )
+ {
+ srcResult = FSReadFork(srcRefNum, fsAtMark + noCacheMask, 0, copyBufferSize, copyBufferPtr, &readActualCount);
+ dstResult = FSWriteFork(dstRefNum, fsAtMark + noCacheMask, 0, readActualCount, copyBufferPtr, NULL);
+ }
+
+ /* make sure there were no errors at the destination */
+ require_noerr_action(dstResult, DestinationFSWriteForkFailed, result = dstResult);
+
+ /* make sure the error at the source was eofErr */
+ require_action(eofErr == srcResult, SourceResultNotEofErr, result = srcResult);
+
+ /* everything went as expected */
+ result = noErr;
+
+SourceResultNotEofErr:
+DestinationFSWriteForkFailed:
+DestinationFSSetForkPositionFailed:
+SourceFSSetForkPositionFailed:
+DestinationFSSetForkSizeFailed:
+SourceFSGetForkSizeFailed:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+#pragma mark ----- Volume Access Routines -----
+
+/*****************************************************************************/
+
+OSErr
+FSGetVolParms(
+ FSVolumeRefNum volRefNum,
+ UInt32 bufferSize,
+ GetVolParmsInfoBuffer *volParmsInfo,
+ UInt32 *actualInfoSize)
+{
+ OSErr result;
+ HParamBlockRec pb;
+
+ /* check parameters */
+ require_action((NULL != volParmsInfo) && (NULL != actualInfoSize),
+ BadParameter, result = paramErr);
+
+ pb.ioParam.ioNamePtr = NULL;
+ pb.ioParam.ioVRefNum = volRefNum;
+ pb.ioParam.ioBuffer = (Ptr)volParmsInfo;
+ pb.ioParam.ioReqCount = (SInt32)bufferSize;
+ result = PBHGetVolParmsSync(&pb);
+ require_noerr(result, PBHGetVolParmsSync);
+
+ /* return number of bytes the file system returned in volParmsInfo buffer */
+ *actualInfoSize = (UInt32)pb.ioParam.ioActCount;
+
+PBHGetVolParmsSync:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetVRefNum(
+ const FSRef *ref,
+ FSVolumeRefNum *vRefNum)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+
+ /* check parameters */
+ require_action(NULL != vRefNum, BadParameter, result = paramErr);
+
+ /* get the volume refNum from the FSRef */
+ result = FSGetCatalogInfo(ref, kFSCatInfoVolume, &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* return volume refNum from catalogInfo */
+ *vRefNum = catalogInfo.volume;
+
+FSGetCatalogInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetVInfo(
+ FSVolumeRefNum volume,
+ HFSUniStr255 *volumeName, /* can be NULL */
+ UInt64 *freeBytes, /* can be NULL */
+ UInt64 *totalBytes) /* can be NULL */
+{
+ OSErr result;
+ FSVolumeInfo info;
+
+ /* ask for the volume's sizes only if needed */
+ result = FSGetVolumeInfo(volume, 0, NULL,
+ (((NULL != freeBytes) || (NULL != totalBytes)) ? kFSVolInfoSizes : kFSVolInfoNone),
+ &info, volumeName, NULL);
+ require_noerr(result, FSGetVolumeInfo);
+
+ if ( NULL != freeBytes )
+ {
+ *freeBytes = info.freeBytes;
+ }
+ if ( NULL != totalBytes )
+ {
+ *totalBytes = info.totalBytes;
+ }
+
+FSGetVolumeInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetVolFileSystemID(
+ FSVolumeRefNum volume,
+ UInt16 *fileSystemID, /* can be NULL */
+ UInt16 *signature) /* can be NULL */
+{
+ OSErr result;
+ FSVolumeInfo info;
+
+ result = FSGetVolumeInfo(volume, 0, NULL, kFSVolInfoFSInfo, &info, NULL, NULL);
+ require_noerr(result, FSGetVolumeInfo);
+
+ if ( NULL != fileSystemID )
+ {
+ *fileSystemID = info.filesystemID;
+ }
+ if ( NULL != signature )
+ {
+ *signature = info.signature;
+ }
+
+FSGetVolumeInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetMountedVolumes(
+ FSRef ***volumeRefsHandle, /* pointer to handle of FSRefs */
+ ItemCount *numVolumes)
+{
+ OSErr result;
+ OSErr memResult;
+ ItemCount volumeIndex;
+ FSRef ref;
+
+ /* check parameters */
+ require_action((NULL != volumeRefsHandle) && (NULL != numVolumes),
+ BadParameter, result = paramErr);
+
+ /* No volumes yet */
+ *numVolumes = 0;
+
+ /* Allocate a handle for the results */
+ *volumeRefsHandle = (FSRef **)NewHandle(0);
+ require_action(NULL != *volumeRefsHandle, NewHandle, result = memFullErr);
+
+ /* Call FSGetVolumeInfo in loop to get all volumes starting with the first */
+ volumeIndex = 1;
+ do
+ {
+ result = FSGetVolumeInfo(0, volumeIndex, NULL, kFSVolInfoNone, NULL, NULL, &ref);
+ if ( noErr == result )
+ {
+ /* concatenate the FSRef to the end of the handle */
+ PtrAndHand(&ref, (Handle)*volumeRefsHandle, sizeof(FSRef));
+ memResult = MemError();
+ require_noerr_action(memResult, MemoryAllocationFailed, result = memResult);
+
+ ++(*numVolumes); /* increment the volume count */
+ ++volumeIndex; /* and the volumeIndex to get the next volume*/
+ }
+ } while ( noErr == result );
+
+ /* nsvErr is OK -- it just means there are no more volumes */
+ require(nsvErr == result, FSGetVolumeInfo);
+
+ return ( noErr );
+
+ /**********************/
+
+MemoryAllocationFailed:
+FSGetVolumeInfo:
+
+ /* dispose of handle if already allocated and clear the outputs */
+ if ( NULL != *volumeRefsHandle )
+ {
+ DisposeHandle((Handle)*volumeRefsHandle);
+ *volumeRefsHandle = NULL;
+ }
+ *numVolumes = 0;
+
+NewHandle:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+#pragma mark ----- FSRef/FSpec/Path/Name Conversion Routines -----
+
+/*****************************************************************************/
+
+OSErr
+FSRefMakeFSSpec(
+ const FSRef *ref,
+ FSSpec *spec)
+{
+ OSErr result;
+
+ /* check parameters */
+ require_action(NULL != spec, BadParameter, result = paramErr);
+
+ result = FSGetCatalogInfo(ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+FSGetCatalogInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSMakeFSRef(
+ FSVolumeRefNum volRefNum,
+ SInt32 dirID,
+ ConstStr255Param name,
+ FSRef *ref)
+{
+ OSErr result;
+ FSRefParam pb;
+
+ /* check parameters */
+ require_action(NULL != ref, BadParameter, result = paramErr);
+
+ pb.ioVRefNum = volRefNum;
+ pb.ioDirID = dirID;
+ pb.ioNamePtr = (StringPtr)name;
+ pb.newRef = ref;
+ result = PBMakeFSRefSync(&pb);
+ require_noerr(result, PBMakeFSRefSync);
+
+PBMakeFSRefSync:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSStatus
+FSMakePath(
+ SInt16 volRefNum,
+ SInt32 dirID,
+ ConstStr255Param name,
+ UInt8 *path,
+ UInt32 maxPathSize)
+{
+ OSStatus result;
+ FSRef ref;
+
+ /* check parameters */
+ require_action(NULL != path, BadParameter, result = paramErr);
+
+ /* convert the inputs to an FSRef */
+ result = FSMakeFSRef(volRefNum, dirID, name, &ref);
+ require_noerr(result, FSMakeFSRef);
+
+ /* and then convert the FSRef to a path */
+ result = FSRefMakePath(&ref, path, maxPathSize);
+ require_noerr(result, FSRefMakePath);
+
+FSRefMakePath:
+FSMakeFSRef:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSStatus
+FSPathMakeFSSpec(
+ const UInt8 *path,
+ FSSpec *spec,
+ Boolean *isDirectory) /* can be NULL */
+{
+ OSStatus result;
+ FSRef ref;
+
+ /* check parameters */
+ require_action(NULL != spec, BadParameter, result = paramErr);
+
+ /* convert the POSIX path to an FSRef */
+ result = FSPathMakeRef(path, &ref, isDirectory);
+ require_noerr(result, FSPathMakeRef);
+
+ /* and then convert the FSRef to an FSSpec */
+ result = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+FSGetCatalogInfo:
+FSPathMakeRef:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+UnicodeNameGetHFSName(
+ UniCharCount nameLength,
+ const UniChar *name,
+ TextEncoding textEncodingHint,
+ Boolean isVolumeName,
+ Str31 hfsName)
+{
+ OSStatus result;
+ ByteCount unicodeByteLength;
+ ByteCount unicodeBytesConverted;
+ ByteCount actualPascalBytes;
+ UnicodeMapping uMapping;
+ UnicodeToTextInfo utInfo;
+
+ /* check parameters */
+ require_action(NULL != hfsName, BadParameter, result = paramErr);
+
+ /* make sure output is valid in case we get errors or there's nothing to convert */
+ hfsName[0] = 0;
+
+ unicodeByteLength = nameLength * sizeof(UniChar);
+ if ( 0 == unicodeByteLength )
+ {
+ /* do nothing */
+ result = noErr;
+ }
+ else
+ {
+ /* if textEncodingHint is kTextEncodingUnknown, get a "default" textEncodingHint */
+ if ( kTextEncodingUnknown == textEncodingHint )
+ {
+ ScriptCode script;
+ RegionCode region;
+
+ script = (ScriptCode)GetScriptManagerVariable(smSysScript);
+ region = (RegionCode)GetScriptManagerVariable(smRegionCode);
+ result = UpgradeScriptInfoToTextEncoding(script, kTextLanguageDontCare, region,
+ NULL, &textEncodingHint );
+ if ( paramErr == result )
+ {
+ /* ok, ignore the region and try again */
+ result = UpgradeScriptInfoToTextEncoding(script, kTextLanguageDontCare,
+ kTextRegionDontCare, NULL, &textEncodingHint );
+ }
+ if ( noErr != result )
+ {
+ /* ok... try something */
+ textEncodingHint = kTextEncodingMacRoman;
+ }
+ }
+
+ uMapping.unicodeEncoding = CreateTextEncoding(kTextEncodingUnicodeV2_0,
+ kUnicodeCanonicalDecompVariant, kUnicode16BitFormat);
+ uMapping.otherEncoding = GetTextEncodingBase(textEncodingHint);
+ uMapping.mappingVersion = kUnicodeUseHFSPlusMapping;
+
+ result = CreateUnicodeToTextInfo(&uMapping, &utInfo);
+ require_noerr(result, CreateUnicodeToTextInfo);
+
+ result = ConvertFromUnicodeToText(utInfo, unicodeByteLength, name, kUnicodeLooseMappingsMask,
+ 0, NULL, 0, NULL, /* offsetCounts & offsetArrays */
+ isVolumeName ? kHFSMaxVolumeNameChars : kHFSMaxFileNameChars,
+ &unicodeBytesConverted, &actualPascalBytes, &hfsName[1]);
+ require_noerr(result, ConvertFromUnicodeToText);
+
+ hfsName[0] = (unsigned char)actualPascalBytes; /* fill in length byte */
+
+ConvertFromUnicodeToText:
+
+ /* verify the result in debug builds -- there's really not anything you can do if it fails */
+ verify_noerr(DisposeUnicodeToTextInfo(&utInfo));
+ }
+
+CreateUnicodeToTextInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+HFSNameGetUnicodeName(
+ ConstStr31Param hfsName,
+ TextEncoding textEncodingHint,
+ HFSUniStr255 *unicodeName)
+{
+ ByteCount unicodeByteLength;
+ OSStatus result;
+ UnicodeMapping uMapping;
+ TextToUnicodeInfo tuInfo;
+ ByteCount pascalCharsRead;
+
+ /* check parameters */
+ require_action(NULL != unicodeName, BadParameter, result = paramErr);
+
+ /* make sure output is valid in case we get errors or there's nothing to convert */
+ unicodeName->length = 0;
+
+ if ( 0 == StrLength(hfsName) )
+ {
+ result = noErr;
+ }
+ else
+ {
+ /* if textEncodingHint is kTextEncodingUnknown, get a "default" textEncodingHint */
+ if ( kTextEncodingUnknown == textEncodingHint )
+ {
+ ScriptCode script;
+ RegionCode region;
+
+ script = GetScriptManagerVariable(smSysScript);
+ region = GetScriptManagerVariable(smRegionCode);
+ result = UpgradeScriptInfoToTextEncoding(script, kTextLanguageDontCare, region,
+ NULL, &textEncodingHint);
+ if ( paramErr == result )
+ {
+ /* ok, ignore the region and try again */
+ result = UpgradeScriptInfoToTextEncoding(script, kTextLanguageDontCare,
+ kTextRegionDontCare, NULL, &textEncodingHint);
+ }
+ if ( noErr != result )
+ {
+ /* ok... try something */
+ textEncodingHint = kTextEncodingMacRoman;
+ }
+ }
+
+ uMapping.unicodeEncoding = CreateTextEncoding(kTextEncodingUnicodeV2_0,
+ kUnicodeCanonicalDecompVariant, kUnicode16BitFormat);
+ uMapping.otherEncoding = GetTextEncodingBase(textEncodingHint);
+ uMapping.mappingVersion = kUnicodeUseHFSPlusMapping;
+
+ result = CreateTextToUnicodeInfo(&uMapping, &tuInfo);
+ require_noerr(result, CreateTextToUnicodeInfo);
+
+ result = ConvertFromTextToUnicode(tuInfo, hfsName[0], &hfsName[1],
+ 0, /* no control flag bits */
+ 0, NULL, 0, NULL, /* offsetCounts & offsetArrays */
+ sizeof(unicodeName->unicode), /* output buffer size in bytes */
+ &pascalCharsRead, &unicodeByteLength, unicodeName->unicode);
+ require_noerr(result, ConvertFromTextToUnicode);
+
+ /* convert from byte count to char count */
+ unicodeName->length = unicodeByteLength / sizeof(UniChar);
+
+ConvertFromTextToUnicode:
+
+ /* verify the result in debug builds -- there's really not anything you can do if it fails */
+ verify_noerr(DisposeTextToUnicodeInfo(&tuInfo));
+ }
+
+CreateTextToUnicodeInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+#pragma mark ----- File/Directory Manipulation Routines -----
+
+/*****************************************************************************/
+
+Boolean FSRefValid(const FSRef *ref)
+{
+ return ( noErr == FSGetCatalogInfo(ref, kFSCatInfoNone, NULL, NULL, NULL, NULL) );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetParentRef(
+ const FSRef *ref,
+ FSRef *parentRef)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+
+ /* check parameters */
+ require_action(NULL != parentRef, BadParameter, result = paramErr);
+
+ result = FSGetCatalogInfo(ref, kFSCatInfoNodeID, &catalogInfo, NULL, NULL, parentRef);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /*
+ * Note: FSRefs always point to real file system objects. So, there cannot
+ * be a FSRef to the parent of volume root directories. Early versions of
+ * Mac OS X do not handle this case correctly and incorrectly return a
+ * FSRef for the parent of volume root directories instead of returning an
+ * invalid FSRef (a cleared FSRef is invalid). The next three lines of code
+ * ensure that you won't run into this bug. WW9D!
+ */
+ if ( fsRtDirID == catalogInfo.nodeID )
+ {
+ /* clear parentRef and return noErr which is the proper behavior */
+ memset(parentRef, 0, sizeof(FSRef));
+ }
+
+FSGetCatalogInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetFileDirName(
+ const FSRef *ref,
+ HFSUniStr255 *outName)
+{
+ OSErr result;
+
+ /* check parameters */
+ require_action(NULL != outName, BadParameter, result = paramErr);
+
+ result = FSGetCatalogInfo(ref, kFSCatInfoNone, NULL, outName, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+FSGetCatalogInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetNodeID(
+ const FSRef *ref,
+ long *nodeID, /* can be NULL */
+ Boolean *isDirectory) /* can be NULL */
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+ FSCatalogInfoBitmap whichInfo;
+
+ /* determine what catalog information to get */
+ whichInfo = kFSCatInfoNone; /* start with none */
+ if ( NULL != nodeID )
+ {
+ whichInfo |= kFSCatInfoNodeID;
+ }
+ if ( NULL != isDirectory )
+ {
+ whichInfo |= kFSCatInfoNodeFlags;
+ }
+
+ result = FSGetCatalogInfo(ref, whichInfo, &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ if ( NULL != nodeID )
+ {
+ *nodeID = catalogInfo.nodeID;
+ }
+ if ( NULL != isDirectory )
+ {
+ *isDirectory = (0 != (kFSNodeIsDirectoryMask & catalogInfo.nodeFlags));
+ }
+
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetUserPrivilegesPermissions(
+ const FSRef *ref,
+ UInt8 *userPrivileges, /* can be NULL */
+ UInt32 permissions[4]) /* can be NULL */
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+ FSCatalogInfoBitmap whichInfo;
+
+ /* determine what catalog information to get */
+ whichInfo = kFSCatInfoNone; /* start with none */
+ if ( NULL != userPrivileges )
+ {
+ whichInfo |= kFSCatInfoUserPrivs;
+ }
+ if ( NULL != permissions )
+ {
+ whichInfo |= kFSCatInfoPermissions;
+ }
+
+ result = FSGetCatalogInfo(ref, whichInfo, &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ if ( NULL != userPrivileges )
+ {
+ *userPrivileges = catalogInfo.userPrivileges;
+ }
+ if ( NULL != permissions )
+ {
+ BlockMoveData(&catalogInfo.permissions, permissions, sizeof(UInt32) * 4);
+ }
+
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSCheckLock(
+ const FSRef *ref)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+ FSVolumeInfo volumeInfo;
+
+ /* get nodeFlags and vRefNum for container */
+ result = FSGetCatalogInfo(ref, kFSCatInfoNodeFlags + kFSCatInfoVolume, &catalogInfo, NULL, NULL,NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* is file locked? */
+ if ( 0 != (catalogInfo.nodeFlags & kFSNodeLockedMask) )
+ {
+ result = fLckdErr; /* file is locked */
+ }
+ else
+ {
+ /* file isn't locked, but is volume locked? */
+
+ /* get volume flags */
+ result = FSGetVolumeInfo(catalogInfo.volume, 0, NULL, kFSVolInfoFlags, &volumeInfo, NULL, NULL);
+ require_noerr(result, FSGetVolumeInfo);
+
+ if ( 0 != (volumeInfo.flags & kFSVolFlagHardwareLockedMask) )
+ {
+ result = wPrErr; /* volume locked by hardware */
+ }
+ else if ( 0 != (volumeInfo.flags & kFSVolFlagSoftwareLockedMask) )
+ {
+ result = vLckdErr; /* volume locked by software */
+ }
+ }
+
+FSGetVolumeInfo:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetForkSizes(
+ const FSRef *ref,
+ UInt64 *dataLogicalSize, /* can be NULL */
+ UInt64 *rsrcLogicalSize) /* can be NULL */
+{
+ OSErr result;
+ FSCatalogInfoBitmap whichInfo;
+ FSCatalogInfo catalogInfo;
+
+ whichInfo = kFSCatInfoNodeFlags;
+ if ( NULL != dataLogicalSize )
+ {
+ /* get data fork size */
+ whichInfo |= kFSCatInfoDataSizes;
+ }
+ if ( NULL != rsrcLogicalSize )
+ {
+ /* get resource fork size */
+ whichInfo |= kFSCatInfoRsrcSizes;
+ }
+
+ /* get nodeFlags and catalog info */
+ result = FSGetCatalogInfo(ref, whichInfo, &catalogInfo, NULL, NULL,NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* make sure FSRef was to a file */
+ require_action(0 == (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask), FSRefNotFile, result = notAFileErr);
+
+ if ( NULL != dataLogicalSize )
+ {
+ /* return data fork size */
+ *dataLogicalSize = catalogInfo.dataLogicalSize;
+ }
+ if ( NULL != rsrcLogicalSize )
+ {
+ /* return resource fork size */
+ *rsrcLogicalSize = catalogInfo.rsrcLogicalSize;
+ }
+
+FSRefNotFile:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetTotalForkSizes(
+ const FSRef *ref,
+ UInt64 *totalLogicalSize, /* can be NULL */
+ UInt64 *totalPhysicalSize, /* can be NULL */
+ ItemCount *forkCount) /* can be NULL */
+{
+ OSErr result;
+ CatPositionRec forkIterator;
+ SInt64 forkSize;
+ SInt64 *forkSizePtr;
+ UInt64 forkPhysicalSize;
+ UInt64 *forkPhysicalSizePtr;
+
+ /* Determine if forkSize needed */
+ if ( NULL != totalLogicalSize)
+ {
+ *totalLogicalSize = 0;
+ forkSizePtr = &forkSize;
+ }
+ else
+ {
+ forkSizePtr = NULL;
+ }
+
+ /* Determine if forkPhysicalSize is needed */
+ if ( NULL != totalPhysicalSize )
+ {
+ *totalPhysicalSize = 0;
+ forkPhysicalSizePtr = &forkPhysicalSize;
+ }
+ else
+ {
+ forkPhysicalSizePtr = NULL;
+ }
+
+ /* zero fork count if returning it */
+ if ( NULL != forkCount )
+ {
+ *forkCount = 0;
+ }
+
+ /* Iterate through the forks to get the sizes */
+ forkIterator.initialize = 0;
+ do
+ {
+ result = FSIterateForks(ref, &forkIterator, NULL, forkSizePtr, forkPhysicalSizePtr);
+ if ( noErr == result )
+ {
+ if ( NULL != totalLogicalSize )
+ {
+ *totalLogicalSize += forkSize;
+ }
+
+ if ( NULL != totalPhysicalSize )
+ {
+ *totalPhysicalSize += forkPhysicalSize;
+ }
+
+ if ( NULL != forkCount )
+ {
+ ++*forkCount;
+ }
+ }
+ } while ( noErr == result );
+
+ /* any error result other than errFSNoMoreItems is serious */
+ require(errFSNoMoreItems == result, FSIterateForks);
+
+ /* Normal exit */
+ result = noErr;
+
+FSIterateForks:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSBumpDate(
+ const FSRef *ref)
+{
+ OSStatus result;
+ FSCatalogInfo catalogInfo;
+ UTCDateTime oldDateTime;
+#if !BuildingMoreFilesXForMacOS9
+ FSRef parentRef;
+ Boolean notifyParent;
+#endif
+
+#if !BuildingMoreFilesXForMacOS9
+ /* Get the node flags, the content modification date and time, and the parent ref */
+ result = FSGetCatalogInfo(ref, kFSCatInfoNodeFlags + kFSCatInfoContentMod, &catalogInfo, NULL, NULL, &parentRef);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* Notify the parent if this is a file */
+ notifyParent = (0 == (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask));
+#else
+ /* Get the content modification date and time */
+ result = FSGetCatalogInfo(ref, kFSCatInfoContentMod, &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+#endif
+
+ oldDateTime = catalogInfo.contentModDate;
+
+ /* Get the current date and time */
+ result = GetUTCDateTime(&catalogInfo.contentModDate, kUTCDefaultOptions);
+ require_noerr(result, GetUTCDateTime);
+
+ /* if the old date and time is the the same as the current, bump the seconds by one */
+ if ( (catalogInfo.contentModDate.fraction == oldDateTime.fraction) &&
+ (catalogInfo.contentModDate.lowSeconds == oldDateTime.lowSeconds) &&
+ (catalogInfo.contentModDate.highSeconds == oldDateTime.highSeconds) )
+ {
+ ++catalogInfo.contentModDate.lowSeconds;
+ if ( 0 == catalogInfo.contentModDate.lowSeconds )
+ {
+ ++catalogInfo.contentModDate.highSeconds;
+ }
+ }
+
+ /* Bump the content modification date and time */
+ result = FSSetCatalogInfo(ref, kFSCatInfoContentMod, &catalogInfo);
+ require_noerr(result, FSSetCatalogInfo);
+
+#if !BuildingMoreFilesXForMacOS9
+ /*
+ * The problem with FNNotify is that it is not available under Mac OS 9
+ * and there's no way to test for that except for looking for the symbol
+ * or something. So, I'll just conditionalize this for those who care
+ * to send a notification.
+ */
+
+ /* Send a notification for the parent of the file, or for the directory */
+ result = FNNotify(notifyParent ? &parentRef : ref, kFNDirectoryModifiedMessage, kNilOptions);
+ require_noerr(result, FNNotify);
+#endif
+
+ /* ignore errors from FSSetCatalogInfo (volume might be write protected) and FNNotify */
+FNNotify:
+FSSetCatalogInfo:
+
+ return ( noErr );
+
+ /**********************/
+
+GetUTCDateTime:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetFinderInfo(
+ const FSRef *ref,
+ FinderInfo *info, /* can be NULL */
+ ExtendedFinderInfo *extendedInfo, /* can be NULL */
+ Boolean *isDirectory) /* can be NULL */
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+ FSCatalogInfoBitmap whichInfo;
+
+ /* determine what catalog information is really needed */
+ whichInfo = kFSCatInfoNone;
+
+ if ( NULL != info )
+ {
+ /* get FinderInfo */
+ whichInfo |= kFSCatInfoFinderInfo;
+ }
+
+ if ( NULL != extendedInfo )
+ {
+ /* get ExtendedFinderInfo */
+ whichInfo |= kFSCatInfoFinderXInfo;
+ }
+
+ if ( NULL != isDirectory )
+ {
+ whichInfo |= kFSCatInfoNodeFlags;
+ }
+
+ result = FSGetCatalogInfo(ref, whichInfo, &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* return FinderInfo if requested */
+ if ( NULL != info )
+ {
+ BlockMoveData(catalogInfo.finderInfo, info, sizeof(FinderInfo));
+ }
+
+ /* return ExtendedFinderInfo if requested */
+ if ( NULL != extendedInfo)
+ {
+ BlockMoveData(catalogInfo.extFinderInfo, extendedInfo, sizeof(ExtendedFinderInfo));
+ }
+
+ /* set isDirectory Boolean if requested */
+ if ( NULL != isDirectory)
+ {
+ *isDirectory = (0 != (kFSNodeIsDirectoryMask & catalogInfo.nodeFlags));
+ }
+
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSSetFinderInfo(
+ const FSRef *ref,
+ const FinderInfo *info,
+ const ExtendedFinderInfo *extendedInfo)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+ FSCatalogInfoBitmap whichInfo;
+
+ /* determine what catalog information will be set */
+ whichInfo = kFSCatInfoNone; /* start with none */
+ if ( NULL != info )
+ {
+ /* set FinderInfo */
+ whichInfo |= kFSCatInfoFinderInfo;
+ BlockMoveData(info, catalogInfo.finderInfo, sizeof(FinderInfo));
+ }
+ if ( NULL != extendedInfo )
+ {
+ /* set ExtendedFinderInfo */
+ whichInfo |= kFSCatInfoFinderXInfo;
+ BlockMoveData(extendedInfo, catalogInfo.extFinderInfo, sizeof(ExtendedFinderInfo));
+ }
+
+ result = FSSetCatalogInfo(ref, whichInfo, &catalogInfo);
+ require_noerr(result, FSGetCatalogInfo);
+
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSChangeCreatorType(
+ const FSRef *ref,
+ OSType fileCreator,
+ OSType fileType)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+ FSRef parentRef;
+
+ /* get nodeFlags, finder info, and parent FSRef */
+ result = FSGetCatalogInfo(ref, kFSCatInfoNodeFlags + kFSCatInfoFinderInfo, &catalogInfo , NULL, NULL, &parentRef);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* make sure FSRef was to a file */
+ require_action(0 == (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask), FSRefNotFile, result = notAFileErr);
+
+ /* If fileType not 0x00000000, change fileType */
+ if ( fileType != (OSType)0x00000000 )
+ {
+ ((FileInfo *)&catalogInfo.finderInfo)->fileType = fileType;
+ }
+
+ /* If creator not 0x00000000, change creator */
+ if ( fileCreator != (OSType)0x00000000 )
+ {
+ ((FileInfo *)&catalogInfo.finderInfo)->fileCreator = fileCreator;
+ }
+
+ /* now, save the new information back to disk */
+ result = FSSetCatalogInfo(ref, kFSCatInfoFinderInfo, &catalogInfo);
+ require_noerr(result, FSSetCatalogInfo);
+
+ /* and attempt to bump the parent directory's mod date to wake up */
+ /* the Finder to the change we just made (ignore errors from this) */
+ verify_noerr(FSBumpDate(&parentRef));
+
+FSSetCatalogInfo:
+FSRefNotFile:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSChangeFinderFlags(
+ const FSRef *ref,
+ Boolean setBits,
+ UInt16 flagBits)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+ FSRef parentRef;
+
+ /* get the current finderInfo */
+ result = FSGetCatalogInfo(ref, kFSCatInfoFinderInfo, &catalogInfo, NULL, NULL, &parentRef);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* set or clear the appropriate bits in the finderInfo.finderFlags */
+ if ( setBits )
+ {
+ /* OR in the bits */
+ ((FileInfo *)&catalogInfo.finderInfo)->finderFlags |= flagBits;
+ }
+ else
+ {
+ /* AND out the bits */
+ ((FileInfo *)&catalogInfo.finderInfo)->finderFlags &= ~flagBits;
+ }
+
+ /* save the modified finderInfo */
+ result = FSSetCatalogInfo(ref, kFSCatInfoFinderInfo, &catalogInfo);
+ require_noerr(result, FSSetCatalogInfo);
+
+ /* and attempt to bump the parent directory's mod date to wake up the Finder */
+ /* to the change we just made (ignore errors from this) */
+ verify_noerr(FSBumpDate(&parentRef));
+
+FSSetCatalogInfo:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSSetInvisible(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, true, kIsInvisible) );
+}
+
+OSErr
+FSClearInvisible(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, false, kIsInvisible) );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSSetNameLocked(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, true, kNameLocked) );
+}
+
+OSErr
+FSClearNameLocked(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, false, kNameLocked) );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSSetIsStationery(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, true, kIsStationery) );
+}
+
+OSErr
+FSClearIsStationery(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, false, kIsStationery) );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSSetHasCustomIcon(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, true, kHasCustomIcon) );
+}
+
+OSErr
+FSClearHasCustomIcon(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, false, kHasCustomIcon) );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSClearHasBeenInited(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, false, kHasBeenInited) );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSCopyFileMgrAttributes(
+ const FSRef *sourceRef,
+ const FSRef *destinationRef,
+ Boolean copyLockBit)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+
+ /* get the source information */
+ result = FSGetCatalogInfo(sourceRef, kFSCatInfoSettableInfo, &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* don't copy the hasBeenInited bit; clear it */
+ ((FileInfo *)&catalogInfo.finderInfo)->finderFlags &= ~kHasBeenInited;
+
+ /* should the locked bit be copied? */
+ if ( !copyLockBit )
+ {
+ /* no, make sure the locked bit is clear */
+ catalogInfo.nodeFlags &= ~kFSNodeLockedMask;
+ }
+
+ /* set the destination information */
+ result = FSSetCatalogInfo(destinationRef, kFSCatInfoSettableInfo, &catalogInfo);
+ require_noerr(result, FSSetCatalogInfo);
+
+FSSetCatalogInfo:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSMoveRenameObjectUnicode(
+ const FSRef *ref,
+ const FSRef *destDirectory,
+ UniCharCount nameLength,
+ const UniChar *name, /* can be NULL (no rename during move) */
+ TextEncoding textEncodingHint,
+ FSRef *newRef) /* if function fails along the way, newRef is final location of file */
+{
+ OSErr result;
+ FSVolumeRefNum vRefNum;
+ FSCatalogInfo catalogInfo;
+ FSRef originalDirectory;
+ TextEncoding originalTextEncodingHint;
+ HFSUniStr255 originalName;
+ HFSUniStr255 uniqueName; /* unique name given to object while moving it to destination */
+ long theSeed; /* the seed for generating unique names */
+
+ /* check parameters */
+ require_action(NULL != newRef, BadParameter, result = paramErr);
+
+ /* newRef = input to start with */
+ BlockMoveData(ref, newRef, sizeof(FSRef));
+
+ /* get destDirectory's vRefNum */
+ result = FSGetCatalogInfo(destDirectory, kFSCatInfoVolume, &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, DestinationBad);
+
+ /* save vRefNum */
+ vRefNum = catalogInfo.volume;
+
+ /* get ref's vRefNum, TextEncoding, name and parent directory*/
+ result = FSGetCatalogInfo(ref, kFSCatInfoTextEncoding + kFSCatInfoVolume, &catalogInfo, &originalName, NULL, &originalDirectory);
+ require_noerr(result, SourceBad);
+
+ /* save TextEncoding */
+ originalTextEncodingHint = catalogInfo.textEncodingHint;
+
+ /* make sure ref and destDirectory are on same volume */
+ require_action(vRefNum == catalogInfo.volume, NotSameVolume, result = diffVolErr);
+
+ /* Skip a few steps if we're not renaming */
+ if ( NULL != name )
+ {
+ /* generate a name that is unique in both directories */
+ theSeed = 0x4a696d4c; /* a fine unlikely filename */
+
+ result = GenerateUniqueHFSUniStr(&theSeed, &originalDirectory, destDirectory, &uniqueName);
+ require_noerr(result, GenerateUniqueHFSUniStrFailed);
+
+ /* Rename the object to uniqueName */
+ result = FSRenameUnicode(ref, uniqueName.length, uniqueName.unicode, kTextEncodingUnknown, newRef);
+ require_noerr(result, FSRenameUnicodeBeforeMoveFailed);
+
+ if ( FSCompareFSRefs(destDirectory, &originalDirectory) != noErr )
+ {
+ /* Move object to its new home */
+ result = FSMoveObject(newRef, destDirectory, newRef);
+ require_noerr(result, FSMoveObjectAfterRenameFailed);
+ }
+
+ /* Rename the object to new name */
+ result = FSRenameUnicode(ref, nameLength, name, textEncodingHint, newRef);
+ require_noerr(result, FSRenameUnicodeAfterMoveFailed);
+ }
+ else
+ {
+ /* Move object to its new home */
+ result = FSMoveObject(newRef, destDirectory, newRef);
+ require_noerr(result, FSMoveObjectNoRenameFailed);
+ }
+
+ return ( result );
+
+ /*************/
+
+/*
+ * failure handling code when renaming
+ */
+
+FSRenameUnicodeAfterMoveFailed:
+
+ /* Error handling: move object back to original location - ignore errors */
+ verify_noerr(FSMoveObject(newRef, &originalDirectory, newRef));
+
+FSMoveObjectAfterRenameFailed:
+
+ /* Error handling: rename object back to original name - ignore errors */
+ verify_noerr(FSRenameUnicode(newRef, originalName.length, originalName.unicode, originalTextEncodingHint, newRef));
+
+FSRenameUnicodeBeforeMoveFailed:
+GenerateUniqueHFSUniStrFailed:
+
+/*
+ * failure handling code for renaming or not
+ */
+FSMoveObjectNoRenameFailed:
+NotSameVolume:
+SourceBad:
+DestinationBad:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+/*
+ The FSDeleteContainerLevel function deletes the contents of a container
+ directory. All files and subdirectories in the specified container are
+ deleted. If a locked file or directory is encountered, it is unlocked
+ and then deleted. If any unexpected errors are encountered,
+ FSDeleteContainerLevel quits and returns to the caller.
+
+ container --> FSRef to a directory.
+ theGlobals --> A pointer to a FSDeleteContainerGlobals struct
+ which contains the variables that do not need to
+ be allocated each time FSDeleteContainerLevel
+ recurses. That lets FSDeleteContainerLevel use
+ less stack space per recursion level.
+*/
+
+static
+void
+FSDeleteContainerLevel(
+ const FSRef *container,
+ FSDeleteContainerGlobals *theGlobals)
+{
+ /* level locals */
+ FSIterator iterator;
+ FSRef itemToDelete;
+ UInt16 nodeFlags;
+
+ /* Open FSIterator for flat access and give delete optimization hint */
+ theGlobals->result = FSOpenIterator(container, kFSIterateFlat + kFSIterateDelete, &iterator);
+ require_noerr(theGlobals->result, FSOpenIterator);
+
+ /* delete the contents of the directory */
+ do
+ {
+ /* get 1 item to delete */
+ theGlobals->result = FSGetCatalogInfoBulk(iterator, 1, &theGlobals->actualObjects,
+ NULL, kFSCatInfoNodeFlags, &theGlobals->catalogInfo,
+ &itemToDelete, NULL, NULL);
+ if ( (noErr == theGlobals->result) && (1 == theGlobals->actualObjects) )
+ {
+ /* save node flags in local in case we have to recurse */
+ nodeFlags = theGlobals->catalogInfo.nodeFlags;
+
+ /* is it a file or directory? */
+ if ( 0 != (nodeFlags & kFSNodeIsDirectoryMask) )
+ {
+ /* it's a directory -- delete its contents before attempting to delete it */
+ FSDeleteContainerLevel(&itemToDelete, theGlobals);
+ }
+ /* are we still OK to delete? */
+ if ( noErr == theGlobals->result )
+ {
+ /* is item locked? */
+ if ( 0 != (nodeFlags & kFSNodeLockedMask) )
+ {
+ /* then attempt to unlock it (ignore result since FSDeleteObject will set it correctly) */
+ theGlobals->catalogInfo.nodeFlags = nodeFlags & ~kFSNodeLockedMask;
+ (void) FSSetCatalogInfo(&itemToDelete, kFSCatInfoNodeFlags, &theGlobals->catalogInfo);
+ }
+ /* delete the item */
+ theGlobals->result = FSDeleteObject(&itemToDelete);
+ }
+ }
+ } while ( noErr == theGlobals->result );
+
+ /* we found the end of the items normally, so return noErr */
+ if ( errFSNoMoreItems == theGlobals->result )
+ {
+ theGlobals->result = noErr;
+ }
+
+ /* close the FSIterator (closing an open iterator should never fail) */
+ verify_noerr(FSCloseIterator(iterator));
+
+FSOpenIterator:
+
+ return;
+}
+
+/*****************************************************************************/
+
+OSErr
+FSDeleteContainerContents(
+ const FSRef *container)
+{
+ FSDeleteContainerGlobals theGlobals;
+
+ /* delete container's contents */
+ FSDeleteContainerLevel(container, &theGlobals);
+
+ return ( theGlobals.result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSDeleteContainer(
+ const FSRef *container)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+
+ /* get nodeFlags for container */
+ result = FSGetCatalogInfo(container, kFSCatInfoNodeFlags, &catalogInfo, NULL, NULL,NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* make sure container is a directory */
+ require_action(0 != (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask), ContainerNotDirectory, result = dirNFErr);
+
+ /* delete container's contents */
+ result = FSDeleteContainerContents(container);
+ require_noerr(result, FSDeleteContainerContents);
+
+ /* is container locked? */
+ if ( 0 != (catalogInfo.nodeFlags & kFSNodeLockedMask) )
+ {
+ /* then attempt to unlock container (ignore result since FSDeleteObject will set it correctly) */
+ catalogInfo.nodeFlags &= ~kFSNodeLockedMask;
+ (void) FSSetCatalogInfo(container, kFSCatInfoNodeFlags, &catalogInfo);
+ }
+
+ /* delete the container */
+ result = FSDeleteObject(container);
+
+FSDeleteContainerContents:
+ContainerNotDirectory:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+/*
+ The FSIterateContainerLevel function iterates the contents of a container
+ directory and calls a IterateContainerFilterProc function once for each
+ file and directory found.
+
+ theGlobals --> A pointer to a FSIterateContainerGlobals struct
+ which contains the variables needed globally by
+ all recusion levels of FSIterateContainerLevel.
+ That makes FSIterateContainer thread safe since
+ each call to it uses its own global world.
+ It also contains the variables that do not need
+ to be allocated each time FSIterateContainerLevel
+ recurses. That lets FSIterateContainerLevel use
+ less stack space per recursion level.
+*/
+
+static
+void
+FSIterateContainerLevel(
+ FSIterateContainerGlobals *theGlobals)
+{
+ FSIterator iterator;
+
+ /* If maxLevels is zero, we aren't checking levels */
+ /* If currentLevel < maxLevels, look at this level */
+ if ( (theGlobals->maxLevels == 0) ||
+ (theGlobals->currentLevel < theGlobals->maxLevels) )
+ {
+ /* Open FSIterator for flat access to theGlobals->ref */
+ theGlobals->result = FSOpenIterator(&theGlobals->ref, kFSIterateFlat, &iterator);
+ require_noerr(theGlobals->result, FSOpenIterator);
+
+ ++theGlobals->currentLevel; /* Go to next level */
+
+ /* Call FSGetCatalogInfoBulk in loop to get all items in the container */
+ do
+ {
+ theGlobals->result = FSGetCatalogInfoBulk(iterator, 1, &theGlobals->actualObjects,
+ &theGlobals->containerChanged, theGlobals->whichInfo, &theGlobals->catalogInfo,
+ &theGlobals->ref, theGlobals->specPtr, theGlobals->namePtr);
+ if ( (noErr == theGlobals->result || errFSNoMoreItems == theGlobals->result) &&
+ (0 != theGlobals->actualObjects) )
+ {
+ /* Call the IterateFilterProc */
+ theGlobals->quitFlag = CallIterateContainerFilterProc(theGlobals->iterateFilter,
+ theGlobals->containerChanged, theGlobals->currentLevel,
+ &theGlobals->catalogInfo, &theGlobals->ref,
+ theGlobals->specPtr, theGlobals->namePtr, theGlobals->yourDataPtr);
+ /* Is it a directory? */
+ if ( 0 != (theGlobals->catalogInfo.nodeFlags & kFSNodeIsDirectoryMask) )
+ {
+ /* Keep going? */
+ if ( !theGlobals->quitFlag )
+ {
+ /* Dive again if the IterateFilterProc didn't say "quit" */
+ FSIterateContainerLevel(theGlobals);
+ }
+ }
+ }
+ /* time to fall back a level? */
+ } while ( (noErr == theGlobals->result) && (!theGlobals->quitFlag) );
+
+ /* errFSNoMoreItems is OK - it only means we hit the end of this level */
+ /* afpAccessDenied is OK, too - it only means we cannot see inside a directory */
+ if ( (errFSNoMoreItems == theGlobals->result) ||
+ (afpAccessDenied == theGlobals->result) )
+ {
+ theGlobals->result = noErr;
+ }
+
+ --theGlobals->currentLevel; /* Return to previous level as we leave */
+
+ /* Close the FSIterator (closing an open iterator should never fail) */
+ verify_noerr(FSCloseIterator(iterator));
+ }
+
+FSOpenIterator:
+
+ return;
+}
+
+/*****************************************************************************/
+
+OSErr
+FSIterateContainer(
+ const FSRef *container,
+ ItemCount maxLevels,
+ FSCatalogInfoBitmap whichInfo,
+ Boolean wantFSSpec,
+ Boolean wantName,
+ IterateContainerFilterProcPtr iterateFilter,
+ void *yourDataPtr)
+{
+ OSErr result;
+ FSIterateContainerGlobals theGlobals;
+
+ /* make sure there is an iterateFilter */
+ require_action(iterateFilter != NULL, NoIterateFilter, result = paramErr);
+
+ /*
+ * set up the globals we need to access from the recursive routine
+ */
+ theGlobals.iterateFilter = iterateFilter;
+ /* we need the node flags no matter what was requested so we can detect files vs. directories */
+ theGlobals.whichInfo = whichInfo | kFSCatInfoNodeFlags;
+ /* start with input container -- the first OpenIterator will ensure it is a directory */
+ theGlobals.ref = *container;
+ if ( wantFSSpec )
+ {
+ theGlobals.specPtr = &theGlobals.spec;
+ }
+ else
+ {
+ theGlobals.specPtr = NULL;
+ }
+ if ( wantName )
+ {
+ theGlobals.namePtr = &theGlobals.name;
+ }
+ else
+ {
+ theGlobals.namePtr = NULL;
+ }
+ theGlobals.yourDataPtr = yourDataPtr;
+ theGlobals.maxLevels = maxLevels;
+ theGlobals.currentLevel = 0;
+ theGlobals.quitFlag = false;
+ theGlobals.containerChanged = false;
+ theGlobals.result = noErr;
+ theGlobals.actualObjects = 0;
+
+ /* here we go into recursion land... */
+ FSIterateContainerLevel(&theGlobals);
+ result = theGlobals.result;
+ require_noerr(result, FSIterateContainerLevel);
+
+FSIterateContainerLevel:
+NoIterateFilter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetDirectoryItems(
+ const FSRef *container,
+ FSRef ***refsHandle, /* pointer to handle of FSRefs */
+ ItemCount *numRefs,
+ Boolean *containerChanged)
+{
+ /* Grab items 10 at a time. */
+ enum { kMaxItemsPerBulkCall = 10 };
+
+ OSErr result;
+ OSErr memResult;
+ FSIterator iterator;
+ FSRef refs[kMaxItemsPerBulkCall];
+ ItemCount actualObjects;
+ Boolean changed;
+
+ /* check parameters */
+ require_action((NULL != refsHandle) && (NULL != numRefs) && (NULL != containerChanged),
+ BadParameter, result = paramErr);
+
+ *numRefs = 0;
+ *containerChanged = false;
+ *refsHandle = (FSRef **)NewHandle(0);
+ require_action(NULL != *refsHandle, NewHandle, result = memFullErr);
+
+ /* open an FSIterator */
+ result = FSOpenIterator(container, kFSIterateFlat, &iterator);
+ require_noerr(result, FSOpenIterator);
+
+ /* Call FSGetCatalogInfoBulk in loop to get all items in the container */
+ do
+ {
+ result = FSGetCatalogInfoBulk(iterator, kMaxItemsPerBulkCall, &actualObjects,
+ &changed, kFSCatInfoNone, NULL, refs, NULL, NULL);
+
+ /* if the container changed, set containerChanged for output, but keep going */
+ if ( changed )
+ {
+ *containerChanged = changed;
+ }
+
+ /* any result other than noErr and errFSNoMoreItems is serious */
+ require((noErr == result) || (errFSNoMoreItems == result), FSGetCatalogInfoBulk);
+
+ /* add objects to output array and count */
+ if ( 0 != actualObjects )
+ {
+ /* concatenate the FSRefs to the end of the handle */
+ PtrAndHand(refs, (Handle)*refsHandle, actualObjects * sizeof(FSRef));
+ memResult = MemError();
+ require_noerr_action(memResult, MemoryAllocationFailed, result = memResult);
+
+ *numRefs += actualObjects;
+ }
+ } while ( noErr == result );
+
+ verify_noerr(FSCloseIterator(iterator)); /* closing an open iterator should never fail, but... */
+
+ return ( noErr );
+
+ /**********************/
+
+MemoryAllocationFailed:
+FSGetCatalogInfoBulk:
+
+ /* close the iterator */
+ verify_noerr(FSCloseIterator(iterator));
+
+FSOpenIterator:
+ /* dispose of handle if already allocated and clear the outputs */
+ if ( NULL != *refsHandle )
+ {
+ DisposeHandle((Handle)*refsHandle);
+ *refsHandle = NULL;
+ }
+ *numRefs = 0;
+
+NewHandle:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+/*
+ The GenerateUniqueName function generates a HFSUniStr255 name that is
+ unique in both dir1 and dir2.
+
+ startSeed --> A pointer to a long which is used to generate the
+ unique name.
+ <-- It is modified on output to a value which should
+ be used to generate the next unique name.
+ dir1 --> The first directory.
+ dir2 --> The second directory.
+ uniqueName <-- A pointer to a HFSUniStr255 where the unique name
+ is to be returned.
+*/
+
+static
+OSErr
+GenerateUniqueHFSUniStr(
+ long *startSeed,
+ const FSRef *dir1,
+ const FSRef *dir2,
+ HFSUniStr255 *uniqueName)
+{
+ OSErr result;
+ long i;
+ FSRefParam pb;
+ FSRef newRef;
+ unsigned char hexStr[17] = "0123456789ABCDEF";
+
+ /* set up the parameter block */
+ pb.name = uniqueName->unicode;
+ pb.nameLength = 8; /* always 8 characters */
+ pb.textEncodingHint = kTextEncodingUnknown;
+ pb.newRef = &newRef;
+
+ /* loop until we get fnfErr with a filename in both directories */
+ result = noErr;
+ while ( fnfErr != result )
+ {
+ /* convert startSeed to 8 character Unicode string */
+ uniqueName->length = 8;
+ for ( i = 0; i < 8; ++i )
+ {
+ uniqueName->unicode[i] = hexStr[((*startSeed >> ((7-i)*4)) & 0xf)];
+ }
+
+ /* try in dir1 */
+ pb.ref = dir1;
+ result = PBMakeFSRefUnicodeSync(&pb);
+ if ( fnfErr == result )
+ {
+ /* try in dir2 */
+ pb.ref = dir2;
+ result = PBMakeFSRefUnicodeSync(&pb);
+ if ( fnfErr != result )
+ {
+ /* exit if anything other than noErr or fnfErr */
+ require_noerr(result, Dir2PBMakeFSRefUnicodeSyncFailed);
+ }
+ }
+ else
+ {
+ /* exit if anything other than noErr or fnfErr */
+ require_noerr(result, Dir1PBMakeFSRefUnicodeSyncFailed);
+ }
+
+ /* increment seed for next pass through loop, */
+ /* or for next call to GenerateUniqueHFSUniStr */
+ ++(*startSeed);
+ }
+
+ /* we have a unique file name which doesn't exist in dir1 or dir2 */
+ result = noErr;
+
+Dir2PBMakeFSRefUnicodeSyncFailed:
+Dir1PBMakeFSRefUnicodeSyncFailed:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSExchangeObjectsCompat(
+ const FSRef *sourceRef,
+ const FSRef *destRef,
+ FSRef *newSourceRef,
+ FSRef *newDestRef)
+{
+ enum
+ {
+ /* get all settable info except for mod dates, plus the volume refNum and parent directory ID */
+ kGetCatInformationMask = (kFSCatInfoSettableInfo |
+ kFSCatInfoVolume |
+ kFSCatInfoParentDirID) &
+ ~(kFSCatInfoContentMod | kFSCatInfoAttrMod),
+ /* set everything possible except for mod dates */
+ kSetCatinformationMask = kFSCatInfoSettableInfo &
+ ~(kFSCatInfoContentMod | kFSCatInfoAttrMod)
+ };
+
+ OSErr result;
+ GetVolParmsInfoBuffer volParmsInfo;
+ UInt32 infoSize;
+ FSCatalogInfo sourceCatalogInfo; /* source file's catalog information */
+ FSCatalogInfo destCatalogInfo; /* destination file's catalog information */
+ HFSUniStr255 sourceName; /* source file's Unicode name */
+ HFSUniStr255 destName; /* destination file's Unicode name */
+ FSRef sourceCurrentRef; /* FSRef to current location of source file throughout this function */
+ FSRef destCurrentRef; /* FSRef to current location of destination file throughout this function */
+ FSRef sourceParentRef; /* FSRef to parent directory of source file */
+ FSRef destParentRef; /* FSRef to parent directory of destination file */
+ HFSUniStr255 sourceUniqueName; /* unique name given to source file while exchanging it with destination */
+ HFSUniStr255 destUniqueName; /* unique name given to destination file while exchanging it with source */
+ long theSeed; /* the seed for generating unique names */
+ Boolean sameParentDirs; /* true if source and destinatin parent directory is the same */
+
+ /* check parameters */
+ require_action((NULL != newSourceRef) && (NULL != newDestRef), BadParameter, result = paramErr);
+
+ /* output refs and current refs = input refs to start with */
+ BlockMoveData(sourceRef, newSourceRef, sizeof(FSRef));
+ BlockMoveData(sourceRef, &sourceCurrentRef, sizeof(FSRef));
+
+ BlockMoveData(destRef, newDestRef, sizeof(FSRef));
+ BlockMoveData(destRef, &destCurrentRef, sizeof(FSRef));
+
+ /* get source volume's vRefNum */
+ result = FSGetCatalogInfo(&sourceCurrentRef, kFSCatInfoVolume, &sourceCatalogInfo, NULL, NULL, NULL);
+ require_noerr(result, DetermineSourceVRefNumFailed);
+
+ /* see if that volume supports FSExchangeObjects */
+ result = FSGetVolParms(sourceCatalogInfo.volume, sizeof(GetVolParmsInfoBuffer),
+ &volParmsInfo, &infoSize);
+ if ( (noErr == result) && VolSupportsFSExchangeObjects(&volParmsInfo) )
+ {
+ /* yes - use FSExchangeObjects */
+ result = FSExchangeObjects(sourceRef, destRef);
+ }
+ else
+ {
+ /* no - emulate FSExchangeObjects */
+
+ /* Note: The compatibility case won't work for files with *Btree control blocks. */
+ /* Right now the only *Btree files are created by the system. */
+
+ /* get all catalog information and Unicode names for each file */
+ result = FSGetCatalogInfo(&sourceCurrentRef, kGetCatInformationMask, &sourceCatalogInfo, &sourceName, NULL, &sourceParentRef);
+ require_noerr(result, SourceFSGetCatalogInfoFailed);
+
+ result = FSGetCatalogInfo(&destCurrentRef, kGetCatInformationMask, &destCatalogInfo, &destName, NULL, &destParentRef);
+ require_noerr(result, DestFSGetCatalogInfoFailed);
+
+ /* make sure source and destination are on same volume */
+ require_action(sourceCatalogInfo.volume == destCatalogInfo.volume, NotSameVolume, result = diffVolErr);
+
+ /* make sure both files are *really* files */
+ require_action((0 == (sourceCatalogInfo.nodeFlags & kFSNodeIsDirectoryMask)) &&
+ (0 == (destCatalogInfo.nodeFlags & kFSNodeIsDirectoryMask)), NotAFile, result = notAFileErr);
+
+ /* generate 2 names that are unique in both directories */
+ theSeed = 0x4a696d4c; /* a fine unlikely filename */
+
+ result = GenerateUniqueHFSUniStr(&theSeed, &sourceParentRef, &destParentRef, &sourceUniqueName);
+ require_noerr(result, GenerateUniqueHFSUniStr1Failed);
+
+ result = GenerateUniqueHFSUniStr(&theSeed, &sourceParentRef, &destParentRef, &destUniqueName);
+ require_noerr(result, GenerateUniqueHFSUniStr2Failed);
+
+ /* rename sourceCurrentRef to sourceUniqueName */
+ result = FSRenameUnicode(&sourceCurrentRef, sourceUniqueName.length, sourceUniqueName.unicode, kTextEncodingUnknown, newSourceRef);
+ require_noerr(result, FSRenameUnicode1Failed);
+ BlockMoveData(newSourceRef, &sourceCurrentRef, sizeof(FSRef));
+
+ /* rename destCurrentRef to destUniqueName */
+ result = FSRenameUnicode(&destCurrentRef, destUniqueName.length, destUniqueName.unicode, kTextEncodingUnknown, newDestRef);
+ require_noerr(result, FSRenameUnicode2Failed);
+ BlockMoveData(newDestRef, &destCurrentRef, sizeof(FSRef));
+
+ /* are the source and destination parent directories the same? */
+ sameParentDirs = ( sourceCatalogInfo.parentDirID == destCatalogInfo.parentDirID );
+ if ( !sameParentDirs )
+ {
+ /* move source file to dest parent directory */
+ result = FSMoveObject(&sourceCurrentRef, &destParentRef, newSourceRef);
+ require_noerr(result, FSMoveObject1Failed);
+ BlockMoveData(newSourceRef, &sourceCurrentRef, sizeof(FSRef));
+
+ /* move dest file to source parent directory */
+ result = FSMoveObject(&destCurrentRef, &sourceParentRef, newDestRef);
+ require_noerr(result, FSMoveObject2Failed);
+ BlockMoveData(newDestRef, &destCurrentRef, sizeof(FSRef));
+ }
+
+ /* At this point, the files are in their new locations (if they were moved). */
+ /* The source file is named sourceUniqueName and is in the directory referred to */
+ /* by destParentRef. The destination file is named destUniqueName and is in the */
+ /* directory referred to by sourceParentRef. */
+
+ /* give source file the dest file's catalog information except for mod dates */
+ result = FSSetCatalogInfo(&sourceCurrentRef, kSetCatinformationMask, &destCatalogInfo);
+ require_noerr(result, FSSetCatalogInfo1Failed);
+
+ /* give dest file the source file's catalog information except for mod dates */
+ result = FSSetCatalogInfo(&destCurrentRef, kSetCatinformationMask, &sourceCatalogInfo);
+ require_noerr(result, FSSetCatalogInfo2Failed);
+
+ /* rename source file with dest file's name */
+ result = FSRenameUnicode(&sourceCurrentRef, destName.length, destName.unicode, destCatalogInfo.textEncodingHint, newSourceRef);
+ require_noerr(result, FSRenameUnicode3Failed);
+ BlockMoveData(newSourceRef, &sourceCurrentRef, sizeof(FSRef));
+
+ /* rename dest file with source file's name */
+ result = FSRenameUnicode(&destCurrentRef, sourceName.length, sourceName.unicode, sourceCatalogInfo.textEncodingHint, newDestRef);
+ require_noerr(result, FSRenameUnicode4Failed);
+
+ /* we're done with no errors, so swap newSourceRef and newDestRef */
+ BlockMoveData(newDestRef, newSourceRef, sizeof(FSRef));
+ BlockMoveData(&sourceCurrentRef, newDestRef, sizeof(FSRef));
+ }
+
+ return ( result );
+
+ /**********************/
+
+/* If there are any failures while emulating FSExchangeObjects, attempt to reverse any steps */
+/* already taken. In any case, newSourceRef and newDestRef will refer to the files in whatever */
+/* state and location they ended up in so that both files can be found by the calling code. */
+
+FSRenameUnicode4Failed:
+
+ /* attempt to rename source file to sourceUniqueName */
+ if ( noErr == FSRenameUnicode(&sourceCurrentRef, sourceUniqueName.length, sourceUniqueName.unicode, kTextEncodingUnknown, newSourceRef) )
+ {
+ BlockMoveData(newSourceRef, &sourceCurrentRef, sizeof(FSRef));
+ }
+
+FSRenameUnicode3Failed:
+
+ /* attempt to restore dest file's catalog information */
+ verify_noerr(FSSetCatalogInfo(&destCurrentRef, kFSCatInfoSettableInfo, &destCatalogInfo));
+
+FSSetCatalogInfo2Failed:
+
+ /* attempt to restore source file's catalog information */
+ verify_noerr(FSSetCatalogInfo(&sourceCurrentRef, kFSCatInfoSettableInfo, &sourceCatalogInfo));
+
+FSSetCatalogInfo1Failed:
+
+ if ( !sameParentDirs )
+ {
+ /* attempt to move dest file back to dest directory */
+ if ( noErr == FSMoveObject(&destCurrentRef, &destParentRef, newDestRef) )
+ {
+ BlockMoveData(newDestRef, &destCurrentRef, sizeof(FSRef));
+ }
+ }
+
+FSMoveObject2Failed:
+
+ if ( !sameParentDirs )
+ {
+ /* attempt to move source file back to source directory */
+ if ( noErr == FSMoveObject(&sourceCurrentRef, &sourceParentRef, newSourceRef) )
+ {
+ BlockMoveData(newSourceRef, &sourceCurrentRef, sizeof(FSRef));
+ }
+ }
+
+FSMoveObject1Failed:
+
+ /* attempt to rename dest file to original name */
+ verify_noerr(FSRenameUnicode(&destCurrentRef, destName.length, destName.unicode, destCatalogInfo.textEncodingHint, newDestRef));
+
+FSRenameUnicode2Failed:
+
+ /* attempt to rename source file to original name */
+ verify_noerr(FSRenameUnicode(&sourceCurrentRef, sourceName.length, sourceName.unicode, sourceCatalogInfo.textEncodingHint, newSourceRef));
+
+FSRenameUnicode1Failed:
+GenerateUniqueHFSUniStr2Failed:
+GenerateUniqueHFSUniStr1Failed:
+NotAFile:
+NotSameVolume:
+DestFSGetCatalogInfoFailed:
+SourceFSGetCatalogInfoFailed:
+DetermineSourceVRefNumFailed:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+#pragma mark ----- Shared Environment Routines -----
+
+/*****************************************************************************/
+
+/* Renamed from FSLockRange to MFX_FSLockRange to avoid a conflict with
+ * the FSLockRange function present in the system library since Mac OS X
+ * 10.4. */
+
+OSErr
+MFX_FSLockRange(
+ SInt16 refNum,
+ SInt32 rangeLength,
+ SInt32 rangeStart)
+{
+ OSErr result;
+ ParamBlockRec pb;
+
+ pb.ioParam.ioRefNum = refNum;
+ pb.ioParam.ioReqCount = rangeLength;
+ pb.ioParam.ioPosMode = fsFromStart;
+ pb.ioParam.ioPosOffset = rangeStart;
+ result = PBLockRangeSync(&pb);
+ require_noerr(result, PBLockRangeSync);
+
+PBLockRangeSync:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+/* Renamed from FSUnlockRange to MFX_FSUnlockRange to avoid a conflict with
+ * the FSUnlockRange function present in the system library since Mac OS X
+ * 10.4. */
+
+OSErr
+MFX_FSUnlockRange(
+ SInt16 refNum,
+ SInt32 rangeLength,
+ SInt32 rangeStart)
+{
+ OSErr result;
+ ParamBlockRec pb;
+
+ pb.ioParam.ioRefNum = refNum;
+ pb.ioParam.ioReqCount = rangeLength;
+ pb.ioParam.ioPosMode = fsFromStart;
+ pb.ioParam.ioPosOffset = rangeStart;
+ result = PBUnlockRangeSync(&pb);
+ require_noerr(result, PBUnlockRangeSync);
+
+PBUnlockRangeSync:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetDirAccess(
+ const FSRef *ref,
+ SInt32 *ownerID, /* can be NULL */
+ SInt32 *groupID, /* can be NULL */
+ SInt32 *accessRights) /* can be NULL */
+{
+ OSErr result;
+ FSSpec spec;
+ HParamBlockRec pb;
+
+ /* get FSSpec from FSRef */
+ result = FSGetCatalogInfo(ref, kFSCatInfoNone, NULL, NULL, &spec, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* get directory access info for FSSpec */
+ pb.accessParam.ioNamePtr = (StringPtr)spec.name;
+ pb.accessParam.ioVRefNum = spec.vRefNum;
+ pb.fileParam.ioDirID = spec.parID;
+ result = PBHGetDirAccessSync(&pb);
+ require_noerr(result, PBHGetDirAccessSync);
+
+ /* return the IDs and access rights */
+ if ( NULL != ownerID )
+ {
+ *ownerID = pb.accessParam.ioACOwnerID;
+ }
+ if ( NULL != groupID )
+ {
+ *groupID = pb.accessParam.ioACGroupID;
+ }
+ if ( NULL != accessRights )
+ {
+ *accessRights = pb.accessParam.ioACAccess;
+ }
+
+PBHGetDirAccessSync:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSSetDirAccess(
+ const FSRef *ref,
+ SInt32 ownerID,
+ SInt32 groupID,
+ SInt32 accessRights)
+{
+ OSErr result;
+ FSSpec spec;
+ HParamBlockRec pb;
+
+ enum
+ {
+ /* Just the bits that can be set */
+ kSetDirAccessSettableMask = (kioACAccessBlankAccessMask +
+ kioACAccessEveryoneWriteMask + kioACAccessEveryoneReadMask + kioACAccessEveryoneSearchMask +
+ kioACAccessGroupWriteMask + kioACAccessGroupReadMask + kioACAccessGroupSearchMask +
+ kioACAccessOwnerWriteMask + kioACAccessOwnerReadMask + kioACAccessOwnerSearchMask)
+ };
+
+ /* get FSSpec from FSRef */
+ result = FSGetCatalogInfo(ref, kFSCatInfoNone, NULL, NULL, &spec, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* set directory access info for FSSpec */
+ pb.accessParam.ioNamePtr = (StringPtr)spec.name;
+ pb.accessParam.ioVRefNum = spec.vRefNum;
+ pb.fileParam.ioDirID = spec.parID;
+ pb.accessParam.ioACOwnerID = ownerID;
+ pb.accessParam.ioACGroupID = groupID;
+ pb.accessParam.ioACAccess = accessRights & kSetDirAccessSettableMask;
+ result = PBHSetDirAccessSync(&pb);
+ require_noerr(result, PBHSetDirAccessSync);
+
+PBHSetDirAccessSync:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetVolMountInfoSize(
+ FSVolumeRefNum volRefNum,
+ SInt16 *size)
+{
+ OSErr result;
+ ParamBlockRec pb;
+
+ /* check parameters */
+ require_action(NULL != size, BadParameter, result = paramErr);
+
+ pb.ioParam.ioNamePtr = NULL;
+ pb.ioParam.ioVRefNum = volRefNum;
+ pb.ioParam.ioBuffer = (Ptr)size;
+ result = PBGetVolMountInfoSize(&pb);
+ require_noerr(result, PBGetVolMountInfoSize);
+
+PBGetVolMountInfoSize:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetVolMountInfo(
+ FSVolumeRefNum volRefNum,
+ void *volMountInfo)
+{
+ OSErr result;
+ ParamBlockRec pb;
+
+ /* check parameters */
+ require_action(NULL != volMountInfo, BadParameter, result = paramErr);
+
+ pb.ioParam.ioNamePtr = NULL;
+ pb.ioParam.ioVRefNum = volRefNum;
+ pb.ioParam.ioBuffer = (Ptr)volMountInfo;
+ result = PBGetVolMountInfo(&pb);
+ require_noerr(result, PBGetVolMountInfo);
+
+PBGetVolMountInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+// This function exists in Mac OS X 10.5, we cannot re-define it here.
+// We don't use this function, so just don't compile it.
+#if 0
+OSErr
+FSVolumeMount(
+ const void *volMountInfo,
+ FSVolumeRefNum *volRefNum)
+{
+ OSErr result;
+ ParamBlockRec pb;
+
+ /* check parameters */
+ require_action(NULL != volRefNum, BadParameter, result = paramErr);
+
+ pb.ioParam.ioBuffer = (Ptr)volMountInfo;
+ result = PBVolumeMount(&pb);
+ require_noerr(result, PBVolumeMount);
+
+ /* return the volume reference number */
+ *volRefNum = pb.ioParam.ioVRefNum;
+
+PBVolumeMount:
+BadParameter:
+
+ return ( result );
+}
+#endif
+
+/*****************************************************************************/
+
+OSErr
+FSMapID(
+ FSVolumeRefNum volRefNum,
+ SInt32 ugID,
+ SInt16 objType,
+ Str31 name)
+{
+ OSErr result;
+ HParamBlockRec pb;
+
+ /* check parameters */
+ require_action(NULL != name, BadParameter, result = paramErr);
+
+ pb.objParam.ioNamePtr = NULL;
+ pb.objParam.ioVRefNum = volRefNum;
+ pb.objParam.ioObjType = objType;
+ pb.objParam.ioObjNamePtr = name;
+ pb.objParam.ioObjID = ugID;
+ result = PBHMapIDSync(&pb);
+ require_noerr(result, PBHMapIDSync);
+
+PBHMapIDSync:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSMapName(
+ FSVolumeRefNum volRefNum,
+ ConstStr255Param name,
+ SInt16 objType,
+ SInt32 *ugID)
+{
+ OSErr result;
+ HParamBlockRec pb;
+
+ /* check parameters */
+ require_action(NULL != ugID, BadParameter, result = paramErr);
+
+ pb.objParam.ioNamePtr = NULL;
+ pb.objParam.ioVRefNum = volRefNum;
+ pb.objParam.ioObjType = objType;
+ pb.objParam.ioObjNamePtr = (StringPtr)name;
+ result = PBHMapNameSync(&pb);
+ require_noerr(result, PBHMapNameSync);
+
+ /* return the user or group ID */
+ *ugID = pb.objParam.ioObjID;
+
+PBHMapNameSync:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSCopyFile(
+ const FSRef *srcFileRef,
+ const FSRef *dstDirectoryRef,
+ UniCharCount nameLength,
+ const UniChar *copyName, /* can be NULL (no rename during copy) */
+ TextEncoding textEncodingHint,
+ FSRef *newRef) /* can be NULL */
+{
+ OSErr result;
+ FSSpec srcFileSpec;
+ FSCatalogInfo catalogInfo;
+ HParamBlockRec pb;
+ Str31 hfsName;
+ GetVolParmsInfoBuffer volParmsInfo;
+ UInt32 infoSize;
+
+ /* get source FSSpec from source FSRef */
+ result = FSGetCatalogInfo(srcFileRef, kFSCatInfoNone, NULL, NULL, &srcFileSpec, NULL);
+ require_noerr(result, FSGetCatalogInfo_srcFileRef);
+
+ /* Make sure the volume supports CopyFile */
+ result = FSGetVolParms(srcFileSpec.vRefNum, sizeof(GetVolParmsInfoBuffer),
+ &volParmsInfo, &infoSize);
+ require_action((noErr == result) && VolHasCopyFile(&volParmsInfo),
+ NoCopyFileSupport, result = paramErr);
+
+ /* get destination volume reference number and destination directory ID from destination FSRef */
+ result = FSGetCatalogInfo(dstDirectoryRef, kFSCatInfoVolume + kFSCatInfoNodeID,
+ &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo_dstDirectoryRef);
+
+ /* tell the server to copy the object */
+ pb.copyParam.ioVRefNum = srcFileSpec.vRefNum;
+ pb.copyParam.ioDirID = srcFileSpec.parID;
+ pb.copyParam.ioNamePtr = (StringPtr)srcFileSpec.name;
+ pb.copyParam.ioDstVRefNum = catalogInfo.volume;
+ pb.copyParam.ioNewDirID = (long)catalogInfo.nodeID;
+ pb.copyParam.ioNewName = NULL;
+ if ( NULL != copyName )
+ {
+ result = UnicodeNameGetHFSName(nameLength, copyName, textEncodingHint, false, hfsName);
+ require_noerr(result, UnicodeNameGetHFSName);
+
+ pb.copyParam.ioCopyName = hfsName;
+ }
+ else
+ {
+ pb.copyParam.ioCopyName = NULL;
+ }
+ result = PBHCopyFileSync(&pb);
+ require_noerr(result, PBHCopyFileSync);
+
+ if ( NULL != newRef )
+ {
+ verify_noerr(FSMakeFSRef(pb.copyParam.ioDstVRefNum, pb.copyParam.ioNewDirID,
+ pb.copyParam.ioCopyName, newRef));
+ }
+
+PBHCopyFileSync:
+UnicodeNameGetHFSName:
+FSGetCatalogInfo_dstDirectoryRef:
+NoCopyFileSupport:
+FSGetCatalogInfo_srcFileRef:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSMoveRename(
+ const FSRef *srcFileRef,
+ const FSRef *dstDirectoryRef,
+ UniCharCount nameLength,
+ const UniChar *moveName, /* can be NULL (no rename during move) */
+ TextEncoding textEncodingHint,
+ FSRef *newRef) /* can be NULL */
+{
+ OSErr result;
+ FSSpec srcFileSpec;
+ FSCatalogInfo catalogInfo;
+ HParamBlockRec pb;
+ Str31 hfsName;
+ GetVolParmsInfoBuffer volParmsInfo;
+ UInt32 infoSize;
+
+ /* get source FSSpec from source FSRef */
+ result = FSGetCatalogInfo(srcFileRef, kFSCatInfoNone, NULL, NULL, &srcFileSpec, NULL);
+ require_noerr(result, FSGetCatalogInfo_srcFileRef);
+
+ /* Make sure the volume supports MoveRename */
+ result = FSGetVolParms(srcFileSpec.vRefNum, sizeof(GetVolParmsInfoBuffer),
+ &volParmsInfo, &infoSize);
+ require_action((noErr == result) && VolHasMoveRename(&volParmsInfo),
+ NoMoveRenameSupport, result = paramErr);
+
+ /* get destination volume reference number and destination directory ID from destination FSRef */
+ result = FSGetCatalogInfo(dstDirectoryRef, kFSCatInfoVolume + kFSCatInfoNodeID,
+ &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo_dstDirectoryRef);
+
+ /* make sure the source and destination are on the same volume */
+ require_action(srcFileSpec.vRefNum == catalogInfo.volume, NotSameVolume, result = diffVolErr);
+
+ /* tell the server to move and rename the object */
+ pb.copyParam.ioVRefNum = srcFileSpec.vRefNum;
+ pb.copyParam.ioDirID = srcFileSpec.parID;
+ pb.copyParam.ioNamePtr = (StringPtr)srcFileSpec.name;
+ pb.copyParam.ioNewDirID = (long)catalogInfo.nodeID;
+ pb.copyParam.ioNewName = NULL;
+ if ( NULL != moveName )
+ {
+ result = UnicodeNameGetHFSName(nameLength, moveName, textEncodingHint, false, hfsName);
+ require_noerr(result, UnicodeNameGetHFSName);
+
+ pb.copyParam.ioCopyName = hfsName;
+ }
+ else
+ {
+ pb.copyParam.ioCopyName = NULL;
+ }
+ result = PBHMoveRenameSync(&pb);
+ require_noerr(result, PBHMoveRenameSync);
+
+ if ( NULL != newRef )
+ {
+ verify_noerr(FSMakeFSRef(pb.copyParam.ioVRefNum, pb.copyParam.ioNewDirID,
+ pb.copyParam.ioCopyName, newRef));
+ }
+
+PBHMoveRenameSync:
+UnicodeNameGetHFSName:
+NotSameVolume:
+FSGetCatalogInfo_dstDirectoryRef:
+NoMoveRenameSupport:
+FSGetCatalogInfo_srcFileRef:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+#pragma mark ----- File ID Routines -----
+
+/*****************************************************************************/
+
+OSErr
+FSResolveFileIDRef(
+ FSVolumeRefNum volRefNum,
+ SInt32 fileID,
+ FSRef *ref)
+{
+ OSErr result;
+ FIDParam pb;
+ Str255 tempStr;
+
+ /* check parameters */
+ require_action(NULL != ref, BadParameter, result = paramErr);
+
+ /* resolve the file ID reference */
+ tempStr[0] = 0;
+ pb.ioNamePtr = tempStr;
+ pb.ioVRefNum = volRefNum;
+ pb.ioFileID = fileID;
+ result = PBResolveFileIDRefSync((HParmBlkPtr)&pb);
+ require_noerr(result, PBResolveFileIDRefSync);
+
+ /* and then make an FSRef to the file */
+ result = FSMakeFSRef(volRefNum, pb.ioSrcDirID, tempStr, ref);
+ require_noerr(result, FSMakeFSRef);
+
+FSMakeFSRef:
+PBResolveFileIDRefSync:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSCreateFileIDRef(
+ const FSRef *ref,
+ SInt32 *fileID)
+{
+ OSErr result;
+ FSSpec spec;
+ FIDParam pb;
+
+ /* check parameters */
+ require_action(NULL != fileID, BadParameter, result = paramErr);
+
+ /* Get an FSSpec from the FSRef */
+ result = FSGetCatalogInfo(ref, kFSCatInfoNone, NULL, NULL, &spec, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* Create (or get) the file ID reference using the FSSpec */
+ pb.ioNamePtr = (StringPtr)spec.name;
+ pb.ioVRefNum = spec.vRefNum;
+ pb.ioSrcDirID = spec.parID;
+ result = PBCreateFileIDRefSync((HParmBlkPtr)&pb);
+ require((noErr == result) || (fidExists == result) || (afpIDExists == result),
+ PBCreateFileIDRefSync);
+
+ /* return the file ID reference */
+ *fileID = pb.ioFileID;
+
+PBCreateFileIDRefSync:
+FSGetCatalogInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+#pragma mark ----- Utility Routines -----
+
+/*****************************************************************************/
+
+Ptr
+GetTempBuffer(
+ ByteCount buffReqSize,
+ ByteCount *buffActSize)
+{
+ enum
+ {
+ kSlopMemory = 0x00008000 /* 32K - Amount of free memory to leave when allocating buffers */
+ };
+
+ Ptr tempPtr;
+
+ /* check parameters */
+ require_action(NULL != buffActSize, BadParameter, tempPtr = NULL);
+
+ /* Make request a multiple of 4K bytes */
+ buffReqSize = buffReqSize & 0xfffff000;
+
+ if ( buffReqSize < 0x00001000 )
+ {
+ /* Request was smaller than 4K bytes - make it 4K */
+ buffReqSize = 0x00001000;
+ }
+
+ /* Attempt to allocate the memory */
+ tempPtr = NewPtr(buffReqSize);
+
+ /* If request failed, go to backup plan */
+ if ( (tempPtr == NULL) && (buffReqSize > 0x00001000) )
+ {
+ /*
+ ** Try to get largest 4K byte block available
+ ** leaving some slop for the toolbox if possible
+ */
+ long freeMemory = (FreeMem() - kSlopMemory) & 0xfffff000;
+
+ buffReqSize = MaxBlock() & 0xfffff000;
+
+ if ( buffReqSize > freeMemory )
+ {
+ buffReqSize = freeMemory;
+ }
+
+ if ( buffReqSize == 0 )
+ {
+ buffReqSize = 0x00001000;
+ }
+
+ tempPtr = NewPtr(buffReqSize);
+ }
+
+ /* Return bytes allocated */
+ if ( tempPtr != NULL )
+ {
+ *buffActSize = buffReqSize;
+ }
+ else
+ {
+ *buffActSize = 0;
+ }
+
+BadParameter:
+
+ return ( tempPtr );
+}
+
+/*****************************************************************************/
+
+OSErr
+FileRefNumGetFSRef(
+ short refNum,
+ FSRef *ref)
+{
+ return ( FSGetForkCBInfo(refNum, 0, NULL, NULL, NULL, ref, NULL) );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSSetDefault(
+ const FSRef *newDefault,
+ FSRef *oldDefault)
+{
+ OSErr result;
+ FSVolumeRefNum vRefNum;
+ long dirID;
+ FSCatalogInfo catalogInfo;
+
+ /* check parameters */
+ require_action((NULL != newDefault) && (NULL != oldDefault), BadParameter, result = paramErr);
+
+ /* Get nodeFlags, vRefNum and dirID (nodeID) of newDefault */
+ result = FSGetCatalogInfo(newDefault,
+ kFSCatInfoNodeFlags + kFSCatInfoVolume + kFSCatInfoNodeID,
+ &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* Make sure newDefault is a directory */
+ require_action(0 != (kFSNodeIsDirectoryMask & catalogInfo.nodeFlags), NewDefaultNotDirectory,
+ result = dirNFErr);
+
+ /* Get the current working directory. */
+ result = HGetVol(NULL, &vRefNum, &dirID);
+ require_noerr(result, HGetVol);
+
+ /* Return the oldDefault FSRef */
+ result = FSMakeFSRef(vRefNum, dirID, NULL, oldDefault);
+ require_noerr(result, FSMakeFSRef);
+
+ /* Set the new current working directory */
+ result = HSetVol(NULL, catalogInfo.volume, catalogInfo.nodeID);
+ require_noerr(result, HSetVol);
+
+HSetVol:
+FSMakeFSRef:
+HGetVol:
+NewDefaultNotDirectory:
+FSGetCatalogInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSRestoreDefault(
+ const FSRef *oldDefault)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+
+ /* check parameters */
+ require_action(NULL != oldDefault, BadParameter, result = paramErr);
+
+ /* Get nodeFlags, vRefNum and dirID (nodeID) of oldDefault */
+ result = FSGetCatalogInfo(oldDefault,
+ kFSCatInfoNodeFlags + kFSCatInfoVolume + kFSCatInfoNodeID,
+ &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* Make sure oldDefault is a directory */
+ require_action(0 != (kFSNodeIsDirectoryMask & catalogInfo.nodeFlags), OldDefaultNotDirectory,
+ result = dirNFErr);
+
+ /* Set the current working directory to oldDefault */
+ result = HSetVol(NULL, catalogInfo.volume, catalogInfo.nodeID);
+ require_noerr(result, HSetVol);
+
+HSetVol:
+OldDefaultNotDirectory:
+FSGetCatalogInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
diff --git a/src/libs/xpcom18a4/xpcom/MoreFiles/MoreFilesX.h b/src/libs/xpcom18a4/xpcom/MoreFiles/MoreFilesX.h
new file mode 100644
index 00000000..378e4552
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/MoreFiles/MoreFilesX.h
@@ -0,0 +1,1800 @@
+/*
+ File: MoreFilesX.h
+
+ Contains: A collection of useful high-level File Manager routines
+ which use the HFS Plus APIs wherever possible.
+
+ Version: MoreFilesX 1.0.1
+
+
+*/
+
+/* ***** 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) 2000
+ * 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 ***** */
+
+
+// Modified 2006-01-23 - added this comment.
+
+#ifndef __MOREFILESX__
+#define __MOREFILESX__
+
+#ifndef __CARBON__
+ #if defined(__MACH__)
+ #include <Carbon/Carbon.h>
+ #else
+ #include <Carbon.h>
+ #endif
+#endif
+
+#if PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if PRAGMA_IMPORT
+#pragma import on
+#endif
+
+#if PRAGMA_STRUCT_ALIGN
+ #pragma options align=mac68k
+#elif PRAGMA_STRUCT_PACKPUSH
+ #pragma pack(push, 2)
+#elif PRAGMA_STRUCT_PACK
+ #pragma pack(2)
+#endif
+
+/*****************************************************************************/
+
+#pragma mark ----- FinderInfo and ExtendedFinderInfo -----
+
+/*
+ * FSGetFinderInfo and FSSetFinderInfo use these unions for Finder information.
+ */
+
+union FinderInfo
+{
+ FileInfo file;
+ FolderInfo folder;
+};
+typedef union FinderInfo FinderInfo;
+
+union ExtendedFinderInfo
+{
+ ExtendedFileInfo file;
+ ExtendedFolderInfo folder;
+};
+typedef union ExtendedFinderInfo ExtendedFinderInfo;
+
+/*****************************************************************************/
+
+#pragma mark ----- GetVolParmsInfoBuffer Macros -----
+
+/*
+ * Macros to get information out of GetVolParmsInfoBuffer.
+ */
+
+/* version 1 field getters */
+#define GetVolParmsInfoVersion(volParms) \
+ ((volParms)->vMVersion)
+#define GetVolParmsInfoAttrib(volParms) \
+ ((volParms)->vMAttrib)
+#define GetVolParmsInfoLocalHand(volParms) \
+ ((volParms)->vMLocalHand)
+#define GetVolParmsInfoServerAdr(volParms) \
+ ((volParms)->vMServerAdr)
+
+/* version 2 field getters (assume zero result if version < 2) */
+#define GetVolParmsInfoVolumeGrade(volParms) \
+ (((volParms)->vMVersion >= 2) ? (volParms)->vMVolumeGrade : 0)
+#define GetVolParmsInfoForeignPrivID(volParms) \
+ (((volParms)->vMVersion >= 2) ? (volParms)->vMForeignPrivID : 0)
+
+/* version 3 field getters (assume zero result if version < 3) */
+#define GetVolParmsInfoExtendedAttributes(volParms) \
+ (((volParms)->vMVersion >= 3) ? (volParms)->vMExtendedAttributes : 0)
+
+/* attribute bits supported by all versions of GetVolParmsInfoBuffer */
+#define VolIsNetworkVolume(volParms) \
+ ((volParms)->vMServerAdr != 0)
+#define VolHasLimitFCBs(volParms) \
+ (((volParms)->vMAttrib & (1L << bLimitFCBs)) != 0)
+#define VolHasLocalWList(volParms) \
+ (((volParms)->vMAttrib & (1L << bLocalWList)) != 0)
+#define VolHasNoMiniFndr(volParms) \
+ (((volParms)->vMAttrib & (1L << bNoMiniFndr)) != 0)
+#define VolHasNoVNEdit(volParms) \
+ (((volParms)->vMAttrib & (1L << bNoVNEdit)) != 0)
+#define VolHasNoLclSync(volParms) \
+ (((volParms)->vMAttrib & (1L << bNoLclSync)) != 0)
+#define VolHasTrshOffLine(volParms) \
+ (((volParms)->vMAttrib & (1L << bTrshOffLine)) != 0)
+#define VolHasNoSwitchTo(volParms) \
+ (((volParms)->vMAttrib & (1L << bNoSwitchTo)) != 0)
+#define VolHasNoDeskItems(volParms) \
+ (((volParms)->vMAttrib & (1L << bNoDeskItems)) != 0)
+#define VolHasNoBootBlks(volParms) \
+ (((volParms)->vMAttrib & (1L << bNoBootBlks)) != 0)
+#define VolHasAccessCntl(volParms) \
+ (((volParms)->vMAttrib & (1L << bAccessCntl)) != 0)
+#define VolHasNoSysDir(volParms) \
+ (((volParms)->vMAttrib & (1L << bNoSysDir)) != 0)
+#define VolHasExtFSVol(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasExtFSVol)) != 0)
+#define VolHasOpenDeny(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasOpenDeny)) != 0)
+#define VolHasCopyFile(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasCopyFile)) != 0)
+#define VolHasMoveRename(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasMoveRename)) != 0)
+#define VolHasDesktopMgr(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasDesktopMgr)) != 0)
+#define VolHasShortName(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasShortName)) != 0)
+#define VolHasFolderLock(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasFolderLock)) != 0)
+#define VolHasPersonalAccessPrivileges(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasPersonalAccessPrivileges)) != 0)
+#define VolHasUserGroupList(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasUserGroupList)) != 0)
+#define VolHasCatSearch(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasCatSearch)) != 0)
+#define VolHasFileIDs(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasFileIDs)) != 0)
+#define VolHasBTreeMgr(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasBTreeMgr)) != 0)
+#define VolHasBlankAccessPrivileges(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasBlankAccessPrivileges)) != 0)
+#define VolSupportsAsyncRequests(volParms) \
+ (((volParms)->vMAttrib & (1L << bSupportsAsyncRequests)) != 0)
+#define VolSupportsTrashVolumeCache(volParms) \
+ (((volParms)->vMAttrib & (1L << bSupportsTrashVolumeCache)) != 0)
+
+/* attribute bits supported by version 3 and greater versions of GetVolParmsInfoBuffer */
+#define VolIsEjectable(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bIsEjectable)) != 0)
+#define VolSupportsHFSPlusAPIs(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsHFSPlusAPIs)) != 0)
+#define VolSupportsFSCatalogSearch(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsFSCatalogSearch)) != 0)
+#define VolSupportsFSExchangeObjects(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsFSExchangeObjects)) != 0)
+#define VolSupports2TBFiles(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupports2TBFiles)) != 0)
+#define VolSupportsLongNames(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsLongNames)) != 0)
+#define VolSupportsMultiScriptNames(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsMultiScriptNames)) != 0)
+#define VolSupportsNamedForks(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsNamedForks)) != 0)
+#define VolSupportsSubtreeIterators(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsSubtreeIterators)) != 0)
+#define VolL2PCanMapFileBlocks(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bL2PCanMapFileBlocks)) != 0)
+#define VolParentModDateChanges(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bParentModDateChanges)) != 0)
+#define VolAncestorModDateChanges(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bAncestorModDateChanges)) != 0)
+#define VolSupportsSymbolicLinks(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsSymbolicLinks)) != 0)
+#define VolIsAutoMounted(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bIsAutoMounted)) != 0)
+
+/*****************************************************************************/
+
+#pragma mark ----- userPrivileges Bit Masks and Macros -----
+
+/*
+ * Bit masks and macros to get common information out of userPrivileges byte
+ * returned by FSGetCatalogInfo.
+ *
+ * Note: The userPrivileges byte is the same as the ioACUser byte returned
+ * by PBGetCatInfo, and is the 1's complement of the user's privileges
+ * byte returned in ioACAccess by PBHGetDirAccess. That's where the
+ * ioACUser names came from.
+ *
+ * The userPrivileges are user's effective privileges based on the
+ * user ID and the groups that user belongs to, and the owner, group,
+ * and everyone privileges for the given directory.
+ */
+
+enum
+{
+ /* mask for just the access restriction bits */
+ kioACUserAccessMask = (kioACUserNoSeeFolderMask +
+ kioACUserNoSeeFilesMask +
+ kioACUserNoMakeChangesMask),
+ /* common access privilege settings */
+ kioACUserFull = 0x00, /* no access restiction bits on */
+ kioACUserNone = kioACUserAccessMask, /* all access restiction bits on */
+ kioACUserDropBox = (kioACUserNoSeeFolderMask +
+ kioACUserNoSeeFilesMask), /* make changes, but not see files or folders */
+ kioACUserBulletinBoard = kioACUserNoMakeChangesMask /* see files and folders, but not make changes */
+};
+
+
+/* Macros for testing ioACUser bits. */
+
+#define UserIsOwner(userPrivileges) \
+ (((userPrivileges) & kioACUserNotOwnerMask) == 0)
+#define UserHasFullAccess(userPrivileges) \
+ (((userPrivileges) & (kioACUserAccessMask)) == kioACUserFull)
+#define UserHasDropBoxAccess(userPrivileges) \
+ (((userPrivileges) & kioACUserAccessMask) == kioACUserDropBox)
+#define UserHasBulletinBoard(userPrivileges) \
+ (((userPrivileges) & kioACUserAccessMask) == kioACUserBulletinBoard)
+#define UserHasNoAccess(userPrivileges) \
+ (((userPrivileges) & kioACUserAccessMask) == kioACUserNone)
+
+/*****************************************************************************/
+
+#pragma mark ----- File Access Routines -----
+
+/*****************************************************************************/
+
+#pragma mark FSCopyFork
+
+OSErr
+FSCopyFork(
+ SInt16 srcRefNum,
+ SInt16 dstRefNum,
+ void *copyBufferPtr,
+ ByteCount copyBufferSize);
+
+/*
+ The FSCopyFork function copies all data from the source fork to the
+ destination fork of open file forks and makes sure the destination EOF
+ is equal to the source EOF.
+
+ srcRefNum --> The source file reference number.
+ dstRefNum --> The destination file reference number.
+ copyBufferPtr --> Pointer to buffer to use during copy. The
+ buffer should be at least 4K-bytes minimum.
+ The larger the buffer, the faster the copy
+ (up to a point).
+ copyBufferSize --> The size of the copy buffer.
+*/
+
+/*****************************************************************************/
+
+#pragma mark ----- Volume Access Routines -----
+
+/*****************************************************************************/
+
+#pragma mark FSGetVolParms
+
+OSErr
+FSGetVolParms(
+ FSVolumeRefNum volRefNum,
+ UInt32 bufferSize,
+ GetVolParmsInfoBuffer *volParmsInfo,
+ UInt32 *actualInfoSize);
+
+/*
+ The FSGetVolParms function returns information about the characteristics
+ of a volume. A result of paramErr usually just means the volume doesn't
+ support GetVolParms and the feature you were going to check
+ for isn't available.
+
+ volRefNum --> Volume specification.
+ bufferSize --> Size of buffer pointed to by volParmsInfo.
+ volParmsInfo <-- A GetVolParmsInfoBuffer record where the volume
+ attributes information is returned.
+ actualInfoSize <-- The number of bytes actually returned
+ in volParmsInfo.
+
+ __________
+
+ Also see: The GetVolParmsInfoBuffer Macros for checking attribute bits
+ in this file
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetVRefNum
+
+OSErr
+FSGetVRefNum(
+ const FSRef *ref,
+ FSVolumeRefNum *vRefNum);
+
+/*
+ The FSGetVRefNum function determines the volume reference
+ number of a volume from a FSRef.
+
+ ref --> The FSRef.
+ vRefNum <-- The volume reference number.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetVInfo
+
+OSErr
+FSGetVInfo(
+ FSVolumeRefNum volume,
+ HFSUniStr255 *volumeName, /* can be NULL */
+ UInt64 *freeBytes, /* can be NULL */
+ UInt64 *totalBytes); /* can be NULL */
+
+/*
+ The FSGetVInfo function returns the name, available space (in bytes),
+ and total space (in bytes) for the specified volume.
+
+ volume --> The volume reference number.
+ volumeName <** An optional pointer to a HFSUniStr255.
+ If not NULL, the volume name will be returned in
+ the HFSUniStr255.
+ freeBytes <** An optional pointer to a UInt64.
+ If not NULL, the number of free bytes on the
+ volume will be returned in the UInt64.
+ totalBytes <** An optional pointer to a UInt64.
+ If not NULL, the total number of bytes on the
+ volume will be returned in the UInt64.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetVolFileSystemID
+
+OSErr
+FSGetVolFileSystemID(
+ FSVolumeRefNum volume,
+ UInt16 *fileSystemID, /* can be NULL */
+ UInt16 *signature); /* can be NULL */
+
+/*
+ The FSGetVolFileSystemID function returns the file system ID and signature
+ of a mounted volume. The file system ID identifies the file system
+ that handles requests to a particular volume. The signature identifies the
+ volume type of the volume (for example, FSID 0 is Macintosh HFS Plus, HFS
+ or MFS, where a signature of 0x4244 identifies the volume as HFS).
+ Here's a partial list of file system ID numbers (only Apple's file systems
+ are listed):
+ FSID File System
+ ----- -----------------------------------------------------
+ $0000 Macintosh HFS Plus, HFS or MFS
+ $0100 ProDOS File System
+ $0101 PowerTalk Mail Enclosures
+ $4147 ISO 9660 File Access (through Foreign File Access)
+ $4242 High Sierra File Access (through Foreign File Access)
+ $464D QuickTake File System (through Foreign File Access)
+ $4953 Macintosh PC Exchange (MS-DOS)
+ $4A48 Audio CD Access (through Foreign File Access)
+ $4D4B Apple Photo Access (through Foreign File Access)
+ $6173 AppleShare (later versions of AppleShare only)
+
+ See the Technical Note "FL 35 - Determining Which File System
+ Is Active" and the "Guide to the File System Manager" for more
+ information.
+
+ volume --> The volume reference number.
+ fileSystemID <** An optional pointer to a UInt16.
+ If not NULL, the volume's file system ID will
+ be returned in the UInt16.
+ signature <** An optional pointer to a UInt16.
+ If not NULL, the volume's signature will
+ be returned in the UInt16.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetMountedVolumes
+
+OSErr
+FSGetMountedVolumes(
+ FSRef ***volumeRefsHandle, /* pointer to handle of FSRefs */
+ ItemCount *numVolumes);
+
+/*
+ The FSGetMountedVolumes function returns the list of volumes currently
+ mounted in an array of FSRef records. The array of FSRef records is
+ returned in a Handle, volumeRefsHandle, which is allocated by
+ FSGetMountedVolumes. The caller is responsible for disposing of
+ volumeRefsHandle if the FSGetMountedVolumes returns noErr.
+
+ volumeRefsHandle <-- Pointer to an FSRef Handle where the array of
+ FSRefs is to be returned.
+ numVolumes <-- The number of volumes returned in the array.
+*/
+
+/*****************************************************************************/
+
+#pragma mark ----- FSRef/FSpec/Path/Name Conversion Routines -----
+
+/*****************************************************************************/
+
+#pragma mark FSRefMakeFSSpec
+
+OSErr
+FSRefMakeFSSpec(
+ const FSRef *ref,
+ FSSpec *spec);
+
+/*
+ The FSRefMakeFSSpec function returns an FSSpec for the file or
+ directory specified by the ref parameter.
+
+ ref --> An FSRef specifying the file or directory.
+ spec <-- The FSSpec.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSMakeFSRef
+
+OSErr
+FSMakeFSRef(
+ FSVolumeRefNum volRefNum,
+ SInt32 dirID,
+ ConstStr255Param name,
+ FSRef *ref);
+
+/*
+ The FSMakeFSRef function creates an FSRef from the traditional
+ volume reference number, directory ID and pathname inputs. It is
+ functionally equivalent to FSMakeFSSpec followed by FSpMakeFSRef.
+
+ volRefNum --> Volume specification.
+ dirID --> Directory specification.
+ name --> The file or directory name, or NULL.
+ ref <-- The FSRef.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSMakePath
+
+OSStatus
+FSMakePath(
+ SInt16 vRefNum,
+ SInt32 dirID,
+ ConstStr255Param name,
+ UInt8 *path,
+ UInt32 maxPathSize);
+
+/*
+ The FSMakePath function creates a pathname from the traditional volume reference
+ number, directory ID, and pathname inputs. It is functionally equivalent to
+ FSMakeFSSpec, FSpMakeFSRef, FSRefMakePath.
+
+ volRefNum --> Volume specification.
+ dirID --> Directory specification.
+ name --> The file or directory name, or NULL.
+ path <-- A pointer to a buffer which FSMakePath will
+ fill with a C string representing the pathname
+ to the file or directory specified. The format of
+ the pathname returned can be determined with the
+ Gestalt selector gestaltFSAttr's
+ gestaltFSUsesPOSIXPathsForConversion bit.
+ If the gestaltFSUsesPOSIXPathsForConversion bit is
+ clear, the pathname is a Mac OS File Manager full
+ pathname in a C string, and file or directory names
+ in the pathname may be mangled as returned by
+ the File Manager. If the
+ gestaltFSUsesPOSIXPathsForConversion bit is set,
+ the pathname is a UTF8 encoded POSIX absolute
+ pathname in a C string. In either case, the
+ pathname returned can be passed back to
+ FSPathMakeRef to create an FSRef to the file or
+ directory, or FSPathMakeFSSpec to craete an FSSpec
+ to the file or directory.
+ maxPathSize --> The size of the path buffer in bytes. If the path
+ buffer is too small for the pathname string,
+ FSMakePath returns pathTooLongErr or
+ buffersTooSmall.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSPathMakeFSSpec
+
+OSStatus
+FSPathMakeFSSpec(
+ const UInt8 *path,
+ FSSpec *spec,
+ Boolean *isDirectory); /* can be NULL */
+
+/*
+ The FSPathMakeFSSpec function converts a pathname to an FSSpec.
+
+ path --> A pointer to a C String that is the pathname. The
+ format of the pathname you must supply can be
+ determined with the Gestalt selector gestaltFSAttr's
+ gestaltFSUsesPOSIXPathsForConversion bit.
+ If the gestaltFSUsesPOSIXPathsForConversion bit is
+ clear, the pathname must be a Mac OS File Manager
+ full pathname in a C string. If the
+ gestaltFSUsesPOSIXPathsForConversion bit is set,
+ the pathname must be a UTF8 encoded POSIX absolute
+ pathname in a C string.
+ spec <-- The FSSpec.
+ isDirectory <** An optional pointer to a Boolean.
+ If not NULL, true will be returned in the Boolean
+ if the specified path is a directory, or false will
+ be returned in the Boolean if the specified path is
+ a file.
+*/
+
+/*****************************************************************************/
+
+#pragma mark UnicodeNameGetHFSName
+
+OSErr
+UnicodeNameGetHFSName(
+ UniCharCount nameLength,
+ const UniChar *name,
+ TextEncoding textEncodingHint,
+ Boolean isVolumeName,
+ Str31 hfsName);
+
+/*
+ The UnicodeNameGetHFSName function converts a Unicode string
+ to a Pascal Str31 (or Str27) string using an algorithm similar to that used
+ by the File Manager. Note that if the name is too long or cannot be converted
+ using the given text encoding hint, you will get an error instead of the
+ mangled name that the File Manager would return.
+
+ nameLength --> Number of UniChar in name parameter.
+ name --> The Unicode string to convert.
+ textEncodingHint --> The text encoding hint used for the conversion.
+ You can pass kTextEncodingUnknown to use the
+ "default" textEncodingHint.
+ isVolumeName --> If true, the output name will be limited to
+ 27 characters (kHFSMaxVolumeNameChars). If false,
+ the output name will be limited to 31 characters
+ (kHFSMaxFileNameChars).
+ hfsName <-- The hfsName as a Pascal string.
+
+ __________
+
+ Also see: HFSNameGetUnicodeName
+*/
+
+/*****************************************************************************/
+
+#pragma mark HFSNameGetUnicodeName
+
+OSErr
+HFSNameGetUnicodeName(
+ ConstStr31Param hfsName,
+ TextEncoding textEncodingHint,
+ HFSUniStr255 *unicodeName);
+
+/*
+ The HFSNameGetUnicodeName function converts a Pascal Str31 string to an
+ Unicode HFSUniStr255 string using the same routines as the File Manager.
+
+ hfsName --> The Pascal string to convert.
+ textEncodingHint --> The text encoding hint used for the conversion.
+ You can pass kTextEncodingUnknown to use the
+ "default" textEncodingHint.
+ unicodeName <-- The Unicode string.
+
+ __________
+
+ Also see: UnicodeNameGetHFSName
+*/
+
+/*****************************************************************************/
+
+#pragma mark ----- File/Directory Manipulation Routines -----
+
+/*****************************************************************************/
+
+#pragma mark FSRefValid
+
+Boolean FSRefValid(const FSRef *ref);
+
+/*
+ The FSRefValid function determines if an FSRef is valid. If the result is
+ true, then the FSRef refers to an existing file or directory.
+
+ ref --> FSRef to a file or directory.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetParentRef
+
+OSErr
+FSGetParentRef(
+ const FSRef *ref,
+ FSRef *parentRef);
+
+/*
+ The FSGetParentRef function gets the parent directory FSRef of the
+ specified object.
+
+ Note: FSRefs always point to real file system objects. So, there cannot
+ be a FSRef to the parent of volume root directories. If you call
+ FSGetParentRef with a ref to the root directory of a volume, the
+ function result will be noErr and the parentRef will be invalid (using it
+ for other file system requests will fail).
+
+ ref --> FSRef to a file or directory.
+ parentRef <-- The parent directory's FSRef.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetFileDirName
+
+OSErr
+FSGetFileDirName(
+ const FSRef *ref,
+ HFSUniStr255 *outName);
+
+/*
+ The FSGetFileDirName function gets the name of the file or directory
+ specified.
+
+ ref --> FSRef to a file or directory.
+ outName <-- The file or directory name.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetNodeID
+
+OSErr
+FSGetNodeID(
+ const FSRef *ref,
+ long *nodeID, /* can be NULL */
+ Boolean *isDirectory); /* can be NULL */
+
+/*
+ The GetNodeIDFromFSRef function gets the node ID number of the
+ file or directory specified (note: the node ID is the directory ID
+ for directories).
+
+ ref --> FSRef to a file or directory.
+ nodeID <** An optional pointer to a long.
+ If not NULL, the node ID will be returned in
+ the long.
+ isDirectory <** An optional pointer to a Boolean.
+ If not NULL, true will be returned in the Boolean
+ if the object is a directory, or false will be
+ returned in the Boolean if object is a file.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetUserPrivilegesPermissions
+
+OSErr
+FSGetUserPrivilegesPermissions(
+ const FSRef *ref,
+ UInt8 *userPrivileges, /* can be NULL */
+ UInt32 permissions[4]); /* can be NULL */
+
+/*
+ The FSGetUserPrivilegesPermissions function gets the userPrivileges and/or
+ permissions of the file or directory specified.
+
+ ref --> FSRef to a file or directory.
+ userPrivileges <** An optional pointer to a UInt8.
+ If not NULL, the userPrivileges will be returned
+ in the UInt8.
+ permissions <** An optional pointer to an UInt32[4] array.
+ If not NULL, the permissions will be returned
+ in the UInt32[4] array.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSCheckLock
+
+OSErr
+FSCheckLock(
+ const FSRef *ref);
+
+/*
+ The FSCheckLock function determines if a file or directory is locked.
+ If FSCheckLock returns noErr, then the file or directory is not locked
+ and the volume it is on is not locked either. If FSCheckLock returns
+ fLckdErr, then the file or directory is locked. If FSCheckLock returns
+ wPrErr, then the volume is locked by hardware (i.e., locked tab on
+ removable media). If FSCheckLock returns vLckdErr, then the volume is
+ locked by software.
+
+ ref --> FSRef to a file or directory.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetForkSizes
+
+OSErr
+FSGetForkSizes(
+ const FSRef *ref,
+ UInt64 *dataLogicalSize, /* can be NULL */
+ UInt64 *rsrcLogicalSize); /* can be NULL */
+
+/*
+ The FSGetForkSizes returns the size of the data and/or resource fork for
+ the specified file.
+
+ ref --> FSRef to a file or directory.
+ dataLogicalSize <** An optional pointer to a UInt64.
+ If not NULL, the data fork's size will be
+ returned in the UInt64.
+ rsrcLogicalSize <** An optional pointer to a UInt64.
+ If not NULL, the resource fork's size will be
+ returned in the UInt64.
+
+ __________
+
+ Also see: FSGetTotalForkSizes
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetTotalForkSizes
+
+OSErr
+FSGetTotalForkSizes(
+ const FSRef *ref,
+ UInt64 *totalLogicalSize, /* can be NULL */
+ UInt64 *totalPhysicalSize, /* can be NULL */
+ ItemCount *forkCount); /* can be NULL */
+
+/*
+ The FSGetTotalForkSizes returns the total logical size and/or the total
+ physical size of the specified file (i.e., it adds the sizes of all file
+ forks). It optionally returns the number of file forks.
+
+ ref --> FSRef to a file or directory.
+ totalLogicalSize <** An optional pointer to a UInt64.
+ If not NULL, the sum of all fork logical sizes
+ will be returned in the UInt64.
+ totalPhysicalSize <** An optional pointer to a UInt64.
+ If not NULL, the sum of all fork physical sizes
+ will be returned in the UInt64.
+ forkCount <** An optional pointer to a ItemCount.
+ If not NULL, the number of file forks
+ will be returned in the ItemCount.
+
+ __________
+
+ Also see: FSGetForkSizes
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSBumpDate
+
+OSErr
+FSBumpDate(
+ const FSRef *ref);
+
+/*
+ The FSBumpDate function changes the content modification date of a file
+ or directory to the current date/time. If the content modification date
+ is already equal to the current date/time, then add one second to the
+ content modification date.
+
+ ref --> FSRef to a file or directory.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetFinderInfo
+
+OSErr
+FSGetFinderInfo(
+ const FSRef *ref,
+ FinderInfo *info, /* can be NULL */
+ ExtendedFinderInfo *extendedInfo, /* can be NULL */
+ Boolean *isDirectory); /* can be NULL */
+
+/*
+ The FSGetFinderInfo function gets the finder information for a file or
+ directory.
+
+ ref --> FSRef to a file or directory.
+ info <** An optional pointer to a FinderInfo.
+ If not NULL, the FileInfo (if ref is a file) or
+ the FolderInfo (if ref is a folder) will be
+ returned in the FinderInfo.
+ extendedInfo <** An optional pointer to a ExtendedFinderInfo.
+ If not NULL, the ExtendedFileInfo (if ref is a file)
+ or the ExtendedFolderInfo (if ref is a folder) will
+ be returned in the ExtendedFinderInfo.
+ isDirectory <** An optional pointer to a Boolean.
+ If not NULL, true will be returned in the Boolean
+ if the object is a directory, or false will be
+ returned in the Boolean if object is a file.
+
+ __________
+
+ Also see: FSSetFinderInfo
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSSetFinderInfo
+
+OSErr
+FSSetFinderInfo(
+ const FSRef *ref,
+ const FinderInfo *info, /* can be NULL */
+ const ExtendedFinderInfo *extendedInfo); /* can be NULL */
+
+/*
+ The FSSetFinderInfo function sets the finder information for a file or
+ directory.
+
+ ref --> FSRef to a file or directory.
+ info **> A pointer to a FinderInfo record with the new
+ FileInfo (if ref is a file) or new FolderInfo
+ (if ref is a folder), or NULL if the FinderInfo
+ is not to be changed.
+ extendedInfo **> A pointer to a FinderInfo record with the new
+ ExtendedFileInfo (if ref is a file) or new
+ ExtendedFolderInfo (if ref is a folder), or NULL
+ if the ExtendedFinderInfo is not to be changed.
+
+ __________
+
+ Also see: FSGetFinderInfo
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSChangeCreatorType
+
+OSErr
+FSChangeCreatorType(
+ const FSRef *ref,
+ OSType fileCreator,
+ OSType fileType);
+
+/*
+ The FSChangeCreatorType function changes the creator and/or file type of a file.
+
+ ref --> FSRef to a file.
+ creator --> The new creator type or 0x00000000 to leave
+ the creator type alone.
+ fileType --> The new file type or 0x00000000 to leave the
+ file type alone.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSChangeFinderFlags
+
+OSErr
+FSChangeFinderFlags(
+ const FSRef *ref,
+ Boolean setBits,
+ UInt16 flagBits);
+
+/*
+ The FSChangeFinderFlags function sets or clears flag bits in
+ the finderFlags field of a file's FileInfo record or a
+ directory's FolderInfo record.
+
+ ref --> FSRef to a file or directory.
+ setBits --> If true, then set the bits specified in flagBits.
+ If false, then clear the bits specified in flagBits.
+ flagBits --> The flagBits parameter specifies which Finder Flag
+ bits to set or clear. If a bit in flagBits is set,
+ then the same bit in fdFlags is either set or
+ cleared depending on the state of the setBits
+ parameter.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSSetInvisible
+
+OSErr
+FSSetInvisible(
+ const FSRef *ref);
+
+#pragma mark FSClearInvisible
+
+OSErr
+FSClearInvisible(
+ const FSRef *ref);
+
+/*
+ The FSSetInvisible and FSClearInvisible functions set or clear the
+ kIsInvisible bit in the finderFlags field of the specified file or
+ directory's finder information.
+
+ ref --> FSRef to a file or directory.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSSetNameLocked
+
+OSErr
+FSSetNameLocked(
+ const FSRef *ref);
+
+#pragma mark FSClearNameLocked
+
+OSErr
+FSClearNameLocked(
+ const FSRef *ref);
+
+/*
+ The FSSetNameLocked and FSClearNameLocked functions set or clear the
+ kNameLocked bit bit in the finderFlags field of the specified file or
+ directory's finder information.
+
+ ref --> FSRef to a file or directory.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSSetIsStationery
+
+OSErr
+FSSetIsStationery(
+ const FSRef *ref);
+
+#pragma mark FSClearIsStationery
+
+OSErr
+FSClearIsStationery(
+ const FSRef *ref);
+
+/*
+ The FSSetIsStationery and FSClearIsStationery functions set or clear the
+ kIsStationery bit bit in the finderFlags field of the specified file or
+ directory's finder information.
+
+ ref --> FSRef to a file or directory.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSSetHasCustomIcon
+
+OSErr
+FSSetHasCustomIcon(
+ const FSRef *ref);
+
+#pragma mark FSClearHasCustomIcon
+
+OSErr
+FSClearHasCustomIcon(
+ const FSRef *ref);
+
+/*
+ The FSSetHasCustomIcon and FSClearHasCustomIcon functions set or clear the
+ kHasCustomIcon bit bit in the finderFlags field of the specified file or
+ directory's finder information.
+
+ ref --> FSRef to a file or directory.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSClearHasBeenInited
+
+OSErr
+FSClearHasBeenInited(
+ const FSRef *ref);
+
+/*
+ The FSClearHasBeenInited function clears the kHasBeenInited bit in the
+ finderFlags field of the specified file or directory's finder information.
+
+ Note: There is no FSSetHasBeenInited function because ONLY the Finder
+ should set the kHasBeenInited bit.
+
+ ref --> FSRef to a file or directory.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSCopyFileMgrAttributes
+
+OSErr
+FSCopyFileMgrAttributes(
+ const FSRef *sourceRef,
+ const FSRef *destinationRef,
+ Boolean copyLockBit);
+
+/*
+ The CopyFileMgrAttributes function copies all File Manager attributes
+ from the source file or directory to the destination file or directory.
+ If copyLockBit is true, then set the locked state of the destination
+ to match the source.
+
+ sourceRef --> FSRef to a file or directory.
+ destinationRef --> FSRef to a file or directory.
+ copyLockBit --> If true, set the locked state of the destination
+ to match the source.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSMoveRenameObjectUnicode
+
+OSErr
+FSMoveRenameObjectUnicode(
+ const FSRef *ref,
+ const FSRef *destDirectory,
+ UniCharCount nameLength,
+ const UniChar *name, /* can be NULL (no rename during move) */
+ TextEncoding textEncodingHint,
+ FSRef *newRef); /* if function fails along the way, newRef is final location of file */
+
+/*
+ The FSMoveRenameObjectUnicode function moves a file or directory and
+ optionally renames it. The source and destination locations must be on
+ the same volume.
+
+ Note: If the input ref parameter is invalid, this call will fail and
+ newRef, like ref, will be invalid.
+
+ ref --> FSRef to a file or directory.
+ destDirectory --> FSRef to the destination directory.
+ nameLength --> Number of UniChar in name parameter.
+ name --> An Unicode string with the new name for the
+ moved object, or NULL if no rename is wanted.
+ textEncodingHint --> The text encoding hint used for the rename.
+ You can pass kTextEncodingUnknown to use the
+ "default" textEncodingHint.
+ newRef <-- The new FSRef of the object moved. Note that if
+ this function fails at any step along the way,
+ newRef is still then final location of the object.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSDeleteContainerContents
+
+OSErr
+FSDeleteContainerContents(
+ const FSRef *container);
+
+/*
+ The FSDeleteContainerContents function deletes the contents of a container
+ directory. All files and subdirectories in the specified container are
+ deleted. If a locked file or directory is encountered, it is unlocked and
+ then deleted. If any unexpected errors are encountered,
+ FSDeleteContainerContents quits and returns to the caller.
+
+ container --> FSRef to a directory.
+
+ __________
+
+ Also see: FSDeleteContainer
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSDeleteContainer
+
+OSErr
+FSDeleteContainer(
+ const FSRef *container);
+
+/*
+ The FSDeleteContainer function deletes a container directory and its contents.
+ All files and subdirectories in the specified container are deleted.
+ If a locked file or directory is encountered, it is unlocked and then
+ deleted. After deleting the container's contents, the container is
+ deleted. If any unexpected errors are encountered, FSDeleteContainer
+ quits and returns to the caller.
+
+ container --> FSRef to a directory.
+
+ __________
+
+ Also see: FSDeleteContainerContents
+*/
+
+/*****************************************************************************/
+
+#pragma mark IterateContainerFilterProcPtr
+
+typedef CALLBACK_API( Boolean , IterateContainerFilterProcPtr ) (
+ Boolean containerChanged,
+ ItemCount currentLevel,
+ const FSCatalogInfo *catalogInfo,
+ const FSRef *ref,
+ const FSSpec *spec,
+ const HFSUniStr255 *name,
+ void *yourDataPtr);
+
+/*
+ This is the prototype for the IterateContainerFilterProc function which
+ is called once for each file and directory found by FSIterateContainer.
+ The IterateContainerFilterProc can use the read-only data it receives for
+ whatever it wants.
+
+ The result of the IterateContainerFilterProc function indicates if
+ iteration should be stopped. To stop iteration, return true; to continue
+ iteration, return false.
+
+ The yourDataPtr parameter can point to whatever data structure you might
+ want to access from within the IterateContainerFilterProc.
+
+ containerChanged --> Set to true if the container's contents changed
+ during iteration.
+ currentLevel --> The current recursion level into the container.
+ 1 = the container, 2 = the container's immediate
+ subdirectories, etc.
+ catalogInfo --> The catalog information for the current object.
+ Only the fields requested by the whichInfo
+ parameter passed to FSIterateContainer are valid.
+ ref --> The FSRef to the current object.
+ spec --> The FSSpec to the current object if the wantFSSpec
+ parameter passed to FSIterateContainer is true.
+ name --> The name of the current object if the wantName
+ parameter passed to FSIterateContainer is true.
+ yourDataPtr --> An optional pointer to whatever data structure you
+ might want to access from within the
+ IterateFilterProc.
+ result <-- To stop iteration, return true; to continue
+ iteration, return false.
+
+ __________
+
+ Also see: FSIterateContainer
+*/
+
+/*****************************************************************************/
+
+#pragma mark CallIterateContainerFilterProc
+
+#define CallIterateContainerFilterProc(userRoutine, containerChanged, currentLevel, catalogInfo, ref, spec, name, yourDataPtr) \
+ (*(userRoutine))((containerChanged), (currentLevel), (catalogInfo), (ref), (spec), (name), (yourDataPtr))
+
+/*****************************************************************************/
+
+#pragma mark FSIterateContainer
+
+OSErr
+FSIterateContainer(
+ const FSRef *container,
+ ItemCount maxLevels,
+ FSCatalogInfoBitmap whichInfo,
+ Boolean wantFSSpec,
+ Boolean wantName,
+ IterateContainerFilterProcPtr iterateFilter,
+ void *yourDataPtr);
+
+/*
+ The FSIterateContainer function performs a recursive iteration (scan) of the
+ specified container directory and calls your IterateContainerFilterProc
+ function once for each file and directory found.
+
+ The maxLevels parameter lets you control how deep the recursion goes.
+ If maxLevels is 1, FSIterateContainer only scans the specified directory;
+ if maxLevels is 2, FSIterateContainer scans the specified directory and
+ one subdirectory below the specified directory; etc. Set maxLevels to
+ zero to scan all levels.
+
+ The yourDataPtr parameter can point to whatever data structure you might
+ want to access from within your IterateContainerFilterProc.
+
+ container --> The FSRef to the container directory to iterate.
+ maxLevels --> Maximum number of directory levels to scan or
+ zero to scan all directory levels.
+ whichInfo --> The fields of the FSCatalogInfo you wish to get.
+ wantFSSpec --> Set to true if you want the FSSpec to each
+ object passed to your IterateContainerFilterProc.
+ wantName --> Set to true if you want the name of each
+ object passed to your IterateContainerFilterProc.
+ iterateFilter --> A pointer to the IterateContainerFilterProc you
+ want called once for each file and directory found
+ by FSIterateContainer.
+ yourDataPtr --> An optional pointer to whatever data structure you
+ might want to access from within the
+ IterateFilterProc.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetDirectoryItems
+
+OSErr
+FSGetDirectoryItems(
+ const FSRef *container,
+ FSRef ***refsHandle, /* pointer to handle of FSRefs */
+ ItemCount *numRefs,
+ Boolean *containerChanged);
+
+/*
+ The FSGetDirectoryItems function returns the list of items in the specified
+ container. The array of FSRef records is returned in a Handle, refsHandle,
+ which is allocated by FSGetDirectoryItems. The caller is responsible for
+ disposing of refsHandle if the FSGetDirectoryItems returns noErr.
+
+ container --> FSRef to a directory.
+ refsHandle <-- Pointer to an FSRef Handle where the array of
+ FSRefs is to be returned.
+ numRefs <-- The number of FSRefs returned in the array.
+ containerChanged <-- Set to true if the container changes while the
+ list of items is being obtained.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSExchangeObjectsCompat
+
+OSErr
+FSExchangeObjectsCompat(
+ const FSRef *sourceRef,
+ const FSRef *destRef,
+ FSRef *newSourceRef,
+ FSRef *newDestRef);
+
+/*
+ The FSExchangeObjectsCompat function exchanges the data between two files.
+
+ The FSExchangeObjectsCompat function is an enhanced version of
+ FSExchangeObjects function. The two enhancements FSExchangeObjectsCompat
+ provides are:
+
+ 1, FSExchangeObjectsCompat will work on volumes which do not support
+ FSExchangeObjects. FSExchangeObjectsCompat does this by emulating
+ FSExchangeObjects through a series of File Manager operations. If
+ there is a failure at any step along the way, FSExchangeObjectsCompat
+ attempts to undo any steps already taken to leave the files in their
+ original state in their original locations.
+
+ 2. FSExchangeObjectsCompat returns new FSRefs to the source and
+ destination files. Note that if this function fails at any step along
+ the way, newSourceRef and newDestRef still give you access to the final
+ locations of the files being exchanged -- even if they are renamed or
+ not in their original locations.
+
+ sourceRef --> FSRef to the source file.
+ destRef --> FSRef to the destination file.
+ newSourceRef <-- The new FSRef to the source file.
+ newDestRef <-- The new FSRef to the destination file.
+*/
+
+/*****************************************************************************/
+
+#pragma mark ----- Shared Environment Routines -----
+
+/*****************************************************************************/
+
+#pragma mark MFX_FSLockRange
+/* Renamed from FSLockRange to MFX_FSLockRange to avoid a conflict with
+ * the FSLockRange function present in the system library since Mac OS X
+ * 10.4. */
+
+OSErr
+MFX_FSLockRange(
+ SInt16 refNum,
+ SInt32 rangeLength,
+ SInt32 rangeStart);
+
+/*
+ The LockRange function locks (denies access to) a portion of a file
+ that was opened with shared read/write permission.
+
+ refNum --> The file reference number of an open file.
+ rangeLength --> The number of bytes in the range.
+ rangeStart --> The starting byte in the range to lock.
+
+ __________
+
+ Also see: UnlockRange
+*/
+
+/*****************************************************************************/
+
+#pragma mark MFX_FSUnlockRange
+/* Renamed from FSUnlockRange to MFX_FSUnlockRange to avoid a conflict with
+ * the FSUnlockRange function present in the system library since Mac OS X
+ * 10.4. */
+
+OSErr
+MFX_FSUnlockRange(
+ SInt16 refNum,
+ SInt32 rangeLength,
+ SInt32 rangeStart);
+
+/*
+ The UnlockRange function unlocks (allows access to) a previously locked
+ portion of a file that was opened with shared read/write permission.
+
+ refNum --> The file reference number of an open file.
+ rangeLength --> The number of bytes in the range.
+ rangeStart --> The starting byte in the range to unlock.
+
+ __________
+
+ Also see: LockRange
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetDirAccess
+
+OSErr
+FSGetDirAccess(
+ const FSRef *ref,
+ SInt32 *ownerID, /* can be NULL */
+ SInt32 *groupID, /* can be NULL */
+ SInt32 *accessRights); /* can be NULL */
+
+/*
+ The FSGetDirAccess function retrieves the directory access control
+ information for a directory on a shared volume.
+
+ ref --> An FSRef specifying the directory.
+ ownerID <** An optional pointer to a SInt32.
+ If not NULL, the directory's owner ID
+ will be returned in the SInt32.
+ groupID <** An optional pointer to a SInt32.
+ If not NULL, the directory's group ID, or 0
+ if no group affiliation, will be returned in
+ the SInt32.
+ accessRights <** An optional pointer to a SInt32.
+ If not NULL, the directory's access rights
+ will be returned in the SInt32.
+
+ __________
+
+ Also see: FSSetDirAccess, FSMapID, FSMapName
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSSetDirAccess
+
+OSErr
+FSSetDirAccess(
+ const FSRef *ref,
+ SInt32 ownerID,
+ SInt32 groupID,
+ SInt32 accessRights);
+
+/*
+ The FSpSetDirAccess function changes the directory access control
+ information for a directory on a shared volume. You must be the owner of
+ a directory to change its access control information.
+
+ ref --> An FSRef specifying the directory.
+ ownerID --> The directory's owner ID.
+ groupID --> The directory's group ID or 0 if no group affiliation.
+ accessRights --> The directory's access rights.
+
+ __________
+
+ Also see: FSGetDirAccess, FSMapID, FSMapName
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetVolMountInfoSize
+
+OSErr
+FSGetVolMountInfoSize(
+ FSVolumeRefNum volRefNum,
+ SInt16 *size);
+
+/*
+ The FSGetVolMountInfoSize function determines the how much space the
+ program needs to allocate for a volume mounting information record.
+
+ volRefNum --> Volume specification.
+ size <-- The space needed (in bytes) of the volume
+ mounting information record.
+
+ __________
+
+ Also see: FSGetVolMountInfo, VolumeMount
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetVolMountInfo
+
+OSErr
+FSGetVolMountInfo(
+ FSVolumeRefNum volRefNum,
+ void *volMountInfo);
+
+/*
+ The FSGetVolMountInfo function retrieves a volume mounting information
+ record containing all the information needed to mount the volume,
+ except for passwords.
+
+ volRefNum --> Volume specification.
+ volMountInfo <-- The volume mounting information.
+
+ __________
+
+ Also see: FSGetVolMountInfoSize, VolumeMount
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSVolumeMount
+
+// This function exists in Mac OS X 10.5, we cannot re-define it here.
+// We don't use this function, so just don't compile it.
+#if 0
+OSErr
+FSVolumeMount(
+ const void *volMountInfo,
+ FSVolumeRefNum *volRefNum);
+#endif
+
+/*
+ The VolumeMount function mounts a volume using a volume mounting
+ information record.
+
+ volMountInfo --> A volume mounting information record.
+ volRefNum <-- The volume reference number.
+
+ __________
+
+ Also see: FSGetVolMountInfoSize, FSGetVolMountInfo
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSMapID
+
+OSErr
+FSMapID(
+ FSVolumeRefNum volRefNum,
+ SInt32 ugID,
+ SInt16 objType,
+ Str31 name);
+
+/*
+ The FSMapID function determines the name of a user or group if you know
+ the user or group ID.
+
+ volRefNum --> Volume specification.
+ objType --> The mapping function code:
+ kOwnerID2Name to map a user ID to a user name
+ kGroupID2Name to map a group ID to a group name
+ name <** An optional pointer to a buffer (minimum Str31).
+ If not NULL, the user or group name
+ will be returned in the buffer.
+
+ __________
+
+ Also see: FSGetDirAccess, FSSetDirAccess, FSMapName
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSMapName
+
+OSErr
+FSMapName(
+ FSVolumeRefNum volRefNum,
+ ConstStr255Param name,
+ SInt16 objType,
+ SInt32 *ugID);
+
+/*
+ The FSMapName function determines the user or group ID if you know the
+ user or group name.
+
+ volRefNum --> Volume specification.
+ name --> The user or group name.
+ objType --> The mapping function code:
+ kOwnerName2ID to map a user name to a user ID
+ kGroupName2ID to map a user name to a group ID
+ ugID <-- The user or group ID.
+
+ __________
+
+ Also see: FSGetDirAccess, FSSetDirAccess, FSMapID
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSCopyFile
+
+OSErr
+FSCopyFile(
+ const FSRef *srcFileRef,
+ const FSRef *dstDirectoryRef,
+ UniCharCount nameLength,
+ const UniChar *copyName, /* can be NULL (no rename during copy) */
+ TextEncoding textEncodingHint,
+ FSRef *newRef); /* can be NULL */
+
+/*
+ The FSCopyFile function duplicates a file and optionally renames it.
+ The source and destination volumes must be on the same file server.
+ This function instructs the server to copy the file.
+
+ srcFileRef --> An FSRef specifying the source file.
+ dstDirectoryRef --> An FSRef specifying the destination directory.
+ nameLength --> Number of UniChar in copyName parameter (ignored
+ if copyName is NULL).
+ copyName --> Points to the new file name if the file is to be
+ renamed, or NULL if the file isn't to be renamed.
+ textEncodingHint --> The text encoding hint used for the rename.
+ You can pass kTextEncodingUnknown to use the
+ "default" textEncodingHint.
+ newRef <** An optional pointer to a FSRef.
+ If not NULL, the FSRef of the duplicated file
+ will be returned in the FSRef.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSMoveRename
+
+OSErr
+FSMoveRename(
+ const FSRef *srcFileRef,
+ const FSRef *dstDirectoryRef,
+ UniCharCount nameLength,
+ const UniChar *moveName, /* can be NULL (no rename during move) */
+ TextEncoding textEncodingHint,
+ FSRef *newRef); /* can be NULL */
+
+/*
+ The FSMoveRename function moves a file or directory (object), and
+ optionally renames it. The source and destination locations must be on
+ the same shared volume.
+
+ srcFileRef --> An FSRef specifying the source file.
+ dstDirectoryRef --> An FSRef specifying the destination directory.
+ nameLength --> Number of UniChar in moveName parameter (ignored
+ if copyName is NULL)
+ moveName --> Points to the new object name if the object is to be
+ renamed, or NULL if the object isn't to be renamed.
+ textEncodingHint --> The text encoding hint used for the rename.
+ You can pass kTextEncodingUnknown to use the
+ "default" textEncodingHint.
+ newRef <** An optional pointer to a FSRef.
+ If not NULL, the FSRef of the moved object
+ will be returned in the FSRef.
+*/
+
+/*****************************************************************************/
+
+#pragma mark ----- File ID Routines -----
+
+/*****************************************************************************/
+
+#pragma mark FSResolveFileIDRef
+
+OSErr
+FSResolveFileIDRef(
+ FSVolumeRefNum volRefNum,
+ SInt32 fileID,
+ FSRef *ref);
+
+/*
+ The FSResolveFileIDRef function returns an FSRef for the file with the
+ specified file ID reference.
+
+ volRefNum --> Volume specification.
+ fileID --> The file ID reference.
+ ref <-- The FSRef for the file ID reference.
+
+ __________
+
+ Also see: FSCreateFileIDRef, FSDeleteFileIDRef
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSCreateFileIDRef
+
+OSErr
+FSCreateFileIDRef(
+ const FSRef *ref,
+ SInt32 *fileID);
+
+/*
+ The FSCreateFileIDRef function creates a file ID reference for the
+ specified file, or if a file ID reference already exists, supplies
+ the file ID reference and returns the result code fidExists or afpIDExists.
+
+ ref --> The FSRef for the file.
+ fileID <-- The file ID reference (if result is noErr,
+ fidExists, or afpIDExists).
+
+ __________
+
+ Also see: GetFSRefFromFileIDRef, FSDeleteFileIDRef
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSDeleteFileIDRef
+
+/*
+ Why is there no FSDeleteFileIDRef routine? There are two reasons:
+
+ 1. Since Mac OS 8.1, PBDeleteFileIDRef hasn't deleted file ID references.
+ On HFS volumes, deleting a file ID reference breaks aliases (which
+ use file ID references to track files as they are moved around on a
+ volume) and file ID references are automatically deleted when the file
+ they refer to is deleted. On HFS Plus volumes, file ID references are
+ always created when a file is created, deleted when the file is deleted,
+ and cannot be deleted at any other time.
+
+ 2. PBDeleteFileIDRef causes a memory access fault under Mac OS X 10.0
+ through 10.1.x. While this will be fixed in a future release, the
+ implementation, like the Mac OS 8/9 implementation, does not delete
+ file ID references.
+
+ __________
+
+ Also see: GetFSRefFromFileIDRef, FSCreateFileIDRef
+*/
+
+/*****************************************************************************/
+
+#pragma mark ----- Utility Routines -----
+
+/*****************************************************************************/
+
+#pragma mark GetTempBuffer
+
+Ptr
+GetTempBuffer(
+ ByteCount buffReqSize,
+ ByteCount *buffActSize);
+
+/*
+ The GetTempBuffer function allocates a temporary buffer for file system
+ operations which is at least 4K bytes and a multiple of 4K bytes.
+
+ buffReqSize --> Size you'd like the buffer to be.
+ buffActSize <-- The size of the buffer allocated.
+ function result <-- Pointer to memory allocated, or NULL if no memory
+ was available. The caller is responsible for
+ disposing of this buffer with DisposePtr.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FileRefNumGetFSRef
+
+OSErr
+FileRefNumGetFSRef(
+ short refNum,
+ FSRef *ref);
+
+/*
+ The FileRefNumGetFSRef function gets the FSRef of an open file.
+
+ refNum --> The file reference number of an open file.
+ ref <-- The FSRef to the open file.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSSetDefault
+
+OSErr
+FSSetDefault(
+ const FSRef *newDefault,
+ FSRef *oldDefault);
+
+/*
+ The FSSetDefault function sets the current working directory to the
+ directory specified by newDefault. The previous current working directory
+ is returned in oldDefault and must be used to restore the current working
+ directory to its previous state with the FSRestoreDefault function.
+ These two functions are designed to be used as a wrapper around
+ Standard I/O routines where the location of the file is implied to be the
+ current working directory. This is how you should use these functions:
+
+ result = FSSetDefault(&newDefault, &oldDefault);
+ if ( noErr == result )
+ {
+ // call the Stdio functions like remove, rename,
+ // fopen, freopen, etc here!
+
+ result = FSRestoreDefault(&oldDefault);
+ }
+
+ newDefault --> An FSRef that specifies the new current working
+ directory.
+ oldDefault <-- The previous current working directory's FSRef.
+
+ __________
+
+ Also see: FSRestoreDefault
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSRestoreDefault
+
+OSErr
+FSRestoreDefault(
+ const FSRef *oldDefault);
+
+/*
+ The FSRestoreDefault function restores the current working directory
+ to the directory specified by oldDefault. The oldDefault parameter was
+ previously obtained from the FSSetDefault function.
+ These two functions are designed to be used as a wrapper around
+ Standard I/O routines where the location of the file is implied to be the
+ current working directory. This is how you should use these functions:
+
+ result = FSSetDefault(&newDefault, &oldDefault);
+ if ( noErr == result )
+ {
+ // call the Stdio functions like remove, rename,
+ // fopen, freopen, etc here!
+
+ result = FSRestoreDefault(&oldDefault);
+ }
+
+ oldDefault --> The FSRef of the location to restore.
+
+ __________
+
+ Also see: FSSetDefault
+*/
+
+/*****************************************************************************/
+
+#if PRAGMA_STRUCT_ALIGN
+ #pragma options align=reset
+#elif PRAGMA_STRUCT_PACKPUSH
+ #pragma pack(pop)
+#elif PRAGMA_STRUCT_PACK
+ #pragma pack()
+#endif
+
+#ifdef PRAGMA_IMPORT_OFF
+#pragma import off
+#elif PRAGMA_IMPORT
+#pragma import reset
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MOREFILESX__ */
+
diff --git a/src/libs/xpcom18a4/xpcom/base/.cvsignore b/src/libs/xpcom18a4/xpcom/base/.cvsignore
new file mode 100644
index 00000000..235f7398
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+bloatblame
diff --git a/src/libs/xpcom18a4/xpcom/base/Makefile.in b/src/libs/xpcom18a4/xpcom/base/Makefile.in
new file mode 100644
index 00000000..a897bca8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/Makefile.in
@@ -0,0 +1,133 @@
+#
+# ***** 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_base
+LIBRARY_NAME = xpcombase_s
+GRE_MODULE = 1
+
+REQUIRES = string \
+ $(NULL)
+
+CPPSRCS = \
+ nsAllocator.cpp \
+ nsConsoleMessage.cpp \
+ nsConsoleService.cpp \
+ nsDebugImpl.cpp \
+ nsErrorService.cpp \
+ nsExceptionService.cpp \
+ nsID.cpp \
+ nsMemoryImpl.cpp \
+ nsTraceRefcntImpl.cpp \
+ $(NULL)
+
+ifdef GC_LEAK_DETECTOR
+CSRCS += nsGarbageCollector.c
+CPPSRCS += nsLeakDetector.cpp
+REQUIRES += boehm
+endif
+
+EXPORTS = \
+ nsAgg.h \
+ nsAutoPtr.h \
+ nsCom.h \
+ nsDebugImpl.h \
+ nsIAllocator.h \
+ nsIID.h \
+ nsISupportsObsolete.h \
+ nsTraceRefcntImpl.h \
+ nsWeakPtr.h \
+ $(NULL)
+
+ifeq ($(OS_ARCH),WINNT)
+ifdef MOZ_DEBUG
+CSRCS += pure_api.c
+EXPORTS += pure.h
+endif
+CPPSRCS += nsStackFrameWin.cpp
+endif
+
+ifneq ($(OS_ARCH),WINNT)
+CPPSRCS += nsStackFrameUnix.cpp
+endif
+
+SDK_XPIDLSRCS = \
+ nsIDebug.idl \
+ nsIInterfaceRequestor.idl \
+ nsIMemory.idl \
+ nsIProgrammingLanguage.idl \
+ nsISupports.idl \
+ nsITraceRefcnt.idl \
+ nsIWeakReference.idl \
+ nsrootidl.idl \
+
+SDK_HEADERS = \
+ nsError.h \
+ nsID.h \
+ nsISupportsBase.h \
+ nscore.h \
+
+XPIDLSRCS = \
+ nsIConsoleListener.idl \
+ nsIConsoleMessage.idl \
+ nsIConsoleService.idl \
+ nsIErrorService.idl \
+ nsIException.idl \
+ nsIExceptionService.idl \
+ $(NULL)
+
+ifdef GC_LEAK_DETECTOR
+XPIDLSRCS += nsILeakDetector.idl
+endif
+
+# 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/base/nsAgg.h b/src/libs/xpcom18a4/xpcom/base/nsAgg.h
new file mode 100644
index 00000000..c818639e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsAgg.h
@@ -0,0 +1,155 @@
+/* -*- 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 nsAgg_h___
+#define nsAgg_h___
+
+#include "nsISupports.h"
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Put this in your class's declaration:
+#define NS_DECL_AGGREGATED \
+ NS_DECL_ISUPPORTS \
+ \
+public: \
+ \
+ /* You must implement this operation instead of the nsISupports */ \
+ /* methods if you inherit from nsAggregated. */ \
+ NS_IMETHOD \
+ AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr); \
+ \
+protected: \
+ \
+ class Internal : public nsISupports { \
+ public: \
+ \
+ Internal() {} \
+ \
+ NS_IMETHOD QueryInterface(const nsIID& aIID, \
+ void** aInstancePtr); \
+ NS_IMETHOD_(nsrefcnt) AddRef(void); \
+ NS_IMETHOD_(nsrefcnt) Release(void); \
+ \
+ }; \
+ \
+ friend class Internal; \
+ \
+ nsISupports* fOuter; \
+ Internal fAggregated; \
+ \
+ nsISupports* GetInner(void) { return &fAggregated; } \
+ \
+public: \
+
+
+// Put this in your class's constructor:
+#define NS_INIT_AGGREGATED(outer) \
+ PR_BEGIN_MACRO \
+ fOuter = outer ? outer : &fAggregated; \
+ PR_END_MACRO
+
+
+// Put this in your class's implementation file:
+#define NS_IMPL_AGGREGATED(_class) \
+NS_IMETHODIMP \
+_class::QueryInterface(const nsIID& aIID, void** aInstancePtr) \
+{ \
+ return fOuter->QueryInterface(aIID, aInstancePtr); \
+} \
+ \
+NS_IMETHODIMP_(nsrefcnt) \
+_class::AddRef(void) \
+{ \
+ return fOuter->AddRef(); \
+} \
+ \
+NS_IMETHODIMP_(nsrefcnt) \
+_class::Release(void) \
+{ \
+ return fOuter->Release(); \
+} \
+ \
+NS_IMETHODIMP \
+_class::Internal::QueryInterface(const nsIID& aIID, void** aInstancePtr) \
+{ \
+ _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \
+ return agg->AggregatedQueryInterface(aIID, aInstancePtr); \
+} \
+ \
+NS_IMETHODIMP_(nsrefcnt) \
+_class::Internal::AddRef(void) \
+{ \
+ _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \
+ NS_PRECONDITION(PRInt32(agg->mRefCnt) >= 0, "illegal refcnt"); \
+ ++agg->mRefCnt; \
+ NS_LOG_ADDREF(this, agg->mRefCnt, #_class, sizeof(*this)); \
+ return agg->mRefCnt; \
+} \
+ \
+NS_IMETHODIMP_(nsrefcnt) \
+_class::Internal::Release(void) \
+{ \
+ _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \
+ NS_PRECONDITION(0 != agg->mRefCnt, "dup release"); \
+ --agg->mRefCnt; \
+ NS_LOG_RELEASE(this, agg->mRefCnt, #_class); \
+ if (agg->mRefCnt == 0) { \
+ agg->mRefCnt = 1; /* stabilize */ \
+ NS_DELETEXPCOM(agg); \
+ return 0; \
+ } \
+ return agg->mRefCnt; \
+} \
+
+// for use with QI macros in nsISupportsUtils.h:
+
+#define NS_INTERFACE_MAP_BEGIN_AGGREGATED(_class) \
+ NS_IMPL_AGGREGATED_QUERY_HEAD(_class)
+
+#define NS_IMPL_AGGREGATED_QUERY_HEAD(_class) \
+NS_IMETHODIMP \
+_class::AggregatedQueryInterface(REFNSIID aIID, void** aInstancePtr) \
+{ \
+ NS_ASSERTION(aInstancePtr, \
+ "AggregatedQueryInterface requires a non-NULL result ptr!"); \
+ if ( !aInstancePtr ) \
+ return NS_ERROR_NULL_POINTER; \
+ nsISupports* foundInterface;
+
+#endif /* nsAgg_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/base/nsAllocator.cpp b/src/libs/xpcom18a4/xpcom/base/nsAllocator.cpp
new file mode 100644
index 00000000..d565329d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsAllocator.cpp
@@ -0,0 +1,41 @@
+/* -*- 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 ***** */
+
+////////////////////////////////////////////////////////////////////////////////
+// obsolete
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libs/xpcom18a4/xpcom/base/nsAllocator.h b/src/libs/xpcom18a4/xpcom/base/nsAllocator.h
new file mode 100644
index 00000000..5320469c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsAllocator.h
@@ -0,0 +1,50 @@
+/* -*- 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 ***** */
+
+////////////////////////////////////////////////////////////////////////////////
+// obsolete
+////////////////////////////////////////////////////////////////////////////////
+
+#ifndef nsAllocator_h__
+#define nsAllocator_h__
+
+#include "nsIAllocator.h"
+#include "prmem.h"
+#include "nsAgg.h"
+#include "nsIFactory.h"
+
+#endif // nsAllocator_h__
diff --git a/src/libs/xpcom18a4/xpcom/base/nsAutoPtr.h b/src/libs/xpcom18a4/xpcom/base/nsAutoPtr.h
new file mode 100644
index 00000000..874b1e31
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsAutoPtr.h
@@ -0,0 +1,1353 @@
+/* -*- 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):
+ * Scott Collins <scc@mozilla.org> (original author of nsCOMPtr)
+ * 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 ***** */
+
+#ifndef nsAutoPtr_h___
+#define nsAutoPtr_h___
+
+ // Wrapping includes can speed up compiles (see "Large Scale C++ Software Design")
+#ifndef nsCOMPtr_h___
+ // For |already_AddRefed|, |nsDerivedSafe|, |NSCAP_Zero|,
+ // |NSCAP_DONT_PROVIDE_NONCONST_OPEQ|,
+ // |NSCAP_FEATURE_INLINE_STARTASSIGNMENT|
+#include "nsCOMPtr.h"
+#endif
+
+/*****************************************************************************/
+
+// template <class T> class nsAutoPtrGetterTransfers;
+
+template <class T>
+class nsAutoPtr
+ {
+ private:
+ void**
+ begin_assignment()
+ {
+ assign(0);
+ return NS_REINTERPRET_CAST(void**, &mRawPtr);
+ }
+
+ void
+ assign( T* newPtr )
+ {
+ T* oldPtr = mRawPtr;
+ mRawPtr = newPtr;
+ delete oldPtr;
+ }
+
+ private:
+ T* mRawPtr;
+
+ public:
+ typedef T element_type;
+
+ ~nsAutoPtr()
+ {
+ delete mRawPtr;
+ }
+
+ // Constructors
+
+ nsAutoPtr()
+ : mRawPtr(0)
+ // default constructor
+ {
+ }
+
+ nsAutoPtr( T* aRawPtr )
+ : mRawPtr(aRawPtr)
+ // construct from a raw pointer (of the right type)
+ {
+ }
+
+ nsAutoPtr( nsAutoPtr<T>& aSmartPtr )
+ : mRawPtr( aSmartPtr.forget() )
+ // Construct by transferring ownership from another smart pointer.
+ {
+ }
+
+
+ // Assignment operators
+
+ nsAutoPtr<T>&
+ operator=( T* rhs )
+ // assign from a raw pointer (of the right type)
+ {
+ assign(rhs);
+ return *this;
+ }
+
+ nsAutoPtr<T>& operator=( nsAutoPtr<T>& rhs )
+ // assign by transferring ownership from another smart pointer.
+ {
+ assign(rhs.forget());
+ return *this;
+ }
+
+ // Other pointer operators
+
+ T*
+ get() const
+ /*
+ Prefer the implicit conversion provided automatically by
+ |operator T*() const|. Use |get()| _only_ to resolve
+ ambiguity.
+ */
+ {
+ return mRawPtr;
+ }
+
+ operator T*() const
+ /*
+ ...makes an |nsAutoPtr| act like its underlying raw pointer
+ type whenever it is used in a context where a raw pointer
+ is expected. It is this operator that makes an |nsAutoPtr|
+ substitutable for a raw pointer.
+
+ Prefer the implicit use of this operator to calling |get()|,
+ except where necessary to resolve ambiguity.
+ */
+ {
+ return get();
+ }
+
+ T*
+ forget()
+ {
+ T* temp = mRawPtr;
+ mRawPtr = 0;
+ return temp;
+ }
+
+ T*
+ operator->() const
+ {
+ NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoPtr with operator->().");
+ return get();
+ }
+
+#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
+ // broken version for IRIX
+
+ nsAutoPtr<T>*
+ get_address() const
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return NS_CONST_CAST(nsAutoPtr<T>*, this);
+ }
+
+#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+ nsAutoPtr<T>*
+ get_address()
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return this;
+ }
+
+ const nsAutoPtr<T>*
+ get_address() const
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return this;
+ }
+
+#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+ public:
+ T&
+ operator*() const
+ {
+ NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoPtr with operator*().");
+ return *get();
+ }
+
+ T**
+ StartAssignment()
+ {
+#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
+ return NS_REINTERPRET_CAST(T**, begin_assignment());
+#else
+ assign(0);
+ return NS_REINTERPRET_CAST(T**, &mRawPtr);
+#endif
+ }
+ };
+
+#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+// This is the broken version for IRIX, which can't handle the version below.
+
+template <class T>
+inline
+nsAutoPtr<T>*
+address_of( const nsAutoPtr<T>& aPtr )
+ {
+ return aPtr.get_address();
+ }
+
+#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+template <class T>
+inline
+nsAutoPtr<T>*
+address_of( nsAutoPtr<T>& aPtr )
+ {
+ return aPtr.get_address();
+ }
+
+template <class T>
+inline
+const nsAutoPtr<T>*
+address_of( const nsAutoPtr<T>& aPtr )
+ {
+ return aPtr.get_address();
+ }
+
+#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+template <class T>
+class nsAutoPtrGetterTransfers
+ /*
+ ...
+
+ This class is designed to be used for anonymous temporary objects in the
+ argument list of calls that return COM interface pointers, e.g.,
+
+ nsAutoPtr<IFoo> fooP;
+ ...->GetTransferedPointer(getter_Transfers(fooP))
+
+ DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_Transfers()| instead.
+
+ When initialized with a |nsAutoPtr|, as in the example above, it returns
+ a |void**|, a |T**|, or an |nsISupports**| as needed, that the
+ outer call (|GetTransferedPointer| in this case) can fill in.
+
+ This type should be a nested class inside |nsAutoPtr<T>|.
+ */
+ {
+ public:
+ explicit
+ nsAutoPtrGetterTransfers( nsAutoPtr<T>& aSmartPtr )
+ : mTargetSmartPtr(aSmartPtr)
+ {
+ // nothing else to do
+ }
+
+ operator void**()
+ {
+ return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
+ }
+
+ operator T**()
+ {
+ return mTargetSmartPtr.StartAssignment();
+ }
+
+ T*&
+ operator*()
+ {
+ return *(mTargetSmartPtr.StartAssignment());
+ }
+
+ private:
+ nsAutoPtr<T>& mTargetSmartPtr;
+ };
+
+template <class T>
+inline
+nsAutoPtrGetterTransfers<T>
+getter_Transfers( nsAutoPtr<T>& aSmartPtr )
+ /*
+ Used around a |nsAutoPtr| when
+ ...makes the class |nsAutoPtrGetterTransfers<T>| invisible.
+ */
+ {
+ return nsAutoPtrGetterTransfers<T>(aSmartPtr);
+ }
+
+
+
+ // Comparing two |nsAutoPtr|s
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const nsAutoPtr<T>& lhs, const nsAutoPtr<U>& rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs.get());
+ }
+
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const nsAutoPtr<T>& lhs, const nsAutoPtr<U>& rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs.get());
+ }
+
+
+ // Comparing an |nsAutoPtr| to a raw pointer
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const nsAutoPtr<T>& lhs, const U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const U* lhs, const nsAutoPtr<T>& rhs )
+ {
+ return NS_STATIC_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const nsAutoPtr<T>& lhs, const U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const U* lhs, const nsAutoPtr<T>& rhs )
+ {
+ return NS_STATIC_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
+ }
+
+ // To avoid ambiguities caused by the presence of builtin |operator==|s
+ // creating a situation where one of the |operator==| defined above
+ // has a better conversion for one argument and the builtin has a
+ // better conversion for the other argument, define additional
+ // |operator==| without the |const| on the raw pointer.
+ // See bug 65664 for details.
+
+#ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const nsAutoPtr<T>& lhs, U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) == NS_CONST_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( U* lhs, const nsAutoPtr<T>& rhs )
+ {
+ return NS_CONST_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const nsAutoPtr<T>& lhs, U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) != NS_CONST_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( U* lhs, const nsAutoPtr<T>& rhs )
+ {
+ return NS_CONST_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
+ }
+#endif
+
+
+
+ // Comparing an |nsAutoPtr| to |0|
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( const nsAutoPtr<T>& lhs, NSCAP_Zero* rhs )
+ // specifically to allow |smartPtr == 0|
+ {
+ return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( NSCAP_Zero* lhs, const nsAutoPtr<T>& rhs )
+ // specifically to allow |0 == smartPtr|
+ {
+ return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator!=( const nsAutoPtr<T>& lhs, NSCAP_Zero* rhs )
+ // specifically to allow |smartPtr != 0|
+ {
+ return NS_STATIC_CAST(const void*, lhs.get()) != NS_REINTERPRET_CAST(const void*, rhs);
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator!=( NSCAP_Zero* lhs, const nsAutoPtr<T>& rhs )
+ // specifically to allow |0 != smartPtr|
+ {
+ return NS_REINTERPRET_CAST(const void*, lhs) != NS_STATIC_CAST(const void*, rhs.get());
+ }
+
+
+#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
+
+ // We need to explicitly define comparison operators for `int'
+ // because the compiler is lame.
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( const nsAutoPtr<T>& lhs, int rhs )
+ // specifically to allow |smartPtr == 0|
+ {
+ return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( int lhs, const nsAutoPtr<T>& rhs )
+ // specifically to allow |0 == smartPtr|
+ {
+ return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
+ }
+
+#endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
+
+/*****************************************************************************/
+
+// template <class T> class nsAutoArrayPtrGetterTransfers;
+
+template <class T>
+class nsAutoArrayPtr
+ {
+ private:
+ void**
+ begin_assignment()
+ {
+ assign(0);
+ return NS_REINTERPRET_CAST(void**, &mRawPtr);
+ }
+
+ void
+ assign( T* newPtr )
+ {
+ T* oldPtr = mRawPtr;
+ mRawPtr = newPtr;
+ delete [] oldPtr;
+ }
+
+ private:
+ T* mRawPtr;
+
+ public:
+ typedef T element_type;
+
+ ~nsAutoArrayPtr()
+ {
+ delete [] mRawPtr;
+ }
+
+ // Constructors
+
+ nsAutoArrayPtr()
+ : mRawPtr(0)
+ // default constructor
+ {
+ }
+
+ nsAutoArrayPtr( T* aRawPtr )
+ : mRawPtr(aRawPtr)
+ // construct from a raw pointer (of the right type)
+ {
+ }
+
+ nsAutoArrayPtr( nsAutoArrayPtr<T>& aSmartPtr )
+ : mRawPtr( aSmartPtr.forget() )
+ // Construct by transferring ownership from another smart pointer.
+ {
+ }
+
+
+ // Assignment operators
+
+ nsAutoArrayPtr<T>&
+ operator=( T* rhs )
+ // assign from a raw pointer (of the right type)
+ {
+ assign(rhs);
+ return *this;
+ }
+
+ nsAutoArrayPtr<T>& operator=( nsAutoArrayPtr<T>& rhs )
+ // assign by transferring ownership from another smart pointer.
+ {
+ assign(rhs.forget());
+ return *this;
+ }
+
+ // Other pointer operators
+
+ T*
+ get() const
+ /*
+ Prefer the implicit conversion provided automatically by
+ |operator T*() const|. Use |get()| _only_ to resolve
+ ambiguity.
+ */
+ {
+ return mRawPtr;
+ }
+
+ operator T*() const
+ /*
+ ...makes an |nsAutoArrayPtr| act like its underlying raw pointer
+ type whenever it is used in a context where a raw pointer
+ is expected. It is this operator that makes an |nsAutoArrayPtr|
+ substitutable for a raw pointer.
+
+ Prefer the implicit use of this operator to calling |get()|,
+ except where necessary to resolve ambiguity.
+ */
+ {
+ return get();
+ }
+
+ T*
+ forget()
+ {
+ T* temp = mRawPtr;
+ mRawPtr = 0;
+ return temp;
+ }
+
+ T*
+ operator->() const
+ {
+ NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoArrayPtr with operator->().");
+ return get();
+ }
+
+#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
+ // broken version for IRIX
+
+ nsAutoArrayPtr<T>*
+ get_address() const
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return NS_CONST_CAST(nsAutoArrayPtr<T>*, this);
+ }
+
+#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+ nsAutoArrayPtr<T>*
+ get_address()
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return this;
+ }
+
+ const nsAutoArrayPtr<T>*
+ get_address() const
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return this;
+ }
+
+#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+ public:
+ T&
+ operator*() const
+ {
+ NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoArrayPtr with operator*().");
+ return *get();
+ }
+
+ T**
+ StartAssignment()
+ {
+#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
+ return NS_REINTERPRET_CAST(T**, begin_assignment());
+#else
+ assign(0);
+ return NS_REINTERPRET_CAST(T**, &mRawPtr);
+#endif
+ }
+ };
+
+#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+// This is the broken version for IRIX, which can't handle the version below.
+
+template <class T>
+inline
+nsAutoArrayPtr<T>*
+address_of( const nsAutoArrayPtr<T>& aPtr )
+ {
+ return aPtr.get_address();
+ }
+
+#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+template <class T>
+inline
+nsAutoArrayPtr<T>*
+address_of( nsAutoArrayPtr<T>& aPtr )
+ {
+ return aPtr.get_address();
+ }
+
+template <class T>
+inline
+const nsAutoArrayPtr<T>*
+address_of( const nsAutoArrayPtr<T>& aPtr )
+ {
+ return aPtr.get_address();
+ }
+
+#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+template <class T>
+class nsAutoArrayPtrGetterTransfers
+ /*
+ ...
+
+ This class is designed to be used for anonymous temporary objects in the
+ argument list of calls that return COM interface pointers, e.g.,
+
+ nsAutoArrayPtr<IFoo> fooP;
+ ...->GetTransferedPointer(getter_Transfers(fooP))
+
+ DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_Transfers()| instead.
+
+ When initialized with a |nsAutoArrayPtr|, as in the example above, it returns
+ a |void**|, a |T**|, or an |nsISupports**| as needed, that the
+ outer call (|GetTransferedPointer| in this case) can fill in.
+
+ This type should be a nested class inside |nsAutoArrayPtr<T>|.
+ */
+ {
+ public:
+ explicit
+ nsAutoArrayPtrGetterTransfers( nsAutoArrayPtr<T>& aSmartPtr )
+ : mTargetSmartPtr(aSmartPtr)
+ {
+ // nothing else to do
+ }
+
+ operator void**()
+ {
+ return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
+ }
+
+ operator T**()
+ {
+ return mTargetSmartPtr.StartAssignment();
+ }
+
+ T*&
+ operator*()
+ {
+ return *(mTargetSmartPtr.StartAssignment());
+ }
+
+ private:
+ nsAutoArrayPtr<T>& mTargetSmartPtr;
+ };
+
+template <class T>
+inline
+nsAutoArrayPtrGetterTransfers<T>
+getter_Transfers( nsAutoArrayPtr<T>& aSmartPtr )
+ /*
+ Used around a |nsAutoArrayPtr| when
+ ...makes the class |nsAutoArrayPtrGetterTransfers<T>| invisible.
+ */
+ {
+ return nsAutoArrayPtrGetterTransfers<T>(aSmartPtr);
+ }
+
+
+
+ // Comparing two |nsAutoArrayPtr|s
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const nsAutoArrayPtr<T>& lhs, const nsAutoArrayPtr<U>& rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs.get());
+ }
+
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const nsAutoArrayPtr<T>& lhs, const nsAutoArrayPtr<U>& rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs.get());
+ }
+
+
+ // Comparing an |nsAutoArrayPtr| to a raw pointer
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const nsAutoArrayPtr<T>& lhs, const U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const U* lhs, const nsAutoArrayPtr<T>& rhs )
+ {
+ return NS_STATIC_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const nsAutoArrayPtr<T>& lhs, const U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const U* lhs, const nsAutoArrayPtr<T>& rhs )
+ {
+ return NS_STATIC_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
+ }
+
+ // To avoid ambiguities caused by the presence of builtin |operator==|s
+ // creating a situation where one of the |operator==| defined above
+ // has a better conversion for one argument and the builtin has a
+ // better conversion for the other argument, define additional
+ // |operator==| without the |const| on the raw pointer.
+ // See bug 65664 for details.
+
+#ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const nsAutoArrayPtr<T>& lhs, U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) == NS_CONST_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( U* lhs, const nsAutoArrayPtr<T>& rhs )
+ {
+ return NS_CONST_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const nsAutoArrayPtr<T>& lhs, U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) != NS_CONST_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( U* lhs, const nsAutoArrayPtr<T>& rhs )
+ {
+ return NS_CONST_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
+ }
+#endif
+
+
+
+ // Comparing an |nsAutoArrayPtr| to |0|
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( const nsAutoArrayPtr<T>& lhs, NSCAP_Zero* rhs )
+ // specifically to allow |smartPtr == 0|
+ {
+ return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( NSCAP_Zero* lhs, const nsAutoArrayPtr<T>& rhs )
+ // specifically to allow |0 == smartPtr|
+ {
+ return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator!=( const nsAutoArrayPtr<T>& lhs, NSCAP_Zero* rhs )
+ // specifically to allow |smartPtr != 0|
+ {
+ return NS_STATIC_CAST(const void*, lhs.get()) != NS_REINTERPRET_CAST(const void*, rhs);
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator!=( NSCAP_Zero* lhs, const nsAutoArrayPtr<T>& rhs )
+ // specifically to allow |0 != smartPtr|
+ {
+ return NS_REINTERPRET_CAST(const void*, lhs) != NS_STATIC_CAST(const void*, rhs.get());
+ }
+
+
+#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
+
+ // We need to explicitly define comparison operators for `int'
+ // because the compiler is lame.
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( const nsAutoArrayPtr<T>& lhs, int rhs )
+ // specifically to allow |smartPtr == 0|
+ {
+ return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( int lhs, const nsAutoArrayPtr<T>& rhs )
+ // specifically to allow |0 == smartPtr|
+ {
+ return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
+ }
+
+#endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
+
+
+/*****************************************************************************/
+
+// template <class T> class nsRefPtrGetterAddRefs;
+
+template <class T>
+class nsRefPtr
+ {
+ private:
+
+ void
+ assign_with_AddRef( T* rawPtr )
+ {
+ if ( rawPtr )
+ rawPtr->AddRef();
+ assign_assuming_AddRef(rawPtr);
+ }
+
+ void**
+ begin_assignment()
+ {
+ assign_assuming_AddRef(0);
+ return NS_REINTERPRET_CAST(void**, &mRawPtr);
+ }
+
+ void
+ assign_assuming_AddRef( T* newPtr )
+ {
+ T* oldPtr = mRawPtr;
+ mRawPtr = newPtr;
+ if ( oldPtr )
+ oldPtr->Release();
+ }
+
+ private:
+ T* mRawPtr;
+
+ public:
+ typedef T element_type;
+
+ ~nsRefPtr()
+ {
+ if ( mRawPtr )
+ mRawPtr->Release();
+ }
+
+ // Constructors
+
+ nsRefPtr()
+ : mRawPtr(0)
+ // default constructor
+ {
+ }
+
+ nsRefPtr( const nsRefPtr<T>& aSmartPtr )
+ : mRawPtr(aSmartPtr.mRawPtr)
+ // copy-constructor
+ {
+ if ( mRawPtr )
+ mRawPtr->AddRef();
+ }
+
+ nsRefPtr( T* aRawPtr )
+ : mRawPtr(aRawPtr)
+ // construct from a raw pointer (of the right type)
+ {
+ if ( mRawPtr )
+ mRawPtr->AddRef();
+ }
+
+ nsRefPtr( const already_AddRefed<T>& aSmartPtr )
+ : mRawPtr(aSmartPtr.mRawPtr)
+ // construct from |dont_AddRef(expr)|
+ {
+ }
+
+ // Assignment operators
+
+ nsRefPtr<T>&
+ operator=( const nsRefPtr<T>& rhs )
+ // copy assignment operator
+ {
+ assign_with_AddRef(rhs.mRawPtr);
+ return *this;
+ }
+
+ nsRefPtr<T>&
+ operator=( T* rhs )
+ // assign from a raw pointer (of the right type)
+ {
+ assign_with_AddRef(rhs);
+ return *this;
+ }
+
+ nsRefPtr<T>&
+ operator=( const already_AddRefed<T>& rhs )
+ // assign from |dont_AddRef(expr)|
+ {
+ assign_assuming_AddRef(rhs.mRawPtr);
+ return *this;
+ }
+
+ // Other pointer operators
+
+ void
+ swap( nsRefPtr<T>& rhs )
+ // ...exchange ownership with |rhs|; can save a pair of refcount operations
+ {
+ T* temp = rhs.mRawPtr;
+ rhs.mRawPtr = mRawPtr;
+ mRawPtr = temp;
+ }
+
+ void
+ swap( T*& rhs )
+ // ...exchange ownership with |rhs|; can save a pair of refcount operations
+ {
+ T* temp = rhs;
+ rhs = mRawPtr;
+ mRawPtr = temp;
+ }
+
+ nsDerivedSafe<T>*
+ get() const
+ /*
+ Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<T>*() const|.
+ Use |get()| _only_ to resolve ambiguity.
+
+ Returns a |nsDerivedSafe<T>*| to deny clients the use of |AddRef| and |Release|.
+ */
+ {
+ return NS_CONST_CAST(nsDerivedSafe<T>*,
+ NS_REINTERPRET_CAST(const nsDerivedSafe<T>*, mRawPtr));
+ }
+
+ operator nsDerivedSafe<T>*() const
+ /*
+ ...makes an |nsRefPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|,
+ and |delete|) whenever it is used in a context where a raw pointer is expected. It is this operator
+ that makes an |nsRefPtr| substitutable for a raw pointer.
+
+ Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity.
+ */
+ {
+ return get();
+ }
+
+ nsDerivedSafe<T>*
+ operator->() const
+ {
+ NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsRefPtr with operator->().");
+ return get();
+ }
+
+#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
+ // broken version for IRIX
+
+ nsRefPtr<T>*
+ get_address() const
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return NS_CONST_CAST(nsRefPtr<T>*, this);
+ }
+
+#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+ nsRefPtr<T>*
+ get_address()
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return this;
+ }
+
+ const nsRefPtr<T>*
+ get_address() const
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return this;
+ }
+
+#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+ public:
+ nsDerivedSafe<T>&
+ operator*() const
+ {
+ NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsRefPtr with operator*().");
+ return *get();
+ }
+
+ T**
+ StartAssignment()
+ {
+#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
+ return NS_REINTERPRET_CAST(T**, begin_assignment());
+#else
+ assign_assuming_AddRef(0);
+ return NS_REINTERPRET_CAST(T**, &mRawPtr);
+#endif
+ }
+ };
+
+#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+// This is the broken version for IRIX, which can't handle the version below.
+
+template <class T>
+inline
+nsRefPtr<T>*
+address_of( const nsRefPtr<T>& aPtr )
+ {
+ return aPtr.get_address();
+ }
+
+#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+template <class T>
+inline
+nsRefPtr<T>*
+address_of( nsRefPtr<T>& aPtr )
+ {
+ return aPtr.get_address();
+ }
+
+template <class T>
+inline
+const nsRefPtr<T>*
+address_of( const nsRefPtr<T>& aPtr )
+ {
+ return aPtr.get_address();
+ }
+
+#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+template <class T>
+class nsRefPtrGetterAddRefs
+ /*
+ ...
+
+ This class is designed to be used for anonymous temporary objects in the
+ argument list of calls that return COM interface pointers, e.g.,
+
+ nsRefPtr<IFoo> fooP;
+ ...->GetAddRefedPointer(getter_AddRefs(fooP))
+
+ DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
+
+ When initialized with a |nsRefPtr|, as in the example above, it returns
+ a |void**|, a |T**|, or an |nsISupports**| as needed, that the
+ outer call (|GetAddRefedPointer| in this case) can fill in.
+
+ This type should be a nested class inside |nsRefPtr<T>|.
+ */
+ {
+ public:
+ explicit
+ nsRefPtrGetterAddRefs( nsRefPtr<T>& aSmartPtr )
+ : mTargetSmartPtr(aSmartPtr)
+ {
+ // nothing else to do
+ }
+
+ operator void**()
+ {
+ return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
+ }
+
+ operator T**()
+ {
+ return mTargetSmartPtr.StartAssignment();
+ }
+
+ T*&
+ operator*()
+ {
+ return *(mTargetSmartPtr.StartAssignment());
+ }
+
+ private:
+ nsRefPtr<T>& mTargetSmartPtr;
+ };
+
+template <class T>
+inline
+nsRefPtrGetterAddRefs<T>
+getter_AddRefs( nsRefPtr<T>& aSmartPtr )
+ /*
+ Used around a |nsRefPtr| when
+ ...makes the class |nsRefPtrGetterAddRefs<T>| invisible.
+ */
+ {
+ return nsRefPtrGetterAddRefs<T>(aSmartPtr);
+ }
+
+
+
+ // Comparing two |nsRefPtr|s
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const nsRefPtr<T>& lhs, const nsRefPtr<U>& rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs.get());
+ }
+
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const nsRefPtr<T>& lhs, const nsRefPtr<U>& rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs.get());
+ }
+
+
+ // Comparing an |nsRefPtr| to a raw pointer
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const nsRefPtr<T>& lhs, const U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const U* lhs, const nsRefPtr<T>& rhs )
+ {
+ return NS_STATIC_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const nsRefPtr<T>& lhs, const U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const U* lhs, const nsRefPtr<T>& rhs )
+ {
+ return NS_STATIC_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
+ }
+
+ // To avoid ambiguities caused by the presence of builtin |operator==|s
+ // creating a situation where one of the |operator==| defined above
+ // has a better conversion for one argument and the builtin has a
+ // better conversion for the other argument, define additional
+ // |operator==| without the |const| on the raw pointer.
+ // See bug 65664 for details.
+
+#ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const nsRefPtr<T>& lhs, U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) == NS_CONST_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( U* lhs, const nsRefPtr<T>& rhs )
+ {
+ return NS_CONST_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const nsRefPtr<T>& lhs, U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) != NS_CONST_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( U* lhs, const nsRefPtr<T>& rhs )
+ {
+ return NS_CONST_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
+ }
+#endif
+
+
+
+ // Comparing an |nsRefPtr| to |0|
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( const nsRefPtr<T>& lhs, NSCAP_Zero* rhs )
+ // specifically to allow |smartPtr == 0|
+ {
+ return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( NSCAP_Zero* lhs, const nsRefPtr<T>& rhs )
+ // specifically to allow |0 == smartPtr|
+ {
+ return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator!=( const nsRefPtr<T>& lhs, NSCAP_Zero* rhs )
+ // specifically to allow |smartPtr != 0|
+ {
+ return NS_STATIC_CAST(const void*, lhs.get()) != NS_REINTERPRET_CAST(const void*, rhs);
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator!=( NSCAP_Zero* lhs, const nsRefPtr<T>& rhs )
+ // specifically to allow |0 != smartPtr|
+ {
+ return NS_REINTERPRET_CAST(const void*, lhs) != NS_STATIC_CAST(const void*, rhs.get());
+ }
+
+
+#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
+
+ // We need to explicitly define comparison operators for `int'
+ // because the compiler is lame.
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( const nsRefPtr<T>& lhs, int rhs )
+ // specifically to allow |smartPtr == 0|
+ {
+ return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( int lhs, const nsRefPtr<T>& rhs )
+ // specifically to allow |0 == smartPtr|
+ {
+ return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
+ }
+
+#endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
+
+/*****************************************************************************/
+
+#endif // !defined(nsAutoPtr_h___)
diff --git a/src/libs/xpcom18a4/xpcom/base/nsCom.h b/src/libs/xpcom18a4/xpcom/base/nsCom.h
new file mode 100644
index 00000000..54b0b8bf
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsCom.h
@@ -0,0 +1,43 @@
+/* -*- 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 nsCom_h__
+#define nsCom_h__
+#include "nscore.h"
+#endif
+
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsConsoleMessage.cpp b/src/libs/xpcom18a4/xpcom/base/nsConsoleMessage.cpp
new file mode 100644
index 00000000..02dc589b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsConsoleMessage.cpp
@@ -0,0 +1,69 @@
+/* -*- 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 ***** */
+
+/*
+ * Base implementation for console messages.
+ */
+
+#include "nsConsoleMessage.h"
+#include "nsReadableUtils.h"
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsConsoleMessage, nsIConsoleMessage)
+
+nsConsoleMessage::nsConsoleMessage()
+{
+}
+
+nsConsoleMessage::nsConsoleMessage(const PRUnichar *message)
+{
+ mMessage.Assign(message);
+}
+
+NS_IMETHODIMP
+nsConsoleMessage::GetMessage(PRUnichar **result) {
+ *result = ToNewUnicode(mMessage);
+
+ return NS_OK;
+}
+
+// NS_IMETHODIMP
+// nsConsoleMessage::Init(const PRUnichar *message) {
+// nsAutoString newMessage(message);
+// mMessage = ToNewUnicode(newMessage);
+// return NS_OK;
+// }
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsConsoleMessage.h b/src/libs/xpcom18a4/xpcom/base/nsConsoleMessage.h
new file mode 100644
index 00000000..3d4a7e6c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsConsoleMessage.h
@@ -0,0 +1,58 @@
+/* -*- 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 __nsconsolemessage_h__
+#define __nsconsolemessage_h__
+
+#include "nsIConsoleMessage.h"
+#include "nsString.h"
+
+class nsConsoleMessage : public nsIConsoleMessage {
+public:
+ nsConsoleMessage();
+ nsConsoleMessage(const PRUnichar *message);
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSICONSOLEMESSAGE
+
+private:
+ ~nsConsoleMessage() {}
+
+ nsString mMessage;
+};
+
+#endif /* __nsconsolemessage_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/base/nsConsoleService.cpp b/src/libs/xpcom18a4/xpcom/base/nsConsoleService.cpp
new file mode 100644
index 00000000..1b369071
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsConsoleService.cpp
@@ -0,0 +1,321 @@
+/* -*- 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 ***** */
+
+/*
+ * Maintains a circular buffer of recent messages, and notifies
+ * listeners when new messages are logged.
+ */
+
+/* Threadsafe. */
+
+#include "nsMemory.h"
+#include "nsIServiceManager.h"
+#include "nsIProxyObjectManager.h"
+#include "nsSupportsArray.h"
+
+#include "nsConsoleService.h"
+#include "nsConsoleMessage.h"
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsConsoleService, nsIConsoleService)
+
+nsConsoleService::nsConsoleService()
+ : mCurrent(0), mFull(PR_FALSE), mListening(PR_FALSE), mLock(nsnull)
+{
+ // XXX grab this from a pref!
+ // hm, but worry about circularity, bc we want to be able to report
+ // prefs errs...
+ mBufferSize = 250;
+
+ // XXX deal with these two allocations by detecting null mLock in factory?
+ mMessages = (nsIConsoleMessage **)
+ nsMemory::Alloc(mBufferSize * sizeof(nsIConsoleMessage *));
+
+ mLock = PR_NewLock();
+
+ // Array elements should be 0 initially for circular buffer algorithm.
+ for (PRUint32 i = 0; i < mBufferSize; i++) {
+ mMessages[i] = nsnull;
+ }
+
+}
+
+nsConsoleService::~nsConsoleService()
+{
+ PRUint32 i = 0;
+ while (i < mBufferSize && mMessages[i] != nsnull) {
+ NS_RELEASE(mMessages[i]);
+ i++;
+ }
+
+#ifdef DEBUG_mccabe
+ if (mListeners.Count() != 0) {
+ fprintf(stderr,
+ "WARNING - %d console error listeners still registered!\n"
+ "More calls to nsIConsoleService::UnregisterListener needed.\n",
+ mListeners.Count());
+ }
+
+#endif
+
+ nsMemory::Free(mMessages);
+ if (mLock)
+ PR_DestroyLock(mLock);
+}
+
+static PRBool PR_CALLBACK snapshot_enum_func(nsHashKey *key, void *data, void* closure)
+{
+ nsISupportsArray *array = (nsISupportsArray *)closure;
+
+ // Copy each element into the temporary nsSupportsArray...
+ array->AppendElement((nsISupports*)data);
+ return PR_TRUE;
+}
+
+// nsIConsoleService methods
+NS_IMETHODIMP
+nsConsoleService::LogMessage(nsIConsoleMessage *message)
+{
+ if (message == nsnull)
+ return NS_ERROR_INVALID_ARG;
+
+ nsSupportsArray listenersSnapshot;
+ nsIConsoleMessage *retiredMessage;
+
+ NS_ADDREF(message); // early, in case it's same as replaced below.
+
+ /*
+ * Lock while updating buffer, and while taking snapshot of
+ * listeners array.
+ */
+ {
+ nsAutoLock lock(mLock);
+
+ /*
+ * If there's already a message in the slot we're about to replace,
+ * we've wrapped around, and we need to release the old message. We
+ * save a pointer to it, so we can release below outside the lock.
+ */
+ retiredMessage = mMessages[mCurrent];
+
+ mMessages[mCurrent++] = message;
+ if (mCurrent == mBufferSize) {
+ mCurrent = 0; // wrap around.
+ mFull = PR_TRUE;
+ }
+
+ /*
+ * Copy the listeners into the snapshot array - in case a listener
+ * is removed during an Observe(...) notification...
+ */
+ mListeners.Enumerate(snapshot_enum_func, &listenersSnapshot);
+ }
+ if (retiredMessage != nsnull)
+ NS_RELEASE(retiredMessage);
+
+ /*
+ * Iterate through any registered listeners and tell them about
+ * the message. We use the mListening flag to guard against
+ * recursive message logs. This could sometimes result in
+ * listeners being skipped because of activity on other threads,
+ * when we only care about the recursive case.
+ */
+ nsCOMPtr<nsIConsoleListener> listener;
+ nsresult rv;
+ nsresult returned_rv;
+ PRUint32 snapshotCount;
+ rv = listenersSnapshot.Count(&snapshotCount);
+ if (NS_FAILED(rv))
+ return rv;
+
+ {
+ nsAutoLock lock(mLock);
+ if (mListening)
+ return NS_OK;
+ mListening = PR_TRUE;
+ }
+
+ returned_rv = NS_OK;
+ for (PRUint32 i = 0; i < snapshotCount; i++) {
+ rv = listenersSnapshot.GetElementAt(i, getter_AddRefs(listener));
+ if (NS_FAILED(rv)) {
+ returned_rv = rv;
+ break; // fall thru to mListening restore code below.
+ }
+ listener->Observe(message);
+ }
+
+ {
+ nsAutoLock lock(mLock);
+ mListening = PR_FALSE;
+ }
+
+ return returned_rv;
+}
+
+NS_IMETHODIMP
+nsConsoleService::LogStringMessage(const PRUnichar *message)
+{
+ nsConsoleMessage *msg = new nsConsoleMessage(message);
+ return this->LogMessage(msg);
+}
+
+NS_IMETHODIMP
+nsConsoleService::GetMessageArray(nsIConsoleMessage ***messages, PRUint32 *count)
+{
+ nsIConsoleMessage **messageArray;
+
+ /*
+ * Lock the whole method, as we don't want anyone mucking with mCurrent or
+ * mFull while we're copying out the buffer.
+ */
+ nsAutoLock lock(mLock);
+
+ if (mCurrent == 0 && !mFull) {
+ /*
+ * Make a 1-length output array so that nobody gets confused,
+ * and return a count of 0. This should result in a 0-length
+ * array object when called from script.
+ */
+ messageArray = (nsIConsoleMessage **)
+ nsMemory::Alloc(sizeof (nsIConsoleMessage *));
+ *messageArray = nsnull;
+ *messages = messageArray;
+ *count = 0;
+
+ return NS_OK;
+ }
+
+ PRUint32 resultSize = mFull ? mBufferSize : mCurrent;
+ messageArray =
+ (nsIConsoleMessage **)nsMemory::Alloc((sizeof (nsIConsoleMessage *))
+ * resultSize);
+
+ if (messageArray == nsnull) {
+ *messages = nsnull;
+ *count = 0;
+ return NS_ERROR_FAILURE;
+ }
+
+ PRUint32 i;
+ if (mFull) {
+ for (i = 0; i < mBufferSize; i++) {
+ // if full, fill the buffer starting from mCurrent (which'll be
+ // oldest) wrapping around the buffer to the most recent.
+ messageArray[i] = mMessages[(mCurrent + i) % mBufferSize];
+ NS_ADDREF(messageArray[i]);
+ }
+ } else {
+ for (i = 0; i < mCurrent; i++) {
+ messageArray[i] = mMessages[i];
+ NS_ADDREF(messageArray[i]);
+ }
+ }
+ *count = resultSize;
+ *messages = messageArray;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsConsoleService::RegisterListener(nsIConsoleListener *listener) {
+ nsresult rv;
+
+ /*
+ * Store a threadsafe proxy to the listener rather than the
+ * listener itself; we want the console service to be callable
+ * from any thread, but listeners can be implemented in
+ * thread-specific ways, and we always want to call them on their
+ * originating thread. JavaScript is the motivating example.
+ */
+ nsCOMPtr<nsIConsoleListener> proxiedListener;
+
+ rv = GetProxyForListener(listener, getter_AddRefs(proxiedListener));
+ if (NS_FAILED(rv))
+ return rv;
+
+ {
+ nsAutoLock lock(mLock);
+ nsISupportsKey key(listener);
+
+ /*
+ * Put the proxy event listener into a hashtable using the *real*
+ * listener as the key.
+ *
+ * This is necessary because proxy objects do *not* maintain
+ * nsISupports identity. Therefore, since GetProxyForListener(...)
+ * can return different proxies for the same object (see bug #85831)
+ * we need to use the real object as the unique key...
+ */
+ mListeners.Put(&key, proxiedListener);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsConsoleService::UnregisterListener(nsIConsoleListener *listener) {
+ nsAutoLock lock(mLock);
+
+ nsISupportsKey key(listener);
+ mListeners.Remove(&key);
+ return NS_OK;
+}
+
+nsresult
+nsConsoleService::GetProxyForListener(nsIConsoleListener* aListener,
+ nsIConsoleListener** aProxy)
+{
+ nsresult rv;
+ *aProxy = nsnull;
+
+ nsCOMPtr<nsIProxyObjectManager> proxyManager =
+ (do_GetService(NS_XPCOMPROXY_CONTRACTID));
+
+ if (proxyManager == nsnull)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ /*
+ * NOTE this will fail if the calling thread doesn't have an eventQ.
+ *
+ * Would it be better to catch that case and leave the listener unproxied?
+ */
+ rv = proxyManager->GetProxyForObject(NS_CURRENT_EVENTQ,
+ NS_GET_IID(nsIConsoleListener),
+ aListener,
+ PROXY_ASYNC | PROXY_ALWAYS,
+ (void**) aProxy);
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/base/nsConsoleService.h b/src/libs/xpcom18a4/xpcom/base/nsConsoleService.h
new file mode 100644
index 00000000..59758f84
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsConsoleService.h
@@ -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 ***** */
+
+/*
+ * nsConsoleService class declaration.
+ */
+
+#ifndef __nsconsoleservice_h__
+#define __nsconsoleservice_h__
+
+#include "nsCOMPtr.h"
+#include "nsHashtable.h"
+#include "nsAutoLock.h"
+
+#include "nsIConsoleService.h"
+
+class nsConsoleService : public nsIConsoleService
+{
+public:
+ nsConsoleService();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSICONSOLESERVICE
+
+private:
+ ~nsConsoleService();
+
+ // build (or find) a proxy for the listener
+ nsresult GetProxyForListener(nsIConsoleListener* aListener,
+ nsIConsoleListener** aProxy);
+
+ // Circular buffer of saved messages
+ nsIConsoleMessage **mMessages;
+
+ // How big?
+ PRUint32 mBufferSize;
+
+ // Index of slot in mMessages that'll be filled by *next* log message
+ PRUint32 mCurrent;
+
+ // Is the buffer full? (Has mCurrent wrapped around at least once?)
+ PRBool mFull;
+
+ // Listeners to notify whenever a new message is logged.
+ nsSupportsHashtable mListeners;
+
+ // Current listener being notified of a logged error - to prevent
+ // stack overflows.
+ PRBool mListening;
+
+ // To serialize interesting methods.
+ PRLock *mLock;
+};
+
+#endif /* __nsconsoleservice_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/base/nsDebugImpl.cpp b/src/libs/xpcom18a4/xpcom/base/nsDebugImpl.cpp
new file mode 100644
index 00000000..f8806092
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsDebugImpl.cpp
@@ -0,0 +1,477 @@
+/* -*- 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):
+ * IBM Corp.
+ * Henry Sobotka
+ *
+ * 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 "nsXPCOMPrivate.h"
+#include "nsDebugImpl.h"
+#include "nsDebug.h"
+#include "prprf.h"
+#include "prlog.h"
+#include "prinit.h"
+#include "plstr.h"
+#include "nsError.h"
+#include "prerror.h"
+#include "prerr.h"
+
+#if defined(XP_BEOS)
+/* For DEBUGGER macros */
+#include <Debug.h>
+#endif
+
+#if defined(XP_UNIX) || defined(_WIN32) || defined(XP_OS2) || defined(XP_BEOS)
+/* for abort() and getenv() */
+#include <stdlib.h>
+#endif
+
+#if defined(XP_UNIX) && !defined(UNIX_CRASH_ON_ASSERT)
+#include <signal.h>
+/* for nsTraceRefcnt::WalkTheStack() */
+#include "nsISupportsUtils.h"
+#include "nsTraceRefcntImpl.h"
+
+#if defined(__GNUC__) && defined(__i386)
+# define DebugBreak() { asm("int $3"); }
+#elif defined(__APPLE__) && defined(TARGET_CARBON)
+# include "MacTypes.h"
+# define DebugBreak() { Debugger(); }
+#else
+# define DebugBreak()
+#endif
+#endif
+
+#if defined(XP_OS2)
+ /* Added definitions for DebugBreak() for 2 different OS/2 compilers. Doing
+ * the int3 on purpose so that a developer can step over the
+ * instruction if so desired. Not always possible if trapping due to exception
+ * handling IBM-AKR
+ */
+ #define INCL_WINDIALOGS // need for WinMessageBox
+ #include <os2.h>
+ #include <string.h>
+
+ #if defined(DEBUG)
+ #define DebugBreak() { asm("int $3"); }
+ #else
+ #define DebugBreak()
+ #endif /* DEBUG */
+#endif /* XP_OS2 */
+
+#if defined(_WIN32)
+#include <windows.h>
+#include <signal.h>
+#elif defined(XP_MAC)
+ #define TEMP_MAC_HACK
+
+ //------------------------
+ #ifdef TEMP_MAC_HACK
+ #include <MacTypes.h>
+ #include <Processes.h>
+ #include <string.h>
+
+ // TEMPORARY UNTIL WE HAVE MACINTOSH ENVIRONMENT VARIABLES THAT CAN TURN ON
+ // LOGGING ON MACINTOSH
+ // At this moment, NSPR's logging is a no-op on Macintosh.
+
+ #include <stdarg.h>
+ #include <stdio.h>
+
+ #undef PR_LOG
+ #undef PR_LogFlush
+ #define PR_LOG(module,level,args) dprintf args
+ #define PR_LogFlush()
+ static void dprintf(const char *format, ...)
+ {
+ va_list ap;
+ Str255 buffer;
+
+ va_start(ap, format);
+ buffer[0] = std::vsnprintf((char *)buffer + 1, sizeof(buffer) - 1, format, ap);
+ va_end(ap);
+ if (PL_strcasestr((char *)&buffer[1], "warning"))
+ printf("¥¥¥%s\n", (char*)buffer + 1);
+ else
+ DebugStr(buffer);
+ }
+ #endif // TEMP_MAC_HACK
+ //------------------------
+#elif defined(XP_UNIX)
+#include<stdlib.h>
+#endif
+
+/*
+ * Determine if debugger is present in windows.
+ */
+#if defined (_WIN32)
+
+typedef WINBASEAPI BOOL (WINAPI* LPFNISDEBUGGERPRESENT)();
+PRBool InDebugger()
+{
+ PRBool fReturn = PR_FALSE;
+ LPFNISDEBUGGERPRESENT lpfnIsDebuggerPresent = NULL;
+ HINSTANCE hKernel = LoadLibrary("Kernel32.dll");
+
+ if(hKernel)
+ {
+ lpfnIsDebuggerPresent =
+ (LPFNISDEBUGGERPRESENT)GetProcAddress(hKernel, "IsDebuggerPresent");
+ if(lpfnIsDebuggerPresent)
+ {
+ fReturn = (*lpfnIsDebuggerPresent)();
+ }
+ FreeLibrary(hKernel);
+ }
+
+ return fReturn;
+}
+
+#endif /* WIN32*/
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsDebugImpl, nsIDebug)
+
+nsDebugImpl::nsDebugImpl()
+{
+}
+
+/**
+ * Implementation of the nsDebug methods. Note that this code is
+ * always compiled in, in case some other module that uses it is
+ * compiled with debugging even if this library is not.
+ */
+static PRLogModuleInfo* gDebugLog;
+
+static void InitLog(void)
+{
+ if (0 == gDebugLog) {
+ gDebugLog = PR_NewLogModule("nsDebug");
+ gDebugLog->level = PR_LOG_DEBUG;
+ }
+}
+
+
+
+NS_IMETHODIMP
+nsDebugImpl::Assertion(const char *aStr, const char *aExpr, const char *aFile, PRInt32 aLine)
+{
+ InitLog();
+
+ char buf[1000];
+ PR_snprintf(buf, sizeof(buf),
+ "###!!! ASSERTION: %s: '%s', file %s, line %d",
+ aStr, aExpr, aFile, aLine);
+
+ // Write out the assertion message to the debug log
+ PR_LOG(gDebugLog, PR_LOG_ERROR, ("%s", buf));
+ PR_LogFlush();
+
+ // And write it out to the stderr
+ fprintf(stderr, "%s\n", buf);
+ fflush(stderr);
+
+#if defined(_WIN32)
+ char* assertBehavior = getenv("XPCOM_DEBUG_BREAK");
+ if (assertBehavior && strcmp(assertBehavior, "warn") == 0)
+ return NS_OK;
+
+ if(!InDebugger())
+ {
+ DWORD code = IDRETRY;
+
+ /* Create the debug dialog out of process to avoid the crashes caused by
+ * Windows events leaking into our event loop from an in process dialog.
+ * We do this by launching windbgdlg.exe (built in xpcom/windbgdlg).
+ * See http://bugzilla.mozilla.org/show_bug.cgi?id=54792
+ */
+ PROCESS_INFORMATION pi;
+ STARTUPINFO si;
+ char executable[MAX_PATH];
+ char* pName;
+
+ memset(&pi, 0, sizeof(pi));
+
+ memset(&si, 0, sizeof(si));
+ si.cb = sizeof(si);
+ si.wShowWindow = SW_SHOW;
+
+ if(GetModuleFileName(GetModuleHandle(XPCOM_DLL), executable, MAX_PATH) &&
+ NULL != (pName = strrchr(executable, '\\')) &&
+ NULL != strcpy(pName+1, "windbgdlg.exe") &&
+#ifdef DEBUG_jband
+ (printf("Launching %s\n", executable), PR_TRUE) &&
+#endif
+ CreateProcess(executable, buf, NULL, NULL, PR_FALSE,
+ DETACHED_PROCESS | NORMAL_PRIORITY_CLASS,
+ NULL, NULL, &si, &pi) &&
+ WAIT_OBJECT_0 == WaitForSingleObject(pi.hProcess, INFINITE) &&
+ GetExitCodeProcess(pi.hProcess, &code))
+ {
+ CloseHandle(pi.hProcess);
+ }
+
+ switch(code)
+ {
+ case IDABORT:
+ //This should exit us
+ raise(SIGABRT);
+ //If we are ignored exit this way..
+ _exit(3);
+ break;
+
+ case IDIGNORE:
+ return NS_OK;
+ // Fall Through
+ }
+ }
+#endif
+
+#if defined(XP_OS2)
+ char* assertBehavior = getenv("XPCOM_DEBUG_BREAK");
+ if (assertBehavior && strcmp(assertBehavior, "warn") == 0)
+ return NS_OK;
+
+ char msg[1200];
+ PR_snprintf(msg, sizeof(msg),
+ "%s\n\nClick Cancel to Debug Application.\n"
+ "Click Enter to continue running the Application.", buf);
+ ULONG code = MBID_ERROR;
+ code = WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, msg,
+ "nsDebug::Assertion", 0,
+ MB_ERROR | MB_ENTERCANCEL);
+
+ /* It is possible that we are executing on a thread that doesn't have a
+ * message queue. In that case, the message won't appear, and code will
+ * be 0xFFFF. We'll give the user a chance to debug it by calling
+ * Break()
+ * Actually, that's a really bad idea since this happens a lot with threadsafe
+ * assertions and since it means that you can't actually run the debug build
+ * outside a debugger without it crashing constantly.
+ */
+ if(( code == MBID_ENTER ) || (code == MBID_ERROR))
+ {
+ return NS_OK;
+ // If Retry, Fall Through
+ }
+#endif
+
+ Break(aFile, aLine);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDebugImpl::Break(const char *aFile, PRInt32 aLine)
+{
+#ifndef TEMP_MAC_HACK
+ // Write out the assertion message to the debug log
+ InitLog();
+
+ PR_LOG(gDebugLog, PR_LOG_ERROR,
+ ("###!!! Break: at file %s, line %d", aFile, aLine));
+ PR_LogFlush();
+
+ fprintf(stderr, "Break: at file %s, line %d\n",aFile, aLine); fflush(stderr);
+ fflush(stderr);
+
+#if defined(_WIN32)
+#ifdef _M_IX86
+ ::DebugBreak();
+#endif
+#elif defined(XP_UNIX) && !defined(UNIX_CRASH_ON_ASSERT)
+ fprintf(stderr, "\07");
+
+ char *assertBehavior = getenv("XPCOM_DEBUG_BREAK");
+
+ if (!assertBehavior) {
+
+ // the default; nothing else to do
+ ;
+
+ } else if ( strcmp(assertBehavior, "suspend")== 0 ) {
+
+ // the suspend case is first because we wanna send the signal before
+ // other threads have had a chance to get too far from the state that
+ // caused this assertion (in case they happen to have been involved).
+ //
+ fprintf(stderr, "Suspending process; attach with the debugger.\n");
+ kill(0, SIGSTOP);
+
+ } else if ( strcmp(assertBehavior, "warn")==0 ) {
+
+ // same as default; nothing else to do (see "suspend" case comment for
+ // why this compare isn't done as part of the default case)
+ //
+ ;
+
+ }
+ else if ( strcmp(assertBehavior,"stack")==0 ) {
+
+ // walk the stack
+ //
+ nsTraceRefcntImpl::WalkTheStack(stderr);
+ }
+ else if ( strcmp(assertBehavior,"abort")==0 ) {
+
+ // same as UNIX_CRASH_ON_ASSERT
+ //
+ Abort(aFile, aLine);
+
+ } else if ( strcmp(assertBehavior,"trap")==0 ) {
+
+ DebugBreak();
+
+ } else {
+
+ fprintf(stderr, "unrecognized value of XPCOM_DEBUG_BREAK env var!\n");
+
+ }
+ fflush(stderr); // this shouldn't really be necessary, i don't think,
+ // but maybe there's some lame stdio that buffers stderr
+
+#elif defined(XP_BEOS)
+ {
+#ifdef UNIX_CRASH_ON_ASSERT
+ char buf[2000];
+ sprintf(buf, "Break: at file %s, line %d", aFile, aLine);
+ DEBUGGER(buf);
+#endif
+ }
+#else
+ Abort(aFile, aLine);
+#endif
+#endif // TEMP_MAC_HACK
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDebugImpl::Abort(const char *aFile, PRInt32 aLine)
+{
+ InitLog();
+
+ PR_LOG(gDebugLog, PR_LOG_ERROR,
+ ("###!!! Abort: at file %s, line %d", aFile, aLine));
+ PR_LogFlush();
+ fprintf(stderr, "\07 Abort\n"); fflush(stderr);
+ fflush(stderr);
+
+#if defined(_WIN32)
+#ifdef _M_IX86
+ long* __p = (long*) 0x7;
+ *__p = 0x7;
+#else /* _M_ALPHA */
+ PR_Abort();
+#endif
+#elif defined(XP_MAC)
+ ExitToShell();
+#elif defined(XP_UNIX)
+ PR_Abort();
+#elif defined(XP_OS2)
+ DebugBreak();
+ return NS_OK;
+#elif defined(XP_BEOS)
+ {
+#ifndef DEBUG_cls
+ char buf[2000];
+ sprintf(buf, "Abort: at file %s, line %d", aFile, aLine);
+ DEBUGGER(buf);
+#endif
+ }
+#endif
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDebugImpl::Warning(const char* aMessage,
+ const char* aFile, PRIntn aLine)
+{
+ InitLog();
+
+ char buf[1000];
+ PR_snprintf(buf, sizeof(buf),
+ "WARNING: %s, file %s, line %d",
+ aMessage, aFile, aLine);
+
+ // Write out the warning message to the debug log
+ PR_LOG(gDebugLog, PR_LOG_ERROR, ("%s", buf));
+
+ // And write it out to the stdout
+ fprintf(stderr, "%s\n", buf);
+ fflush(stderr);
+ return NS_OK;
+}
+
+NS_METHOD
+nsDebugImpl::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
+{
+ *aInstancePtr = nsnull;
+ nsIDebug* debug = new nsDebugImpl();
+ if (!debug)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = debug->QueryInterface(aIID, aInstancePtr);
+ if (NS_FAILED(rv)) {
+ delete debug;
+ }
+
+ return rv;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+NS_COM nsresult
+NS_ErrorAccordingToNSPR()
+{
+ PRErrorCode err = PR_GetError();
+ switch (err) {
+ case PR_OUT_OF_MEMORY_ERROR: return NS_ERROR_OUT_OF_MEMORY;
+ case PR_WOULD_BLOCK_ERROR: return NS_BASE_STREAM_WOULD_BLOCK;
+ case PR_FILE_NOT_FOUND_ERROR: return NS_ERROR_FILE_NOT_FOUND;
+ case PR_READ_ONLY_FILESYSTEM_ERROR: return NS_ERROR_FILE_READ_ONLY;
+ case PR_NOT_DIRECTORY_ERROR: return NS_ERROR_FILE_NOT_DIRECTORY;
+ case PR_IS_DIRECTORY_ERROR: return NS_ERROR_FILE_IS_DIRECTORY;
+ case PR_LOOP_ERROR: return NS_ERROR_FILE_UNRESOLVABLE_SYMLINK;
+ case PR_FILE_EXISTS_ERROR: return NS_ERROR_FILE_ALREADY_EXISTS;
+ case PR_FILE_IS_LOCKED_ERROR: return NS_ERROR_FILE_IS_LOCKED;
+ case PR_FILE_TOO_BIG_ERROR: return NS_ERROR_FILE_TOO_BIG;
+ case PR_NO_DEVICE_SPACE_ERROR: return NS_ERROR_FILE_NO_DEVICE_SPACE;
+ case PR_NAME_TOO_LONG_ERROR: return NS_ERROR_FILE_NAME_TOO_LONG;
+ case PR_DIRECTORY_NOT_EMPTY_ERROR: return NS_ERROR_FILE_DIR_NOT_EMPTY;
+ case PR_NO_ACCESS_RIGHTS_ERROR: return NS_ERROR_FILE_ACCESS_DENIED;
+ default: return NS_ERROR_FAILURE;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsDebugImpl.h b/src/libs/xpcom18a4/xpcom/base/nsDebugImpl.h
new file mode 100644
index 00000000..b6ca9770
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsDebugImpl.h
@@ -0,0 +1,61 @@
+/* ***** 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
+ *
+ * The Initial Developer of the Original Code is Doug Turner <dougt@meer.net>
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * 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 "nsIDebug.h"
+
+class nsDebugImpl : public nsIDebug
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIDEBUG
+
+ nsDebugImpl();
+ static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+private:
+ ~nsDebugImpl() {}
+};
+
+
+#define NS_DEBUG_CONTRACTID "@mozilla.org/xpcom/debug;1"
+#define NS_DEBUG_CLASSNAME "nsDebug Interface"
+#define NS_DEBUG_CID \
+{ /* a80b1fb3-aaf6-4852-b678-c27eb7a518af */ \
+ 0xa80b1fb3, \
+ 0xaaf6, \
+ 0x4852, \
+ {0xb6, 0x78, 0xc2, 0x7e, 0xb7, 0xa5, 0x18, 0xaf} \
+}
diff --git a/src/libs/xpcom18a4/xpcom/base/nsError.h b/src/libs/xpcom18a4/xpcom/base/nsError.h
new file mode 100644
index 00000000..e0f3fe54
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsError.h
@@ -0,0 +1,317 @@
+/* -*- 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 nsError_h__
+#define nsError_h__
+
+#ifndef nscore_h___
+#include "nscore.h" /* needed for nsresult */
+#endif
+
+/*
+ * To add error code to your module, you need to do the following:
+ *
+ * 1) Add a module offset code. Add yours to the bottom of the list
+ * right below this comment, adding 1.
+ *
+ * 2) In your module, define a header file which uses one of the
+ * NE_ERROR_GENERATExxxxxx macros. Some examples below:
+ *
+ * #define NS_ERROR_MYMODULE_MYERROR1 NS_ERROR_GENERATE(NS_ERROR_SEVERITY_ERROR,NS_ERROR_MODULE_MYMODULE,1)
+ * #define NS_ERROR_MYMODULE_MYERROR2 NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_MYMODULE,2)
+ * #define NS_ERROR_MYMODULE_MYERROR3 NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_MYMODULE,3)
+ *
+ */
+
+
+/**
+ * @name Standard Module Offset Code. Each Module should identify a unique number
+ * and then all errors associated with that module become offsets from the
+ * base associated with that module id. There are 16 bits of code bits for
+ * each module.
+ */
+
+#define NS_ERROR_MODULE_XPCOM 1
+#define NS_ERROR_MODULE_BASE 2
+#define NS_ERROR_MODULE_GFX 3
+#define NS_ERROR_MODULE_WIDGET 4
+#define NS_ERROR_MODULE_CALENDAR 5
+#define NS_ERROR_MODULE_NETWORK 6
+#define NS_ERROR_MODULE_PLUGINS 7
+#define NS_ERROR_MODULE_LAYOUT 8
+#define NS_ERROR_MODULE_HTMLPARSER 9
+#define NS_ERROR_MODULE_RDF 10
+#define NS_ERROR_MODULE_UCONV 11
+#define NS_ERROR_MODULE_REG 12
+#define NS_ERROR_MODULE_FILES 13
+#define NS_ERROR_MODULE_DOM 14
+#define NS_ERROR_MODULE_IMGLIB 15
+#define NS_ERROR_MODULE_MAILNEWS 16
+#define NS_ERROR_MODULE_EDITOR 17
+#define NS_ERROR_MODULE_XPCONNECT 18
+#define NS_ERROR_MODULE_PROFILE 19
+#define NS_ERROR_MODULE_LDAP 20
+#define NS_ERROR_MODULE_SECURITY 21
+#define NS_ERROR_MODULE_DOM_XPATH 22
+#define NS_ERROR_MODULE_DOM_RANGE 23
+#define NS_ERROR_MODULE_URILOADER 24
+#define NS_ERROR_MODULE_CONTENT 25
+#define NS_ERROR_MODULE_PYXPCOM 26
+#define NS_ERROR_MODULE_XSLT 27
+#define NS_ERROR_MODULE_IPC 28
+#define NS_ERROR_MODULE_SVG 29
+
+/* NS_ERROR_MODULE_GENERAL should be used by modules that do not
+ * care if return code values overlap. Callers of methods that
+ * return such codes should be aware that they are not
+ * globally unique. Implementors should be careful about blindly
+ * returning codes from other modules that might also use
+ * the generic base.
+ */
+#define NS_ERROR_MODULE_GENERAL 51
+
+/**
+ * @name Standard Error Handling Macros
+ */
+
+#define NS_FAILED(_nsresult) (NS_UNLIKELY((_nsresult) & 0x80000000))
+#define NS_SUCCEEDED(_nsresult) (NS_LIKELY(!((_nsresult) & 0x80000000)))
+
+/**
+ * @name Severity Code. This flag identifies the level of warning
+ */
+
+#define NS_ERROR_SEVERITY_SUCCESS 0
+#define NS_ERROR_SEVERITY_ERROR 1
+
+/**
+ * @name Mozilla Code. This flag separates consumers of mozilla code
+ * from the native platform
+ */
+
+#define NS_ERROR_MODULE_BASE_OFFSET 0x45
+
+/**
+ * @name Standard Error Generating Macros
+ */
+
+#define NS_ERROR_GENERATE(sev,module,code) \
+ ((nsresult) (((PRUint32)(sev)<<31) | ((PRUint32)(module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | ((PRUint32)(code))) )
+
+#define NS_ERROR_GENERATE_SUCCESS(module,code) \
+ ((nsresult) (((PRUint32)(NS_ERROR_SEVERITY_SUCCESS)<<31) | ((PRUint32)(module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | ((PRUint32)(code))) )
+
+#define NS_ERROR_GENERATE_FAILURE(module,code) \
+ ((nsresult) (((PRUint32)(NS_ERROR_SEVERITY_ERROR)<<31) | ((PRUint32)(module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | ((PRUint32)(code))) )
+
+/**
+ * @name Standard Macros for retrieving error bits
+ */
+
+#define NS_ERROR_GET_CODE(err) ((err) & 0xffff)
+#define NS_ERROR_GET_MODULE(err) (((((err) >> 16) - NS_ERROR_MODULE_BASE_OFFSET) & 0x1fff))
+#define NS_ERROR_GET_SEVERITY(err) (((err) >> 31) & 0x1)
+
+/**
+ * @name Standard return values
+ */
+
+/*@{*/
+
+/* Standard "it worked" return value */
+#define NS_OK 0
+
+#define NS_ERROR_BASE ((nsresult) 0xC1F30000)
+
+/* Returned when an instance is not initialized */
+#define NS_ERROR_NOT_INITIALIZED (NS_ERROR_BASE + 1)
+
+/* Returned when an instance is already initialized */
+#define NS_ERROR_ALREADY_INITIALIZED (NS_ERROR_BASE + 2)
+
+/* Returned by a not implemented function */
+#define NS_ERROR_NOT_IMPLEMENTED ((nsresult) 0x80004001L)
+
+/* Returned when a given interface is not supported. */
+#define NS_NOINTERFACE ((nsresult) 0x80004002L)
+#define NS_ERROR_NO_INTERFACE NS_NOINTERFACE
+
+#define NS_ERROR_INVALID_POINTER ((nsresult) 0x80004003L)
+#define NS_ERROR_NULL_POINTER NS_ERROR_INVALID_POINTER
+
+/* Returned when a function aborts */
+#define NS_ERROR_ABORT ((nsresult) 0x80004004L)
+
+/* Returned when a function fails */
+#define NS_ERROR_FAILURE ((nsresult) 0x80004005L)
+
+/* Returned when an IPC fails */
+#define NS_ERROR_CALL_FAILED ((nsresult) 0x800706beL)
+
+/* Returned when an unexpected error occurs */
+#define NS_ERROR_UNEXPECTED ((nsresult) 0x8000ffffL)
+
+/* Returned when a memory allocation fails */
+#define NS_ERROR_OUT_OF_MEMORY ((nsresult) 0x8007000eL)
+
+/* Returned when an illegal value is passed */
+#define NS_ERROR_ILLEGAL_VALUE ((nsresult) 0x80070057L)
+#define NS_ERROR_INVALID_ARG NS_ERROR_ILLEGAL_VALUE
+
+/* Returned when a class doesn't allow aggregation */
+#define NS_ERROR_NO_AGGREGATION ((nsresult) 0x80040110L)
+
+/* Returned when an operation can't complete due to an unavailable resource */
+#define NS_ERROR_NOT_AVAILABLE ((nsresult) 0x80040111L)
+
+/* Returned when a class is not registered */
+#define NS_ERROR_FACTORY_NOT_REGISTERED ((nsresult) 0x80040154L)
+
+/* Returned when a class cannot be registered, but may be tried again later */
+#define NS_ERROR_FACTORY_REGISTER_AGAIN ((nsresult) 0x80040155L)
+
+/* Returned when a dynamically loaded factory couldn't be found */
+#define NS_ERROR_FACTORY_NOT_LOADED ((nsresult) 0x800401f8L)
+
+/* Returned when a factory doesn't support signatures */
+#define NS_ERROR_FACTORY_NO_SIGNATURE_SUPPORT \
+ (NS_ERROR_BASE + 0x101)
+
+/* Returned when a factory already is registered */
+#define NS_ERROR_FACTORY_EXISTS (NS_ERROR_BASE + 0x100)
+
+/* Socket failures */
+#define NS_ERROR_SOCKET_FAIL (NS_ERROR_BASE + 0x200)
+
+
+/* For COM compatibility reasons, we want to use exact error code numbers
+ for NS_ERROR_PROXY_INVALID_IN_PARAMETER and NS_ERROR_PROXY_INVALID_OUT_PARAMETER.
+ The first matches:
+
+ #define RPC_E_INVALID_PARAMETER _HRESULT_TYPEDEF_(0x80010010L)
+
+ Errors returning this mean that the xpcom proxy code could not create a proxy for
+ one of the in paramaters.
+
+ Because of this, we are ignoring the convention if using a base and offset for
+ error numbers.
+
+*/
+
+/* Returned when a proxy could not be create a proxy for one of the IN parameters
+ This is returned only when the "real" meathod has NOT been invoked.
+*/
+
+#define NS_ERROR_PROXY_INVALID_IN_PARAMETER ((nsresult) 0x80010010L)
+
+/* Returned when a proxy could not be create a proxy for one of the OUT parameters
+ This is returned only when the "real" meathod has ALREADY been invoked.
+*/
+
+#define NS_ERROR_PROXY_INVALID_OUT_PARAMETER ((nsresult) 0x80010011L)
+
+
+/*@}*/
+
+ /* I/O Errors */
+
+ /* Stream closed */
+#define NS_BASE_STREAM_CLOSED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 2)
+ /* Error from the operating system */
+#define NS_BASE_STREAM_OSERROR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 3)
+ /* Illegal arguments */
+#define NS_BASE_STREAM_ILLEGAL_ARGS NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 4)
+ /* For unichar streams */
+#define NS_BASE_STREAM_NO_CONVERTER NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 5)
+ /* For unichar streams */
+#define NS_BASE_STREAM_BAD_CONVERSION NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 6)
+
+#define NS_BASE_STREAM_WOULD_BLOCK NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 7)
+
+
+#define NS_ERROR_FILE_UNRECOGNIZED_PATH NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 1)
+#define NS_ERROR_FILE_UNRESOLVABLE_SYMLINK NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 2)
+#define NS_ERROR_FILE_EXECUTION_FAILED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 3)
+#define NS_ERROR_FILE_UNKNOWN_TYPE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 4)
+#define NS_ERROR_FILE_DESTINATION_NOT_DIR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 5)
+#define NS_ERROR_FILE_TARGET_DOES_NOT_EXIST NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 6)
+#define NS_ERROR_FILE_COPY_OR_MOVE_FAILED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 7)
+#define NS_ERROR_FILE_ALREADY_EXISTS NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 8)
+#define NS_ERROR_FILE_INVALID_PATH NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 9)
+#define NS_ERROR_FILE_DISK_FULL NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 10)
+#define NS_ERROR_FILE_CORRUPTED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 11)
+#define NS_ERROR_FILE_NOT_DIRECTORY NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 12)
+#define NS_ERROR_FILE_IS_DIRECTORY NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 13)
+#define NS_ERROR_FILE_IS_LOCKED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 14)
+#define NS_ERROR_FILE_TOO_BIG NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 15)
+#define NS_ERROR_FILE_NO_DEVICE_SPACE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 16)
+#define NS_ERROR_FILE_NAME_TOO_LONG NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 17)
+#define NS_ERROR_FILE_NOT_FOUND NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 18)
+#define NS_ERROR_FILE_READ_ONLY NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 19)
+#define NS_ERROR_FILE_DIR_NOT_EMPTY NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 20)
+#define NS_ERROR_FILE_ACCESS_DENIED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 21)
+
+#define NS_SUCCESS_FILE_DIRECTORY_EMPTY NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_FILES, 1)
+
+ /* Result codes used by nsIVariant */
+
+#define NS_ERROR_CANNOT_CONVERT_DATA NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 1)
+#define NS_ERROR_OBJECT_IS_IMMUTABLE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 2)
+#define NS_ERROR_LOSS_OF_SIGNIFICANT_DATA NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 3)
+
+#define NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCOM, 1)
+
+
+ /*
+ * This will return the nsresult corresponding to the most recent NSPR failure
+ * returned by PR_GetError.
+ *
+ ***********************************************************************
+ * Do not depend on this function. It will be going away!
+ ***********************************************************************
+ */
+extern NS_COM nsresult
+NS_ErrorAccordingToNSPR();
+
+
+#ifdef _MSC_VER
+#pragma warning(disable: 4251) /* 'nsCOMPtr<class nsIInputStream>' needs to have dll-interface to be used by clients of class 'nsInputStream' */
+#pragma warning(disable: 4275) /* non dll-interface class 'nsISupports' used as base for dll-interface class 'nsIRDFNode' */
+#endif
+
+#endif
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsErrorService.cpp b/src/libs/xpcom18a4/xpcom/base/nsErrorService.cpp
new file mode 100644
index 00000000..f38495ed
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsErrorService.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):
+ *
+ * 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 "nsErrorService.h"
+#include "nsCRT.h"
+
+static void* PR_CALLBACK
+CloneCString(nsHashKey *aKey, void *aData, void* closure)
+{
+ return nsCRT::strdup((const char*)aData);
+}
+
+static PRBool PR_CALLBACK
+DeleteCString(nsHashKey *aKey, void *aData, void* closure)
+{
+ nsCRT::free((char*)aData);
+ return PR_TRUE;
+}
+
+nsInt2StrHashtable::nsInt2StrHashtable()
+ : mHashtable(CloneCString, nsnull, DeleteCString, nsnull, 16)
+{
+}
+
+nsresult
+nsInt2StrHashtable::Put(PRUint32 key, const char* aData)
+{
+ char* value = nsCRT::strdup(aData);
+ if (value == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ nsPRUint32Key k(key);
+ char* oldValue = (char*)mHashtable.Put(&k, value);
+ if (oldValue)
+ nsCRT::free(oldValue);
+ return NS_OK;
+}
+
+char*
+nsInt2StrHashtable::Get(PRUint32 key)
+{
+ nsPRUint32Key k(key);
+ const char* value = (const char*)mHashtable.Get(&k);
+ if (value == nsnull)
+ return nsnull;
+ return nsCRT::strdup(value);
+}
+
+nsresult
+nsInt2StrHashtable::Remove(PRUint32 key)
+{
+ nsPRUint32Key k(key);
+ char* oldValue = (char*)mHashtable.Remove(&k);
+ if (oldValue)
+ nsCRT::free(oldValue);
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+NS_IMPL_ISUPPORTS1(nsErrorService, nsIErrorService)
+
+NS_METHOD
+nsErrorService::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
+{
+ NS_ENSURE_NO_AGGREGATION(outer);
+ nsErrorService* serv = new nsErrorService();
+ if (serv == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(serv);
+ nsresult rv = serv->QueryInterface(aIID, aInstancePtr);
+ NS_RELEASE(serv);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsErrorService::RegisterErrorStringBundle(PRInt16 errorModule, const char *stringBundleURL)
+{
+ return mErrorStringBundleURLMap.Put(errorModule, stringBundleURL);
+}
+
+NS_IMETHODIMP
+nsErrorService::UnregisterErrorStringBundle(PRInt16 errorModule)
+{
+ return mErrorStringBundleURLMap.Remove(errorModule);
+}
+
+NS_IMETHODIMP
+nsErrorService::GetErrorStringBundle(PRInt16 errorModule, char **result)
+{
+ char* value = mErrorStringBundleURLMap.Get(errorModule);
+ if (value == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ *result = value;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsErrorService::RegisterErrorStringBundleKey(nsresult error, const char *stringBundleKey)
+{
+ return mErrorStringBundleKeyMap.Put(error, stringBundleKey);
+}
+
+NS_IMETHODIMP
+nsErrorService::UnregisterErrorStringBundleKey(nsresult error)
+{
+ return mErrorStringBundleKeyMap.Remove(error);
+}
+
+NS_IMETHODIMP
+nsErrorService::GetErrorStringBundleKey(nsresult error, char **result)
+{
+ char* value = mErrorStringBundleKeyMap.Get(error);
+ if (value == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ *result = value;
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libs/xpcom18a4/xpcom/base/nsErrorService.h b/src/libs/xpcom18a4/xpcom/base/nsErrorService.h
new file mode 100644
index 00000000..70a30c0e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsErrorService.h
@@ -0,0 +1,76 @@
+/* -*- 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 nsErrorService_h__
+#define nsErrorService_h__
+
+#include "nsIErrorService.h"
+#include "nsHashtable.h"
+
+class nsInt2StrHashtable
+{
+public:
+ nsInt2StrHashtable();
+
+ nsresult Put(PRUint32 key, const char* aData);
+ char* Get(PRUint32 key);
+ nsresult Remove(PRUint32 key);
+
+protected:
+ nsObjectHashtable mHashtable;
+};
+
+class nsErrorService : public nsIErrorService
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIERRORSERVICE
+
+ nsErrorService() {}
+
+ static NS_METHOD
+ Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+private:
+ ~nsErrorService() {}
+
+protected:
+ nsInt2StrHashtable mErrorStringBundleURLMap;
+ nsInt2StrHashtable mErrorStringBundleKeyMap;
+};
+
+#endif // nsErrorService_h__
diff --git a/src/libs/xpcom18a4/xpcom/base/nsExceptionService.cpp b/src/libs/xpcom18a4/xpcom/base/nsExceptionService.cpp
new file mode 100644
index 00000000..f68f2d5f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsExceptionService.cpp
@@ -0,0 +1,383 @@
+/* -*- 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
+ * ActiveState Tool Corp..
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <MarkH@ActiveState.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 "nsISupports.h"
+#include "nsExceptionService.h"
+#include "nsIServiceManager.h"
+#include "nsCOMPtr.h"
+#include "prthread.h"
+#include "prlock.h"
+static const PRUintn BAD_TLS_INDEX = (PRUintn) -1;
+
+#define CHECK_SERVICE_USE_OK() if (tlsIndex == BAD_TLS_INDEX) return NS_ERROR_NOT_INITIALIZED
+#define CHECK_MANAGER_USE_OK() if (!mService || nsExceptionService::tlsIndex == BAD_TLS_INDEX) return NS_ERROR_NOT_INITIALIZED
+
+// A key for our registered module providers hashtable
+class nsProviderKey : public nsHashKey {
+protected:
+ PRUint32 mKey;
+public:
+ nsProviderKey(PRUint32 key) : mKey(key) {}
+ PRUint32 HashCode(void) const {
+ return mKey;
+ }
+ PRBool Equals(const nsHashKey *aKey) const {
+ return mKey == ((const nsProviderKey *) aKey)->mKey;
+ }
+ nsHashKey *Clone() const {
+ return new nsProviderKey(mKey);
+ }
+ PRUint32 GetValue() { return mKey; }
+};
+
+/** Exception Manager definition **/
+class nsExceptionManager : public nsIExceptionManager
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIEXCEPTIONMANAGER
+
+ nsExceptionManager(nsExceptionService *svc);
+ /* additional members */
+ nsCOMPtr<nsIException> mCurrentException;
+ nsExceptionManager *mNextThread; // not ref-counted.
+ nsExceptionService *mService; // not ref-counted
+#ifdef NS_DEBUG
+ static PRInt32 totalInstances;
+#endif
+
+#ifdef NS_DEBUG
+ inline nsrefcnt ReleaseQuiet() {
+ // shut up NS_ASSERT_OWNINGTHREAD (see explanation below)
+ nsAutoOwningThread old = _mOwningThread;
+ _mOwningThread = nsAutoOwningThread();
+ nsrefcnt ref = Release();
+ NS_ASSERTION(ref == 0, "the object is still referenced by other threads while it shouldn't");
+ if (ref != 0)
+ _mOwningThread = old;
+ return ref;
+ }
+#else
+ inline nsrefcnt ReleaseQuiet(void) { return Release(); }
+#endif
+
+private:
+ ~nsExceptionManager();
+};
+
+
+#ifdef NS_DEBUG
+PRInt32 nsExceptionManager::totalInstances = 0;
+#endif
+
+// Note: the nsExceptionManager object is single threaded - the exception
+// service itself ensures one per thread. However, there are two methods that
+// may be called on foreign threads: DropAllThreads (called on the thread
+// shutting down xpcom) and ThreadDestruct (called after xpcom destroyed the
+// internal thread struct, so that PR_GetCurrentThread() will create a new one
+// from scratch which will obviously not match the old one stored in the
+// instance on creation). In both cases, there should be no other threads
+// holding objects (i.e. it's thread-safe to call them), but
+// NS_CheckThreadSafe() assertions will still happen and yell in the debug
+// build. Since it is quite annoying, we use a special ReleaseQuiet() method
+// in DoDropThread() to shut them up.
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsExceptionManager, nsIExceptionManager)
+
+nsExceptionManager::nsExceptionManager(nsExceptionService *svc) :
+ mNextThread(nsnull),
+ mService(svc)
+{
+ /* member initializers and constructor code */
+#ifdef NS_DEBUG
+ PR_AtomicIncrement(&totalInstances);
+#endif
+}
+
+nsExceptionManager::~nsExceptionManager()
+{
+ /* destructor code */
+#ifdef NS_DEBUG
+ PR_AtomicDecrement(&totalInstances);
+#endif // NS_DEBUG
+}
+
+/* void setCurrentException (in nsIException error); */
+NS_IMETHODIMP nsExceptionManager::SetCurrentException(nsIException *error)
+{
+ CHECK_MANAGER_USE_OK();
+ mCurrentException = error;
+ return NS_OK;
+}
+
+/* nsIException getCurrentException (); */
+NS_IMETHODIMP nsExceptionManager::GetCurrentException(nsIException **_retval)
+{
+ CHECK_MANAGER_USE_OK();
+ *_retval = mCurrentException;
+ NS_IF_ADDREF(*_retval);
+ return NS_OK;
+}
+
+/* nsIException getExceptionFromProvider( in nsresult rc, in nsIException defaultException); */
+NS_IMETHODIMP nsExceptionManager::GetExceptionFromProvider(nsresult rc, nsIException * defaultException, nsIException **_retval)
+{
+ CHECK_MANAGER_USE_OK();
+ // Just delegate back to the service with the provider map.
+ return mService->GetExceptionFromProvider(rc, defaultException, _retval);
+}
+
+/* The Exception Service */
+
+PRUintn nsExceptionService::tlsIndex = BAD_TLS_INDEX;
+PRLock *nsExceptionService::lock = nsnull;
+nsExceptionManager *nsExceptionService::firstThread = nsnull;
+
+#ifdef NS_DEBUG
+PRInt32 nsExceptionService::totalInstances = 0;
+#endif
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsExceptionService, nsIExceptionService, nsIObserver)
+
+nsExceptionService::nsExceptionService()
+ : mProviders(4, PR_TRUE) /* small, thread-safe hashtable */
+{
+#ifdef NS_DEBUG
+ if (PR_AtomicIncrement(&totalInstances)!=1) {
+ NS_ERROR("The nsExceptionService is a singleton!");
+ }
+#endif
+ /* member initializers and constructor code */
+ if (tlsIndex == BAD_TLS_INDEX) {
+ PRStatus status;
+ status = PR_NewThreadPrivateIndex( &tlsIndex, ThreadDestruct );
+ NS_WARN_IF_FALSE(status==0, "ScriptErrorService could not allocate TLS storage.");
+ }
+ lock = PR_NewLock();
+ NS_WARN_IF_FALSE(lock, "Error allocating ExceptionService lock");
+
+ // observe XPCOM shutdown.
+ nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1");
+ NS_WARN_IF_FALSE(observerService, "Could not get observer service!");
+ if (observerService)
+ observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
+}
+
+nsExceptionService::~nsExceptionService()
+{
+ Shutdown();
+ if (lock) {
+ PRLock *tmp = lock;
+ lock = nsnull;
+ PR_DestroyLock(tmp);
+ }
+ /* destructor code */
+#ifdef NS_DEBUG
+ PR_AtomicDecrement(&totalInstances);
+#endif
+}
+
+/*static*/
+void nsExceptionService::ThreadDestruct( void *data )
+{
+ if (!lock) {
+ NS_WARNING("nsExceptionService ignoring thread destruction after shutdown");
+ return;
+ }
+ DropThread( (nsExceptionManager *)data );
+}
+
+
+void nsExceptionService::Shutdown()
+{
+ PRUintn tmp = tlsIndex;
+ tlsIndex = BAD_TLS_INDEX;
+ PR_SetThreadPrivate(tmp, nsnull);
+ mProviders.Reset();
+ if (lock) {
+ DropAllThreads();
+ }
+}
+
+/* void setCurrentException (in nsIException error); */
+NS_IMETHODIMP nsExceptionService::SetCurrentException(nsIException *error)
+{
+ CHECK_SERVICE_USE_OK();
+ nsCOMPtr<nsIExceptionManager> sm;
+ nsresult nr = GetCurrentExceptionManager(getter_AddRefs(sm));
+ if (NS_FAILED(nr))
+ return nr;
+ return sm->SetCurrentException(error);
+}
+
+/* nsIException getCurrentException (); */
+NS_IMETHODIMP nsExceptionService::GetCurrentException(nsIException **_retval)
+{
+ CHECK_SERVICE_USE_OK();
+ nsCOMPtr<nsIExceptionManager> sm;
+ nsresult nr = GetCurrentExceptionManager(getter_AddRefs(sm));
+ if (NS_FAILED(nr))
+ return nr;
+ return sm->GetCurrentException(_retval);
+}
+
+/* nsIException getExceptionFromProvider( in nsresult rc, in nsIException defaultException); */
+NS_IMETHODIMP nsExceptionService::GetExceptionFromProvider(nsresult rc,
+ nsIException * defaultException, nsIException **_retval)
+{
+ CHECK_SERVICE_USE_OK();
+ return DoGetExceptionFromProvider(rc, defaultException, _retval);
+}
+
+/* readonly attribute nsIExceptionManager currentExceptionManager; */
+NS_IMETHODIMP nsExceptionService::GetCurrentExceptionManager(nsIExceptionManager * *aCurrentScriptManager)
+{
+ CHECK_SERVICE_USE_OK();
+ nsExceptionManager *mgr = (nsExceptionManager *)PR_GetThreadPrivate(tlsIndex);
+ if (mgr == nsnull) {
+ // Stick the new exception object in with no reference count.
+ mgr = new nsExceptionManager(this);
+ if (mgr == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ PR_SetThreadPrivate(tlsIndex, mgr);
+ // The reference count is held in the thread-list
+ AddThread(mgr);
+ }
+ *aCurrentScriptManager = mgr;
+ NS_ADDREF(*aCurrentScriptManager);
+ return NS_OK;
+}
+
+/* void registerErrorProvider (in nsIExceptionProvider provider, in PRUint32 moduleCode); */
+NS_IMETHODIMP nsExceptionService::RegisterExceptionProvider(nsIExceptionProvider *provider, PRUint32 errorModule)
+{
+ CHECK_SERVICE_USE_OK();
+
+ nsProviderKey key(errorModule);
+ if (mProviders.Put(&key, provider)) {
+ NS_WARNING("Registration of exception provider overwrote another provider with the same module code!");
+ }
+ return NS_OK;
+}
+
+/* void unregisterErrorProvider (in nsIExceptionProvider provider, in PRUint32 errorModule); */
+NS_IMETHODIMP nsExceptionService::UnregisterExceptionProvider(nsIExceptionProvider *provider, PRUint32 errorModule)
+{
+ CHECK_SERVICE_USE_OK();
+ nsProviderKey key(errorModule);
+ if (!mProviders.Remove(&key)) {
+ NS_WARNING("Attempt to unregister an unregistered exception provider!");
+ return NS_ERROR_UNEXPECTED;
+ }
+ return NS_OK;
+}
+
+// nsIObserver
+NS_IMETHODIMP nsExceptionService::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData)
+{
+ Shutdown();
+ return NS_OK;
+}
+
+nsresult
+nsExceptionService::DoGetExceptionFromProvider(nsresult errCode,
+ nsIException * defaultException,
+ nsIException **_exc)
+{
+ // Check for an existing exception
+ nsresult nr = GetCurrentException(_exc);
+ if (NS_SUCCEEDED(nr) && *_exc) {
+ (*_exc)->GetResult(&nr);
+ // If it matches our result then use it
+ if (nr == errCode)
+ return NS_OK;
+ NS_RELEASE(*_exc);
+ }
+ nsProviderKey key(NS_ERROR_GET_MODULE(errCode));
+ nsCOMPtr<nsIExceptionProvider> provider =
+ dont_AddRef((nsIExceptionProvider *)mProviders.Get(&key));
+
+ // No provider so we'll return the default exception
+ if (!provider) {
+ *_exc = defaultException;
+ NS_IF_ADDREF(*_exc);
+ return NS_OK;
+ }
+
+ return provider->GetException(errCode, defaultException, _exc);
+}
+
+// thread management
+/*static*/ void nsExceptionService::AddThread(nsExceptionManager *thread)
+{
+ PR_Lock(lock);
+ thread->mNextThread = firstThread;
+ firstThread = thread;
+ NS_ADDREF(thread);
+ PR_Unlock(lock);
+}
+
+/*static*/ void nsExceptionService::DoDropThread(nsExceptionManager *thread)
+{
+ nsExceptionManager **emp = &firstThread;
+ while (*emp != thread) {
+ if (!*emp)
+ {
+ NS_WARNING("Could not find the thread to drop!");
+ return;
+ }
+ emp = &(*emp)->mNextThread;
+ }
+ *emp = thread->mNextThread;
+ thread->ReleaseQuiet();
+ thread = nsnull;
+}
+
+/*static*/ void nsExceptionService::DropThread(nsExceptionManager *thread)
+{
+ PR_Lock(lock);
+ DoDropThread(thread);
+ PR_Unlock(lock);
+}
+
+/*static*/ void nsExceptionService::DropAllThreads()
+{
+ PR_Lock(lock);
+ while (firstThread)
+ DoDropThread(firstThread);
+ PR_Unlock(lock);
+}
diff --git a/src/libs/xpcom18a4/xpcom/base/nsExceptionService.h b/src/libs/xpcom18a4/xpcom/base/nsExceptionService.h
new file mode 100644
index 00000000..441a4c5b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsExceptionService.h
@@ -0,0 +1,94 @@
+/* -*- 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
+ * ActiveState Tool Corp..
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <MarkH@ActiveState.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 nsExceptionService_h__
+#define nsExceptionService_h__
+
+#include "nsVoidArray.h"
+#include "nsIException.h"
+#include "nsIExceptionService.h"
+#include "nsIObserverService.h"
+#include "nsHashtable.h"
+#include "nsIObserver.h"
+
+class nsExceptionManager;
+
+/** Exception Service definition **/
+class nsExceptionService : public nsIExceptionService, public nsIObserver
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIEXCEPTIONSERVICE
+ NS_DECL_NSIEXCEPTIONMANAGER
+ NS_DECL_NSIOBSERVER
+
+ nsExceptionService();
+
+ /* additional members */
+ nsresult DoGetExceptionFromProvider(nsresult errCode,
+ nsIException *defaultException,
+ nsIException **_richError);
+ void Shutdown();
+
+
+ /* thread management and cleanup */
+ static void AddThread(nsExceptionManager *);
+ static void DropThread(nsExceptionManager *);
+ static void DoDropThread(nsExceptionManager *thread);
+
+ static void DropAllThreads();
+ static nsExceptionManager *firstThread;
+
+ nsSupportsHashtable mProviders;
+
+ /* single lock protects both providers hashtable
+ and thread list */
+ static PRLock* lock;
+
+ static PRUintn tlsIndex;
+ static void PR_CALLBACK ThreadDestruct( void *data );
+#ifdef NS_DEBUG
+ static PRInt32 totalInstances;
+#endif
+
+private:
+ ~nsExceptionService();
+};
+
+
+#endif // nsExceptionService_h__
diff --git a/src/libs/xpcom18a4/xpcom/base/nsGarbageCollector.c b/src/libs/xpcom18a4/xpcom/base/nsGarbageCollector.c
new file mode 100644
index 00000000..b0447598
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsGarbageCollector.c
@@ -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 the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Patrick Beard <beard@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 ***** */
+
+/*
+ nsGarbageCollector.c
+ */
+
+#ifdef GC_LEAK_DETECTOR
+
+/* for FILE */
+#include <stdio.h>
+
+/* NSPR stuff */
+#include "generic_threads.h"
+#include "prthread.h"
+#include "prlock.h"
+
+/* Linux/Win32 export private NSPR files to include/private */
+#ifdef XP_MAC
+#include "pprthred.h"
+#else
+#include "private/pprthred.h"
+#endif
+
+#include "nsLeakDetector.h"
+
+extern FILE *GC_stdout, *GC_stderr;
+
+extern void GC_gcollect(void);
+extern void GC_clear_roots(void);
+
+static PRStatus PR_CALLBACK scanner(PRThread* t, void** baseAddr, PRUword count, void* closure)
+{
+ char* begin = (char*)baseAddr;
+ char* end = (char*)(baseAddr + count);
+ GC_mark_range_proc marker = (GC_mark_range_proc) closure;
+ marker(begin, end);
+ return PR_SUCCESS;
+}
+
+static void mark_all_stacks(GC_mark_range_proc marker)
+{
+ /* PR_ThreadScanStackPointers(PR_GetCurrentThread(), &scanner, marker); */
+ PR_ScanStackPointers(&scanner, (void *)marker);
+}
+
+static void locker(void* mutex)
+{
+ PR_Lock(mutex);
+}
+
+static void unlocker(void* mutex)
+{
+ PR_Unlock(mutex);
+}
+
+static void stopper(void* unused)
+{
+ PR_SuspendAll();
+}
+
+static void starter(void* unused)
+{
+ PR_ResumeAll();
+}
+
+nsresult NS_InitGarbageCollector()
+{
+ PRLock* mutex;
+
+ /* redirect GC's stderr to catch startup leaks. */
+ GC_stderr = fopen("StartupLeaks", "w");
+
+ mutex = PR_NewLock();
+ if (mutex == NULL)
+ return NS_ERROR_FAILURE;
+
+ GC_generic_init_threads(&mark_all_stacks, mutex,
+ &locker, &unlocker,
+ &stopper, &starter);
+
+ return NS_OK;
+}
+
+nsresult NS_ShutdownGarbageCollector()
+{
+ /* do anything you need to shut down the collector. */
+ return NS_OK;
+}
+
+#endif /* GC_LEAK_DETECTOR */
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIAllocator.h b/src/libs/xpcom18a4/xpcom/base/nsIAllocator.h
new file mode 100644
index 00000000..2195f42d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIAllocator.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):
+ *
+ * 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 ***** */
+
+/**
+ * XXX This file is obsolete. Use nsIMemory.idl or nsMemory.h instead.
+ */
+
+#ifndef nsIAllocator_h___
+#define nsIAllocator_h___
+
+#include "nsMemory.h"
+
+#define nsIAllocator nsIMemory
+#define nsAllocator nsMemory
+#define GetGlobalAllocator GetGlobalMemoryService
+
+#define NS_IALLOCATOR_IID NS_GET_IID(nsIMemory)
+#define NS_ALLOCATOR_CONTRACTID NS_MEMORY_CONTRACTID
+#define NS_ALLOCATOR_CLASSNAME NS_MEMORY_CLASSNAME
+#define NS_ALLOCATOR_CID NS_MEMORY_CID
+
+#endif /* nsIAllocator_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIConsoleListener.idl b/src/libs/xpcom18a4/xpcom/base/nsIConsoleListener.idl
new file mode 100644
index 00000000..f983132d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIConsoleListener.idl
@@ -0,0 +1,49 @@
+/* -*- 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 ***** */
+
+/*
+ * Used by the console service to notify listeners of new console messages.
+ */
+
+#include "nsISupports.idl"
+#include "nsIConsoleMessage.idl"
+
+[scriptable, uuid(eaaf61d6-1dd1-11b2-bc6e-8fc96480f20d)]
+interface nsIConsoleListener : nsISupports
+{
+ void observe(in nsIConsoleMessage aMessage);
+};
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIConsoleMessage.idl b/src/libs/xpcom18a4/xpcom/base/nsIConsoleMessage.idl
new file mode 100644
index 00000000..0662a2d2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIConsoleMessage.idl
@@ -0,0 +1,56 @@
+/* -*- 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 "nsISupports.idl"
+
+/**
+ * This is intended as a base interface; implementations may want to
+ * provide an object that can be qi'ed to provide more specific
+ * message information.
+ */
+[scriptable, uuid(41bd8784-1dd2-11b2-9553-8606958fffe1)]
+interface nsIConsoleMessage : nsISupports
+{
+ readonly attribute wstring message;
+};
+
+%{ C++
+#define NS_CONSOLEMESSAGE_CID \
+{ 0x56c9d666, 0x1dd2, 0x11b2, { 0xb4, 0x3c, 0xa8, 0x4b, 0xf3, 0xb3, 0xec, 0xbb }}
+
+#define NS_CONSOLEMESSAGE_CONTRACTID "@mozilla.org/consolemessage;1"
+%}
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIConsoleService.idl b/src/libs/xpcom18a4/xpcom/base/nsIConsoleService.idl
new file mode 100644
index 00000000..283c7acc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIConsoleService.idl
@@ -0,0 +1,85 @@
+/* -*- 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 "nsIConsoleListener.idl"
+#include "nsIConsoleMessage.idl"
+
+[scriptable, uuid(a647f184-1dd1-11b2-a9d1-8537b201161b)]
+interface nsIConsoleService : nsISupports
+{
+ void logMessage(in nsIConsoleMessage message);
+
+ /**
+ * Convenience method for logging simple messages.
+ */
+ void logStringMessage(in wstring message);
+
+ /**
+ * Get an array of all the messages logged so far. If no messages
+ * are logged, this function will return a count of 0, but still
+ * will allocate one word for messages, so as to show up as a
+ * 0-length array when called from script.
+ */
+ void getMessageArray([array, size_is(count)] out nsIConsoleMessage messages,
+ out PRUint32 count);
+
+ /**
+ * To guard against stack overflows from listeners that could log
+ * messages (it's easy to do this inadvertently from listeners
+ * implemented in JavaScript), we don't call any listeners when
+ * another error is already being logged.
+ */
+ void registerListener(in nsIConsoleListener listener);
+
+ /**
+ * Each registered listener should also be unregistered.
+ */
+ void unregisterListener(in nsIConsoleListener listener);
+
+};
+
+
+%{ C++
+#define NS_CONSOLESERVICE_CLASSNAME "Console Service"
+
+#define NS_CONSOLESERVICE_CID \
+{ 0x7e3ff85c, 0x1dd2, 0x11b2, { 0x8d, 0x4b, 0xeb, 0x45, 0x2c, 0xb0, 0xff, 0x40 }}
+
+#define NS_CONSOLESERVICE_CONTRACTID "@mozilla.org/consoleservice;1"
+%}
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsID.cpp b/src/libs/xpcom18a4/xpcom/base/nsID.cpp
new file mode 100644
index 00000000..adb0d41c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsID.cpp
@@ -0,0 +1,152 @@
+/* -*- 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):
+ * Daniel Bratell <bratell@lysator.liu.se>
+ *
+ * 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 "prprf.h"
+#include "prmem.h"
+
+static const char gIDFormat[] =
+ "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}";
+
+static const char gIDFormat2[] =
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
+
+
+/**
+ * Multiplies the_int_var with 16 (0x10) and adds the value of the
+ * hexadecimal digit the_char. If it fails it returns PR_FALSE from
+ * the function it's used in.
+ */
+
+#define ADD_HEX_CHAR_TO_INT_OR_RETURN_FALSE(the_char, the_int_var) \
+ the_int_var = (the_int_var << 4) + the_char; \
+ if(the_char >= '0' && the_char <= '9') the_int_var -= '0'; \
+ else if(the_char >= 'a' && the_char <= 'f') the_int_var -= 'a'-10; \
+ else if(the_char >= 'A' && the_char <= 'F') the_int_var -= 'A'-10; \
+ else return PR_FALSE
+
+
+/**
+ * Parses number_of_chars characters from the char_pointer pointer and
+ * puts the number in the dest_variable. The pointer is moved to point
+ * at the first character after the parsed ones. If it fails it returns
+ * PR_FALSE from the function the macro is used in.
+ */
+
+#define PARSE_CHARS_TO_NUM(char_pointer, dest_variable, number_of_chars) \
+ do { PRInt32 _i=number_of_chars; \
+ dest_variable = 0; \
+ while(_i) { \
+ ADD_HEX_CHAR_TO_INT_OR_RETURN_FALSE(*char_pointer, dest_variable); \
+ char_pointer++; \
+ _i--; \
+ } } while(0)
+
+
+/**
+ * Parses a hyphen from the char_pointer string. If there is no hyphen there
+ * the function returns PR_FALSE from the function it's used in. The
+ * char_pointer is advanced one step.
+ */
+
+ #define PARSE_HYPHEN(char_pointer) if(*(char_pointer++) != '-') return PR_FALSE
+
+/*
+ * Turns a {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} string into
+ * an nsID. It can also handle the old format without the { and }.
+ */
+
+NS_COM PRBool nsID::Parse(const char *aIDStr)
+{
+ /* Optimized for speed */
+ if(!aIDStr) {
+ return PR_FALSE;
+ }
+
+ PRBool expectFormat1 = (aIDStr[0] == '{');
+ if(expectFormat1) aIDStr++;
+
+ PARSE_CHARS_TO_NUM(aIDStr, m0, 8);
+ PARSE_HYPHEN(aIDStr);
+ PARSE_CHARS_TO_NUM(aIDStr, m1, 4);
+ PARSE_HYPHEN(aIDStr);
+ PARSE_CHARS_TO_NUM(aIDStr, m2, 4);
+ PARSE_HYPHEN(aIDStr);
+ int i;
+ for(i=0; i<2; i++)
+ PARSE_CHARS_TO_NUM(aIDStr, m3[i], 2);
+ PARSE_HYPHEN(aIDStr);
+ while(i < 8) {
+ PARSE_CHARS_TO_NUM(aIDStr, m3[i], 2);
+ i++;
+ }
+
+ return expectFormat1 ? *aIDStr == '}' : PR_TRUE;
+}
+
+/*
+ * Returns an allocated string in {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
+ * format. The string is allocated with PR_Malloc and should be freed by
+ * the caller.
+ */
+
+NS_COM char *nsID::ToString() const
+{
+ char *res = (char*)PR_Malloc(39); // use PR_Malloc if this is to be freed with nsCRT::free
+
+ if (res != NULL) {
+ PR_snprintf(res, 39, gIDFormat,
+ m0, (PRUint32) m1, (PRUint32) m2,
+ (PRUint32) m3[0], (PRUint32) m3[1], (PRUint32) m3[2],
+ (PRUint32) m3[3], (PRUint32) m3[4], (PRUint32) m3[5],
+ (PRUint32) m3[6], (PRUint32) m3[7]);
+ }
+ return res;
+}
+
+#ifdef VBOX
+void nsID::ToProvidedString(char (&dest)[NSID_LENGTH]) const
+{
+ PR_snprintf(dest, NSID_LENGTH, gIDFormat,
+ m0, (PRUint32) m1, (PRUint32) m2,
+ (PRUint32) m3[0], (PRUint32) m3[1], (PRUint32) m3[2],
+ (PRUint32) m3[3], (PRUint32) m3[4], (PRUint32) m3[5],
+ (PRUint32) m3[6], (PRUint32) m3[7]);
+}
+#endif
+
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsID.h b/src/libs/xpcom18a4/xpcom/base/nsID.h
new file mode 100644
index 00000000..257ba927
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsID.h
@@ -0,0 +1,166 @@
+/* -*- 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 nsID_h__
+#define nsID_h__
+
+#include <string.h>
+
+#ifndef nscore_h___
+#include "nscore.h"
+#endif
+
+#ifdef VBOX
+#define NSID_LENGTH 39
+#endif
+
+/**
+ * A "unique identifier". This is modeled after OSF DCE UUIDs.
+ * @status FROZEN
+ */
+
+struct nsID {
+ /**
+ * @name Indentifier values
+ */
+
+ //@{
+ PRUint32 m0;
+ PRUint16 m1;
+ PRUint16 m2;
+ PRUint8 m3[8];
+ //@}
+
+ /**
+ * @name Methods
+ */
+
+ //@{
+ /**
+ * Equivalency method. Compares this nsID with another.
+ * @return <b>PR_TRUE</b> if they are the same, <b>PR_FALSE</b> if not.
+ */
+
+ inline PRBool Equals(const nsID& other) const {
+ // One would think that this could be done faster with a really
+ // efficient implementation of memcmp(), but evidently no
+ // memcmp()'s out there are better than this code.
+ //
+ // See bug http://bugzilla.mozilla.org/show_bug.cgi?id=164580 for
+ // details.
+
+ return (PRBool)
+ ((((PRUint32*) &m0)[0] == ((PRUint32*) &other.m0)[0]) &&
+ (((PRUint32*) &m0)[1] == ((PRUint32*) &other.m0)[1]) &&
+ (((PRUint32*) &m0)[2] == ((PRUint32*) &other.m0)[2]) &&
+ (((PRUint32*) &m0)[3] == ((PRUint32*) &other.m0)[3]));
+ }
+
+ /**
+ * nsID Parsing method. Turns a {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
+ * string into an nsID
+ */
+ NS_COM PRBool Parse(const char *aIDStr);
+
+ /**
+ * nsID string encoder. Returns an allocated string in
+ * {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} format. Caller should free string.
+ */
+ NS_COM char* ToString() const;
+
+#ifdef VBOX
+ /**
+ * nsID string encoder. Builds a string in
+ * {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} format, into a char[NSID_LENGTH]
+ * buffer provided by the caller (for instance, on the stack).
+ */
+ NS_COM void ToProvidedString(char (&dest)[NSID_LENGTH]) const;
+#endif
+
+ //@}
+};
+
+/*
+ * Class IDs
+ */
+
+typedef nsID nsCID;
+
+// Define an CID
+#define NS_DEFINE_CID(_name, _cidspec) \
+ const nsCID _name = _cidspec
+
+#define REFNSCID const nsCID&
+
+/**
+ * An "interface id" which can be used to uniquely identify a given
+ * interface.
+ */
+
+typedef nsID nsIID;
+
+/**
+ * A macro shorthand for <tt>const nsIID&<tt>
+ */
+
+#define REFNSIID const nsIID&
+
+/**
+ * Define an IID
+ * obsolete - do not use this macro
+ */
+
+#define NS_DEFINE_IID(_name, _iidspec) \
+ const nsIID _name = _iidspec
+
+/**
+ * A macro to build the static const IID accessor method
+ */
+
+#define NS_DEFINE_STATIC_IID_ACCESSOR(the_iid) \
+ static const nsIID& GetIID() {static const nsIID iid = the_iid; return iid;}
+
+/**
+ * A macro to build the static const CID accessor method
+ */
+
+#define NS_DEFINE_STATIC_CID_ACCESSOR(the_cid) \
+ static const nsID& GetCID() {static const nsID cid = the_cid; return cid;}
+
+#endif
+
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIDebug.idl b/src/libs/xpcom18a4/xpcom/base/nsIDebug.idl
new file mode 100644
index 00000000..73b3912a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIDebug.idl
@@ -0,0 +1,67 @@
+/* ***** 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
+ *
+ * The Initial Developer of the Original Code is Doug Turner <dougt@meer.net>
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * 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 "nsISupports.idl"
+
+/**
+ * nsIDebug is an interface between XPCOM Glue and XPCOM. Users should access
+ * the nsIDebug interface through the static class nsDebug.
+ * @see nsDebug.h
+ *
+ * @status UNDER_REVIEW
+ *
+ */
+
+[scriptable, uuid(3bf0c3d7-3bd9-4cf2-a971-33572c503e1e)]
+interface nsIDebug : nsISupports
+{
+ void assertion(in string aStr,
+ in string aExpr,
+ in string aFile,
+ in long aLine);
+
+ void warning(in string aStr,
+ in string aFile,
+ in long aLine);
+
+ void break(in string aFile,
+ in long aLine);
+
+ void abort(in string aFile,
+ in long aLine);
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIErrorService.idl b/src/libs/xpcom18a4/xpcom/base/nsIErrorService.idl
new file mode 100644
index 00000000..c4ed3964
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIErrorService.idl
@@ -0,0 +1,100 @@
+/* -*- 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"
+
+/**
+ * nsIErrorService: This is an interim service that allows nsresult codes to be mapped to
+ * string bundles that can be used to look up error messages. String bundle keys can also
+ * be mapped.
+ *
+ * This service will eventually get replaced by extending xpidl to allow errors to be defined.
+ * (http://bugzilla.mozilla.org/show_bug.cgi?id=13423).
+ */
+[scriptable, uuid(e72f94b2-5f85-11d4-9877-00c04fa0cf4a)]
+interface nsIErrorService : nsISupports
+{
+ /**
+ * Registers a string bundle URL for an error module. Error modules are obtained from
+ * nsresult code with NS_ERROR_GET_MODULE.
+ */
+ void registerErrorStringBundle(in short errorModule, in string stringBundleURL);
+
+ /**
+ * Registers a string bundle URL for an error module.
+ */
+ void unregisterErrorStringBundle(in short errorModule);
+
+ /**
+ * Retrieves a string bundle URL for an error module.
+ */
+ string getErrorStringBundle(in short errorModule);
+
+ /**
+ * Registers a key in a string bundle for an nsresult error code. Only the code portion
+ * of the nsresult is used (obtained with NS_ERROR_GET_CODE) in this registration. The
+ * string bundle key is used to look up internationalized messages in the string bundle.
+ */
+ void registerErrorStringBundleKey(in nsresult error, in string stringBundleKey);
+
+ /**
+ * Unregisters a key in a string bundle for an nsresult error code.
+ */
+ void unregisterErrorStringBundleKey(in nsresult error);
+
+ /**
+ * Retrieves a key in a string bundle for an nsresult error code. If no key is registered
+ * for the specified nsresult's code (obtained with NS_ERROR_GET_CODE), then the stringified
+ * version of the nsresult code is returned.
+ */
+ string getErrorStringBundleKey(in nsresult error);
+};
+
+%{C++
+
+// The global nsIErrorService:
+#define NS_ERRORSERVICE_NAME "Error Service"
+#define NS_ERRORSERVICE_CONTRACTID "@mozilla.org/xpcom/error-service;1"
+#define NS_ERRORSERVICE_CID \
+{ /* 744afd5e-5f8c-11d4-9877-00c04fa0cf4a */ \
+ 0x744afd5e, \
+ 0x5f8c, \
+ 0x11d4, \
+ {0x98, 0x77, 0x00, 0xc0, 0x4f, 0xa0, 0xcf, 0x4a} \
+}
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIException.idl b/src/libs/xpcom18a4/xpcom/base/nsIException.idl
new file mode 100644
index 00000000..affbb36e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIException.idl
@@ -0,0 +1,101 @@
+/* -*- 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 ***** */
+
+/*
+ * Interfaces for representing cross-language exceptions and stack traces.
+ */
+
+
+#include "nsISupports.idl"
+#include "nsIProgrammingLanguage.idl"
+
+// XXX - most "string"s in this file should probably move to Unicode
+// so may as well use AStrings...
+
+
+[scriptable, uuid(91d82105-7c62-4f8b-9779-154277c0ee90)]
+interface nsIStackFrame : nsISupports
+{
+ // see nsIProgrammingLanguage for list of language consts
+ readonly attribute PRUint32 language;
+ readonly attribute string languageName;
+ readonly attribute string filename;
+ readonly attribute string name;
+ // Valid line numbers begin at '1'. '0' indicates unknown.
+ readonly attribute PRInt32 lineNumber;
+ readonly attribute string sourceLine;
+ readonly attribute nsIStackFrame caller;
+
+ string toString();
+};
+
+[scriptable, uuid(F3A8D3B4-C424-4edc-8BF6-8974C983BA78)]
+interface nsIException : nsISupports
+{
+ // A custom message set by the thrower.
+ readonly attribute string message;
+ // The nsresult associated with this exception.
+ readonly attribute nsresult result;
+ // The name of the error code (ie, a string repr of |result|)
+ readonly attribute string name;
+
+ // Filename location. This is the location that caused the
+ // error, which may or may not be a source file location.
+ // For example, standard language errors would generally have
+ // the same location as their top stack entry. File
+ // parsers may put the location of the file they were parsing,
+ // etc.
+
+ // null indicates "no data"
+ readonly attribute string filename;
+ // Valid line numbers begin at '1'. '0' indicates unknown.
+ readonly attribute PRUint32 lineNumber;
+ // Valid column numbers begin at 0.
+ // We don't have an unambiguous indicator for unknown.
+ readonly attribute PRUint32 columnNumber;
+
+ // A stack trace, if available.
+ readonly attribute nsIStackFrame location;
+ // An inner exception that triggered this, if available.
+ readonly attribute nsIException inner;
+
+ // Arbitary data for the implementation.
+ readonly attribute nsISupports data;
+
+ // A generic formatter - make it suitable to print, etc.
+ string toString();
+};
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIExceptionService.idl b/src/libs/xpcom18a4/xpcom/base/nsIExceptionService.idl
new file mode 100644
index 00000000..22ebe751
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIExceptionService.idl
@@ -0,0 +1,97 @@
+/* -*- 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
+ * ActiveState Tool Corp..
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Hammond <MarkH@ActiveState.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 "nsISupports.idl"
+#include "nsIException.idl"
+
+// An exception provider. These can turn special nsresult codes
+// into nsIExceptions
+
+[scriptable, uuid(0577744c-c1d2-47f2-8bcc-ce7a9e5a88fc)]
+interface nsIExceptionProvider : nsISupports
+{
+ /** Gets an nsIException or returns NULL if not possible. **/
+ nsIException getException(in nsresult result, in nsIException defaultException);
+};
+
+// A ScriptErrorManager for a single thread. These objects
+// are _not_ thread-safe. Use the ScriptErrorService
+// to get a script error manager for your current thread.
+[scriptable, uuid(efc9d00b-231c-4feb-852c-ac017266a415)]
+interface nsIExceptionManager : nsISupports
+{
+ /** Sets (or clears with nsnull) the current error on the this thread. */
+ void setCurrentException( in nsIException error);
+
+ /** Gets the current error for the current thread, or NULL if no error */
+ nsIException getCurrentException();
+
+ /** Gets an exception from a registered exception provider..
+ This has no effect on the "current exception" */
+ nsIException getExceptionFromProvider( in nsresult rc, in nsIException defaultException);
+};
+
+
+// The Exception Service. Allows you to get an set exceptions in a thread
+// safe manner, or to get an ExceptionManager for your specific thread.
+[scriptable, uuid(35A88F54-F267-4414-92A7-191F6454AB52)]
+interface nsIExceptionService : nsIExceptionManager
+{
+ /** Obtains an exception manager for the current thread. */
+ readonly attribute nsIExceptionManager currentExceptionManager;
+
+ /** Installs an "exception provider" which is capable of
+ translating an nsresult into an exception. This enables
+ error providers to return simple nsresults and only provide
+ rich errors when specifically requested. It also has the
+ advantage of allowing code like the DOM to handle all errors
+ in a single function rather than at each XPCOM entry point.
+ NOTE: This interface must be thread-safe - it will be called
+ on whatever thread needs the error translation performed.*/
+ void registerExceptionProvider( in nsIExceptionProvider provider, in PRUint32 moduleCode );
+ void unregisterExceptionProvider( in nsIExceptionProvider provider, in PRUint32 moduleCode );
+};
+
+
+%{ C++
+#define NS_EXCEPTIONSERVICE_CLASSNAME "Exception Service"
+// {35A88F54-F267-4414-92A7-191F6454AB52}
+#define NS_EXCEPTIONSERVICE_CID \
+{ 0x35a88f54, 0xf267, 0x4414, { 0x92, 0xa7, 0x19, 0x1f, 0x64, 0x54, 0xab, 0x52 } }
+#define NS_EXCEPTIONSERVICE_CONTRACTID "@mozilla.org/exceptionservice;1"
+%}
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIID.h b/src/libs/xpcom18a4/xpcom/base/nsIID.h
new file mode 100644
index 00000000..f00d6b23
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIID.h
@@ -0,0 +1,41 @@
+/* -*- 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 __nsIID_h
+#define __nsIID_h
+#include "nsID.h"
+#endif /* __nsIID_h */
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIInterfaceRequestor.idl b/src/libs/xpcom18a4/xpcom/base/nsIInterfaceRequestor.idl
new file mode 100644
index 00000000..31388643
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIInterfaceRequestor.idl
@@ -0,0 +1,72 @@
+/* -*- Mode: IDL; 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 the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Travis Bogard <travis@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 "nsISupports.idl"
+
+/**
+ * The nsIInterfaceRequestor interface defines a generic interface for
+ * requesting interfaces that a given object might provide access to.
+ * This is very similar to QueryInterface found in nsISupports.
+ * The main difference is that interfaces returned from GetInterface()
+ * are not required to provide a way back to the object implementing this
+ * interface. The semantics of QI() dictate that given an interface A that
+ * you QI() on to get to interface B, you must be able to QI on B to get back
+ * to A. This interface however allows you to obtain an interface C from A
+ * that may or most likely will not have the ability to get back to A.
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(033A1470-8B2A-11d3-AF88-00A024FFC08C)]
+interface nsIInterfaceRequestor : nsISupports
+{
+ /**
+ * Retrieves the specified interface pointer.
+ *
+ * @param uuid The IID of the interface being requested.
+ * @param result [out] The interface pointer to be filled in if
+ * the interface is accessible.
+ * @return NS_OK - interface was successfully returned.
+ * NS_NOINTERFACE - interface not accessible.
+ * NS_ERROR* - method failure.
+ */
+ void getInterface(in nsIIDRef uuid,
+ [iid_is(uuid),retval] out nsQIResult result);
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsILeakDetector.idl b/src/libs/xpcom18a4/xpcom/base/nsILeakDetector.idl
new file mode 100644
index 00000000..6d27fa70
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsILeakDetector.idl
@@ -0,0 +1,54 @@
+/* -*- 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 the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Patrick C. Beard <beard@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 "nsISupports.idl"
+
+interface nsICollection;
+
+/**
+ * Controls the leak detector.
+ */
+[scriptable, uuid(a2ec052c-1dd1-11b2-9c92-84be252fe47e)]
+interface nsILeakDetector : nsISupports {
+ void dumpLeaks();
+ void traceObject(in nsISupports object, in PRBool verbose);
+ void traceCollection(in nsICollection objects, in PRBool verbose);
+ void markObject(in nsISupports object, in PRBool marked);
+ readonly attribute nsISupports services;
+};
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIMemory.idl b/src/libs/xpcom18a4/xpcom/base/nsIMemory.idl
new file mode 100644
index 00000000..071aed06
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIMemory.idl
@@ -0,0 +1,126 @@
+/* -*- 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"
+
+/**
+ *
+ * nsIMemory: interface to allocate and deallocate memory. Also provides
+ * for notifications in low-memory situations.
+ *
+ * A client that wishes to be notified of low memory situations (for
+ * example, because the client maintains a large memory cache that
+ * could be released when memory is tight) should register with the
+ * observer service (see nsIObserverService) using the topic
+ * "memory-pressure". There are three specific types of notications
+ * that can occur. These types will be passed as the |aData|
+ * parameter of the of the "memory-pressure" notification:
+ *
+ * "low-memory"
+ * This will be passed as the extra data when the pressure
+ * observer is being asked to flush for low-memory conditions.
+ *
+ * "heap-minimize"
+ * This will be passed as the extra data when the pressure
+ * observer is being asked to flush because of a heap minimize
+ * call.
+ *
+ * "alloc-failure"
+ * This will be passed as the extra data when the pressure
+ * observer has been asked to flush because a malloc() or
+ * realloc() has failed.
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(59e7e77a-38e4-11d4-8cf5-0060b0fc14a3)]
+interface nsIMemory : nsISupports
+{
+ /**
+ * Allocates a block of memory of a particular size. If the memory
+ * cannot be allocated (because of an out-of-memory condition), null
+ * is returned.
+ *
+ * @param size - the size of the block to allocate
+ * @result the block of memory
+ */
+ [noscript, notxpcom] voidPtr alloc(in size_t size);
+
+ /**
+ * Reallocates a block of memory to a new size.
+ *
+ * @param ptr - the block of memory to reallocate
+ * @param size - the new size
+ * @result the reallocated block of memory
+ *
+ * If ptr is null, this function behaves like malloc.
+ * If s is the size of the block to which ptr points, the first
+ * min(s, size) bytes of ptr's block are copied to the new block.
+ * If the allocation succeeds, ptr is freed and a pointer to the
+ * new block returned. If the allocation fails, ptr is not freed
+ * and null is returned. The returned value may be the same as ptr.
+ */
+ [noscript, notxpcom] voidPtr realloc(in voidPtr ptr,
+ in size_t newSize);
+
+ /**
+ * Frees a block of memory. Null is a permissible value, in which case
+ * nothing happens.
+ *
+ * @param ptr - the block of memory to free
+ */
+ [noscript, notxpcom] void free(in voidPtr ptr);
+
+ /**
+ * Attempts to shrink the heap.
+ * @param immediate - if true, heap minimization will occur
+ * immediately if the call was made on the main thread. If
+ * false, the flush will be scheduled to happen when the app is
+ * idle.
+ * @return NS_ERROR_FAILURE if 'immediate' is set an the call
+ * was not on the application's main thread.
+ */
+ void heapMinimize(in boolean immediate);
+
+ /**
+ * This predicate can be used to determine if we're in a low-memory
+ * situation (what constitutes low-memory is platform dependent). This
+ * can be used to trigger the memory pressure observers.
+ */
+ boolean isLowMemory();
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIProgrammingLanguage.idl b/src/libs/xpcom18a4/xpcom/base/nsIProgrammingLanguage.idl
new file mode 100644
index 00000000..2fe6fb58
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIProgrammingLanguage.idl
@@ -0,0 +1,70 @@
+/* -*- 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 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):
+ * 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 ***** */
+
+#include "nsISupports.idl"
+
+%{C++
+#ifdef XP_OS2 // OS2 has UNKNOWN problems :)
+#undef UNKNOWN
+#endif
+%}
+
+/**
+ * Enumeration of Programming Languages
+ * @status FROZEN
+ */
+
+[scriptable, uuid(ea604e90-40ba-11d5-90bb-0010a4e73d9a)]
+interface nsIProgrammingLanguage : nsISupports
+{
+ /**
+ * Identifiers for programming languages.
+ */
+ const PRUint32 UNKNOWN = 0;
+ const PRUint32 CPLUSPLUS = 1;
+ const PRUint32 JAVASCRIPT = 2;
+ const PRUint32 PYTHON = 3;
+ const PRUint32 PERL = 4;
+ const PRUint32 JAVA = 5;
+ const PRUint32 ZX81_BASIC = 6; // it could happen :)
+ const PRUint32 JAVASCRIPT2 = 7;
+ // This list can grow indefinitely. Just don't ever change an existing item.
+
+};
diff --git a/src/libs/xpcom18a4/xpcom/base/nsISupports.idl b/src/libs/xpcom18a4/xpcom/base/nsISupports.idl
new file mode 100644
index 00000000..6bf08ac4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsISupports.idl
@@ -0,0 +1,80 @@
+/* -*- 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 ***** */
+
+/**
+ * The mother of all xpcom interfaces.
+ * @status FROZEN
+ */
+
+/* In order to get both the right typelib and the right header we force
+* the 'real' output from xpidl to be commented out in the generated header
+* and includes a copy of the original nsISupports.h. This is all just to deal
+* with the Mac specific ": public __comobject" thing.
+*/
+
+#include "nsrootidl.idl"
+
+%{C++
+/*
+ * Start commenting out the C++ versions of the below in the output header
+ */
+#if 0
+%}
+
+[scriptable, uuid(00000000-0000-0000-c000-000000000046)]
+interface nsISupports {
+ void QueryInterface(in nsIIDRef uuid,
+ [iid_is(uuid),retval] out nsQIResult result);
+ [noscript, notxpcom] nsrefcnt AddRef();
+ [noscript, notxpcom] nsrefcnt Release();
+};
+
+%{C++
+/*
+ * End commenting out the C++ versions of the above in the output header
+ */
+#endif
+%}
+
+
+%{C++
+#include "nsISupportsBase.h"
+
+#ifndef MOZILLA_STRICT_API
+#include "nsISupportsUtils.h"
+#endif
+%}
diff --git a/src/libs/xpcom18a4/xpcom/base/nsISupportsBase.h b/src/libs/xpcom18a4/xpcom/base/nsISupportsBase.h
new file mode 100644
index 00000000..bea876f5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsISupportsBase.h
@@ -0,0 +1,119 @@
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * 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 nsISupportsBase_h__
+#define nsISupportsBase_h__
+
+#ifndef nscore_h___
+#include "nscore.h"
+#endif
+
+#ifndef nsID_h__
+#include "nsID.h"
+#endif
+
+
+/*@{*/
+/**
+ * IID for the nsISupports interface
+ * {00000000-0000-0000-c000-000000000046}
+ *
+ * To maintain binary compatibility with COM's IUnknown, we define the IID
+ * of nsISupports to be the same as that of COM's IUnknown.
+ */
+#define NS_ISUPPORTS_IID \
+ { 0x00000000, 0x0000, 0x0000, \
+ {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} }
+
+/**
+ * Reference count values
+ *
+ * This is the return type for AddRef() and Release() in nsISupports.
+ * IUnknown of COM returns an unsigned long from equivalent functions.
+ * The following ifdef exists to maintain binary compatibility with
+ * IUnknown.
+ */
+#if defined(XP_WIN) && PR_BYTES_PER_LONG == 4
+typedef unsigned long nsrefcnt;
+#else
+typedef PRUint32 nsrefcnt;
+#endif
+
+/**
+ * Basic component object model interface. Objects which implement
+ * this interface support runtime interface discovery (QueryInterface)
+ * and a reference counted memory model (AddRef/Release). This is
+ * modelled after the win32 IUnknown API.
+ */
+class NS_NO_VTABLE nsISupports {
+public:
+
+ /**
+ * @name Methods
+ */
+
+ //@{
+ /**
+ * A run time mechanism for interface discovery.
+ * @param aIID [in] A requested interface IID
+ * @param aInstancePtr [out] A pointer to an interface pointer to
+ * receive the result.
+ * @return <b>NS_OK</b> if the interface is supported by the associated
+ * instance, <b>NS_NOINTERFACE</b> if it is not.
+ * <b>NS_ERROR_INVALID_POINTER</b> if <i>aInstancePtr</i> is <b>NULL</b>.
+ */
+ NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) = 0;
+ /**
+ * Increases the reference count for this interface.
+ * The associated instance will not be deleted unless
+ * the reference count is returned to zero.
+ *
+ * @return The resulting reference count.
+ */
+ NS_IMETHOD_(nsrefcnt) AddRef(void) = 0;
+
+ /**
+ * Decreases the reference count for this interface.
+ * Generally, if the reference count returns to zero,
+ * the associated instance is deleted.
+ *
+ * @return The resulting reference count.
+ */
+ NS_IMETHOD_(nsrefcnt) Release(void) = 0;
+
+ //@}
+};
+/*@}*/
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/base/nsISupportsObsolete.h b/src/libs/xpcom18a4/xpcom/base/nsISupportsObsolete.h
new file mode 100644
index 00000000..874d859f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsISupportsObsolete.h
@@ -0,0 +1,243 @@
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * 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 nsISupportsObsolete_h__
+#define nsISupportsObsolete_h__
+
+#include "prcmon.h"
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+#define NS_INIT_REFCNT() NS_INIT_ISUPPORTS()
+
+/**
+ * Macro to free an array of pointers to nsISupports (or classes
+ * derived from it). A convenience wrapper around
+ * NS_FREE_XPCOM_POINTER_ARRAY.
+ *
+ * Note that if you know that none of your nsISupports pointers are
+ * going to be 0, you can gain a bit of speed by calling
+ * NS_FREE_XPCOM_POINTER_ARRAY directly and using NS_RELEASE as your
+ * free function.
+ *
+ * @param size Number of elements in the array. If not a constant, this
+ * should be a PRInt32. Note that this means this macro
+ * will not work if size >= 2^31.
+ * @param array The array to be freed.
+ */
+#define NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(size, array) \
+ NS_FREE_XPCOM_POINTER_ARRAY((size), (array), NS_IF_RELEASE)
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+/* use these functions to associate get/set methods with a
+ C++ member variable
+*/
+
+#define NS_METHOD_GETTER(_method, _type, _member) \
+_method(_type* aResult) \
+{\
+ if (!aResult) return NS_ERROR_NULL_POINTER; \
+ *aResult = _member; \
+ return NS_OK; \
+}
+
+#define NS_METHOD_SETTER(_method, _type, _member) \
+_method(_type aResult) \
+{ \
+ _member = aResult; \
+ return NS_OK; \
+}
+
+/*
+ * special for strings to get/set char* strings
+ * using PL_strdup and PR_FREEIF
+ */
+#define NS_METHOD_GETTER_STR(_method,_member) \
+_method(char* *aString) \
+{ \
+ if (!aString) return NS_ERROR_NULL_POINTER; \
+ if (!(*aString = PL_strdup(_member))) \
+ return NS_ERROR_OUT_OF_MEMORY; \
+ return NS_OK; \
+}
+
+#define NS_METHOD_SETTER_STR(_method, _member) \
+_method(const char *aString) \
+{ \
+ if (_member) PR_Free(_member); \
+ if (!aString) \
+ _member = nsnull; \
+ else if (!(_member = PL_strdup(aString))) \
+ return NS_ERROR_OUT_OF_MEMORY; \
+ return NS_OK; \
+}
+
+/* Getter/Setter macros.
+ Usage:
+ NS_IMPL_[CLASS_]GETTER[_<type>](method, [type,] member);
+ NS_IMPL_[CLASS_]SETTER[_<type>](method, [type,] member);
+ NS_IMPL_[CLASS_]GETSET[_<type>]([class, ]postfix, [type,] member);
+
+ where:
+ CLASS_ - implementation is inside a class definition
+ (otherwise the class name is needed)
+ Do NOT use in publicly exported header files, because
+ the implementation may be included many times over.
+ Instead, use the non-CLASS_ version.
+ _<type> - For more complex (STR, IFACE) data types
+ (otherwise the simple data type is needed)
+ method - name of the method, such as GetWidth or SetColor
+ type - simple data type if required
+ member - class member variable such as m_width or mColor
+ class - the class name, such as Window or MyObject
+ postfix - Method part after Get/Set such as "Width" for "GetWidth"
+
+ Example:
+ class Window {
+ public:
+ NS_IMPL_CLASS_GETSET(Width, int, m_width);
+ NS_IMPL_CLASS_GETTER_STR(GetColor, m_color);
+ NS_IMETHOD SetColor(char *color);
+
+ private:
+ int m_width; // read/write
+ char *m_color; // readonly
+ };
+
+ // defined outside of class
+ NS_IMPL_SETTER_STR(Window::GetColor, m_color);
+
+ Questions/Comments to alecf@netscape.com
+*/
+
+
+/*
+ * Getter/Setter implementation within a class definition
+ */
+
+/* simple data types */
+#define NS_IMPL_CLASS_GETTER(_method, _type, _member) \
+NS_IMETHOD NS_METHOD_GETTER(_method, _type, _member)
+
+#define NS_IMPL_CLASS_SETTER(_method, _type, _member) \
+NS_IMETHOD NS_METHOD_SETTER(_method, _type, _member)
+
+#define NS_IMPL_CLASS_GETSET(_postfix, _type, _member) \
+NS_IMPL_CLASS_GETTER(Get##_postfix, _type, _member) \
+NS_IMPL_CLASS_SETTER(Set##_postfix, _type, _member)
+
+/* strings */
+#define NS_IMPL_CLASS_GETTER_STR(_method, _member) \
+NS_IMETHOD NS_METHOD_GETTER_STR(_method, _member)
+
+#define NS_IMPL_CLASS_SETTER_STR(_method, _member) \
+NS_IMETHOD NS_METHOD_SETTER_STR(_method, _member)
+
+#define NS_IMPL_CLASS_GETSET_STR(_postfix, _member) \
+NS_IMPL_CLASS_GETTER_STR(Get##_postfix, _member) \
+NS_IMPL_CLASS_SETTER_STR(Set##_postfix, _member)
+
+/* Getter/Setter implementation outside of a class definition */
+
+/* simple data types */
+#define NS_IMPL_GETTER(_method, _type, _member) \
+NS_IMETHODIMP NS_METHOD_GETTER(_method, _type, _member)
+
+#define NS_IMPL_SETTER(_method, _type, _member) \
+NS_IMETHODIMP NS_METHOD_SETTER(_method, _type, _member)
+
+#define NS_IMPL_GETSET(_class, _postfix, _type, _member) \
+NS_IMPL_GETTER(_class::Get##_postfix, _type, _member) \
+NS_IMPL_SETTER(_class::Set##_postfix, _type, _member)
+
+/* strings */
+#define NS_IMPL_GETTER_STR(_method, _member) \
+NS_IMETHODIMP NS_METHOD_GETTER_STR(_method, _member)
+
+#define NS_IMPL_SETTER_STR(_method, _member) \
+NS_IMETHODIMP NS_METHOD_SETTER_STR(_method, _member)
+
+#define NS_IMPL_GETSET_STR(_class, _postfix, _member) \
+NS_IMPL_GETTER_STR(_class::Get##_postfix, _member) \
+NS_IMPL_SETTER_STR(_class::Set##_postfix, _member)
+
+/**
+ * IID for the nsIsThreadsafe interface
+ * {88210890-47a6-11d2-bec3-00805f8a66dc}
+ *
+ * This interface is *only* used for debugging purposes to determine if
+ * a given component is threadsafe.
+ */
+#define NS_ISTHREADSAFE_IID \
+ { 0x88210890, 0x47a6, 0x11d2, \
+ {0xbe, 0xc3, 0x00, 0x80, 0x5f, 0x8a, 0x66, 0xdc} }
+
+#define NS_LOCK_INSTANCE() \
+ PR_CEnterMonitor((void*)this)
+#define NS_UNLOCK_INSTANCE() \
+ PR_CExitMonitor((void*)this)
+
+/**
+ * This implements query interface with two assumptions: First, the
+ * class in question implements nsISupports and its own interface and
+ * nothing else. Second, the implementation of the class's primary
+ * inheritance chain leads to its own interface.
+ *
+ * @param _class The name of the class implementing the method
+ * @param _classiiddef The name of the #define symbol that defines the IID
+ * for the class (e.g. NS_ISUPPORTS_IID)
+ */
+#if defined(NS_DEBUG)
+#define NS_VERIFY_THREADSAFE_INTERFACE(_iface) \
+ if (NULL != (_iface)) { \
+ nsISupports* tmp; \
+ static NS_DEFINE_IID(kIsThreadsafeIID, NS_ISTHREADSAFE_IID); \
+ NS_PRECONDITION((NS_OK == _iface->QueryInterface(kIsThreadsafeIID, \
+ (void**)&tmp)), \
+ "Interface is not threadsafe"); \
+ }
+#else
+#define NS_VERIFY_THREADSAFE_INTERFACE(_iface)
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/base/nsISystemInfo.idl b/src/libs/xpcom18a4/xpcom/base/nsISystemInfo.idl
new file mode 100644
index 00000000..0351196a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsISystemInfo.idl
@@ -0,0 +1,62 @@
+/* -*- 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):
+ * Mike Shaver <shaver@mozilla.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 ***** */
+
+#include "nsISupports.idl"
+
+/**
+ * System information service.
+ *
+ * At present, a thin wrapper around PR_GetSystemInfo.
+ */
+
+[scriptable,uuid(4189b420-1dd2-11b2-bff7-daaf5c1f7b10)]
+interface nsISystemInfo : nsISupports
+{
+ /** The system hostname. */
+ readonly attribute string hostname;
+
+ /** The operating system name. */
+ readonly attribute string OSName;
+
+ /** The operating system version. */
+ readonly attribute string OSVersion;
+
+ /** The processor architecture of the machine. */
+ readonly attribute string architecture;
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsITraceRefcnt.idl b/src/libs/xpcom18a4/xpcom/base/nsITraceRefcnt.idl
new file mode 100644
index 00000000..536861a0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsITraceRefcnt.idl
@@ -0,0 +1,72 @@
+/* ***** 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
+ *
+ * The Initial Developer of the Original Code is Doug Turner <dougt@meer.net>
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * 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 "nsISupports.idl"
+
+/**
+ * nsITraceRefcnt is an interface between XPCOM Glue and XPCOM. Users should
+ * access the nsITraceRefcnt interface through the static class nsTraceRefcnt.
+ * @see nsTraceRefcnt.h
+ *
+ * @status UNDER_REVIEW
+ */
+
+[uuid(273dc92f-0fe6-4545-96a9-21be77828039)]
+interface nsITraceRefcnt : nsISupports
+{
+ void logAddRef(in voidPtr aPtr,
+ in nsrefcnt aNewRefcnt,
+ in string aTypeName,
+ in unsigned long aInstanceSize);
+
+ void logRelease(in voidPtr aPtr,
+ in nsrefcnt aNewRefcnt,
+ in string aTypeName);
+
+ void logCtor(in voidPtr aPtr,
+ in string aTypeName,
+ in unsigned long aInstanceSize);
+
+ void logDtor(in voidPtr aPtr,
+ in string aTypeName,
+ in unsigned long aInstanceSize);
+
+
+ void logAddCOMPtr(in voidPtr aPtr, in nsISupports aObject);
+
+ void logReleaseCOMPtr(in voidPtr aPtr, in nsISupports aObject);
+};
diff --git a/src/libs/xpcom18a4/xpcom/base/nsIWeakReference.idl b/src/libs/xpcom18a4/xpcom/base/nsIWeakReference.idl
new file mode 100644
index 00000000..2806fc8a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsIWeakReference.idl
@@ -0,0 +1,102 @@
+/* -*- 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 the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * 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 "nsISupports.idl"
+
+
+/**
+ * An instance of |nsIWeakReference| is a proxy object that cooperates with
+ * its referent to give clients a non-owning, non-dangling reference. Clients
+ * own the proxy, and should generally manage it with an |nsCOMPtr| (see the
+ * type |nsWeakPtr| for a |typedef| name that stands out) as they would any
+ * other XPCOM object. The |QueryReferent| member function provides a
+ * (hopefully short-lived) owning reference on demand, through which clients
+ * can get useful access to the referent, while it still exists.
+ *
+ * @status FROZEN
+ * @version 1.0
+ * @see nsISupportsWeakReference
+ * @see nsWeakReference
+ * @see nsWeakPtr
+ */
+[scriptable, uuid(9188bc85-f92e-11d2-81ef-0060083a0bcf)]
+interface nsIWeakReference : nsISupports
+ {
+ /**
+ * |QueryReferent| queries the referent, if it exists, and like |QueryInterface|, produces
+ * an owning reference to the desired interface. It is designed to look and act exactly
+ * like (a proxied) |QueryInterface|. Don't hold on to the produced interface permanently;
+ * that would defeat the purpose of using a non-owning |nsIWeakReference| in the first place.
+ */
+ void QueryReferent( in nsIIDRef uuid, [iid_is(uuid), retval] out nsQIResult result );
+ };
+
+
+/**
+ * |nsISupportsWeakReference| is a factory interface which produces appropriate
+ * instances of |nsIWeakReference|. Weak references in this scheme can only be
+ * produced for objects that implement this interface.
+ *
+ * @status FROZEN
+ * @version 1.0
+ * @see nsIWeakReference
+ * @see nsSupportsWeakReference
+ */
+[scriptable, uuid(9188bc86-f92e-11d2-81ef-0060083a0bcf)]
+interface nsISupportsWeakReference : nsISupports
+ {
+ /**
+ * |GetWeakReference| produces an appropriate instance of |nsIWeakReference|.
+ * As with all good XPCOM `getters', you own the resulting interface and should
+ * manage it with an |nsCOMPtr|.
+ *
+ * @see nsIWeakReference
+ * @see nsWeakPtr
+ * @see nsCOMPtr
+ */
+ nsIWeakReference GetWeakReference();
+ };
+
+
+%{C++
+#ifndef MOZILLA_STRICT_API
+#include "nsIWeakReferenceUtils.h"
+#endif
+%}
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsLeakDetector.cpp b/src/libs/xpcom18a4/xpcom/base/nsLeakDetector.cpp
new file mode 100644
index 00000000..a42f77bf
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsLeakDetector.cpp
@@ -0,0 +1,248 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * ***** 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 the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Patrick C. Beard <beard@netscape.com>
+ * Scott Collins <scc@mozilla.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 ***** */
+
+#if defined(GC_LEAK_DETECTOR)
+
+#include "nsLeakDetector.h"
+#include "nsCOMPtr.h"
+#include "nsIComponentManager.h"
+#include "nsIServiceManager.h"
+#include "nsIGenericFactory.h"
+#include "nsILeakDetector.h"
+#include "nsICollection.h"
+
+#include <stdio.h>
+#include <time.h>
+
+#include "gc.h"
+
+extern "C" {
+extern FILE *GC_stdout, *GC_stderr;
+extern void GC_trace_object(GC_PTR object, int verbose);
+extern void GC_mark_object(GC_PTR object, GC_word mark);
+}
+
+static nsresult nextLeakFile()
+{
+ if (GC_stderr != NULL)
+ fclose(GC_stderr);
+
+ // generate a time stamped report name.
+ time_t timer;
+ time(&timer);
+ tm* now = localtime(&timer);
+
+ char reportName[256];
+ sprintf(reportName, "Leaks%02d%02d%02d",
+ now->tm_hour, now->tm_min, now->tm_sec);
+ GC_stderr = fopen(reportName, "w");
+
+ return NS_OK;
+}
+
+static FILE* openTraceFile()
+{
+ // generate a time stamped report name.
+ time_t timer;
+ time(&timer);
+ tm* now = localtime(&timer);
+
+ char reportName[256];
+ sprintf(reportName, "Trace%02d%02d%02d",
+ now->tm_hour, now->tm_min, now->tm_sec);
+ return fopen(reportName, "w");
+}
+
+class nsLeakDetector : public nsILeakDetector {
+public:
+ nsLeakDetector();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSILEAKDETECTOR
+private:
+ ~nsLeakDetector() {}
+};
+
+NS_IMPL_ISUPPORTS1(nsLeakDetector, nsILeakDetector)
+
+nsLeakDetector::nsLeakDetector() {
+ }
+
+NS_METHOD nsLeakDetector::DumpLeaks()
+{
+ GC_gcollect();
+
+ return nextLeakFile();
+}
+
+NS_METHOD nsLeakDetector::TraceObject(nsISupports* object, PRBool verbose)
+{
+ FILE* trace = openTraceFile();
+ if (trace != NULL) {
+ FILE* old_stderr = GC_stderr;
+ GC_stderr = trace;
+ GC_trace_object(object, (verbose ? 1 : 0));
+ GC_stderr = old_stderr;
+ fclose(trace);
+ return NS_OK;
+ }
+ return NS_ERROR_FAILURE;
+}
+
+NS_METHOD nsLeakDetector::TraceCollection(nsICollection* objects, PRBool verbose)
+{
+ PRUint32 count;
+ if (NS_FAILED(objects->Count(&count)))
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsISupports>* elements = new nsCOMPtr<nsISupports>[count];
+ if (elements == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ for (PRUint32 i = 0; i < count; ++i)
+ objects->GetElementAt(i, getter_AddRefs(elements[i]));
+
+ nsresult rv = NS_ERROR_FAILURE;
+ FILE* trace = openTraceFile();
+ if (trace != NULL) {
+ FILE* old_stderr = GC_stderr;
+ GC_stderr = trace;
+ GC_trace_object(elements, (verbose ? 1 : 0));
+ GC_stderr = old_stderr;
+ fclose(trace);
+ rv = NS_OK;
+ }
+
+ delete[] elements;
+
+ return rv;
+}
+
+NS_METHOD nsLeakDetector::MarkObject(nsISupports* object, PRBool marked)
+{
+ GC_mark_object(object, (marked ? 1 : 0));
+ return NS_OK;
+}
+
+NS_METHOD nsLeakDetector::GetServices(nsISupports* *result)
+{
+ return NS_GetServiceManager((nsIServiceManager**)result);
+}
+
+#define NS_CLEAKDETECTOR_CID_STR "bb1ba360-1dd1-11b2-b30e-aa2314429f54"
+#define NS_CLEAKDETECTOR_CID {0xbb1ba360, 0x1dd1, 0x11b2, {0xb3, 0x0e, 0xaa, 0x23, 0x14, 0x42, 0x9f, 0x54}}
+#define NS_CLEAKDETECTOR_CONTRACTID "@mozilla.org/xpcom/leakdetector;1"
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsLeakDetector)
+
+static NS_DEFINE_CID(kCLeakDetectorCID, NS_CLEAKDETECTOR_CID);
+
+nsresult NS_InitLeakDetector()
+{
+ nsresult rv;
+
+ // open the first leak file.
+ rv = nextLeakFile();
+ if (NS_FAILED(rv))
+ return rv;
+
+ static const nsModuleComponentInfo info = {
+ "Leak Detector", kCLeakDetectorCID, NS_CLEAKDETECTOR_CONTRACTID, nsLeakDetectorConstructor
+ };
+
+ // create a generic factory for the leak detector.
+ nsCOMPtr<nsIGenericFactory> factory;
+ rv = NS_NewGenericFactory(getter_AddRefs(factory), &info);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // register this factory with the component manager.
+ return nsComponentManager::RegisterFactory(info.mCID, info.mDescription, info.mContractID, factory, PR_TRUE);
+}
+
+#ifdef XP_MAC
+#define SHUTDOWN_LEAKS_EARLY
+#undef SHUTDOWN_LEAKS_MEDIUM
+#undef SHUTDOWN_LEAKS_LATE
+#else
+#undef SHUTDOWN_LEAKS_EARLY
+#undef SHUTDOWN_LEAKS_MEDIUM
+#define SHUTDOWN_LEAKS_LATE
+#endif
+
+class LeakDetectorFinalizer
+{
+public:
+ ~LeakDetectorFinalizer();
+};
+
+#ifdef SHUTDOWN_LEAKS_LATE
+// do shutdown leaks when XPCOM library is unloaded
+LeakDetectorFinalizer gLeakDetectorFinalizer;
+#endif
+
+LeakDetectorFinalizer::~LeakDetectorFinalizer()
+{
+ GC_gcollect();
+
+#if 0
+ nextLeakFile();
+ if (GC_stdout != NULL) {
+ fprintf(GC_stdout, "ShutDown Leaks\n");
+ GC_clear_roots();
+ GC_gcollect();
+ }
+#endif
+}
+
+nsresult NS_ShutdownLeakDetector()
+{
+#if defined(SHUTDOWN_LEAKS_MEDIUM)
+ // Make this the first atexit() called so it's before the atexit() crashes
+ // see http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=23552
+ static LeakDetectorFinalizer trick;
+#elif defined(SHUTDOWN_LEAKS_EARLY)
+ // do shutdown leaks now
+ LeakDetectorFinalizer trick;
+#endif
+ return NS_OK;
+}
+
+#endif /* defined(GC_LEAK_DETECTOR) */
diff --git a/src/libs/xpcom18a4/xpcom/base/nsLeakDetector.h b/src/libs/xpcom18a4/xpcom/base/nsLeakDetector.h
new file mode 100644
index 00000000..5c560401
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsLeakDetector.h
@@ -0,0 +1,60 @@
+/* -*- 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 the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Patrick C. Beard <beard@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 nsLeakDetector_h
+#define nsLeakDetector_h
+
+#ifndef nsError_h
+#include "nsError.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+nsresult NS_InitGarbageCollector(void);
+nsresult NS_InitLeakDetector(void);
+nsresult NS_ShutdownLeakDetector(void);
+nsresult NS_ShutdownGarbageCollector(void);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* nsLeakDetector_h */
diff --git a/src/libs/xpcom18a4/xpcom/base/nsMemoryImpl.cpp b/src/libs/xpcom18a4/xpcom/base/nsMemoryImpl.cpp
new file mode 100644
index 00000000..8aa16e58
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsMemoryImpl.cpp
@@ -0,0 +1,548 @@
+/* -*- 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 "nsMemoryImpl.h"
+#include "prmem.h"
+#include "nsAlgorithm.h"
+#include "nsIServiceManager.h"
+#include "nsIObserverService.h"
+#include "nsAutoLock.h"
+#include "nsIThread.h"
+#include "nsIEventQueueService.h"
+#include "nsString.h"
+
+#if defined(XP_WIN)
+#include <windows.h>
+#define NS_MEMORY_FLUSHER_THREAD
+#elif defined(XP_MAC)
+#include <MacMemory.h>
+#define NS_MEMORY_FLUSHER_THREAD
+#else
+// Need to implement the nsIMemory::IsLowMemory() predicate
+#undef NS_MEMORY_FLUSHER_THREAD
+#endif
+
+//----------------------------------------------------------------------
+
+#if defined(XDEBUG_waterson)
+#define NS_TEST_MEMORY_FLUSHER
+#endif
+
+/**
+ * A runnable that is used to periodically check the status
+ * of the system, determine if too much memory is in use,
+ * and if so, trigger a "memory flush".
+ */
+class MemoryFlusher : public nsIRunnable
+{
+protected:
+ nsMemoryImpl* mMemoryImpl; // WEAK, it owns us.
+ PRBool mRunning;
+ PRIntervalTime mTimeout;
+ PRLock* mLock;
+ PRCondVar* mCVar;
+
+ MemoryFlusher(nsMemoryImpl* aMemoryImpl);
+
+ enum {
+ kInitialTimeout = 60 /*seconds*/
+ };
+
+private:
+ ~MemoryFlusher();
+
+public:
+ /**
+ * Create a memory flusher.
+ * @param aResult the memory flusher
+ * @param aMemoryImpl the owning nsMemoryImpl object
+ * @return NS_OK if the memory flusher was created successfully
+ */
+ static nsresult
+ Create(MemoryFlusher** aResult, nsMemoryImpl* aMemoryImpl);
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIRUNNABLE
+
+ /**
+ * Stop the memory flusher.
+ */
+ nsresult Stop();
+};
+
+
+MemoryFlusher::MemoryFlusher(nsMemoryImpl* aMemoryImpl)
+ : mMemoryImpl(aMemoryImpl),
+ mRunning(PR_FALSE),
+ mTimeout(PR_SecondsToInterval(kInitialTimeout)),
+ mLock(nsnull),
+ mCVar(nsnull)
+{
+}
+
+MemoryFlusher::~MemoryFlusher()
+{
+ if (mLock)
+ PR_DestroyLock(mLock);
+
+ if (mCVar)
+ PR_DestroyCondVar(mCVar);
+}
+
+
+nsresult
+MemoryFlusher::Create(MemoryFlusher** aResult, nsMemoryImpl* aMemoryImpl)
+{
+ MemoryFlusher* result = new MemoryFlusher(aMemoryImpl);
+ if (! result)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ do {
+ if ((result->mLock = PR_NewLock()) == nsnull)
+ break;
+
+ if ((result->mCVar = PR_NewCondVar(result->mLock)) == nsnull)
+ break;
+
+ NS_ADDREF(*aResult = result);
+ return NS_OK;
+ } while (0);
+
+ // Something bad happened if we get here...
+ delete result;
+ return NS_ERROR_OUT_OF_MEMORY;
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(MemoryFlusher, nsIRunnable)
+
+NS_IMETHODIMP
+MemoryFlusher::Run()
+{
+ nsresult rv;
+
+ mRunning = PR_TRUE;
+
+ while (1) {
+ PRStatus status;
+
+ {
+ nsAutoLock l(mLock);
+ if (! mRunning) {
+ rv = NS_OK;
+ break;
+ }
+
+ status = PR_WaitCondVar(mCVar, mTimeout);
+ }
+
+ if (status != PR_SUCCESS) {
+ rv = NS_ERROR_FAILURE;
+ break;
+ }
+
+ if (! mRunning) {
+ rv = NS_OK;
+ break;
+ }
+
+ PRBool isLowMemory;
+ rv = mMemoryImpl->IsLowMemory(&isLowMemory);
+ if (NS_FAILED(rv))
+ break;
+
+#ifdef NS_TEST_MEMORY_FLUSHER
+ // Fire the flusher *every* time
+ isLowMemory = PR_TRUE;
+#endif
+
+ if (isLowMemory) {
+ mMemoryImpl->FlushMemory(NS_LITERAL_STRING("low-memory").get(), PR_FALSE);
+ }
+ }
+
+ mRunning = PR_FALSE;
+
+ return rv;
+}
+
+
+nsresult
+MemoryFlusher::Stop()
+{
+ if (mRunning) {
+ nsAutoLock l(mLock);
+ mRunning = PR_FALSE;
+ PR_NotifyCondVar(mCVar);
+ }
+
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------
+
+nsMemoryImpl* gMemory = nsnull;
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsMemoryImpl, nsIMemory)
+
+NS_METHOD
+nsMemoryImpl::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
+{
+ NS_ENSURE_ARG_POINTER(aInstancePtr);
+ NS_ENSURE_PROPER_AGGREGATION(outer, aIID);
+ if (gMemory && NS_SUCCEEDED(gMemory->QueryInterface(aIID, aInstancePtr)))
+ return NS_OK;
+
+ nsMemoryImpl* mm = new nsMemoryImpl();
+ if (mm == NULL)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv;
+
+ do {
+ rv = mm->QueryInterface(aIID, aInstancePtr);
+ if (NS_FAILED(rv))
+ break;
+
+ rv = NS_ERROR_OUT_OF_MEMORY;
+
+ mm->mFlushLock = PR_NewLock();
+ if (! mm->mFlushLock)
+ break;
+
+ rv = NS_OK;
+ } while (0);
+
+ if (NS_FAILED(rv))
+ delete mm;
+
+ return rv;
+}
+
+
+nsMemoryImpl::nsMemoryImpl()
+ : mFlusher(nsnull),
+ mFlushLock(nsnull),
+ mIsFlushing(PR_FALSE)
+{
+}
+
+nsMemoryImpl::~nsMemoryImpl()
+{
+ if (mFlushLock)
+ PR_DestroyLock(mFlushLock);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Define NS_OUT_OF_MEMORY_TESTER if you want to force memory failures
+
+#ifdef DEBUG_xwarren
+#define NS_OUT_OF_MEMORY_TESTER
+#endif
+
+#ifdef NS_OUT_OF_MEMORY_TESTER
+
+// flush memory one in this number of times:
+#define NS_FLUSH_FREQUENCY 100000
+
+// fail allocation one in this number of flushes:
+#define NS_FAIL_FREQUENCY 10
+
+PRUint32 gFlushFreq = 0;
+PRUint32 gFailFreq = 0;
+
+static void*
+mallocator(PRSize size, PRUint32& counter, PRUint32 max)
+{
+ if (counter++ >= max) {
+ counter = 0;
+ NS_ASSERTION(0, "about to fail allocation... watch out");
+ return nsnull;
+ }
+ return PR_Malloc(size);
+}
+
+static void*
+reallocator(void* ptr, PRSize size, PRUint32& counter, PRUint32 max)
+{
+ if (counter++ >= max) {
+ counter = 0;
+ NS_ASSERTION(0, "about to fail reallocation... watch out");
+ return nsnull;
+ }
+ return PR_Realloc(ptr, size);
+}
+
+#define MALLOC1(s) mallocator(s, gFlushFreq, NS_FLUSH_FREQUENCY)
+#define REALLOC1(p, s) reallocator(p, s, gFlushFreq, NS_FLUSH_FREQUENCY)
+
+#else
+
+#define MALLOC1(s) PR_Malloc(s)
+#define REALLOC1(p, s) PR_Realloc(p, s)
+
+#endif // NS_OUT_OF_MEMORY_TESTER
+
+////////////////////////////////////////////////////////////////////////////////
+
+NS_IMETHODIMP_(void *)
+nsMemoryImpl::Alloc(PRSize size)
+{
+ NS_ASSERTION(size, "nsMemoryImpl::Alloc of 0");
+ void* result = MALLOC1(size);
+ if (! result) {
+ // Request an asynchronous flush
+ FlushMemory(NS_LITERAL_STRING("alloc-failure").get(), PR_FALSE);
+ }
+ return result;
+}
+
+NS_IMETHODIMP_(void *)
+nsMemoryImpl::Realloc(void * ptr, PRSize size)
+{
+ void* result = REALLOC1(ptr, size);
+ if (! result) {
+ // Request an asynchronous flush
+ FlushMemory(NS_LITERAL_STRING("alloc-failure").get(), PR_FALSE);
+ }
+ return result;
+}
+
+NS_IMETHODIMP_(void)
+nsMemoryImpl::Free(void * ptr)
+{
+ PR_Free(ptr);
+}
+
+NS_IMETHODIMP
+nsMemoryImpl::HeapMinimize(PRBool aImmediate)
+{
+ return FlushMemory(NS_LITERAL_STRING("heap-minimize").get(), aImmediate);
+}
+
+NS_IMETHODIMP
+nsMemoryImpl::IsLowMemory(PRBool *result)
+{
+#if defined(XP_WIN)
+ MEMORYSTATUS stat;
+ GlobalMemoryStatus(&stat);
+ *result = ((float)stat.dwAvailPageFile / stat.dwTotalPageFile) < 0.1;
+#elif defined(XP_MAC)
+
+ const long kReserveHeapFreeSpace = (256 * 1024);
+ const long kReserveHeapContigSpace = (128 * 1024);
+
+ long totalSpace, contiguousSpace;
+ // this call measures how much memory would be available if the OS
+ // purged. Despite the name, it does not purge (that happens
+ // automatically when heap space is low).
+ ::PurgeSpace(&totalSpace, &contiguousSpace);
+ if (totalSpace < kReserveHeapFreeSpace || contiguousSpace < kReserveHeapContigSpace)
+ {
+ NS_WARNING("Found that heap mem is low");
+ *result = PR_TRUE;
+ return NS_OK;
+ }
+
+ // see how much temp mem is available (since our allocators allocate 1Mb chunks
+ // in temp mem. We don't use TempMaxMem() (to get contig space) here, because it
+ // compacts the application heap, so can be slow.
+ const long kReserveTempFreeSpace = (2 * 1024 * 1024); // 2Mb
+ long totalTempSpace = ::TempFreeMem();
+ if (totalTempSpace < kReserveTempFreeSpace)
+ {
+ NS_WARNING("Found that temp mem is low");
+ *result = PR_TRUE;
+ return NS_OK;
+ }
+
+ *result = PR_FALSE;
+
+#else
+ *result = PR_FALSE;
+#endif
+ return NS_OK;
+}
+
+nsresult
+nsMemoryImpl::FlushMemory(const PRUnichar* aReason, PRBool aImmediate)
+{
+ nsresult rv;
+
+ if (aImmediate) {
+ // They've asked us to run the flusher *immediately*. We've
+ // got to be on the UI main thread for us to be able to do
+ // that...are we?
+ PRBool isOnUIThread = PR_FALSE;
+
+ nsCOMPtr<nsIThread> main;
+ rv = nsIThread::GetMainThread(getter_AddRefs(main));
+ if (NS_SUCCEEDED(rv)) {
+ nsCOMPtr<nsIThread> current;
+ rv = nsIThread::GetCurrent(getter_AddRefs(current));
+ if (NS_SUCCEEDED(rv)) {
+ if (current == main)
+ isOnUIThread = PR_TRUE;
+ }
+ }
+
+ if (! isOnUIThread) {
+ NS_ERROR("can't synchronously flush memory: not on UI thread");
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ {
+ // Are we already flushing?
+ nsAutoLock l(mFlushLock);
+ if (mIsFlushing)
+ return NS_OK;
+
+ // Well, we are now!
+ mIsFlushing = PR_TRUE;
+ }
+
+ // Run the flushers immediately if we can; otherwise, proxy to the
+ // UI thread an run 'em asynchronously.
+ if (aImmediate) {
+ rv = RunFlushers(this, aReason);
+ }
+ else {
+ nsCOMPtr<nsIEventQueueService> eqs = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv);
+ if (eqs) {
+ nsCOMPtr<nsIEventQueue> eq;
+ rv = eqs->GetThreadEventQueue(NS_UI_THREAD, getter_AddRefs(eq));
+ if (NS_SUCCEEDED(rv)) {
+ PL_InitEvent(&mFlushEvent.mEvent, this, HandleFlushEvent, DestroyFlushEvent);
+ mFlushEvent.mReason = aReason;
+
+ rv = eq->PostEvent(NS_REINTERPRET_CAST(PLEvent*, &mFlushEvent));
+ }
+ }
+ }
+
+ return rv;
+}
+
+nsresult
+nsMemoryImpl::RunFlushers(nsMemoryImpl* aSelf, const PRUnichar* aReason)
+{
+ nsCOMPtr<nsIObserverService> os = do_GetService("@mozilla.org/observer-service;1");
+ if (os) {
+ os->NotifyObservers(aSelf, "memory-pressure", aReason);
+ }
+
+ {
+ // Done flushing
+ nsAutoLock l(aSelf->mFlushLock);
+ aSelf->mIsFlushing = PR_FALSE;
+ }
+
+ return NS_OK;
+}
+
+void*
+nsMemoryImpl::HandleFlushEvent(PLEvent* aEvent)
+{
+ nsMemoryImpl* self = NS_STATIC_CAST(nsMemoryImpl*, PL_GetEventOwner(aEvent));
+ FlushEvent* event = NS_REINTERPRET_CAST(FlushEvent*, aEvent);
+
+ RunFlushers(self, event->mReason);
+ return 0;
+}
+
+void
+nsMemoryImpl::DestroyFlushEvent(PLEvent* aEvent)
+{
+ // no-op, since mEvent is a member of nsMemoryImpl
+}
+
+static void
+EnsureGlobalMemoryService()
+{
+ if (gMemory) return;
+ nsresult rv = nsMemoryImpl::Create(nsnull, NS_GET_IID(nsIMemory), (void**)&gMemory);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "nsMemoryImpl::Create failed");
+ NS_ASSERTION(gMemory, "improper xpcom initialization");
+}
+
+nsresult
+nsMemoryImpl::Startup()
+{
+ EnsureGlobalMemoryService();
+ if (! gMemory)
+ return NS_ERROR_FAILURE;
+
+#ifdef NS_MEMORY_FLUSHER_THREAD
+ nsresult rv;
+
+ // Create and start a memory flusher thread
+ rv = MemoryFlusher::Create(&gMemory->mFlusher, gMemory);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = NS_NewThread(getter_AddRefs(gMemory->mFlusherThread),
+ gMemory->mFlusher,
+ 0, /* XXX use default stack size? */
+ PR_JOINABLE_THREAD);
+
+ if (NS_FAILED(rv)) return rv;
+#endif
+
+ return NS_OK;
+}
+
+nsresult
+nsMemoryImpl::Shutdown()
+{
+ if (gMemory) {
+#ifdef NS_MEMORY_FLUSHER_THREAD
+ if (gMemory->mFlusher) {
+ // Stop the runnable...
+ gMemory->mFlusher->Stop();
+ NS_RELEASE(gMemory->mFlusher);
+
+ // ...and wait for the thread to exit
+ if (gMemory->mFlusherThread)
+ gMemory->mFlusherThread->Join();
+ }
+#endif
+
+ NS_RELEASE(gMemory);
+ gMemory = nsnull;
+ }
+
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/base/nsMemoryImpl.h b/src/libs/xpcom18a4/xpcom/base/nsMemoryImpl.h
new file mode 100644
index 00000000..c9086d11
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsMemoryImpl.h
@@ -0,0 +1,91 @@
+/* -*- 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 nsMemoryImpl_h__
+#define nsMemoryImpl_h__
+
+#include "nsMemory.h"
+#include "nsISupportsArray.h"
+#include "nsIRunnable.h"
+#include "nsIThread.h"
+#include "nsCOMPtr.h"
+#include "plevent.h"
+
+struct PRLock;
+class MemoryFlusher;
+
+class nsMemoryImpl : public nsIMemory
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIMEMORY
+
+ nsMemoryImpl();
+
+ nsresult FlushMemory(const PRUnichar* aReason, PRBool aImmediate);
+
+ // called from xpcom initialization/finalization:
+ static nsresult Startup();
+ static nsresult Shutdown();
+
+ static NS_METHOD
+ Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+private:
+ ~nsMemoryImpl();
+
+protected:
+ MemoryFlusher* mFlusher;
+ nsCOMPtr<nsIThread> mFlusherThread;
+
+ PRLock* mFlushLock;
+ PRBool mIsFlushing;
+
+ struct FlushEvent {
+ PLEvent mEvent;
+ const PRUnichar* mReason;
+ };
+
+ FlushEvent mFlushEvent;
+
+ static nsresult RunFlushers(nsMemoryImpl* aSelf, const PRUnichar* aReason);
+
+ static void* PR_CALLBACK HandleFlushEvent(PLEvent* aEvent);
+ static void PR_CALLBACK DestroyFlushEvent(PLEvent* aEvent);
+};
+
+#endif // nsMemoryImpl_h__
diff --git a/src/libs/xpcom18a4/xpcom/base/nsStackFrameUnix.cpp b/src/libs/xpcom18a4/xpcom/base/nsStackFrameUnix.cpp
new file mode 100644
index 00000000..11fe0fca
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsStackFrameUnix.cpp
@@ -0,0 +1,375 @@
+/* -*- 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 nsStackFrameWin.h code, released
+ * December 20, 2000.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * 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 "nsStackFrameUnix.h"
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "nscore.h"
+
+// On glibc 2.1, the Dl_info api defined in <dlfcn.h> is only exposed
+// if __USE_GNU is defined. I suppose its some kind of standards
+// adherence thing.
+//
+#if (__GLIBC_MINOR__ >= 1) && !defined(__USE_GNU)
+#define __USE_GNU
+#endif
+
+#ifdef HAVE_LIBDL
+#include <dlfcn.h>
+#endif
+
+
+
+// This thing is exported by libstdc++
+// Yes, this is a gcc only hack
+#if defined(MOZ_DEMANGLE_SYMBOLS)
+#include <cxxabi.h>
+#include <stdlib.h> // for free()
+#endif // MOZ_DEMANGLE_SYMBOLS
+
+void DemangleSymbol(const char * aSymbol,
+ char * aBuffer,
+ int aBufLen)
+{
+ aBuffer[0] = '\0';
+
+#if defined(MOZ_DEMANGLE_SYMBOLS)
+ /* See demangle.h in the gcc source for the voodoo */
+ char * demangled = abi::__cxa_demangle(aSymbol,0,0,0);
+
+ if (demangled)
+ {
+ strncpy(aBuffer,demangled,aBufLen);
+ free(demangled);
+ }
+#endif // MOZ_DEMANGLE_SYMBOLS
+}
+
+
+#if defined(linux) && !defined(VBOX) && defined(__GLIBC__) && (defined(__i386) || defined(PPC)) // i386 or PPC Linux stackwalking code
+
+#include <setjmp.h>
+//
+
+void DumpStackToFile(FILE* aStream)
+{
+ jmp_buf jb;
+ setjmp(jb);
+
+ // Stack walking code courtesy Kipp's "leaky".
+
+ // Get the frame pointer out of the jmp_buf
+ void **bp = (void**)
+#if defined(__i386)
+ (jb[0].__jmpbuf[JB_BP]);
+#elif defined(PPC)
+ (jb[0].__jmpbuf[JB_GPR1]);
+#endif
+
+ int skip = 2;
+ for ( ; (void**)*bp > bp; bp = (void**)*bp) {
+ void *pc = *(bp+1);
+ if (--skip <= 0) {
+ Dl_info info;
+ int ok = dladdr(pc, &info);
+ if (!ok) {
+ fprintf(aStream, "UNKNOWN %p\n", pc);
+ continue;
+ }
+
+ PRUint32 foff = (char*)pc - (char*)info.dli_fbase;
+
+ const char * symbol = info.dli_sname;
+ int len;
+ if (!symbol || !(len = strlen(symbol))) {
+ fprintf(aStream, "UNKNOWN [%s +0x%08X]\n",
+ info.dli_fname, foff);
+ continue;
+ }
+
+ char demangled[4096] = "\0";
+
+ DemangleSymbol(symbol, demangled, sizeof(demangled));
+
+ if (strlen(demangled)) {
+ symbol = demangled;
+ len = strlen(symbol);
+ }
+
+ PRUint32 off = (char*)pc - (char*)info.dli_saddr;
+ fprintf(aStream, "%s+0x%08X [%s +0x%08X]\n",
+ symbol, off, info.dli_fname, foff);
+ }
+ }
+}
+
+#elif defined(__sun) && (defined(__sparc) || defined(sparc) || defined(__i386) || defined(i386))
+
+/*
+ * Stack walking code for Solaris courtesy of Bart Smaalder's "memtrak".
+ */
+
+#include <synch.h>
+#include <ucontext.h>
+#include <sys/frame.h>
+#include <sys/regset.h>
+#include <sys/stack.h>
+
+static int load_address ( void * pc, void * arg, FILE * aStream );
+static int write_address_file ( void * pc );
+static struct bucket * newbucket ( void * pc );
+static struct frame * cs_getmyframeptr ( void );
+static void cs_walk_stack ( void * (*read_func)(char * address),
+ struct frame * fp,
+ int (*operate_func)(void *, void *),
+ void * usrarg, FILE * aStream );
+static void cs_operate ( void (*operate_func)(void *, void *),
+ void * usrarg, FILE * aStream );
+
+#ifndef STACK_BIAS
+#define STACK_BIAS 0
+#endif /*STACK_BIAS*/
+
+#define LOGSIZE 4096
+
+/* type of demangling function */
+typedef int demf_t(const char *, char *, size_t);
+
+static demf_t *demf;
+
+static int initialized = 0;
+
+#if defined(sparc) || defined(__sparc)
+#define FRAME_PTR_REGISTER REG_SP
+#endif
+
+#if defined(i386) || defined(__i386)
+#define FRAME_PTR_REGISTER EBP
+#endif
+
+struct bucket {
+ void * pc;
+ int index;
+ struct bucket * next;
+};
+
+struct mybuf {
+ char * buffer;
+ int chars_left;
+};
+
+
+static void myinit();
+
+#pragma init (myinit)
+
+static void
+myinit()
+{
+
+ if (! initialized) {
+#ifndef __GNUC__
+ void *handle;
+ const char *libdem = "libdemangle.so.1";
+
+ /* load libdemangle if we can and need to (only try this once) */
+ if ((handle = dlopen(libdem, RTLD_LAZY)) != NULL) {
+ demf = (demf_t *)dlsym(handle,
+ "cplus_demangle"); /*lint !e611 */
+ /*
+ * lint override above is to prevent lint from
+ * complaining about "suspicious cast".
+ */
+ }
+#endif /*__GNUC__*/
+ }
+ initialized = 1;
+}
+
+
+static int
+write_address_file(void * pc, FILE* aStream)
+{
+ static struct bucket table[2048];
+ static mutex_t lock;
+ struct bucket * ptr;
+
+ unsigned int val = NS_PTR_TO_INT32(pc);
+
+ ptr = table + ((val >> 2)&2047);
+
+ mutex_lock(&lock);
+ while (ptr->next) {
+ if (ptr->next->pc == pc)
+ break;
+ ptr = ptr->next;
+ }
+
+ if (ptr->next) {
+ mutex_unlock(&lock);
+ return (ptr->next->index);
+ } else {
+ char buffer[4096], dembuff[4096];
+ Dl_info info;
+ const char *func = "??", *lib = "??";
+
+ ptr->next = newbucket(pc);
+ mutex_unlock(&lock);
+
+ if (dladdr(pc, & info)) {
+ if (info.dli_fname)
+ lib = info.dli_fname;
+ if (info.dli_sname)
+ func = info.dli_sname;
+ }
+
+#ifdef __GNUC__
+ DemangleSymbol(func, dembuff, sizeof(dembuff));
+#else
+ if (!demf || demf(func, dembuff, sizeof (dembuff)))
+ dembuff[0] = 0;
+#endif /*__GNUC__*/
+ if (strlen(dembuff)) {
+ func = dembuff;
+ }
+ fprintf(aStream, "%u %s:%s+0x%x\n",
+ ptr->next->index,
+ lib,
+ func,
+ (char *)pc - (char*)info.dli_saddr);
+
+ return (ptr->next->index);
+ }
+}
+
+
+static int
+load_address(void * pc, void * arg, FILE * aStream)
+{
+ struct mybuf * buf = (struct mybuf *) arg;
+
+ char name[80];
+ int len;
+
+ sprintf(name, " %u", write_address_file(pc, aStream));
+
+ len = strlen(name);
+
+ if (len >= buf->chars_left)
+ return (1);
+
+ strcat(buf->buffer, name);
+
+ buf->chars_left -= len;
+
+ return (0);
+}
+
+
+static struct bucket *
+newbucket(void * pc)
+{
+ struct bucket * ptr = (struct bucket *) malloc(sizeof (*ptr));
+ static int index; /* protected by lock in caller */
+
+ ptr->index = index++;
+ ptr->next = NULL;
+ ptr->pc = pc;
+ return (ptr);
+}
+
+
+static struct frame *
+csgetframeptr()
+{
+ ucontext_t u;
+ struct frame *fp;
+
+ (void) getcontext(&u);
+
+ fp = (struct frame *)
+ ((char *)u.uc_mcontext.gregs[FRAME_PTR_REGISTER] +
+ STACK_BIAS);
+
+ /* make sure to return parents frame pointer.... */
+
+ return ((struct frame *)((ulong_t)fp->fr_savfp + STACK_BIAS));
+}
+
+
+static void
+cswalkstack(struct frame *fp, int (*operate_func)(void *, void *, FILE *),
+ void *usrarg, FILE * aStream)
+{
+
+ while (fp != 0 && fp->fr_savpc != 0) {
+
+ if (operate_func((void *)fp->fr_savpc, usrarg, aStream) != 0)
+ break;
+ /*
+ * watch out - libthread stacks look funny at the top
+ * so they may not have their STACK_BIAS set
+ */
+
+ fp = (struct frame *)((ulong_t)fp->fr_savfp +
+ (fp->fr_savfp?(ulong_t)STACK_BIAS:0));
+ }
+}
+
+
+static void
+cs_operate(int (*operate_func)(void *, void *, FILE *), void * usrarg, FILE *aStream)
+{
+ cswalkstack(csgetframeptr(), operate_func, usrarg, aStream);
+}
+
+void DumpStackToFile(FILE* aStream)
+{
+ char buffer[LOGSIZE];
+ struct mybuf mybuf;
+
+ if (!initialized)
+ myinit();
+
+ mybuf.chars_left = LOGSIZE - strlen(buffer)-1;
+ mybuf.buffer = buffer;
+ cs_operate(load_address, &mybuf, aStream);
+}
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/base/nsStackFrameUnix.h b/src/libs/xpcom18a4/xpcom/base/nsStackFrameUnix.h
new file mode 100644
index 00000000..1673ae76
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsStackFrameUnix.h
@@ -0,0 +1,46 @@
+/* -*- 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 nsStackFrameWin.h code, released
+ * December 20, 2000.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * 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 nsStackFrameUnix_h___
+#define nsStackFrameUnix_h___
+
+#include "stdio.h"
+
+void DumpStackToFile(FILE* out);
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/base/nsStackFrameWin.cpp b/src/libs/xpcom18a4/xpcom/base/nsStackFrameWin.cpp
new file mode 100644
index 00000000..7228356b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsStackFrameWin.cpp
@@ -0,0 +1,351 @@
+/* -*- 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 nsStackFrameWin.h code, released
+ * December 20, 2003.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Michael Judge, 20-December-2000
+ *
+ * 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 "windows.h"
+#include "imagehlp.h"
+#include "stdio.h"
+#include "nsStackFrameWin.h"
+
+// Define these as static pointers so that we can load the DLL on the
+// fly (and not introduce a link-time dependency on it). Tip o' the
+// hat to Matt Pietrick for this idea. See:
+//
+// http://msdn.microsoft.com/library/periodic/period97/F1/D3/S245C6.htm
+//
+
+
+PR_BEGIN_EXTERN_C
+
+SYMSETOPTIONSPROC _SymSetOptions;
+
+SYMINITIALIZEPROC _SymInitialize;
+
+SYMCLEANUPPROC _SymCleanup;
+
+STACKWALKPROC _StackWalk;
+
+SYMFUNCTIONTABLEACCESSPROC _SymFunctionTableAccess;
+
+SYMGETMODULEBASEPROC _SymGetModuleBase;
+
+SYMGETSYMFROMADDRPROC _SymGetSymFromAddr;
+
+SYMLOADMODULE _SymLoadModule;
+
+SYMUNDNAME _SymUnDName;
+
+SYMGETMODULEINFO _SymGetModuleInfo;
+
+ENUMLOADEDMODULES _EnumerateLoadedModules;
+
+SYMGETLINEFROMADDRPROC _SymGetLineFromAddr;
+
+PR_END_EXTERN_C
+
+
+
+
+PRBool
+EnsureImageHlpInitialized()
+{
+ static PRBool gInitialized = PR_FALSE;
+
+ if (! gInitialized) {
+ HMODULE module = ::LoadLibrary("IMAGEHLP.DLL");
+ if (!module) return PR_FALSE;
+
+ _SymSetOptions = (SYMSETOPTIONSPROC) ::GetProcAddress(module, "SymSetOptions");
+ if (!_SymSetOptions) return PR_FALSE;
+
+ _SymInitialize = (SYMINITIALIZEPROC) ::GetProcAddress(module, "SymInitialize");
+ if (!_SymInitialize) return PR_FALSE;
+
+ _SymCleanup = (SYMCLEANUPPROC)GetProcAddress(module, "SymCleanup");
+ if (!_SymCleanup) return PR_FALSE;
+
+ _StackWalk = (STACKWALKPROC)GetProcAddress(module, "StackWalk");
+ if (!_StackWalk) return PR_FALSE;
+
+ _SymFunctionTableAccess = (SYMFUNCTIONTABLEACCESSPROC) GetProcAddress(module, "SymFunctionTableAccess");
+ if (!_SymFunctionTableAccess) return PR_FALSE;
+
+ _SymGetModuleBase = (SYMGETMODULEBASEPROC)GetProcAddress(module, "SymGetModuleBase");
+ if (!_SymGetModuleBase) return PR_FALSE;
+
+ _SymGetSymFromAddr = (SYMGETSYMFROMADDRPROC)GetProcAddress(module, "SymGetSymFromAddr");
+ if (!_SymGetSymFromAddr) return PR_FALSE;
+
+ _SymLoadModule = (SYMLOADMODULE)GetProcAddress(module, "SymLoadModule");
+ if (!_SymLoadModule) return PR_FALSE;
+
+ _SymUnDName = (SYMUNDNAME)GetProcAddress(module, "SymUnDName");
+ if (!_SymUnDName) return PR_FALSE;
+
+ _SymGetModuleInfo = (SYMGETMODULEINFO)GetProcAddress(module, "SymGetModuleInfo");
+ if (!_SymGetModuleInfo) return PR_FALSE;
+
+ _EnumerateLoadedModules = (ENUMLOADEDMODULES)GetProcAddress(module, "EnumerateLoadedModules");
+ if (!_EnumerateLoadedModules) return PR_FALSE;
+
+ _SymGetLineFromAddr = (SYMGETLINEFROMADDRPROC)GetProcAddress(module, "SymGetLineFromAddr");
+ if (!_SymGetLineFromAddr) return PR_FALSE;
+
+ gInitialized = PR_TRUE;
+ }
+
+ return gInitialized;
+}
+
+/*
+ * Callback used by SymGetModuleInfoEspecial
+ */
+static BOOL CALLBACK callbackEspecial(LPSTR aModuleName, ULONG aModuleBase, ULONG aModuleSize, PVOID aUserContext)
+{
+ BOOL retval = TRUE;
+ DWORD addr = (DWORD)aUserContext;
+
+ /*
+ * You'll want to control this if we are running on an
+ * architecture where the addresses go the other direction.
+ * Not sure this is even a realistic consideration.
+ */
+ const BOOL addressIncreases = TRUE;
+
+ /*
+ * If it falls in side the known range, load the symbols.
+ */
+ if(addressIncreases
+ ? (addr >= aModuleBase && addr <= (aModuleBase + aModuleSize))
+ : (addr <= aModuleBase && addr >= (aModuleBase - aModuleSize))
+ )
+ {
+ BOOL loadRes = FALSE;
+ HANDLE process = GetCurrentProcess();
+
+ loadRes = _SymLoadModule(process, NULL, aModuleName, NULL, aModuleBase, aModuleSize);
+ PR_ASSERT(FALSE != loadRes);
+ }
+
+ return retval;
+}
+
+/*
+ * SymGetModuleInfoEspecial
+ *
+ * Attempt to determine the module information.
+ * Bug 112196 says this DLL may not have been loaded at the time
+ * SymInitialize was called, and thus the module information
+ * and symbol information is not available.
+ * This code rectifies that problem.
+ */
+BOOL SymGetModuleInfoEspecial(HANDLE aProcess, DWORD aAddr, PIMAGEHLP_MODULE aModuleInfo, PIMAGEHLP_LINE aLineInfo)
+{
+ BOOL retval = FALSE;
+
+ /*
+ * Init the vars if we have em.
+ */
+ aModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULE);
+ if (nsnull != aLineInfo) {
+ aLineInfo->SizeOfStruct = sizeof(IMAGEHLP_LINE);
+ }
+
+ /*
+ * Give it a go.
+ * It may already be loaded.
+ */
+ retval = _SymGetModuleInfo(aProcess, aAddr, aModuleInfo);
+
+ if (FALSE == retval) {
+ BOOL enumRes = FALSE;
+
+ /*
+ * Not loaded, here's the magic.
+ * Go through all the modules.
+ */
+ enumRes = _EnumerateLoadedModules(aProcess, callbackEspecial, (PVOID)aAddr);
+ if(FALSE != enumRes)
+ {
+ /*
+ * One final go.
+ * If it fails, then well, we have other problems.
+ */
+ retval = _SymGetModuleInfo(aProcess, aAddr, aModuleInfo);
+ }
+ }
+
+ /*
+ * If we got module info, we may attempt line info as well.
+ * We will not report failure if this does not work.
+ */
+ if (FALSE != retval && nsnull != aLineInfo && nsnull != _SymGetLineFromAddr) {
+ DWORD displacement = 0;
+ BOOL lineRes = FALSE;
+
+ lineRes = _SymGetLineFromAddr(aProcess, aAddr, &displacement, aLineInfo);
+ }
+
+ return retval;
+}
+
+PRBool
+EnsureSymInitialized()
+{
+ static PRBool gInitialized = PR_FALSE;
+
+ if (! gInitialized) {
+ if (! EnsureImageHlpInitialized())
+ return PR_FALSE;
+ _SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
+ gInitialized = _SymInitialize(GetCurrentProcess(), 0, TRUE);
+ }
+ return gInitialized;
+}
+
+
+/**
+ * Walk the stack, translating PC's found into strings and recording the
+ * chain in aBuffer. For this to work properly, the dll's must be rebased
+ * so that the address in the file agrees with the address in memory.
+ * Otherwise StackWalk will return FALSE when it hits a frame in a dll's
+ * whose in memory address doesn't match it's in-file address.
+ *
+ * Fortunately, there is a handy dandy routine in IMAGEHLP.DLL that does
+ * the rebasing and accordingly I've made a tool to use it to rebase the
+ * DLL's in one fell swoop (see xpcom/tools/windows/rebasedlls.cpp).
+ */
+
+
+void
+DumpStackToFile(FILE* aStream)
+{
+ HANDLE myProcess = ::GetCurrentProcess();
+ HANDLE myThread = ::GetCurrentThread();
+ BOOL ok;
+
+ ok = EnsureSymInitialized();
+ if (! ok)
+ return;
+
+ // Get the context information for this thread. That way we will
+ // know where our sp, fp, pc, etc. are and can fill in the
+ // STACKFRAME with the initial values.
+ CONTEXT context;
+ context.ContextFlags = CONTEXT_FULL;
+ ok = GetThreadContext(myThread, &context);
+ if (! ok)
+ return;
+
+ // Setup initial stack frame to walk from
+ STACKFRAME frame;
+ memset(&frame, 0, sizeof(frame));
+ frame.AddrPC.Offset = context.Eip;
+ frame.AddrPC.Mode = AddrModeFlat;
+ frame.AddrStack.Offset = context.Esp;
+ frame.AddrStack.Mode = AddrModeFlat;
+ frame.AddrFrame.Offset = context.Ebp;
+ frame.AddrFrame.Mode = AddrModeFlat;
+
+ // Now walk the stack and map the pc's to symbol names
+ int skip = 2;
+ while (1) {
+ ok = _StackWalk(IMAGE_FILE_MACHINE_I386,
+ myProcess,
+ myThread,
+ &frame,
+ &context,
+ 0, // read process memory routine
+ _SymFunctionTableAccess, // function table access routine
+ _SymGetModuleBase, // module base routine
+ 0); // translate address routine
+
+ if (!ok) {
+ LPVOID lpMsgBuf;
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL
+ );
+ fprintf(aStream, "### ERROR: WalkStack: %s", lpMsgBuf);
+ fflush(aStream);
+ LocalFree( lpMsgBuf );
+ }
+ if (!ok || frame.AddrPC.Offset == 0)
+ break;
+
+ if (skip-- > 0)
+ continue;
+
+ //
+ // Attempt to load module info before we attempt to reolve the symbol.
+ // This just makes sure we get good info if available.
+ //
+ IMAGEHLP_MODULE modInfo;
+ modInfo.SizeOfStruct = sizeof(modInfo);
+ BOOL modInfoRes = TRUE;
+ modInfoRes = SymGetModuleInfoEspecial(myProcess, frame.AddrPC.Offset, &modInfo, nsnull);
+
+ char buf[sizeof(IMAGEHLP_SYMBOL) + 512];
+ PIMAGEHLP_SYMBOL symbol = (PIMAGEHLP_SYMBOL) buf;
+ symbol->SizeOfStruct = sizeof(buf);
+ symbol->MaxNameLength = 512;
+
+ DWORD displacement;
+ ok = _SymGetSymFromAddr(myProcess,
+ frame.AddrPC.Offset,
+ &displacement,
+ symbol);
+
+ if (ok) {
+ fprintf(aStream, "%s+0x%08X\n", symbol->Name, displacement);
+ }
+ else {
+ fprintf(aStream, "0x%08X\n", frame.AddrPC.Offset);
+ }
+ }
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsStackFrameWin.h b/src/libs/xpcom18a4/xpcom/base/nsStackFrameWin.h
new file mode 100644
index 00000000..d9b6585c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsStackFrameWin.h
@@ -0,0 +1,126 @@
+/* -*- 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 nsStackFrameWin.h code, released
+ * December 20, 2000.
+ *
+ * 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):
+ * Michael Judge, 20-December-2000
+ *
+ * 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 nsStackFrameWin_h___
+#define nsStackFrameWin_h___
+
+
+#if defined(_WIN32) && defined(_M_IX86) // WIN32 x86 stack walking code
+#include "nspr.h"
+#include <windows.h>
+#include <imagehlp.h>
+
+// Define these as static pointers so that we can load the DLL on the
+// fly (and not introduce a link-time dependency on it). Tip o' the
+// hat to Matt Pietrick for this idea. See:
+//
+// http://msdn.microsoft.com/library/periodic/period97/F1/D3/S245C6.htm
+//
+PR_BEGIN_EXTERN_C
+
+typedef DWORD (__stdcall *SYMSETOPTIONSPROC)(DWORD);
+extern SYMSETOPTIONSPROC _SymSetOptions;
+
+typedef BOOL (__stdcall *SYMINITIALIZEPROC)(HANDLE, LPSTR, BOOL);
+extern SYMINITIALIZEPROC _SymInitialize;
+
+typedef BOOL (__stdcall *SYMCLEANUPPROC)(HANDLE);
+extern SYMCLEANUPPROC _SymCleanup;
+
+typedef BOOL (__stdcall *STACKWALKPROC)(DWORD,
+ HANDLE,
+ HANDLE,
+ LPSTACKFRAME,
+ LPVOID,
+ PREAD_PROCESS_MEMORY_ROUTINE,
+ PFUNCTION_TABLE_ACCESS_ROUTINE,
+ PGET_MODULE_BASE_ROUTINE,
+ PTRANSLATE_ADDRESS_ROUTINE);
+extern STACKWALKPROC _StackWalk;
+
+typedef LPVOID (__stdcall *SYMFUNCTIONTABLEACCESSPROC)(HANDLE, DWORD);
+extern SYMFUNCTIONTABLEACCESSPROC _SymFunctionTableAccess;
+
+typedef DWORD (__stdcall *SYMGETMODULEBASEPROC)(HANDLE, DWORD);
+extern SYMGETMODULEBASEPROC _SymGetModuleBase;
+
+typedef BOOL (__stdcall *SYMGETSYMFROMADDRPROC)(HANDLE, DWORD, PDWORD, PIMAGEHLP_SYMBOL);
+extern SYMGETSYMFROMADDRPROC _SymGetSymFromAddr;
+
+typedef DWORD ( __stdcall *SYMLOADMODULE)(HANDLE, HANDLE, PSTR, PSTR, DWORD, DWORD);
+extern SYMLOADMODULE _SymLoadModule;
+
+typedef DWORD ( __stdcall *SYMUNDNAME)(PIMAGEHLP_SYMBOL, PSTR, DWORD);
+extern SYMUNDNAME _SymUnDName;
+
+typedef DWORD ( __stdcall *SYMGETMODULEINFO)( HANDLE, DWORD, PIMAGEHLP_MODULE);
+extern SYMGETMODULEINFO _SymGetModuleInfo;
+
+typedef BOOL ( __stdcall *ENUMLOADEDMODULES)( HANDLE, PENUMLOADED_MODULES_CALLBACK, PVOID);
+extern ENUMLOADEDMODULES _EnumerateLoadedModules;
+
+typedef BOOL (__stdcall *SYMGETLINEFROMADDRPROC)(HANDLE, DWORD, PDWORD, PIMAGEHLP_LINE);
+extern SYMGETLINEFROMADDRPROC _SymGetLineFromAddr;
+
+PRBool EnsureSymInitialized();
+
+PRBool EnsureImageHlpInitialized();
+
+/*
+ * SymGetModuleInfoEspecial
+ *
+ * Attempt to determine the module information.
+ * Bug 112196 says this DLL may not have been loaded at the time
+ * SymInitialize was called, and thus the module information
+ * and symbol information is not available.
+ * This code rectifies that problem.
+ * Line information is optional.
+ */
+BOOL SymGetModuleInfoEspecial(HANDLE aProcess, DWORD aAddr, PIMAGEHLP_MODULE aModuleInfo, PIMAGEHLP_LINE aLineInfo);
+
+
+void DumpStackToFile(FILE* out);
+
+PR_END_EXTERN_C
+
+#endif //WIN32
+
+#endif //nsStackFrameWin_h___
+
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsTraceRefcntImpl.cpp b/src/libs/xpcom18a4/xpcom/base/nsTraceRefcntImpl.cpp
new file mode 100644
index 00000000..f74e84df
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsTraceRefcntImpl.cpp
@@ -0,0 +1,1444 @@
+/* -*- 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):
+ * 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 ***** */
+
+#include "nsTraceRefcntImpl.h"
+#include "nscore.h"
+#include "nsISupports.h"
+#include "nsVoidArray.h"
+#include "prprf.h"
+#include "prlog.h"
+#include "plstr.h"
+#include <stdlib.h>
+#include "nsCOMPtr.h"
+#include "nsCRT.h"
+#include <math.h>
+
+#if defined(_WIN32)
+#include <windows.h>
+#elif defined(linux) && !defined(VBOX) && defined(__GLIBC__) && (defined(__i386) || defined(PPC))
+#include <setjmp.h>
+
+//
+// On glibc 2.1, the Dl_info api defined in <dlfcn.h> is only exposed
+// if __USE_GNU is defined. I suppose its some kind of standards
+// adherence thing.
+//
+#if (__GLIBC_MINOR__ >= 1) && !defined(__USE_GNU)
+#define __USE_GNU
+#endif
+
+#include <dlfcn.h>
+#endif
+
+#ifdef HAVE_LIBDL
+#include <dlfcn.h>
+#endif
+
+#if defined(XP_MAC) && !TARGET_CARBON
+#include "macstdlibextras.h"
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+
+NS_COM void
+NS_MeanAndStdDev(double n, double sumOfValues, double sumOfSquaredValues,
+ double *meanResult, double *stdDevResult)
+{
+ double mean = 0.0, var = 0.0, stdDev = 0.0;
+ if (n > 0.0 && sumOfValues >= 0) {
+ mean = sumOfValues / n;
+ double temp = (n * sumOfSquaredValues) - (sumOfValues * sumOfValues);
+ if (temp < 0.0 || n <= 1)
+ var = 0.0;
+ else
+ var = temp / (n * (n - 1));
+ // for some reason, Windows says sqrt(0.0) is "-1.#J" (?!) so do this:
+ stdDev = var != 0.0 ? sqrt(var) : 0.0;
+ }
+ *meanResult = mean;
+ *stdDevResult = stdDev;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+#include "plhash.h"
+#include "prmem.h"
+
+#include "prlock.h"
+
+static PRLock* gTraceLock;
+
+#define LOCK_TRACELOG() PR_Lock(gTraceLock)
+#define UNLOCK_TRACELOG() PR_Unlock(gTraceLock)
+
+static PLHashTable* gBloatView;
+static PLHashTable* gTypesToLog;
+static PLHashTable* gObjectsToLog;
+static PLHashTable* gSerialNumbers;
+static PRInt32 gNextSerialNumber;
+
+static PRBool gLogging;
+static PRBool gLogToLeaky;
+static PRBool gLogLeaksOnly;
+
+static void (*leakyLogAddRef)(void* p, int oldrc, int newrc);
+static void (*leakyLogRelease)(void* p, int oldrc, int newrc);
+
+static PRBool gInitialized = PR_FALSE;
+static FILE *gBloatLog = nsnull;
+static FILE *gRefcntsLog = nsnull;
+static FILE *gAllocLog = nsnull;
+static FILE *gLeakyLog = nsnull;
+static FILE *gCOMPtrLog = nsnull;
+static PRBool gActivityIsLegal = PR_FALSE;
+
+struct serialNumberRecord {
+ PRInt32 serialNumber;
+ PRInt32 refCount;
+ PRInt32 COMPtrCount;
+};
+
+struct nsTraceRefcntStats {
+ nsrefcnt mAddRefs;
+ nsrefcnt mReleases;
+ nsrefcnt mCreates;
+ nsrefcnt mDestroys;
+ double mRefsOutstandingTotal;
+ double mRefsOutstandingSquared;
+ double mObjsOutstandingTotal;
+ double mObjsOutstandingSquared;
+};
+
+#ifdef DEBUG_dbaron_off
+ // I hope to turn this on for everybody once we hit it a little less.
+#define ASSERT_ACTIVITY_IS_LEGAL \
+ NS_WARN_IF_FALSE(gActivityIsLegal, \
+ "XPCOM objects created/destroyed from static ctor/dtor")
+#else
+#define ASSERT_ACTIVITY_IS_LEGAL
+#endif
+
+
+// These functions are copied from nsprpub/lib/ds/plhash.c, with changes
+// to the functions not called Default* to free the serialNumberRecord or
+// the BloatEntry.
+
+static void * PR_CALLBACK
+DefaultAllocTable(void *pool, PRSize size)
+{
+#if defined(XP_MAC)
+#pragma unused (pool)
+#endif
+
+ return PR_MALLOC(size);
+}
+
+static void PR_CALLBACK
+DefaultFreeTable(void *pool, void *item)
+{
+#if defined(XP_MAC)
+#pragma unused (pool)
+#endif
+
+ PR_Free(item);
+}
+
+static PLHashEntry * PR_CALLBACK
+DefaultAllocEntry(void *pool, const void *key)
+{
+#if defined(XP_MAC)
+#pragma unused (pool,key)
+#endif
+
+ return PR_NEW(PLHashEntry);
+}
+
+static void PR_CALLBACK
+SerialNumberFreeEntry(void *pool, PLHashEntry *he, PRUintn flag)
+{
+#if defined(XP_MAC)
+#pragma unused (pool)
+#endif
+
+ if (flag == HT_FREE_ENTRY) {
+ PR_Free(NS_REINTERPRET_CAST(serialNumberRecord*,he->value));
+ PR_Free(he);
+ }
+}
+
+static void PR_CALLBACK
+TypesToLogFreeEntry(void *pool, PLHashEntry *he, PRUintn flag)
+{
+#if defined(XP_MAC)
+#pragma unused (pool)
+#endif
+
+ if (flag == HT_FREE_ENTRY) {
+ nsCRT::free(NS_CONST_CAST(char*,
+ NS_REINTERPRET_CAST(const char*, he->key)));
+ PR_Free(he);
+ }
+}
+
+static const PLHashAllocOps serialNumberHashAllocOps = {
+ DefaultAllocTable, DefaultFreeTable,
+ DefaultAllocEntry, SerialNumberFreeEntry
+};
+
+static const PLHashAllocOps typesToLogHashAllocOps = {
+ DefaultAllocTable, DefaultFreeTable,
+ DefaultAllocEntry, TypesToLogFreeEntry
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+class BloatEntry {
+public:
+ BloatEntry(const char* className, PRUint32 classSize)
+ : mClassSize(classSize) {
+ mClassName = PL_strdup(className);
+ Clear(&mNewStats);
+ Clear(&mAllStats);
+ mTotalLeaked = 0;
+ }
+
+ ~BloatEntry() {
+ PL_strfree(mClassName);
+ }
+
+ PRUint32 GetClassSize() { return (PRUint32)mClassSize; }
+ const char* GetClassName() { return mClassName; }
+
+ static void Clear(nsTraceRefcntStats* stats) {
+ stats->mAddRefs = 0;
+ stats->mReleases = 0;
+ stats->mCreates = 0;
+ stats->mDestroys = 0;
+ stats->mRefsOutstandingTotal = 0;
+ stats->mRefsOutstandingSquared = 0;
+ stats->mObjsOutstandingTotal = 0;
+ stats->mObjsOutstandingSquared = 0;
+ }
+
+ void Accumulate() {
+ mAllStats.mAddRefs += mNewStats.mAddRefs;
+ mAllStats.mReleases += mNewStats.mReleases;
+ mAllStats.mCreates += mNewStats.mCreates;
+ mAllStats.mDestroys += mNewStats.mDestroys;
+ mAllStats.mRefsOutstandingTotal += mNewStats.mRefsOutstandingTotal;
+ mAllStats.mRefsOutstandingSquared += mNewStats.mRefsOutstandingSquared;
+ mAllStats.mObjsOutstandingTotal += mNewStats.mObjsOutstandingTotal;
+ mAllStats.mObjsOutstandingSquared += mNewStats.mObjsOutstandingSquared;
+ Clear(&mNewStats);
+ }
+
+ void AddRef(nsrefcnt refcnt) {
+ mNewStats.mAddRefs++;
+ if (refcnt == 1) {
+ Ctor();
+ }
+ AccountRefs();
+ }
+
+ void Release(nsrefcnt refcnt) {
+ mNewStats.mReleases++;
+ if (refcnt == 0) {
+ Dtor();
+ }
+ AccountRefs();
+ }
+
+ void Ctor() {
+ mNewStats.mCreates++;
+ AccountObjs();
+ }
+
+ void Dtor() {
+ mNewStats.mDestroys++;
+ AccountObjs();
+ }
+
+ void AccountRefs() {
+ PRInt32 cnt = (mNewStats.mAddRefs - mNewStats.mReleases);
+ mNewStats.mRefsOutstandingTotal += cnt;
+ mNewStats.mRefsOutstandingSquared += cnt * cnt;
+ }
+
+ void AccountObjs() {
+ PRInt32 cnt = (mNewStats.mCreates - mNewStats.mDestroys);
+ mNewStats.mObjsOutstandingTotal += cnt;
+ mNewStats.mObjsOutstandingSquared += cnt * cnt;
+ }
+
+ static PRIntn PR_CALLBACK DumpEntry(PLHashEntry *he, PRIntn i, void *arg) {
+ BloatEntry* entry = (BloatEntry*)he->value;
+ if (entry) {
+ entry->Accumulate();
+ NS_STATIC_CAST(nsVoidArray*, arg)->AppendElement(entry);
+ }
+ return HT_ENUMERATE_NEXT;
+ }
+
+ static PRIntn PR_CALLBACK TotalEntries(PLHashEntry *he, PRIntn i, void *arg) {
+ BloatEntry* entry = (BloatEntry*)he->value;
+ if (entry && nsCRT::strcmp(entry->mClassName, "TOTAL") != 0) {
+ entry->Total((BloatEntry*)arg);
+ }
+ return HT_ENUMERATE_NEXT;
+ }
+
+ void Total(BloatEntry* total) {
+ total->mAllStats.mAddRefs += mNewStats.mAddRefs + mAllStats.mAddRefs;
+ total->mAllStats.mReleases += mNewStats.mReleases + mAllStats.mReleases;
+ total->mAllStats.mCreates += mNewStats.mCreates + mAllStats.mCreates;
+ total->mAllStats.mDestroys += mNewStats.mDestroys + mAllStats.mDestroys;
+ total->mAllStats.mRefsOutstandingTotal += mNewStats.mRefsOutstandingTotal + mAllStats.mRefsOutstandingTotal;
+ total->mAllStats.mRefsOutstandingSquared += mNewStats.mRefsOutstandingSquared + mAllStats.mRefsOutstandingSquared;
+ total->mAllStats.mObjsOutstandingTotal += mNewStats.mObjsOutstandingTotal + mAllStats.mObjsOutstandingTotal;
+ total->mAllStats.mObjsOutstandingSquared += mNewStats.mObjsOutstandingSquared + mAllStats.mObjsOutstandingSquared;
+ PRInt32 count = (mNewStats.mCreates + mAllStats.mCreates);
+ total->mClassSize += mClassSize * count; // adjust for average in DumpTotal
+ total->mTotalLeaked += (PRInt32)(mClassSize *
+ ((mNewStats.mCreates + mAllStats.mCreates)
+ -(mNewStats.mDestroys + mAllStats.mDestroys)));
+ }
+
+ nsresult DumpTotal(PRUint32 nClasses, FILE* out) {
+ mClassSize /= mAllStats.mCreates;
+ return Dump(-1, out, nsTraceRefcntImpl::ALL_STATS);
+ }
+
+ static PRBool HaveLeaks(nsTraceRefcntStats* stats) {
+ return ((stats->mAddRefs != stats->mReleases) ||
+ (stats->mCreates != stats->mDestroys));
+ }
+
+ static nsresult PrintDumpHeader(FILE* out, const char* msg) {
+ fprintf(out, "\n== BloatView: %s\n\n", msg);
+ fprintf(out,
+ " |<----------------Class--------------->|<-----Bytes------>|<----------------Objects---------------->|<--------------References-------------->|\n");
+ fprintf(out,
+ " Per-Inst Leaked Total Rem Mean StdDev Total Rem Mean StdDev\n");
+ return NS_OK;
+ }
+
+ nsresult Dump(PRIntn i, FILE* out, nsTraceRefcntImpl::StatisticsType type) {
+ nsTraceRefcntStats* stats = (type == nsTraceRefcntImpl::NEW_STATS) ? &mNewStats : &mAllStats;
+ if (gLogLeaksOnly && !HaveLeaks(stats)) {
+ return NS_OK;
+ }
+
+ double meanRefs, stddevRefs;
+ NS_MeanAndStdDev(stats->mAddRefs + stats->mReleases,
+ stats->mRefsOutstandingTotal,
+ stats->mRefsOutstandingSquared,
+ &meanRefs, &stddevRefs);
+
+ double meanObjs, stddevObjs;
+ NS_MeanAndStdDev(stats->mCreates + stats->mDestroys,
+ stats->mObjsOutstandingTotal,
+ stats->mObjsOutstandingSquared,
+ &meanObjs, &stddevObjs);
+
+ if ((stats->mAddRefs - stats->mReleases) != 0 ||
+ stats->mAddRefs != 0 ||
+ meanRefs != 0 ||
+ stddevRefs != 0 ||
+ (stats->mCreates - stats->mDestroys) != 0 ||
+ stats->mCreates != 0 ||
+ meanObjs != 0 ||
+ stddevObjs != 0) {
+ fprintf(out, "%4d %-40.40s %8d %8d %8d %8d (%8.2f +/- %8.2f) %8d %8d (%8.2f +/- %8.2f)\n",
+ i+1, mClassName,
+ (PRInt32)mClassSize,
+ (nsCRT::strcmp(mClassName, "TOTAL"))
+ ?(PRInt32)((stats->mCreates - stats->mDestroys) * mClassSize)
+ :mTotalLeaked,
+ stats->mCreates,
+ (stats->mCreates - stats->mDestroys),
+ meanObjs,
+ stddevObjs,
+ stats->mAddRefs,
+ (stats->mAddRefs - stats->mReleases),
+ meanRefs,
+ stddevRefs);
+ }
+ return NS_OK;
+ }
+
+protected:
+ char* mClassName;
+ double mClassSize; // this is stored as a double because of the way we compute the avg class size for total bloat
+ PRInt32 mTotalLeaked; // used only for TOTAL entry
+ nsTraceRefcntStats mNewStats;
+ nsTraceRefcntStats mAllStats;
+};
+
+static void PR_CALLBACK
+BloatViewFreeEntry(void *pool, PLHashEntry *he, PRUintn flag)
+{
+#if defined(XP_MAC)
+#pragma unused (pool)
+#endif
+
+ if (flag == HT_FREE_ENTRY) {
+ BloatEntry* entry = NS_REINTERPRET_CAST(BloatEntry*,he->value);
+ delete entry;
+ PR_Free(he);
+ }
+}
+
+const static PLHashAllocOps bloatViewHashAllocOps = {
+ DefaultAllocTable, DefaultFreeTable,
+ DefaultAllocEntry, BloatViewFreeEntry
+};
+
+static void
+RecreateBloatView()
+{
+ gBloatView = PL_NewHashTable(256,
+ PL_HashString,
+ PL_CompareStrings,
+ PL_CompareValues,
+ &bloatViewHashAllocOps, NULL);
+}
+
+static BloatEntry*
+GetBloatEntry(const char* aTypeName, PRUint32 aInstanceSize)
+{
+ if (!gBloatView) {
+ RecreateBloatView();
+ }
+ BloatEntry* entry = NULL;
+ if (gBloatView) {
+ entry = (BloatEntry*)PL_HashTableLookup(gBloatView, aTypeName);
+ if (entry == NULL && aInstanceSize > 0) {
+
+ entry = new BloatEntry(aTypeName, aInstanceSize);
+ PLHashEntry* e = PL_HashTableAdd(gBloatView, aTypeName, entry);
+ if (e == NULL) {
+ delete entry;
+ entry = NULL;
+ }
+ } else {
+ NS_ASSERTION(aInstanceSize == 0 ||
+ entry->GetClassSize() == aInstanceSize,
+ "bad size recorded");
+ }
+ }
+ return entry;
+}
+
+static PRIntn PR_CALLBACK DumpSerialNumbers(PLHashEntry* aHashEntry, PRIntn aIndex, void* aClosure)
+{
+ serialNumberRecord* record = NS_REINTERPRET_CAST(serialNumberRecord *,aHashEntry->value);
+#ifdef HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR
+ fprintf((FILE*) aClosure, "%d (%d references; %d from COMPtrs)\n",
+ record->serialNumber,
+ record->refCount,
+ record->COMPtrCount);
+#else
+ fprintf((FILE*) aClosure, "%d (%d references)\n",
+ record->serialNumber,
+ record->refCount);
+#endif
+ return HT_ENUMERATE_NEXT;
+}
+
+
+#endif /* NS_BUILD_REFCNT_LOGGING */
+
+nsresult
+nsTraceRefcntImpl::DumpStatistics(StatisticsType type, FILE* out)
+{
+ nsresult rv = NS_OK;
+#ifdef NS_BUILD_REFCNT_LOGGING
+ if (gBloatLog == nsnull || gBloatView == nsnull) {
+ return NS_ERROR_FAILURE;
+ }
+ if (out == nsnull) {
+ out = gBloatLog;
+ }
+
+ LOCK_TRACELOG();
+
+ PRBool wasLogging = gLogging;
+ gLogging = PR_FALSE; // turn off logging for this method
+
+ const char* msg;
+ if (type == NEW_STATS) {
+ if (gLogLeaksOnly)
+ msg = "NEW (incremental) LEAK STATISTICS";
+ else
+ msg = "NEW (incremental) LEAK AND BLOAT STATISTICS";
+ }
+ else {
+ if (gLogLeaksOnly)
+ msg = "ALL (cumulative) LEAK STATISTICS";
+ else
+ msg = "ALL (cumulative) LEAK AND BLOAT STATISTICS";
+ }
+ rv = BloatEntry::PrintDumpHeader(out, msg);
+ if (NS_FAILED(rv)) goto done;
+
+ {
+ BloatEntry total("TOTAL", 0);
+ PL_HashTableEnumerateEntries(gBloatView, BloatEntry::TotalEntries, &total);
+ total.DumpTotal(gBloatView->nentries, out);
+
+ nsVoidArray entries;
+ PL_HashTableEnumerateEntries(gBloatView, BloatEntry::DumpEntry, &entries);
+
+ fprintf(stdout, "nsTraceRefcntImpl::DumpStatistics: %d entries\n",
+ entries.Count());
+
+ // Sort the entries alphabetically by classname.
+ PRInt32 i, j;
+ for (i = entries.Count() - 1; i >= 1; --i) {
+ for (j = i - 1; j >= 0; --j) {
+ BloatEntry* left = NS_STATIC_CAST(BloatEntry*, entries[i]);
+ BloatEntry* right = NS_STATIC_CAST(BloatEntry*, entries[j]);
+
+ if (PL_strcmp(left->GetClassName(), right->GetClassName()) < 0) {
+ entries.ReplaceElementAt(right, i);
+ entries.ReplaceElementAt(left, j);
+ }
+ }
+ }
+
+ // Enumerate from back-to-front, so things come out in alpha order
+ for (i = 0; i < entries.Count(); ++i) {
+ BloatEntry* entry = NS_STATIC_CAST(BloatEntry*, entries[i]);
+ entry->Dump(i, out, type);
+ }
+ }
+
+ if (gSerialNumbers) {
+ fprintf(out, "\n\nSerial Numbers of Leaked Objects:\n");
+ PL_HashTableEnumerateEntries(gSerialNumbers, DumpSerialNumbers, out);
+ }
+
+done:
+ gLogging = wasLogging;
+ UNLOCK_TRACELOG();
+#endif
+ return rv;
+}
+
+void
+nsTraceRefcntImpl::ResetStatistics()
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+ LOCK_TRACELOG();
+ if (gBloatView) {
+ PL_HashTableDestroy(gBloatView);
+ gBloatView = nsnull;
+ }
+ UNLOCK_TRACELOG();
+#endif
+}
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+static PRBool LogThisType(const char* aTypeName)
+{
+ void* he = PL_HashTableLookup(gTypesToLog, aTypeName);
+ return nsnull != he;
+}
+
+static PRInt32 GetSerialNumber(void* aPtr, PRBool aCreate)
+{
+#ifdef GC_LEAK_DETECTOR
+ // need to disguise this pointer, so the table won't keep the object alive.
+ aPtr = (void*) ~PLHashNumber(aPtr);
+#endif
+ PLHashEntry** hep = PL_HashTableRawLookup(gSerialNumbers, PLHashNumber(NS_PTR_TO_INT32(aPtr)), aPtr);
+ if (hep && *hep) {
+ return PRInt32((NS_REINTERPRET_CAST(serialNumberRecord*,(*hep)->value))->serialNumber);
+ }
+ else if (aCreate) {
+ serialNumberRecord *record = PR_NEW(serialNumberRecord);
+ record->serialNumber = ++gNextSerialNumber;
+ record->refCount = 0;
+ record->COMPtrCount = 0;
+ PL_HashTableRawAdd(gSerialNumbers, hep, PLHashNumber(NS_PTR_TO_INT32(aPtr)), aPtr, NS_REINTERPRET_CAST(void*,record));
+ return gNextSerialNumber;
+ }
+ else {
+ return 0;
+ }
+}
+
+static PRInt32* GetRefCount(void* aPtr)
+{
+#ifdef GC_LEAK_DETECTOR
+ // need to disguise this pointer, so the table won't keep the object alive.
+ aPtr = (void*) ~PLHashNumber(aPtr);
+#endif
+ PLHashEntry** hep = PL_HashTableRawLookup(gSerialNumbers, PLHashNumber(NS_PTR_TO_INT32(aPtr)), aPtr);
+ if (hep && *hep) {
+ return &((NS_REINTERPRET_CAST(serialNumberRecord*,(*hep)->value))->refCount);
+ } else {
+ return nsnull;
+ }
+}
+
+static PRInt32* GetCOMPtrCount(void* aPtr)
+{
+#ifdef GC_LEAK_DETECTOR
+ // need to disguise this pointer, so the table won't keep the object alive.
+ aPtr = (void*) ~PLHashNumber(aPtr);
+#endif
+ PLHashEntry** hep = PL_HashTableRawLookup(gSerialNumbers, PLHashNumber(NS_PTR_TO_INT32(aPtr)), aPtr);
+ if (hep && *hep) {
+ return &((NS_REINTERPRET_CAST(serialNumberRecord*,(*hep)->value))->COMPtrCount);
+ } else {
+ return nsnull;
+ }
+}
+
+static void RecycleSerialNumberPtr(void* aPtr)
+{
+#ifdef GC_LEAK_DETECTOR
+ // need to disguise this pointer, so the table won't keep the object alive.
+ aPtr = (void*) ~PLHashNumber(aPtr);
+#endif
+ PL_HashTableRemove(gSerialNumbers, aPtr);
+}
+
+static PRBool LogThisObj(PRInt32 aSerialNumber)
+{
+ return nsnull != PL_HashTableLookup(gObjectsToLog, (const void*)(uintptr_t)(aSerialNumber));
+}
+
+static PRBool InitLog(const char* envVar, const char* msg, FILE* *result)
+{
+ const char* value = getenv(envVar);
+ if (value) {
+ if (nsCRT::strcmp(value, "1") == 0) {
+ *result = stdout;
+ fprintf(stdout, "### %s defined -- logging %s to stdout\n",
+ envVar, msg);
+ return PR_TRUE;
+ }
+ else if (nsCRT::strcmp(value, "2") == 0) {
+ *result = stderr;
+ fprintf(stdout, "### %s defined -- logging %s to stderr\n",
+ envVar, msg);
+ return PR_TRUE;
+ }
+ else {
+ FILE *stream = ::fopen(value, "w");
+ if (stream != NULL) {
+ *result = stream;
+ fprintf(stdout, "### %s defined -- logging %s to %s\n",
+ envVar, msg, value);
+ return PR_TRUE;
+ }
+ else {
+ fprintf(stdout, "### %s defined -- unable to log %s to %s\n",
+ envVar, msg, value);
+ return PR_FALSE;
+ }
+ }
+ }
+ return PR_FALSE;
+}
+
+
+static PLHashNumber PR_CALLBACK HashNumber(const void* aKey)
+{
+ return PLHashNumber(NS_PTR_TO_INT32(aKey));
+}
+
+static void InitTraceLog(void)
+{
+ if (gInitialized) return;
+ gInitialized = PR_TRUE;
+
+#if defined(XP_MAC) && !TARGET_CARBON
+ // this can get called before Toolbox has been initialized.
+ InitializeMacToolbox();
+#endif
+
+ PRBool defined;
+ defined = InitLog("XPCOM_MEM_BLOAT_LOG", "bloat/leaks", &gBloatLog);
+ if (!defined)
+ gLogLeaksOnly = InitLog("XPCOM_MEM_LEAK_LOG", "leaks", &gBloatLog);
+ if (defined || gLogLeaksOnly) {
+ RecreateBloatView();
+ if (!gBloatView) {
+ NS_WARNING("out of memory");
+ gBloatLog = nsnull;
+ gLogLeaksOnly = PR_FALSE;
+ }
+ }
+
+ (void)InitLog("XPCOM_MEM_REFCNT_LOG", "refcounts", &gRefcntsLog);
+
+ (void)InitLog("XPCOM_MEM_ALLOC_LOG", "new/delete", &gAllocLog);
+
+ defined = InitLog("XPCOM_MEM_LEAKY_LOG", "for leaky", &gLeakyLog);
+ if (defined) {
+ gLogToLeaky = PR_TRUE;
+ void* p = nsnull;
+ void* q = nsnull;
+#ifdef HAVE_LIBDL
+ p = dlsym(0, "__log_addref");
+ q = dlsym(0, "__log_release");
+#endif
+ if (p && q) {
+ leakyLogAddRef = (void (*)(void*,int,int)) p;
+ leakyLogRelease = (void (*)(void*,int,int)) q;
+ }
+ else {
+ gLogToLeaky = PR_FALSE;
+ fprintf(stdout, "### ERROR: XPCOM_MEM_LEAKY_LOG defined, but can't locate __log_addref and __log_release symbols\n");
+ fflush(stdout);
+ }
+ }
+
+ const char* classes = getenv("XPCOM_MEM_LOG_CLASSES");
+
+#ifdef HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR
+ if (classes) {
+ (void)InitLog("XPCOM_MEM_COMPTR_LOG", "nsCOMPtr", &gCOMPtrLog);
+ } else {
+ if (getenv("XPCOM_MEM_COMPTR_LOG")) {
+ fprintf(stdout, "### XPCOM_MEM_COMPTR_LOG defined -- but XPCOM_MEM_LOG_CLASSES is not defined\n");
+ }
+ }
+#else
+ const char* comptr_log = getenv("XPCOM_MEM_COMPTR_LOG");
+ if (comptr_log) {
+ fprintf(stdout, "### XPCOM_MEM_COMPTR_LOG defined -- but it will not work without dynamic_cast\n");
+ }
+#endif
+
+ if (classes) {
+ // if XPCOM_MEM_LOG_CLASSES was set to some value, the value is interpreted
+ // as a list of class names to track
+ gTypesToLog = PL_NewHashTable(256,
+ PL_HashString,
+ PL_CompareStrings,
+ PL_CompareValues,
+ &typesToLogHashAllocOps, NULL);
+ if (!gTypesToLog) {
+ NS_WARNING("out of memory");
+ fprintf(stdout, "### XPCOM_MEM_LOG_CLASSES defined -- unable to log specific classes\n");
+ }
+ else {
+ fprintf(stdout, "### XPCOM_MEM_LOG_CLASSES defined -- only logging these classes: ");
+ const char* cp = classes;
+ for (;;) {
+ char* cm = (char*) strchr(cp, ',');
+ if (cm) {
+ *cm = '\0';
+ }
+ PL_HashTableAdd(gTypesToLog, nsCRT::strdup(cp), (void*)1);
+ fprintf(stdout, "%s ", cp);
+ if (!cm) break;
+ *cm = ',';
+ cp = cm + 1;
+ }
+ fprintf(stdout, "\n");
+ }
+
+ gSerialNumbers = PL_NewHashTable(256,
+ HashNumber,
+ PL_CompareValues,
+ PL_CompareValues,
+ &serialNumberHashAllocOps, NULL);
+
+
+ }
+
+ const char* objects = getenv("XPCOM_MEM_LOG_OBJECTS");
+ if (objects) {
+ gObjectsToLog = PL_NewHashTable(256,
+ HashNumber,
+ PL_CompareValues,
+ PL_CompareValues,
+ NULL, NULL);
+
+ if (!gObjectsToLog) {
+ NS_WARNING("out of memory");
+ fprintf(stdout, "### XPCOM_MEM_LOG_OBJECTS defined -- unable to log specific objects\n");
+ }
+ else if (! (gRefcntsLog || gAllocLog || gCOMPtrLog)) {
+ fprintf(stdout, "### XPCOM_MEM_LOG_OBJECTS defined -- but none of XPCOM_MEM_(REFCNT|ALLOC|COMPTR)_LOG is defined\n");
+ }
+ else {
+ fprintf(stdout, "### XPCOM_MEM_LOG_OBJECTS defined -- only logging these objects: ");
+ const char* cp = objects;
+ for (;;) {
+ char* cm = (char*) strchr(cp, ',');
+ if (cm) {
+ *cm = '\0';
+ }
+ PRInt32 top = 0;
+ PRInt32 bottom = 0;
+ while (*cp) {
+ if (*cp == '-') {
+ bottom = top;
+ top = 0;
+ ++cp;
+ }
+ top *= 10;
+ top += *cp - '0';
+ ++cp;
+ }
+ if (!bottom) {
+ bottom = top;
+ }
+ for(PRInt32 serialno = bottom; serialno <= top; serialno++) {
+ PL_HashTableAdd(gObjectsToLog, (const void*)serialno, (void*)1);
+ fprintf(stdout, "%d ", serialno);
+ }
+ if (!cm) break;
+ *cm = ',';
+ cp = cm + 1;
+ }
+ fprintf(stdout, "\n");
+ }
+ }
+
+
+ if (gBloatLog || gRefcntsLog || gAllocLog || gLeakyLog || gCOMPtrLog) {
+ gLogging = PR_TRUE;
+ }
+
+ gTraceLock = PR_NewLock();
+}
+
+#endif
+
+#if defined(_WIN32) && defined(_M_IX86) // WIN32 x86 stack walking code
+#include "nsStackFrameWin.h"
+void
+nsTraceRefcntImpl::WalkTheStack(FILE* aStream)
+{
+ DumpStackToFile(aStream);
+}
+
+// WIN32 x86 stack walking code
+// i386 or PPC Linux stackwalking code or Solaris
+#elif (defined(linux) && !defined(VBOX) && defined(__GLIBC__) && (defined(__i386) || defined(PPC))) || (defined(__sun) && (defined(__sparc) || defined(sparc) || defined(__i386) || defined(i386)))
+#include "nsStackFrameUnix.h"
+void
+nsTraceRefcntImpl::WalkTheStack(FILE* aStream)
+{
+ DumpStackToFile(aStream);
+}
+
+#elif defined(XP_MAC)
+
+/**
+ * Stack walking code for the Mac OS.
+ */
+
+#include "gc_fragments.h"
+
+#include <typeinfo>
+
+extern "C" {
+void MWUnmangle(const char *mangled_name, char *unmangled_name, size_t buffersize);
+}
+
+struct traceback_table {
+ long zero;
+ long magic;
+ long reserved;
+ long codeSize;
+ short nameLength;
+ char name[2];
+};
+
+static char* pc2name(long* pc, char name[], long size)
+{
+ name[0] = '\0';
+
+ // make sure pc is instruction aligned (at least).
+ if (UInt32(pc) == (UInt32(pc) & 0xFFFFFFFC)) {
+ long instructionsToLook = 4096;
+ long* instruction = (long*)pc;
+
+ // look for the traceback table.
+ while (instructionsToLook--) {
+ if (instruction[0] == 0x4E800020 && instruction[1] == 0x00000000) {
+ traceback_table* tb = (traceback_table*)&instruction[1];
+ memcpy(name, tb->name + 1, --nameLength);
+ name[nameLength] = '\0';
+ break;
+ }
+ ++instruction;
+ }
+ }
+
+ return name;
+}
+
+struct stack_frame {
+ stack_frame* next; // savedSP
+ void* savedCR;
+ void* savedLR;
+ void* reserved0;
+ void* reserved1;
+ void* savedTOC;
+};
+
+static asm stack_frame* getStackFrame()
+{
+ mr r3, sp
+ blr
+}
+
+NS_COM void
+nsTraceRefcntImpl::WalkTheStack(FILE* aStream)
+{
+ stack_frame* currentFrame = getStackFrame(); // WalkTheStack's frame.
+ currentFrame = currentFrame->next; // WalkTheStack's caller's frame.
+ currentFrame = currentFrame->next; // WalkTheStack's caller's caller's frame.
+
+ while (true) {
+ // LR saved at 8(SP) in each frame. subtract 4 to get address of calling instruction.
+ void* pc = currentFrame->savedLR;
+
+ // convert PC to name, unmangle it, and generate source location, if possible.
+ static char symbol_name[1024], unmangled_name[1024], file_name[256]; UInt32 file_offset;
+
+ if (GC_address_to_source((char*)pc, symbol_name, file_name, &file_offset)) {
+ MWUnmangle(symbol_name, unmangled_name, sizeof(unmangled_name));
+ fprintf(aStream, "%s[%s,%ld]\n", unmangled_name, file_name, file_offset);
+ } else {
+ pc2name((long*)pc, symbol_name, sizeof(symbol_name));
+ MWUnmangle(symbol_name, unmangled_name, sizeof(unmangled_name));
+ fprintf(aStream, "%s(0x%08X)\n", unmangled_name, pc);
+ }
+
+ currentFrame = currentFrame->next;
+ // the bottom-most frame is marked as pointing to NULL, or is ODD if a 68K transition frame.
+ if (currentFrame == NULL || UInt32(currentFrame) & 0x1)
+ break;
+ }
+}
+
+#else // unsupported platform.
+
+void
+nsTraceRefcntImpl::WalkTheStack(FILE* aStream)
+{
+ fprintf(aStream, "write me, dammit!\n");
+}
+
+#endif
+
+//----------------------------------------------------------------------
+
+// This thing is exported by libstdc++
+// Yes, this is a gcc only hack
+#if defined(MOZ_DEMANGLE_SYMBOLS)
+#include <cxxabi.h>
+#include <stdlib.h> // for free()
+#endif // MOZ_DEMANGLE_SYMBOLS
+
+NS_COM void
+nsTraceRefcntImpl::DemangleSymbol(const char * aSymbol,
+ char * aBuffer,
+ int aBufLen)
+{
+ NS_ASSERTION(nsnull != aSymbol,"null symbol");
+ NS_ASSERTION(nsnull != aBuffer,"null buffer");
+ NS_ASSERTION(aBufLen >= 32 ,"pulled 32 out of you know where");
+
+ aBuffer[0] = '\0';
+
+#if defined(MOZ_DEMANGLE_SYMBOLS)
+ /* See demangle.h in the gcc source for the voodoo */
+ char * demangled = abi::__cxa_demangle(aSymbol,0,0,0);
+
+ if (demangled)
+ {
+ strncpy(aBuffer,demangled,aBufLen);
+ free(demangled);
+ }
+#endif // MOZ_DEMANGLE_SYMBOLS
+}
+
+
+//----------------------------------------------------------------------
+
+NS_COM void
+nsTraceRefcntImpl::LoadLibrarySymbols(const char* aLibraryName,
+ void* aLibrayHandle)
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+#if defined(_WIN32) && defined(_M_IX86) /* Win32 x86 only */
+ if (!gInitialized)
+ InitTraceLog();
+
+ if (gAllocLog || gRefcntsLog) {
+ fprintf(stdout, "### Loading symbols for %s\n", aLibraryName);
+ fflush(stdout);
+
+ HANDLE myProcess = ::GetCurrentProcess();
+ BOOL ok = EnsureSymInitialized();
+ if (ok) {
+ const char* baseName = aLibraryName;
+ // just get the base name of the library if a full path was given:
+ PRInt32 len = strlen(aLibraryName);
+ for (PRInt32 i = len - 1; i >= 0; i--) {
+ if (aLibraryName[i] == '\\') {
+ baseName = &aLibraryName[i + 1];
+ break;
+ }
+ }
+ DWORD baseAddr = _SymLoadModule(myProcess,
+ NULL,
+ (char*)baseName,
+ (char*)baseName,
+ 0,
+ 0);
+ ok = (baseAddr != nsnull);
+ }
+ if (!ok) {
+ LPVOID lpMsgBuf;
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL
+ );
+ fprintf(stdout, "### ERROR: LoadLibrarySymbols for %s: %s\n",
+ aLibraryName, lpMsgBuf);
+ fflush(stdout);
+ LocalFree( lpMsgBuf );
+ }
+ }
+#endif
+#endif
+}
+
+//----------------------------------------------------------------------
+
+
+
+
+
+
+// don't use the logging ones. :-)
+NS_IMETHODIMP_(nsrefcnt) nsTraceRefcntImpl::AddRef(void)
+{
+ NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt");
+ ++mRefCnt;
+ return mRefCnt;
+}
+
+NS_IMETHODIMP_(nsrefcnt) nsTraceRefcntImpl::Release(void)
+{
+ NS_PRECONDITION(0 != mRefCnt, "dup release");
+ --mRefCnt;
+ if (mRefCnt == 0) {
+ mRefCnt = 1; /* stabilize */
+ delete this;
+ return 0;
+ }
+ return mRefCnt;
+}
+
+NS_IMPL_QUERY_INTERFACE1(nsTraceRefcntImpl, nsITraceRefcnt)
+
+nsTraceRefcntImpl::nsTraceRefcntImpl()
+{
+ /* member initializers and constructor code */
+}
+
+NS_IMETHODIMP
+nsTraceRefcntImpl::LogAddRef(void* aPtr,
+ nsrefcnt aRefcnt,
+ const char* aClazz,
+ PRUint32 classSize)
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+ ASSERT_ACTIVITY_IS_LEGAL;
+ if (!gInitialized)
+ InitTraceLog();
+ if (gLogging) {
+ LOCK_TRACELOG();
+
+ if (gBloatLog) {
+ BloatEntry* entry = GetBloatEntry(aClazz, classSize);
+ if (entry) {
+ entry->AddRef(aRefcnt);
+ }
+ }
+
+ // Here's the case where neither NS_NEWXPCOM nor MOZ_COUNT_CTOR were used,
+ // yet we still want to see creation information:
+
+ PRBool loggingThisType = (!gTypesToLog || LogThisType(aClazz));
+ PRInt32 serialno = 0;
+ if (gSerialNumbers && loggingThisType) {
+ serialno = GetSerialNumber(aPtr, aRefcnt == 1);
+ PRInt32* count = GetRefCount(aPtr);
+ if(count)
+ (*count)++;
+
+ }
+
+ PRBool loggingThisObject = (!gObjectsToLog || LogThisObj(serialno));
+ if (aRefcnt == 1 && gAllocLog && loggingThisType && loggingThisObject) {
+ fprintf(gAllocLog, "\n<%s> 0x%08X %d Create\n",
+ aClazz, NS_PTR_TO_INT32(aPtr), serialno);
+ WalkTheStack(gAllocLog);
+ }
+
+ if (gRefcntsLog && loggingThisType && loggingThisObject) {
+ if (gLogToLeaky) {
+ (*leakyLogAddRef)(aPtr, aRefcnt - 1, aRefcnt);
+ }
+ else {
+ // Can't use PR_LOG(), b/c it truncates the line
+ fprintf(gRefcntsLog,
+ "\n<%s> 0x%08X %d AddRef %d\n", aClazz, NS_PTR_TO_INT32(aPtr), serialno, aRefcnt);
+ WalkTheStack(gRefcntsLog);
+ fflush(gRefcntsLog);
+ }
+ }
+ UNLOCK_TRACELOG();
+ }
+#endif
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsTraceRefcntImpl::LogRelease(void* aPtr,
+ nsrefcnt aRefcnt,
+ const char* aClazz)
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+ ASSERT_ACTIVITY_IS_LEGAL;
+ if (!gInitialized)
+ InitTraceLog();
+ if (gLogging) {
+ LOCK_TRACELOG();
+
+ if (gBloatLog) {
+ BloatEntry* entry = GetBloatEntry(aClazz, 0);
+ if (entry) {
+ entry->Release(aRefcnt);
+ }
+ }
+
+ PRBool loggingThisType = (!gTypesToLog || LogThisType(aClazz));
+ PRInt32 serialno = 0;
+ if (gSerialNumbers && loggingThisType) {
+ serialno = GetSerialNumber(aPtr, PR_FALSE);
+ PRInt32* count = GetRefCount(aPtr);
+ if(count)
+ (*count)--;
+
+ }
+
+ PRBool loggingThisObject = (!gObjectsToLog || LogThisObj(serialno));
+ if (gRefcntsLog && loggingThisType && loggingThisObject) {
+ if (gLogToLeaky) {
+ (*leakyLogRelease)(aPtr, aRefcnt + 1, aRefcnt);
+ }
+ else {
+ // Can't use PR_LOG(), b/c it truncates the line
+ fprintf(gRefcntsLog,
+ "\n<%s> 0x%08X %d Release %d\n", aClazz, NS_PTR_TO_INT32(aPtr), serialno, aRefcnt);
+ WalkTheStack(gRefcntsLog);
+ fflush(gRefcntsLog);
+ }
+ }
+
+ // Here's the case where neither NS_DELETEXPCOM nor MOZ_COUNT_DTOR were used,
+ // yet we still want to see deletion information:
+
+ if (aRefcnt == 0 && gAllocLog && loggingThisType && loggingThisObject) {
+ fprintf(gAllocLog,
+ "\n<%s> 0x%08X %d Destroy\n",
+ aClazz, NS_PTR_TO_INT32(aPtr), serialno);
+ WalkTheStack(gAllocLog);
+ }
+
+ if (aRefcnt == 0 && gSerialNumbers && loggingThisType) {
+ RecycleSerialNumberPtr(aPtr);
+ }
+
+ UNLOCK_TRACELOG();
+ }
+#endif
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsTraceRefcntImpl::LogCtor(void* aPtr,
+ const char* aType,
+ PRUint32 aInstanceSize)
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+ ASSERT_ACTIVITY_IS_LEGAL;
+ if (!gInitialized)
+ InitTraceLog();
+
+ if (gLogging) {
+ LOCK_TRACELOG();
+
+ if (gBloatLog) {
+ BloatEntry* entry = GetBloatEntry(aType, aInstanceSize);
+ if (entry) {
+ entry->Ctor();
+ }
+ }
+
+ PRBool loggingThisType = (!gTypesToLog || LogThisType(aType));
+ PRInt32 serialno = 0;
+ if (gSerialNumbers && loggingThisType) {
+ serialno = GetSerialNumber(aPtr, PR_TRUE);
+ }
+
+ PRBool loggingThisObject = (!gObjectsToLog || LogThisObj(serialno));
+ if (gAllocLog && loggingThisType && loggingThisObject) {
+ fprintf(gAllocLog, "\n<%s> 0x%08X %d Ctor (%d)\n",
+ aType, NS_PTR_TO_INT32(aPtr), serialno, aInstanceSize);
+ WalkTheStack(gAllocLog);
+ }
+
+ UNLOCK_TRACELOG();
+ }
+#endif
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsTraceRefcntImpl::LogDtor(void* aPtr,
+ const char* aType,
+ PRUint32 aInstanceSize)
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+ ASSERT_ACTIVITY_IS_LEGAL;
+ if (!gInitialized)
+ InitTraceLog();
+
+ if (gLogging) {
+ LOCK_TRACELOG();
+
+ if (gBloatLog) {
+ BloatEntry* entry = GetBloatEntry(aType, aInstanceSize);
+ if (entry) {
+ entry->Dtor();
+ }
+ }
+
+ PRBool loggingThisType = (!gTypesToLog || LogThisType(aType));
+ PRInt32 serialno = 0;
+ if (gSerialNumbers && loggingThisType) {
+ serialno = GetSerialNumber(aPtr, PR_FALSE);
+ RecycleSerialNumberPtr(aPtr);
+ }
+
+ PRBool loggingThisObject = (!gObjectsToLog || LogThisObj(serialno));
+
+ // (If we're on a losing architecture, don't do this because we'll be
+ // using LogDeleteXPCOM instead to get file and line numbers.)
+ if (gAllocLog && loggingThisType && loggingThisObject) {
+ fprintf(gAllocLog, "\n<%s> 0x%08X %d Dtor (%d)\n",
+ aType, NS_PTR_TO_INT32(aPtr), serialno, aInstanceSize);
+ WalkTheStack(gAllocLog);
+ }
+
+ UNLOCK_TRACELOG();
+ }
+#endif
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsTraceRefcntImpl::LogAddCOMPtr(void* aCOMPtr,
+ nsISupports* aObject)
+{
+#if defined(NS_BUILD_REFCNT_LOGGING) && defined(HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR)
+ // Get the most-derived object.
+ void *object = dynamic_cast<void *>(aObject);
+
+ // This is a very indirect way of finding out what the class is
+ // of the object being logged. If we're logging a specific type,
+ // then
+ if (!gTypesToLog || !gSerialNumbers) {
+ return NS_OK;
+ }
+ PRInt32 serialno = GetSerialNumber(object, PR_FALSE);
+ if (serialno == 0) {
+ return NS_OK;
+ }
+
+ if (!gInitialized)
+ InitTraceLog();
+ if (gLogging) {
+ LOCK_TRACELOG();
+
+ PRInt32* count = GetCOMPtrCount(object);
+ if(count)
+ (*count)++;
+
+ PRBool loggingThisObject = (!gObjectsToLog || LogThisObj(serialno));
+
+ if (gCOMPtrLog && loggingThisObject) {
+ fprintf(gCOMPtrLog, "\n<?> 0x%08X %d nsCOMPtrAddRef %d 0x%08X\n",
+ NS_PTR_TO_INT32(object), serialno, count?(*count):-1, NS_PTR_TO_INT32(aCOMPtr));
+ WalkTheStack(gCOMPtrLog);
+ }
+
+ UNLOCK_TRACELOG();
+ }
+#endif
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsTraceRefcntImpl::LogReleaseCOMPtr(void* aCOMPtr,
+ nsISupports* aObject)
+{
+#if defined(NS_BUILD_REFCNT_LOGGING) && defined(HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR)
+ // Get the most-derived object.
+ void *object = dynamic_cast<void *>(aObject);
+
+ // This is a very indirect way of finding out what the class is
+ // of the object being logged. If we're logging a specific type,
+ // then
+ if (!gTypesToLog || !gSerialNumbers) {
+ return NS_OK;
+ }
+ PRInt32 serialno = GetSerialNumber(object, PR_FALSE);
+ if (serialno == 0) {
+ return NS_OK;
+ }
+
+ if (!gInitialized)
+ InitTraceLog();
+ if (gLogging) {
+ LOCK_TRACELOG();
+
+ PRInt32* count = GetCOMPtrCount(object);
+ if(count)
+ (*count)--;
+
+ PRBool loggingThisObject = (!gObjectsToLog || LogThisObj(serialno));
+
+ if (gCOMPtrLog && loggingThisObject) {
+ fprintf(gCOMPtrLog, "\n<?> 0x%08X %d nsCOMPtrRelease %d 0x%08X\n",
+ NS_PTR_TO_INT32(object), serialno, count?(*count):-1, NS_PTR_TO_INT32(aCOMPtr));
+ WalkTheStack(gCOMPtrLog);
+ }
+
+ UNLOCK_TRACELOG();
+ }
+#endif
+ return NS_OK;
+}
+
+NS_COM void
+nsTraceRefcntImpl::Startup()
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+ SetActivityIsLegal(PR_TRUE);
+#endif
+}
+
+NS_COM void
+nsTraceRefcntImpl::Shutdown()
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+
+ if (gBloatView) {
+ PL_HashTableDestroy(gBloatView);
+ gBloatView = nsnull;
+ }
+ if (gTypesToLog) {
+ PL_HashTableDestroy(gTypesToLog);
+ gTypesToLog = nsnull;
+ }
+ if (gObjectsToLog) {
+ PL_HashTableDestroy(gObjectsToLog);
+ gObjectsToLog = nsnull;
+ }
+ if (gSerialNumbers) {
+ PL_HashTableDestroy(gSerialNumbers);
+ gSerialNumbers = nsnull;
+ }
+
+ SetActivityIsLegal(PR_FALSE);
+
+#endif
+}
+
+NS_COM void
+nsTraceRefcntImpl::SetActivityIsLegal(PRBool aLegal)
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+ gActivityIsLegal = aLegal;
+#endif
+}
+
+
+NS_METHOD
+nsTraceRefcntImpl::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
+{
+ *aInstancePtr = nsnull;
+ nsITraceRefcnt* tracer = new nsTraceRefcntImpl();
+ if (!tracer)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = tracer->QueryInterface(aIID, aInstancePtr);
+ if (NS_FAILED(rv)) {
+ delete tracer;
+ }
+
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/base/nsTraceRefcntImpl.h b/src/libs/xpcom18a4/xpcom/base/nsTraceRefcntImpl.h
new file mode 100644
index 00000000..528b285d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsTraceRefcntImpl.h
@@ -0,0 +1,109 @@
+/* -*- 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):
+ * 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 ***** */
+#ifndef nsTraceRefcntImpl_h___
+#define nsTraceRefcntImpl_h___
+
+#include <stdio.h> // for FILE
+#include "nsITraceRefcnt.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define NS_MeanAndStdDev VBoxNsxpNS_MeanAndStdDev
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+class nsTraceRefcntImpl : public nsITraceRefcnt
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSITRACEREFCNT
+
+ nsTraceRefcntImpl();
+
+ static NS_COM void Startup();
+ static NS_COM void Shutdown();
+
+ enum StatisticsType {
+ ALL_STATS,
+ NEW_STATS
+ };
+
+ static NS_COM nsresult DumpStatistics(StatisticsType type = ALL_STATS,
+ FILE* out = 0);
+
+ static NS_COM void ResetStatistics(void);
+
+ static NS_COM void LoadLibrarySymbols(const char* aLibraryName,
+ void* aLibrayHandle);
+
+
+ static NS_COM void DemangleSymbol(const char * aSymbol,
+ char * aBuffer,
+ int aBufLen);
+
+ static NS_COM void WalkTheStack(FILE* aStream);
+ /**
+ * Tell nsTraceRefcnt whether refcounting, allocation, and destruction
+ * activity is legal. This is used to trigger assertions for any such
+ * activity that occurs because of static constructors or destructors.
+ */
+ static NS_COM void SetActivityIsLegal(PRBool aLegal);
+
+ static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+private:
+ ~nsTraceRefcntImpl() {}
+};
+
+#define NS_TRACE_REFCNT_CONTRACTID "@mozilla.org/xpcom/trace-refcnt;1"
+#define NS_TRACE_REFCNT_CLASSNAME "nsTraceRefcnt Interface"
+#define NS_TRACE_REFCNT_CID \
+{ /* e3e7511e-a395-4924-94b1-d527861cded4 */ \
+ 0xe3e7511e, \
+ 0xa395, \
+ 0x4924, \
+ {0x94, 0xb1, 0xd5, 0x27, 0x86, 0x1c, 0xde, 0xd4} \
+} \
+
+////////////////////////////////////////////////////////////////////////////////
+// And now for that utility that you've all been asking for...
+
+extern "C" NS_COM void
+NS_MeanAndStdDev(double n, double sumOfValues, double sumOfSquaredValues,
+ double *meanResult, double *stdDevResult);
+
+////////////////////////////////////////////////////////////////////////////////
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/base/nsWeakPtr.h b/src/libs/xpcom18a4/xpcom/base/nsWeakPtr.h
new file mode 100644
index 00000000..c15e31f0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsWeakPtr.h
@@ -0,0 +1,48 @@
+/* -*- 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 the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * 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 ***** */
+
+#ifndef nsWeakPtr_h__
+#define nsWeakPtr_h__
+
+#include "nsIWeakReference.h"
+#include "nsCOMPtr.h"
+
+// typedef nsCOMPtr<nsIWeakReference> nsWeakPtr;
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/base/nscore.h b/src/libs/xpcom18a4/xpcom/base/nscore.h
new file mode 100644
index 00000000..b7bfa11f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nscore.h
@@ -0,0 +1,468 @@
+/* -*- 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 nscore_h___
+#define nscore_h___
+
+/**
+ * Make sure that we have the proper platform specific
+ * c++ definitions needed by nscore.h
+ */
+#ifndef _XPCOM_CONFIG_H_
+#include "xpcom-config.h"
+#endif
+
+/**
+ * Incorporate the core NSPR data types which XPCOM uses.
+ */
+#include "prtypes.h"
+
+/* Core XPCOM declarations. */
+
+/**
+ * Macros defining the target platform...
+ */
+#ifdef _WIN32
+#define NS_WIN32 1
+
+#elif defined(__unix)
+#define NS_UNIX 1
+
+#elif defined(XP_OS2)
+#define NS_OS2 1
+#endif
+/*----------------------------------------------------------------------*/
+/* Import/export defines */
+
+/**
+ * Using the visibility("hidden") attribute allows the compiler to use
+ * PC-relative addressing to call this function. If a function does not
+ * access any global data, and does not call any methods which are not either
+ * file-local or hidden, then on ELF systems we avoid loading the address of
+ * the PLT into a register at the start of the function, which reduces code
+ * size and frees up a register for general use.
+ *
+ * As a general rule, this should be used for any non-exported symbol
+ * (including virtual method implementations). NS_IMETHOD uses this by
+ * default; if you need to have your NS_IMETHOD functions exported, you can
+ * wrap your class as follows:
+ *
+ * #undef IMETHOD_VISIBILITY
+ * #define IMETHOD_VISIBILITY NS_VISIBILITY_DEFAULT
+ *
+ * class Foo {
+ * ...
+ * };
+ *
+ * #undef IMETHOD_VISIBILITY
+ * #define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN
+ *
+ * Don't forget to change the visibility back to hidden before the end
+ * of a header!
+ *
+ * Other examples:
+ *
+ * NS_HIDDEN_(int) someMethod();
+ * SomeCtor() NS_HIDDEN;
+ */
+
+#ifdef HAVE_VISIBILITY_ATTRIBUTE
+#define NS_VISIBILITY_HIDDEN __attribute__ ((visibility ("hidden")))
+# ifdef VBOX_HAVE_VISIBILITY_HIDDEN
+# define NS_VISIBILITY_DEFAULT __attribute__ ((visibility ("default")))
+# else
+# define NS_VISIBILITY_DEFAULT
+# endif
+
+#define NS_HIDDEN_(type) NS_VISIBILITY_HIDDEN type
+#else
+#define NS_VISIBILITY_HIDDEN
+#define NS_VISIBILITY_DEFAULT
+
+#define NS_HIDDEN_(type) type
+#endif
+
+#define NS_HIDDEN NS_VISIBILITY_HIDDEN
+
+#undef IMETHOD_VISIBILITY
+#define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN
+
+/**
+ * Mark a function as using a potentially non-standard function calling
+ * convention. This can be used on functions that are called very
+ * frequently, to reduce the overhead of the function call. It is still worth
+ * using the macro for C++ functions which take no parameters since it allows
+ * passing |this| in a register.
+ *
+ * - Do not use this on any scriptable interface method since xptcall won't be
+ * aware of the different calling convention.
+ * - This must appear on the declaration, not the definition.
+ * - Adding this to a public function _will_ break binary compatibility.
+ * - This may be used on virtual functions but you must ensure it is applied
+ * to all implementations - the compiler will _not_ warn but it will crash.
+ * - This has no effect for inline functions or functions which take a
+ * variable number of arguments.
+ *
+ * Examples: int NS_FASTCALL func1(char *foo);
+ * NS_HIDDEN_(int) NS_FASTCALL func2(char *foo);
+ */
+
+#if defined(__i386__) && defined(__GNUC__) && (__GNUC__ >= 3) && !defined(XP_OS2)
+#define NS_FASTCALL __attribute__ ((regparm (3), stdcall))
+#else
+#define NS_FASTCALL
+#endif
+
+/* XXX: nike, maybe fix */
+#define NS_EXPORT_STATIC_MEMBER_(type) type
+#define NS_IMPORT_STATIC_MEMBER_(type) type
+
+#ifdef NS_WIN32
+
+#define NS_IMPORT __declspec(dllimport)
+#define NS_IMPORT_(type) type __declspec(dllimport) __stdcall
+#define NS_EXPORT __declspec(dllexport)
+#define NS_EXPORT_(type) type __declspec(dllexport) __stdcall
+#define NS_IMETHOD_(type) virtual type __stdcall
+#define NS_IMETHODIMP_(type) type __stdcall
+#define NS_METHOD_(type) type __stdcall
+#define NS_CALLBACK_(_type, _name) _type (__stdcall * _name)
+#define NS_STDCALL __stdcall
+
+#elif defined(XP_MAC)
+
+#define NS_IMPORT
+#define NS_IMPORT_(type) type
+#define NS_EXPORT __declspec(export)
+#define NS_EXPORT_(type) __declspec(export) type
+#define NS_IMETHOD_(type) virtual type
+#define NS_IMETHODIMP_(type) type
+#define NS_METHOD_(type) type
+#define NS_CALLBACK_(_type, _name) _type (* _name)
+#define NS_STDCALL
+
+#elif defined(XP_OS2) && defined(__declspec)
+
+#define NS_IMPORT __declspec(dllimport)
+#define NS_IMPORT_(type) type __declspec(dllimport) __stdcall
+#define NS_EXPORT __declspec(dllexport)
+#define NS_EXPORT_(type) type __declspec(dllexport) __stdcall
+#define NS_IMETHOD_(type) virtual IMETHOD_VISIBILITY type
+#define NS_IMETHODIMP_(type) type
+#define NS_METHOD_(type) type
+#define NS_CALLBACK_(_type, _name) _type (* _name)
+#define NS_STDCALL
+
+#else
+
+# ifdef VBOX_HAVE_VISIBILITY_HIDDEN
+# define NS_IMPORT
+# define NS_IMPORT_(type) type
+# define NS_EXPORT __attribute__((visibility("default")))
+# define NS_EXPORT_(type) __attribute__((visibility("default"))) type
+# define NS_IMETHOD_(type) virtual IMETHOD_VISIBILITY type
+# define NS_IMETHODIMP_(type) type
+# define NS_METHOD_(type) type
+# define NS_CALLBACK_(_type, _name) _type (* _name)
+# define NS_STDCALL
+# else
+# define NS_IMPORT
+# define NS_IMPORT_(type) type
+# define NS_EXPORT
+# define NS_EXPORT_(type) type
+# define NS_IMETHOD_(type) virtual IMETHOD_VISIBILITY type
+# define NS_IMETHODIMP_(type) type
+# define NS_METHOD_(type) type
+# define NS_CALLBACK_(_type, _name) _type (* _name)
+# define NS_STDCALL
+# endif
+#endif
+
+/**
+ * Macro for creating typedefs for pointer-to-member types which are
+ * declared with stdcall. It is important to use this for any type which is
+ * declared as stdcall (i.e. NS_IMETHOD). For example, instead of writing:
+ *
+ * typedef nsresult (nsIFoo::*someType)(nsISupports* arg);
+ *
+ * you should write:
+ *
+ * typedef
+ * NS_STDCALL_FUNCPROTO(nsresult, someType, nsIFoo, typeFunc, (nsISupports*));
+ *
+ * where nsIFoo::typeFunc is any method declared as
+ * NS_IMETHOD typeFunc(nsISupports*);
+ *
+ * XXX this can be simplified to always use the non-typeof implementation
+ * when http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11893 is fixed.
+ */
+
+#ifdef __GNUC__
+#define NS_STDCALL_FUNCPROTO(ret, name, class, func, args) \
+ typeof(&class::func) name
+#else
+#define NS_STDCALL_FUNCPROTO(ret, name, class, func, args) \
+ ret (NS_STDCALL class::*name) args
+#endif
+
+/**
+ * Generic API modifiers which return the standard XPCOM nsresult type
+ */
+#define NS_IMETHOD NS_IMETHOD_(nsresult)
+#define NS_IMETHODIMP NS_IMETHODIMP_(nsresult)
+#define NS_METHOD NS_METHOD_(nsresult)
+#define NS_CALLBACK(_name) NS_CALLBACK_(nsresult, _name)
+
+/**
+ * Import/Export macros for XPCOM APIs
+ */
+
+#ifdef _IMPL_NS_COM
+#define NS_COM NS_EXPORT
+#elif _IMPL_NS_COM_OFF
+#define NS_COM
+#elif XPCOM_GLUE
+#define NS_COM
+#else
+#define NS_COM NS_IMPORT
+#endif
+
+
+/**
+ * NS_NO_VTABLE is emitted by xpidl in interface declarations whenever
+ * xpidl can determine that the interface can't contain a constructor.
+ * This results in some space savings and possible runtime savings -
+ * see bug 49416. We undefine it first, as xpidl-generated headers
+ * define it for IDL uses that don't include this file.
+ */
+#ifdef NS_NO_VTABLE
+#undef NS_NO_VTABLE
+#endif
+#if defined(_MSC_VER) && _MSC_VER >= 1100
+#define NS_NO_VTABLE __declspec(novtable)
+#else
+#define NS_NO_VTABLE
+#endif
+
+
+/**
+ * Generic XPCOM result data type
+ */
+typedef PRUint32 nsresult;
+
+/**
+ * The preferred symbol for null.
+ */
+#define nsnull 0
+
+#include "nsError.h"
+
+/* ------------------------------------------------------------------------ */
+/* Casting macros for hiding C++ features from older compilers */
+
+ /*
+ All our compiler support template specialization, but not all support the
+ |template <>| notation. The compiler that don't understand this notation
+ just omit it for specialization.
+
+ Need to add an autoconf test for this.
+ */
+
+ /* under Metrowerks (Mac), we don't have autoconf yet */
+#ifdef __MWERKS__
+ #define HAVE_CPP_PARTIAL_SPECIALIZATION
+ #define HAVE_CPP_MODERN_SPECIALIZE_TEMPLATE_SYNTAX
+
+ #define HAVE_CPP_ACCESS_CHANGING_USING
+ #define HAVE_CPP_AMBIGUITY_RESOLVING_USING
+ #define HAVE_CPP_EXPLICIT
+ #define HAVE_CPP_TYPENAME
+ #define HAVE_CPP_BOOL
+ #define HAVE_CPP_NAMESPACE_STD
+ #define HAVE_CPP_UNAMBIGUOUS_STD_NOTEQUAL
+ #define HAVE_CPP_2BYTE_WCHAR_T
+#endif
+
+ /* under VC++ (Windows), we don't have autoconf yet */
+#if defined(_MSC_VER) && (_MSC_VER>=1100)
+ /* VC++ 5.0 and greater implement template specialization, 4.2 is unknown */
+ #define HAVE_CPP_MODERN_SPECIALIZE_TEMPLATE_SYNTAX
+
+ #define HAVE_CPP_EXPLICIT
+ #define HAVE_CPP_TYPENAME
+ #define HAVE_CPP_ACCESS_CHANGING_USING
+
+ #if (_MSC_VER==1100)
+ /* VC++5.0 has an internal compiler error (sometimes) without this */
+ #undef HAVE_CPP_ACCESS_CHANGING_USING
+ #endif
+
+ #define HAVE_CPP_NAMESPACE_STD
+ #define HAVE_CPP_UNAMBIGUOUS_STD_NOTEQUAL
+ #define HAVE_CPP_2BYTE_WCHAR_T
+#endif
+
+#ifndef __PRUNICHAR__
+#define __PRUNICHAR__
+ /* For now, don't use wchar_t on Unix because it breaks the Netscape
+ * commercial build. When this is fixed there will be no need for the
+ * |NS_REINTERPRET_CAST| in nsLiteralString.h either.
+ */
+ #if defined(HAVE_CPP_2BYTE_WCHAR_T) && (defined(NS_WIN32) || defined(XP_MAC))
+ typedef wchar_t PRUnichar;
+ #else
+ typedef PRUint16 PRUnichar;
+ #endif
+#endif
+
+ /*
+ If the compiler doesn't support |explicit|, we'll just make it go away, trusting
+ that the builds under compilers that do have it will keep us on the straight and narrow.
+ */
+#ifndef HAVE_CPP_EXPLICIT
+ #define explicit
+#endif
+
+#ifndef HAVE_CPP_TYPENAME
+ #define typename
+#endif
+
+#ifdef HAVE_CPP_MODERN_SPECIALIZE_TEMPLATE_SYNTAX
+ #define NS_SPECIALIZE_TEMPLATE template <>
+#else
+ #define NS_SPECIALIZE_TEMPLATE
+#endif
+
+/* unix and beos now determine this automatically */
+#if ! defined XP_UNIX && ! defined XP_BEOS && !defined(XP_OS2)
+#ifndef HAVE_CPP_NEW_CASTS
+#define HAVE_CPP_NEW_CASTS 1 /* we'll be optimistic. */
+#endif
+#endif
+
+#if defined(HAVE_CPP_NEW_CASTS)
+#define NS_STATIC_CAST(__type, __ptr) static_cast< __type >(__ptr)
+#define NS_CONST_CAST(__type, __ptr) const_cast< __type >(__ptr)
+
+#define NS_REINTERPRET_POINTER_CAST(__type, __ptr) reinterpret_cast< __type >(__ptr)
+#define NS_REINTERPRET_NONPOINTER_CAST(__type, __obj) reinterpret_cast< __type >(__obj)
+#define NS_REINTERPRET_CAST(__type, __expr) reinterpret_cast< __type >(__expr)
+
+#else
+#define NS_STATIC_CAST(__type, __ptr) ((__type)(__ptr))
+#define NS_CONST_CAST(__type, __ptr) ((__type)(__ptr))
+
+#define NS_REINTERPRET_POINTER_CAST(__type, __ptr) ((__type)((void*)(__ptr)))
+#define NS_REINTERPRET_NONPOINTER_CAST(__type, __obj) ((__type)(__obj))
+
+ /* Note: the following is only appropriate for pointers. */
+#define NS_REINTERPRET_CAST(__type, __expr) NS_REINTERPRET_POINTER_CAST(__type, __expr)
+ /*
+ Why cast to a |void*| first? Well, when old-style casting from
+ a pointer to a base to a pointer to a derived class, the cast will be
+ ambiguous if the source pointer type appears multiple times in the
+ destination, e.g.,
+
+ class Base {};
+ class Derived : public Base, public Base {};
+
+ void foo( Base* b )
+ {
+ ((Derived*)b)->some_derived_member ... // Error: Ambiguous, expand from which |Base|?
+ }
+
+ an old-style cast (like |static_cast|) will change the pointer, but
+ here, doesn't know how. The cast to |void*| prevents it from thinking
+ it needs to expand the original pointer.
+
+ The cost is, |NS_REINTERPRET_CAST| is no longer appropriate for non-pointer
+ conversions. Also, mis-applying |NS_REINTERPRET_CAST| to cast |this| to something
+ will still expand the pointer to the outer object in standards complying compilers.
+ */
+
+ /*
+ No sense in making an NS_DYNAMIC_CAST() macro: you can't duplicate
+ the semantics. So if you want to dynamic_cast, then just use it
+ "straight", no macro.
+ */
+#endif
+
+#if __cplusplus+0 > 201100L
+#define NS_DEFAULT = default
+#define NS_DELETE = delete
+#else
+#define NS_DEFAULT
+#define NS_DELETE
+#endif
+
+
+#ifndef VBOX
+/*
+ * Use these macros to do 64bit safe pointer conversions.
+ */
+
+#define NS_PTR_TO_INT32(x) ((char *)(x) - (char *)0)
+#define NS_INT32_TO_PTR(x) ((void *)((char *)0 + (x)))
+#else /* VBOX */
+// This stuff is (contrary to the comment) totally 64bit unsafe, so strip
+// it down to only do one direction, which is used by the hashing code.
+#define NS_PTR_TO_INT32(x) ((PRInt32)((char *)(x) - (char *)0))
+#endif /* VBOX */
+
+/*
+ * These macros allow you to give a hint to the compiler about branch
+ * probability so that it can better optimize. Use them like this:
+ *
+ * if (NS_LIKELY(v == 1)) {
+ * ... expected code path ...
+ * }
+ *
+ * if (NS_UNLIKELY(v == 0)) {
+ * ... non-expected code path ...
+ * }
+ *
+ */
+
+#if defined(__GNUC__) && (__GNUC__ > 2) && !defined(FORTIFY_RUNNING)
+#define NS_LIKELY(x) (__builtin_expect(!!(x), 1))
+#define NS_UNLIKELY(x) (__builtin_expect(!!(x), 0))
+#else
+#define NS_LIKELY(x) (x)
+#define NS_UNLIKELY(x) (x)
+#endif
+
+#endif /* nscore_h___ */
+
diff --git a/src/libs/xpcom18a4/xpcom/base/nsrootidl.idl b/src/libs/xpcom18a4/xpcom/base/nsrootidl.idl
new file mode 100644
index 00000000..0538e4bc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/nsrootidl.idl
@@ -0,0 +1,128 @@
+/* -*- 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 ***** */
+
+/**
+ * Root idl declarations to be used by all.
+ * @status FROZEN
+ */
+
+%{C++
+
+#include "nscore.h"
+#include "prtime.h"
+
+/*
+ * Forward declarations for new string types
+ */
+class nsAString;
+class nsACString;
+
+/*
+ * Start commenting out the C++ versions of the below in the output header
+ */
+#if 0
+%}
+
+typedef boolean PRBool ;
+typedef octet PRUint8 ;
+typedef unsigned short PRUint16 ;
+typedef unsigned short PRUnichar;
+typedef unsigned long PRUint32 ;
+typedef unsigned long long PRUint64 ;
+typedef unsigned long long PRTime ;
+typedef short PRInt16 ;
+typedef long PRInt32 ;
+typedef long long PRInt64 ;
+
+typedef unsigned long nsrefcnt ;
+typedef unsigned long nsresult ;
+
+// XXX need this built into xpidl compiler so that it's really size_t or PRSize
+// and it's scriptable:
+typedef unsigned long size_t;
+
+[ptr] native voidPtr(void);
+[ptr] native charPtr(char);
+[ptr] native unicharPtr(PRUnichar);
+
+[ref, nsid] native nsIDRef(nsID);
+[ref, nsid] native nsIIDRef(nsIID);
+[ref, nsid] native nsCIDRef(nsCID);
+
+[ptr, nsid] native nsIDPtr(nsID);
+[ptr, nsid] native nsIIDPtr(nsIID);
+[ptr, nsid] native nsCIDPtr(nsCID);
+
+// NOTE: Be careful in using the following 3 types. The *Ref and *Ptr variants
+// are more commonly used (and better supported). Those variants require
+// nsMemory alloc'd copies when used as 'out' params while these types do not.
+// However, currently these types can not be used for 'in' params. And, methods
+// that use them as 'out' params *must* be declared [notxpcom] (with an explicit
+// return type of nsresult). This makes such methods implicitly not scriptable.
+// Use of these types in methods without a [notxpcom] declaration will cause
+// the xpidl compiler to raise an error.
+// See: http://bugzilla.mozilla.org/show_bug.cgi?id=93792
+
+[nsid] native nsIID(nsIID);
+[nsid] native nsID(nsID);
+[nsid] native nsCID(nsCID);
+
+[ptr] native nsQIResult(void);
+
+[ref, domstring] native DOMString(ignored);
+[ref, domstring] native DOMStringRef(ignored);
+[ptr, domstring] native DOMStringPtr(ignored);
+
+[ref, utf8string] native AUTF8String(ignored);
+[ref, utf8string] native AUTF8StringRef(ignored);
+[ptr, utf8string] native AUTF8StringPtr(ignored);
+
+[ref, cstring] native ACString(ignored);
+[ref, cstring] native ACStringRef(ignored);
+[ptr, cstring] native ACStringPtr(ignored);
+
+[ref, astring] native AString(ignored);
+[ref, astring] native AStringRef(ignored);
+[ptr, astring] native AStringPtr(ignored);
+
+%{C++
+/*
+ * End commenting out the C++ versions of the above in the output header
+ */
+#endif
+%}
diff --git a/src/libs/xpcom18a4/xpcom/base/pure.h b/src/libs/xpcom18a4/xpcom/base/pure.h
new file mode 100644
index 00000000..ea11b99d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/pure.h
@@ -0,0 +1,135 @@
+/*
+ * Header file of Pure API function declarations.
+ *
+ * Explicitly no copyright.
+ * You may recompile and redistribute these definitions as required.
+ *
+ * Version 1.0
+ */
+
+#if defined(c_plusplus) || defined(__cplusplus)
+extern "C" {
+#endif
+
+#define PURE_H_VERSION 1
+
+//////////////////////////////
+// API's Specific to Purify //
+//////////////////////////////
+
+// TRUE when Purify is running.
+int __cdecl PurifyIsRunning(void) ;
+//
+// Print a string to the viewer.
+//
+int __cdecl PurePrintf(const char *fmt, ...) ;
+int __cdecl PurifyPrintf(const char *fmt, ...) ;
+//
+// Purify functions for leak and memory-in-use functionalty.
+//
+int __cdecl PurifyNewInuse(void) ;
+int __cdecl PurifyAllInuse(void) ;
+int __cdecl PurifyClearInuse(void) ;
+int __cdecl PurifyNewLeaks(void) ;
+int __cdecl PurifyAllLeaks(void) ;
+int __cdecl PurifyClearLeaks(void) ;
+//
+// Purify functions for handle leakage.
+//
+int __cdecl PurifyAllHandlesInuse(void) ;
+int __cdecl PurifyNewHandlesInuse(void) ;
+//
+// Functions that tell you about the state of memory.
+//
+int __cdecl PurifyDescribe(void *addr) ;
+int __cdecl PurifyWhatColors(void *addr, int size) ;
+//
+// Functions to test the state of memory. If the memory is not
+// accessable, an error is signaled just as if there were a memory
+// reference and the function returns false.
+//
+int __cdecl PurifyAssertIsReadable(const void *addr, int size) ;
+int __cdecl PurifyAssertIsWritable(const void *addr, int size) ;
+//
+// Functions to test the state of memory. If the memory is not
+// accessable, these functions return false. No error is signaled.
+//
+int __cdecl PurifyIsReadable(const void *addr, int size) ;
+int __cdecl PurifyIsWritable(const void *addr, int size) ;
+int __cdecl PurifyIsInitialized(const void *addr, int size) ;
+//
+// Functions to set the state of memory.
+//
+void __cdecl PurifyMarkAsInitialized(void *addr, int size) ;
+void __cdecl PurifyMarkAsUninitialized(void *addr, int size) ;
+//
+// Functions to do late detection of ABWs, FMWs, IPWs.
+//
+#define PURIFY_HEAP_CRT 0xfffffffe
+#define PURIFY_HEAP_ALL 0xfffffffd
+#define PURIFY_HEAP_BLOCKS_LIVE 0x80000000
+#define PURIFY_HEAP_BLOCKS_DEFERRED_FREE 0x40000000
+#define PURIFY_HEAP_BLOCKS_ALL (PURIFY_HEAP_BLOCKS_LIVE|PURIFY_HEAP_BLOCKS_DEFERRED_FREE)
+int __cdecl PurifyHeapValidate(unsigned int hHeap, unsigned int dwFlags, const void *addr) ;
+int __cdecl PurifySetLateDetectScanCounter(int counter);
+int __cdecl PurifySetLateDetectScanInterval(int seconds);
+
+
+////////////////////////////////
+// API's Specific to Quantify //
+////////////////////////////////
+
+// TRUE when Quantify is running.
+int __cdecl QuantifyIsRunning(void) ;
+
+//
+// Functions for controlling collection
+//
+int __cdecl QuantifyDisableRecordingData(void) ;
+int __cdecl QuantifyStartRecordingData(void) ;
+int __cdecl QuantifyStopRecordingData(void) ;
+int __cdecl QuantifyClearData(void) ;
+int __cdecl QuantifyIsRecordingData(void) ;
+
+// Add a comment to the dataset
+int __cdecl QuantifyAddAnnotation(char *) ;
+
+// Save the current data, creating a "checkpoint" dataset
+int __cdecl QuantifySaveData(void) ;
+
+////////////////////////////////
+// API's Specific to Coverage //
+////////////////////////////////
+
+// TRUE when Coverage is running.
+int __cdecl CoverageIsRunning(void) ;
+//
+// Functions for controlling collection
+//
+int __cdecl CoverageDisableRecordingData(void) ;
+int __cdecl CoverageStartRecordingData(void) ;
+int __cdecl CoverageStopRecordingData(void) ;
+int __cdecl CoverageClearData(void) ;
+int __cdecl CoverageIsRecordingData(void) ;
+// Add a comment to the dataset
+int __cdecl CoverageAddAnnotation(char *) ;
+
+// Save the current data, creating a "checkpoint" dataset
+int __cdecl CoverageSaveData(void) ;
+
+
+
+
+////////////////////////////////
+// API's Specific to Purelock //
+////////////////////////////////
+
+// TRUE when Purelock is running.
+int __cdecl PurelockIsRunning(void) ;
+
+
+
+
+#if defined(c_plusplus) || defined(__cplusplus)
+}
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/base/pure_api.c b/src/libs/xpcom18a4/xpcom/base/pure_api.c
new file mode 100644
index 00000000..716460ed
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/base/pure_api.c
@@ -0,0 +1,126 @@
+/*
+ * Header file of Pure API function declarations.
+ *
+ * Explicitly no copyright.
+ * You may recompile and redistribute these definitions as required.
+ *
+ * NOTE1: In some situations when compiling with MFC, you should
+ * enable the setting 'Not using precompiled headers' in Visual C++
+ * to avoid a compiler diagnostic.
+ *
+ * NOTE2: This file works through the use of deep magic. Calls to functions
+ * in this file are replaced with calls into the OCI runtime system
+ * when an instrumented version of this program is run.
+ *
+ * NOTE3: The static vars avoidGy_n (where n is a unique number) are used
+ * to prevent optimizing the functions away when compiler option
+ * /Gy is set. This is needed so that NOTE2 works properly.
+ */
+static int avoidGy_1;
+static int avoidGy_2;
+static int avoidGy_3;
+static int avoidGy_4;
+static int avoidGy_5;
+static int avoidGy_6;
+static int avoidGy_7;
+static int avoidGy_8;
+static int avoidGy_9;
+static int avoidGy_10;
+static int avoidGy_11;
+static int avoidGy_12;
+static int avoidGy_13;
+static int avoidGy_14;
+static int avoidGy_15;
+static int avoidGy_16;
+static int avoidGy_17;
+static int avoidGy_18;
+static int avoidGy_19;
+static int avoidGy_20;
+static int avoidGy_21;
+static int avoidGy_22;
+static int avoidGy_23;
+static int avoidGy_24;
+static int avoidGy_25;
+static int avoidGy_26;
+static int avoidGy_27;
+static int avoidGy_28;
+static int avoidGy_29;
+static int avoidGy_30;
+static int avoidGy_31;
+static int avoidGy_32;
+static int avoidGy_33;
+static int avoidGy_34;
+static int avoidGy_35;
+static int avoidGy_36;
+static int avoidGy_37;
+static int avoidGy_38;
+static int avoidGy_39;
+static int avoidGy_40;
+static int avoidGy_41;
+static int avoidGy_42;
+static int avoidGy_43;
+static int avoidGy_44;
+static int avoidGy_45;
+static int avoidGy_46;
+static int avoidGy_47;
+static int avoidGy_48;
+static int avoidGy_49;
+static int avoidGy_50;
+static int avoidGy_51;
+static int avoidGy_52;
+static int avoidGy_53;
+static int avoidGy_54;
+static int avoidGy_55;
+static int avoidGy_56;
+static int avoidGy_57;
+static int avoidGy_58;
+static int avoidGy_59;
+static int avoidGy_60;
+static int avoidGy_PL_01;
+__declspec(dllexport) int __cdecl PurePrintf(const char *fmt, ...) { avoidGy_1++; fmt; return 0; }
+__declspec(dllexport) int __cdecl PurifyIsRunning(void) { avoidGy_2++; return 0; }
+__declspec(dllexport) int __cdecl PurifyPrintf(const char *fmt, ...) { avoidGy_3++; fmt; return 0; }
+__declspec(dllexport) int __cdecl PurifyNewInuse(void) { avoidGy_4++; return 0; }
+__declspec(dllexport) int __cdecl PurifyAllInuse(void) { avoidGy_5++; return 0; }
+__declspec(dllexport) int __cdecl PurifyClearInuse(void) { avoidGy_6++; return 0; }
+__declspec(dllexport) int __cdecl PurifyNewLeaks(void) { avoidGy_7++; return 0; }
+__declspec(dllexport) int __cdecl PurifyAllLeaks(void) { avoidGy_8++; return 0; }
+__declspec(dllexport) int __cdecl PurifyClearLeaks(void) { avoidGy_9++; return 0; }
+__declspec(dllexport) int __cdecl PurifyAllHandlesInuse(void) { avoidGy_10++; return 0; }
+__declspec(dllexport) int __cdecl PurifyNewHandlesInuse(void) { avoidGy_11++; return 0; }
+__declspec(dllexport) int __cdecl PurifyDescribe(void *addr) { avoidGy_12++; addr; return 0; }
+__declspec(dllexport) int __cdecl PurifyWhatColors(void *addr, int size) { avoidGy_13++; addr; size; return 0; }
+__declspec(dllexport) int __cdecl PurifyAssertIsReadable(const void *addr, int size) { avoidGy_14++; addr; size; return 1; }
+__declspec(dllexport) int __cdecl PurifyAssertIsWritable(const void *addr, int size) { avoidGy_15++; addr; size; return 1; }
+__declspec(dllexport) int __cdecl PurifyIsReadable(const void *addr, int size) { avoidGy_16++; addr; size; return 1; }
+__declspec(dllexport) int __cdecl PurifyIsWritable(const void *addr, int size) { avoidGy_17++; addr; size; return 1; }
+__declspec(dllexport) int __cdecl PurifyIsInitialized(const void *addr, int size) { avoidGy_18++; addr; size; return 1; }
+__declspec(dllexport) int __cdecl PurifyRed(void *addr, int size) { avoidGy_19++; addr; size; return 0; }
+__declspec(dllexport) int __cdecl PurifyGreen(void *addr, int size) { avoidGy_20++; addr; size; return 0; }
+__declspec(dllexport) int __cdecl PurifyYellow(void *addr, int size) { avoidGy_21++; addr; size; return 0; }
+__declspec(dllexport) int __cdecl PurifyBlue(void *addr, int size) { avoidGy_22++; addr; size; return 0; }
+__declspec(dllexport) int __cdecl PurifyMarkAsInitialized(void *addr, int size) { avoidGy_23++; addr; size; return 0; }
+__declspec(dllexport) int __cdecl PurifyMarkAsUninitialized(void *addr, int size) { avoidGy_24++; addr; size; return 0; }
+__declspec(dllexport) int __cdecl PurifyMarkForTrap(void *addr, int size) { avoidGy_25++; addr; size; return 0; }
+__declspec(dllexport) int __cdecl PurifyMarkForNoTrap(void *addr, int size) { avoidGy_26++; addr; size; return 0; }
+__declspec(dllexport) int __cdecl PurifyHeapValidate(unsigned int hHeap, unsigned int dwFlags, const void *addr)
+ { avoidGy_27++; hHeap; dwFlags; addr; return 1; }
+__declspec(dllexport) int __cdecl PurifySetLateDetectScanCounter(int counter) { avoidGy_28++; counter; return 0; };
+__declspec(dllexport) int __cdecl PurifySetLateDetectScanInterval(int seconds) { avoidGy_29++; seconds; return 0; };
+__declspec(dllexport) int __cdecl CoverageIsRunning(void) { avoidGy_30++; return 0; }
+__declspec(dllexport) int __cdecl CoverageDisableRecordingData(void) { avoidGy_31++; return 0; }
+__declspec(dllexport) int __cdecl CoverageStartRecordingData(void) { avoidGy_32++; return 0; }
+__declspec(dllexport) int __cdecl CoverageStopRecordingData(void) { avoidGy_33++; return 0; }
+__declspec(dllexport) int __cdecl CoverageClearData(void) { avoidGy_34++; return 0; }
+__declspec(dllexport) int __cdecl CoverageIsRecordingData(void) { avoidGy_35++; return 0; }
+__declspec(dllexport) int __cdecl CoverageAddAnnotation(char *str) { avoidGy_36++; str; return 0; }
+__declspec(dllexport) int __cdecl CoverageSaveData(void) { avoidGy_37++; return 0; }
+__declspec(dllexport) int __cdecl QuantifyIsRunning(void) { avoidGy_42++; return 0; }
+__declspec(dllexport) int __cdecl QuantifyDisableRecordingData(void) { avoidGy_43++; return 0; }
+__declspec(dllexport) int __cdecl QuantifyStartRecordingData(void) { avoidGy_44++; return 0; }
+__declspec(dllexport) int __cdecl QuantifyStopRecordingData(void) { avoidGy_45++; return 0; }
+__declspec(dllexport) int __cdecl QuantifyClearData(void) { avoidGy_46++; return 0; }
+__declspec(dllexport) int __cdecl QuantifyIsRecordingData(void) { avoidGy_47++; return 0; }
+__declspec(dllexport) int __cdecl QuantifyAddAnnotation(char *str) { avoidGy_48++; str; return 0; }
+__declspec(dllexport) int __cdecl QuantifySaveData(void) { avoidGy_49++; return 0; }
+__declspec(dllexport) int __cdecl PurelockIsRunning(void) { avoidGy_PL_01++; return 0; }
diff --git a/src/libs/xpcom18a4/xpcom/build/.cvsignore b/src/libs/xpcom18a4/xpcom/build/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/build/Makefile.in b/src/libs/xpcom18a4/xpcom/build/Makefile.in
new file mode 100644
index 00000000..5c2386ce
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/Makefile.in
@@ -0,0 +1,165 @@
+#
+# ***** 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
+LIBRARY_NAME = xpcom
+
+PACKAGE_FILE = xpcom.pkg
+PACKAGE_VARS += USE_SHORT_LIBNAME
+
+ifdef ENABLE_TESTS
+PACKAGE_FILE += xpcom-tests.pkg
+endif
+
+# Do not set EXPORT_LIBRARY as we do not want xpcom in the static libs list
+#EXPORT_LIBRARY = 1
+GRE_MODULE = 1
+
+REQUIRES = string \
+ $(NULL)
+
+# pull in MoreFiles for MacOSX
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+REQUIRES += macmorefiles
+endif
+
+CPPSRCS = nsXPComInit.cpp \
+ nsStringAPI.cpp \
+ $(NULL)
+
+ifeq ($(OS_ARCH),WINNT)
+CPPSRCS += dlldeps.cpp
+endif
+
+ifdef XPCOM_USE_LEA
+CSRCS += malloc.c
+endif
+
+ifeq ($(OS_TARGET),OS2)
+CPPSRCS += nsOS2VACLegacy.cpp
+endif
+
+ifdef GC_LEAK_DETECTOR
+EXTRA_DSO_LIBS = boehm
+endif
+
+SHARED_LIBRARY_LIBS = \
+ $(DIST)/lib/$(LIB_PREFIX)xpcomds_s.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)xpcomio_s.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)xpcomcomponents_s.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)xpcomthreads_s.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)xpcomproxy_s.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)xpcombase_s.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)xptcall.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)xptinfo.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)xpt.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)xptcmd.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)string_s.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)xpcomglue_s.$(LIB_SUFFIX) \
+ $(NULL)
+
+LOCAL_INCLUDES = \
+ -I.. \
+ -I$(srcdir)/../glue \
+ -I$(srcdir)/../base \
+ -I$(srcdir)/../ds \
+ -I$(srcdir)/../io \
+ -I$(srcdir)/../components \
+ -I$(srcdir)/../threads \
+ -I$(srcdir)/../threads/_xpidlgen \
+ -I$(srcdir)/../proxy/src \
+ $(NULL)
+
+SDK_HEADERS = \
+ nsXPCOM.h \
+ nsXPCOMCID.h \
+ $(NULL)
+
+SDK_LIBRARY = $(IMPORT_LIBRARY)
+SDK_BINARY = $(SHARED_LIBRARY)
+
+# pull in MoreFiles for MacOSX
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+EXTRA_DSO_LIBS = macmorefiles_s
+EXTRA_DSO_LDOPTS += $(EXTRA_DSO_LIBS)
+EXTRA_DEPS += $(DIST)/lib/$(LIB_PREFIX)macmorefiles_s.$(LIB_SUFFIX)
+endif
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+FORCE_SHARED_LIB = 1
+
+# UNIX98 iconv support
+OS_LIBS += $(LIBICONV)
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += \
+ -D_IMPL_NS_COM \
+ -DEXPORT_XPT_API \
+ -DEXPORT_XPTC_API \
+ -DEXPORT_XPTI_API
+
+EXTRA_DSO_LDOPTS += $(NSPR_LIBS)
+
+ifdef GC_LEAK_DETECTOR
+DEFINES += -DGC_LEAK_DETECTOR
+endif
+
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+CXXFLAGS += $(TK_CFLAGS)
+EXTRA_DSO_LDOPTS += $(TK_LIBS)
+endif
+
+ifeq ($(OS_ARCH),BeOS)
+EXTRA_DSO_LDOPTS += -lbe
+endif
+
+ifeq ($(OS_ARCH),WINNT)
+EXTRA_DSO_LDOPTS += $(call EXPAND_LIBNAME,shell32 ole32 uuid)
+ifneq (,$(MOZ_DEBUG)$(NS_TRACE_MALLOC))
+EXTRA_DSO_LDOPTS += $(call EXPAND_LIBNAME,imagehlp)
+endif
+endif # WINNT
diff --git a/src/libs/xpcom18a4/xpcom/build/dlldeps.cpp b/src/libs/xpcom18a4/xpcom/build/dlldeps.cpp
new file mode 100644
index 00000000..5fc31189
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/dlldeps.cpp
@@ -0,0 +1,202 @@
+/* -*- 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 ***** */
+
+// Force references to all of the symbols that we want exported from
+// the dll that are located in the .lib files we link with
+
+#include "nsVoidArray.h"
+#include "nsValueArray.h"
+#include "nsIAtom.h"
+//#include "nsIBuffer.h"
+#include "nsIByteArrayInputStream.h"
+#include "nsFixedSizeAllocator.h"
+#include "nsRecyclingAllocator.h"
+#include "nsIThread.h"
+#include "nsDeque.h"
+#include "nsTraceRefcnt.h"
+#include "nsTraceRefcntImpl.h"
+#include "nsXPIDLString.h"
+#include "nsIEnumerator.h"
+#include "nsEnumeratorUtils.h"
+#include "nsQuickSort.h"
+#include "nsString.h"
+#include "nsPrintfCString.h"
+#include "nsSupportsArray.h"
+#include "nsArray.h"
+#include "nsArrayEnumerator.h"
+#include "nsProxyEventPrivate.h"
+#include "nsProxyRelease.h"
+#include "xpt_xdr.h"
+#include "xptcall.h"
+#include "nsILocalFile.h"
+#include "nsIGenericFactory.h"
+#include "nsIPipe.h"
+#include "nsStreamUtils.h"
+#include "nsWeakReference.h"
+#include "nsTextFormatter.h"
+#include "nsIStorageStream.h"
+#include "nsLinebreakConverter.h"
+#include "nsIBinaryInputStream.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include "nsReadableUtils.h"
+#include "nsStaticNameTable.h"
+#include "nsProcess.h"
+#include "nsStringEnumerator.h"
+#include "nsIInputStreamTee.h"
+#include "nsCheapSets.h"
+#ifdef DEBUG
+#include "pure.h"
+#endif
+#include "nsHashKeys.h"
+#include "nsTHashtable.h"
+#include "pldhash.h"
+#include "nsVariant.h"
+#include "nsEscape.h"
+#include "nsStreamUtils.h"
+
+#define NS_STRINGAPI_IMPL
+#include "nsStringAPI.h"
+
+void XXXNeverCalled()
+{
+ nsTextFormatter::snprintf(nsnull,0,nsnull);
+ nsTextFormatter::smprintf(nsnull, nsnull);
+ nsTextFormatter::smprintf_free(nsnull);
+ nsVoidArray();
+ nsSmallVoidArray();
+ nsStringHashSet();
+ nsCStringHashSet();
+ nsInt32HashSet();
+ nsVoidHashSet();
+ nsCheapStringSet();
+ nsCheapInt32Set();
+ nsValueArray(0);
+ nsSupportsArray();
+ NS_GetNumberOfAtoms();
+ NS_NewPipe2(nsnull, nsnull, PR_FALSE, PR_FALSE, 0, 0, nsnull);
+ NS_NewInputStreamReadyEvent(nsnull, nsnull, nsnull);
+ NS_NewOutputStreamReadyEvent(nsnull, nsnull, nsnull);
+ NS_AsyncCopy(nsnull, nsnull, nsnull, NS_ASYNCCOPY_VIA_READSEGMENTS, 0, nsnull, nsnull);
+ PL_DHashStubEnumRemove(nsnull, nsnull, nsnull, nsnull);
+ nsIDHashKey::HashKey(nsnull);
+ nsFixedSizeAllocator a;
+ nsRecyclingAllocator recyclingAllocator(2);
+ a.Init(0, 0, 0, 0, 0);
+ a.Alloc(0);
+ a.Free(0, 0);
+ nsIThread::GetCurrent(nsnull);
+ nsDeque(nsnull);
+ nsTraceRefcnt::LogAddCOMPtr(nsnull, nsnull);
+ nsTraceRefcntImpl::DumpStatistics();
+ NS_NewEmptyEnumerator(nsnull);
+ new nsArrayEnumerator(nsnull);
+ NS_QuickSort(nsnull, 0, 0, nsnull, nsnull);
+ nsString();
+ nsProxyObject(nsnull, 0, nsnull);
+ NS_ProxyRelease(nsnull, nsnull, PR_FALSE);
+ XPT_DoString(nsnull, nsnull, nsnull);
+ XPT_DoHeader(nsnull, nsnull, nsnull);
+#ifdef DEBUG
+ PurePrintf(0);
+#endif
+ XPTC_InvokeByIndex(nsnull, 0, 0, nsnull);
+ xptc_dummy();
+ xptc_dummy2();
+ XPTI_GetInterfaceInfoManager();
+ NS_NewGenericFactory(nsnull, nsnull);
+ NS_NewGenericModule2(nsnull, nsnull);
+ NS_GetWeakReference(nsnull);
+ nsCOMPtr<nsISupports> dummyFoo(do_GetInterface(nsnull));
+ NS_NewByteArrayInputStream(nsnull, nsnull, 0);
+ NS_NewStorageStream(0,0, nsnull);
+ nsString foo;
+ nsPrintfCString bar("");
+ nsLinebreakConverter::ConvertStringLineBreaks(foo,
+ nsLinebreakConverter::eLinebreakAny, nsLinebreakConverter::eLinebreakContent);
+ NS_NewLocalFile(nsString(), PR_FALSE, nsnull);
+ NS_NewNativeLocalFile(nsCString(), PR_FALSE, nsnull);
+ new nsProcess();
+ nsStaticCaseInsensitiveNameTable();
+ nsAutoString str1;
+ str1.AssignWithConversion(nsnull, 0);
+ nsCAutoString str2;
+ ToNewUnicode(str1);
+ ToNewUnicode(str2);
+ ToNewCString(str1);
+ ToNewCString(str2);
+ PL_DHashTableFinish(nsnull);
+ NS_NewInputStreamTee(nsnull, nsnull, nsnull);
+ NS_NewArray(nsnull);
+ nsCOMArray<nsISupports> dummyArray;
+ NS_NewArray(nsnull, dummyArray);
+ NS_NewArrayEnumerator(nsnull, dummyArray);
+ new nsVariant();
+ nsUnescape(nsnull);
+ nsEscape(nsnull, url_XAlphas);
+ nsStringArray array;
+ NS_NewStringEnumerator(nsnull, &array);
+ NS_NewAdoptingStringEnumerator(nsnull, &array);
+ nsCStringArray carray;
+ NS_NewUTF8StringEnumerator(nsnull, &carray);
+ NS_NewAdoptingUTF8StringEnumerator(nsnull, &carray);
+ nsVoidableString str3;
+ nsCStringContainer sc1;
+ NS_CStringContainerInit(sc1);
+ NS_CStringContainerFinish(sc1);
+ NS_CStringGetData(str2, nsnull, nsnull);
+ NS_CStringSetData(str2, nsnull, 0);
+ NS_CStringSetDataRange(str2, 0, 0, nsnull, 0);
+ NS_CStringCopy(str2, str2);
+ nsStringContainer sc2;
+ NS_StringContainerInit(sc2);
+ NS_StringContainerFinish(sc2);
+ NS_StringGetData(str1, nsnull, nsnull);
+ NS_StringSetData(str1, nsnull, 0);
+ NS_StringSetDataRange(str1, 0, 0, nsnull, 0);
+ NS_StringCopy(str1, str1);
+ {
+ nsAdoptingCString foo, bar;
+ foo = bar;
+ }
+ {
+ nsAdoptingString foo, bar;
+ foo = bar;
+ }
+ NS_UTF16ToCString(str1, NS_CSTRING_ENCODING_ASCII, str2);
+ NS_CStringToUTF16(str2, NS_CSTRING_ENCODING_ASCII, str1);
+}
diff --git a/src/libs/xpcom18a4/xpcom/build/malloc.c b/src/libs/xpcom18a4/xpcom/build/malloc.c
new file mode 100644
index 00000000..96691829
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/malloc.c
@@ -0,0 +1,5126 @@
+#define USE_MALLOC_LOCK
+#define DEFAULT_TRIM_THRESHOLD (256 * 1024)
+
+/* ---------- To make a malloc.h, start cutting here ------------ */
+
+/*
+ ****************************************************************
+ * THIS IS A PRERELEASE. It has not yet been tested adequately. *
+ * If you use it, please send back comments, suggestions, *
+ * performance reports, etc. *
+ ****************************************************************
+*/
+
+/*
+ A version (aka dlmalloc) of malloc/free/realloc written by Doug
+ Lea and released to the public domain. Use this code without
+ permission or acknowledgement in any way you wish. Send questions,
+ comments, complaints, performance data, etc to dl@cs.oswego.edu
+
+* VERSION 2.7.0pre7 Wed Jan 10 13:33:01 2001 Doug Lea (dl at gee)
+
+ Note: There may be an updated version of this malloc obtainable at
+ ftp://gee.cs.oswego.edu/pub/misc/malloc.c
+ Check before installing!
+
+* Quickstart
+
+ This library is all in one file to simplify the most common usage:
+ ftp it, compile it (-O), and link it into another program. All
+ of the compile-time options default to reasonable values for use on
+ most unix platforms. Compile -DWIN32 for reasonable defaults on windows.
+ You might later want to step through various compile options.
+
+* Why use this malloc?
+
+ This is not the fastest, most space-conserving, most portable, or
+ most tunable malloc ever written. However it is among the fastest
+ while also being among the most space-conserving, portable and tunable.
+ Consistent balance across these factors results in a good general-purpose
+ allocator for malloc-intensive programs.
+
+ The main properties of the algorithms are:
+ * For large (>= 512 bytes) requests, it is a pure best-fit allocator,
+ with ties normally decided via FIFO (i.e. least recently used).
+ * For small (<= 64 bytes by default) requests, it is a caching
+ allocator, that maintains pools of quickly recycled chunks.
+ * In between, and for combinations of large and small requests, it does
+ the best it can trying to meet both goals at once.
+
+ Compared to 2.6.X versions, this version is generally faster,
+ especially for programs that allocate and free many small chunks.
+
+ For a longer but slightly out of date high-level description, see
+ http://gee.cs.oswego.edu/dl/html/malloc.html
+
+ You may already by default be using a c library containing a malloc
+ that is somehow based on some version of this malloc (for example in
+ linux). You might still want to use the one in this file in order to
+ customize settings or to avoid overheads associated with library
+ versions.
+
+* Synopsis of public routines
+
+ (Much fuller descriptions are contained in the program documentation below.)
+
+ malloc(size_t n);
+ Return a pointer to a newly allocated chunk of at least n bytes, or null
+ if no space is available.
+ free(Void_t* p);
+ Release the chunk of memory pointed to by p, or no effect if p is null.
+ realloc(Void_t* p, size_t n);
+ Return a pointer to a chunk of size n that contains the same data
+ as does chunk p up to the minimum of (n, p's size) bytes, or null
+ if no space is available. The returned pointer may or may not be
+ the same as p. If p is null, equivalent to malloc. Unless the
+ #define REALLOC_ZERO_BYTES_FREES below is set, realloc with a
+ size argument of zero (re)allocates a minimum-sized chunk.
+ memalign(size_t alignment, size_t n);
+ Return a pointer to a newly allocated chunk of n bytes, aligned
+ in accord with the alignment argument, which must be a power of
+ two.
+ valloc(size_t n);
+ Equivalent to memalign(pagesize, n), where pagesize is the page
+ size of the system (or as near to this as can be figured out from
+ all the includes/defines below.)
+ pvalloc(size_t n);
+ Equivalent to valloc(minimum-page-that-holds(n)), that is,
+ round up n to nearest pagesize.
+ calloc(size_t unit, size_t quantity);
+ Returns a pointer to quantity * unit bytes, with all locations
+ set to zero.
+ cfree(Void_t* p);
+ Equivalent to free(p).
+ malloc_trim(size_t pad);
+ Release all but pad bytes of freed top-most memory back
+ to the system. Return 1 if successful, else 0.
+ malloc_usable_size(Void_t* p);
+ Report the number usable allocated bytes associated with allocated
+ chunk p. This may or may not report more bytes than were requested,
+ due to alignment and minimum size constraints.
+ malloc_stats();
+ Prints brief summary statistics on stderr.
+ mallinfo()
+ Returns (by copy) a struct containing various summary statistics.
+ mallopt(int parameter_number, int parameter_value)
+ Changes one of the tunable parameters described below. Returns
+ 1 if successful in changing the parameter, else 0.
+
+* Vital statistics:
+
+ Assumed pointer representation: 4 or 8 bytes
+ (Thanks to Wolfram Gloger for contributing most of the
+ changes supporting dual 4/8.)
+
+ Assumed size_t representation: 4 or 8 bytes
+ Note that size_t is allowed to be 4 bytes even if pointers are 8.
+ You can adjust this by defining INTERNAL_SIZE_T
+
+ Alignment: 2 * sizeof(size_t)
+ (i.e., 8 byte alignment with 4byte size_t). This suffices for
+ nearly all current machines and C compilers. However, you can
+ define MALLOC_ALIGNMENT to be wider than this if necessary.
+
+ Minimum overhead per allocated chunk: 4 or 8 bytes
+ Each malloced chunk has a hidden word of overhead holding size
+ and status information.
+
+ Minimum allocated size: 4-byte ptrs: 16 bytes (including 4 overhead)
+ 8-byte ptrs: 24/32 bytes (including, 4/8 overhead)
+
+ When a chunk is freed, 12 (for 4byte ptrs) or 20 (for 8 byte
+ ptrs but 4 byte size) or 24 (for 8/8) additional bytes are
+ needed; 4 (8) for a trailing size field and 8 (16) bytes for
+ free list pointers. Thus, the minimum allocatable size is
+ 16/24/32 bytes.
+
+ Even a request for zero bytes (i.e., malloc(0)) returns a
+ pointer to something of the minimum allocatable size.
+
+ The maximum overhead wastage (i.e., number of extra bytes
+ allocated than were requested in malloc) is less than or equal
+ to the minimum size, except for requests >= mmap_threshold that
+ are serviced via mmap(), where the worst case wastage is 2 *
+ sizeof(size_t) bytes plus the remainder from a system page (the
+ minimal mmap unit); typically 4096 bytes.
+
+ Maximum allocated size: 4-byte size_t: 2^31 minus about two pages
+ 8-byte size_t: 2^63 minus about two pages
+
+ It is assumed that (possibly signed) size_t values suffice
+ to represent chunk sizes. `Possibly signed' is due to the fact
+ that `size_t' may be defined on a system as either a signed or
+ an unsigned type. The ISO C standard says that it must be
+ unsigned, but a few systems are known not to adhere to this.
+ Additionally, even when size_t is unsigned, sbrk (which is by
+ default used to obtain memory from system) accepts signed
+ arguments, and may not be able to handle size_t-wide arguments
+ with negative sign bit. To be conservative, values that would
+ appear as negative after accounting for overhead and alignment
+ are rejected.
+
+ Requests for sizes outside this range will perform an optional
+ failure action and then return null. (Requests may also
+ also fail because a system is out of memory.)
+
+ Thread-safety: NOT thread-safe unless USE_MALLOC_LOCK defined
+
+ When USE_MALLOC_LOCK is defined, wrappers are created to
+ surround every public call with either a pthread mutex or
+ a win32 critical section (depending on WIN32). This is not
+ especially fast, and can be a major bottleneck in programs with
+ many threads. It is designed only to provide minimal protection
+ in concurrent environments, and to provide a basis for
+ extensions. If you are using malloc in a concurrent program,
+ you would be far better off obtaining ptmalloc, which is
+ derived from a version of this malloc, and is well-tuned for
+ concurrent programs. (See http://www.malloc.de)
+
+ Compliance: I believe it is compliant with the 1997 Single Unix Specification
+
+ (See http://www.opennc.org). Probably other standards as well.
+
+* Limitations
+
+ Here are some features that are NOT currently supported
+
+ * No automated mechanism for fully checking that all accesses
+ to malloced memory stay within their bounds. However, there
+ are several add-ons and adaptations of this or other mallocs
+ available that do this.
+ * No support for compaction.
+
+* Synopsis of compile-time options:
+
+ People have reported using previous versions of this malloc on all
+ versions of Unix, sometimes by tweaking some of the defines
+ below. It has been tested most extensively on Solaris and
+ Linux. It is also reported to work on WIN32 platforms.
+ People also report using it in stand-alone embedded systems.
+
+ The implementation is in straight, hand-tuned ANSI C. It is not
+ at all modular. (Sorry!) It uses a lot of macros. To be at all
+ usable, this code should be compiled using an optimizing compiler
+ (for example gcc -O3) that can simplify expressions and control
+ paths. (FAQ: some macros import variables as arguments rather than
+ declare locals because people reported that some debuggers
+ otherwise get confused.)
+
+ OPTION DEFAULT VALUE
+
+ Compilation Environment options:
+
+ __STD_C derived from C compiler defines
+ WIN32 NOT defined
+ HAVE_MEMCPY defined
+ USE_MEMCPY 1 if HAVE_MEMCPY is defined
+ HAVE_MMAP defined as 1
+ MMAP_AS_MORECORE_SIZE (1024 * 1024)
+ HAVE_MREMAP defined as 0 unless linux defined
+ malloc_getpagesize derived from system #includes, or 4096 if not
+ HAVE_USR_INCLUDE_MALLOC_H NOT defined
+ LACKS_UNISTD_H NOT defined unless WIN32
+ LACKS_SYS_PARAM_H NOT defined unless WIN32
+ LACKS_SYS_MMAN_H NOT defined unless WIN32
+
+ Changing default word sizes:
+
+ INTERNAL_SIZE_T size_t
+ MALLOC_ALIGNMENT 2 * sizeof(INTERNAL_SIZE_T)
+
+ Configuration and functionality options:
+
+ USE_DL_PREFIX NOT defined
+ USE_PUBLIC_MALLOC_WRAPPERS NOT defined
+ USE_MALLOC_LOCK NOT defined
+ DEBUG NOT defined
+ REALLOC_ZERO_BYTES_FREES NOT defined
+ MALLOC_FAILURE_ACTION errno = ENOMEM, if __STD_C defined, else no-op
+ TRIM_FASTBINS 0
+
+ Options for customizing MORECORE:
+
+ MORECORE sbrk
+ MORECORE_CONTIGUOUS 1
+
+ Tuning options that are also dynamically changeable via mallopt:
+
+ DEFAULT_MXFAST 64
+ DEFAULT_TRIM_THRESHOLD 128 * 1024
+ DEFAULT_TOP_PAD 0
+ DEFAULT_MMAP_THRESHOLD 128 * 1024
+ DEFAULT_MMAP_MAX 256
+
+ There are several other #defined constants and macros that you
+ probably don't want to touch unless you are extending or adapting malloc.
+
+*/
+#include "xpcom-private.h"
+
+
+
+/*
+ WIN32 sets up defaults for MS environment and compilers.
+ Otherwise defaults are for unix.
+*/
+
+/* #define WIN32 */
+
+#ifdef WIN32
+
+#include <windows.h>
+
+/* Win32 doesn't supply or need the following headers */
+#define LACKS_UNISTD_H
+#define LACKS_SYS_PARAM_H
+#define LACKS_SYS_MMAN_H
+
+/* Use the supplied emulation of sbrk */
+#define MORECORE sbrk
+#define MORECORE_CONTIGUOUS 1
+#define MORECORE_FAILURE ((void*)(-1))
+
+/* Use the supplied emulation mmap, munmap */
+#define HAVE_MMAP 1
+#define MUNMAP_FAILURE (-1)
+/* These values don't really matter in windows mmap emulation */
+#define MAP_PRIVATE 1
+#define MAP_ANONYMOUS 2
+#define PROT_READ 1
+#define PROT_WRITE 2
+
+/* Emulation functions defined at the end of this file */
+
+/* If USE_MALLOC_LOCK, use supplied critical-section-based lock functions */
+#ifdef USE_MALLOC_LOCK
+static int slwait(int *sl);
+static int slrelease(int *sl);
+#endif
+
+static long getpagesize(void);
+static long getregionsize(void);
+static void *sbrk(long size);
+static void *mmap(void *ptr, long size, long prot, long type, long handle, long arg);
+static long munmap(void *ptr, long size);
+
+static void vminfo (unsigned long *free, unsigned long *reserved, unsigned long *committed);
+static int cpuinfo (int whole, unsigned long *kernel, unsigned long *user);
+
+#endif
+
+
+
+/*
+ __STD_C should be nonzero if using ANSI-standard C compiler, a C++
+ compiler, or a C compiler sufficiently close to ANSI to get away
+ with it.
+*/
+
+#ifndef __STD_C
+#ifdef __STDC__
+#define __STD_C 1
+#else
+#if __cplusplus
+#define __STD_C 1
+#else
+#define __STD_C 0
+#endif /*__cplusplus*/
+#endif /*__STDC__*/
+#endif /*__STD_C*/
+
+
+/*
+ Void_t* is the pointer type that malloc should say it returns
+*/
+
+#ifndef Void_t
+#if (__STD_C || defined(WIN32))
+#define Void_t void
+#else
+#define Void_t char
+#endif
+#endif /*Void_t*/
+
+#if __STD_C
+#include <stddef.h> /* for size_t */
+#else
+#include <sys/types.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* define LACKS_UNISTD_H if your system does not have a <unistd.h>. */
+
+/* #define LACKS_UNISTD_H */
+
+#ifndef LACKS_UNISTD_H
+#include <unistd.h>
+#endif
+
+/* define LACKS_SYS_PARAM_H if your system does not have a <sys/param.h>. */
+
+/* #define LACKS_SYS_PARAM_H */
+
+
+#include <stdio.h> /* needed for malloc_stats */
+#include <errno.h> /* needed for optional MALLOC_FAILURE_ACTION */
+
+
+/*
+ Debugging:
+
+ Because freed chunks may be overwritten with bookkeeping fields, this
+ malloc will often die when freed memory is overwritten by user
+ programs. This can be very effective (albeit in an annoying way)
+ in helping track down dangling pointers.
+
+ If you compile with -DDEBUG, a number of assertion checks are
+ enabled that will catch more memory errors. You probably won't be
+ able to make much sense of the actual assertion errors, but they
+ should help you locate incorrectly overwritten memory. The
+ checking is fairly extensive, and will slow down execution
+ noticeably. Calling malloc_stats or mallinfo with DEBUG set will
+ attempt to check every non-mmapped allocated and free chunk in the
+ course of computing the summmaries. (By nature, mmapped regions
+ cannot be checked very much automatically.)
+
+ Setting DEBUG may also be helpful if you are trying to modify
+ this code. The assertions in the check routines spell out in more
+ detail the assumptions and invariants underlying the algorithms.
+
+*/
+
+#if DEBUG
+#include <assert.h>
+#else
+#define assert(x) ((void)0)
+#endif
+
+
+/*
+ INTERNAL_SIZE_T is the word-size used for internal bookkeeping
+ of chunk sizes.
+
+ The default version is the same as size_t.
+
+ While not strictly necessary, it is best to define this as an
+ unsigned type, even if size_t is a signed type. This may avoid some
+ artificial size limitations on some systems.
+
+ On a 64-bit machine, you may be able to reduce malloc overhead by
+ defining INTERNAL_SIZE_T to be a 32 bit `unsigned int' at the
+ expense of not being able to handle more than 2^32 of malloced
+ space. If this limitation is acceptable, you are encouraged to set
+ this unless you are on a platform requiring 16byte alignments. In
+ this case the alignment requirements turn out to negate any
+ potential advantages of decreasing size_t word size.
+
+ Note to implementors: To deal with all this, comparisons and
+ difference computations among INTERNAL_SIZE_Ts should normally cast
+ INTERNAL_SIZE_T's to long or unsigned long, as appropriate, being
+ aware of the fact that casting an unsigned int to a wider long does not
+ sign-extend. (This also makes checking for negative numbers awkward.)
+
+*/
+
+#ifndef INTERNAL_SIZE_T
+#define INTERNAL_SIZE_T size_t
+#endif
+
+/* The corresponding word size */
+#define SIZE_SZ (sizeof(INTERNAL_SIZE_T))
+
+
+/*
+ MALLOC_ALIGNMENT is the minimum alignment for malloc'ed chunks.
+ It must be a power of two at least 2 * SIZE_SZ, even on machines
+ for which smaller alignments would suffice. It may be defined as
+ larger than this though. (Note however that code and data structures
+ are optimized for the case of 8-byte alignment.)
+
+*/
+
+ /* #define MALLOC_ALIGNMENT 16 */
+
+#ifndef MALLOC_ALIGNMENT
+#define MALLOC_ALIGNMENT (2 * SIZE_SZ)
+#endif
+
+/* The corresponding bit mask value */
+#define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1)
+
+
+/*
+ REALLOC_ZERO_BYTES_FREES should be set if a call to
+ realloc with zero bytes should be the same as a call to free.
+ Some people think it should. Otherwise, since this malloc
+ returns a unique pointer for malloc(0), so does realloc(p, 0).
+*/
+
+/* #define REALLOC_ZERO_BYTES_FREES */
+
+
+/*
+ USE_DL_PREFIX will prefix all public routines with the string 'dl'.
+ This is necessary when you only want to use this malloc in one part
+ of a program, using your regular system malloc elsewhere.
+*/
+
+/* #define USE_DL_PREFIX */
+
+
+/*
+ USE_MALLOC_LOCK causes wrapper functions to surround each
+ callable routine with pthread mutex lock/unlock.
+
+ USE_MALLOC_LOCK forces USE_PUBLIC_MALLOC_WRAPPERS to be defined
+*/
+
+/* #define USE_MALLOC_LOCK */
+
+
+/*
+ If USE_PUBLIC_MALLOC_WRAPPERS is defined, every public routine is
+ actually a wrapper function that first calls MALLOC_PREACTION, then
+ calls the internal routine, and follows it with
+ MALLOC_POSTACTION. This is needed for locking, but you can also use
+ this, without USE_MALLOC_LOCK, for purposes of interception,
+ instrumentation, etc. It is a sad fact that using wrappers often
+ noticeably degrades performance of malloc-intensive programs.
+*/
+
+#ifdef USE_MALLOC_LOCK
+#define USE_PUBLIC_MALLOC_WRAPPERS
+#else
+/* #define USE_PUBLIC_MALLOC_WRAPPERS */
+#endif
+
+
+
+
+/*
+ HAVE_MEMCPY should be defined if you are not otherwise using
+ ANSI STD C, but still have memcpy and memset in your C library
+ and want to use them in calloc and realloc. Otherwise simple
+ macro versions are defined below.
+
+ USE_MEMCPY should be defined as 1 if you actually want to
+ have memset and memcpy called. People report that the macro
+ versions are faster than libc versions on some systems.
+
+ Even if USE_MEMCPY is set to 1, loops to copy/clear small chunks
+ (of <= 36 bytes) are manually unrolled in realloc and calloc.
+*/
+
+#define HAVE_MEMCPY
+
+#ifndef USE_MEMCPY
+#ifdef HAVE_MEMCPY
+#define USE_MEMCPY 1
+#else
+#define USE_MEMCPY 0
+#endif
+#endif
+
+
+#if (__STD_C || defined(HAVE_MEMCPY))
+
+#ifdef WIN32
+ /*
+ On Win32 platforms, 'memset()' and 'memcpy()' are already declared in
+ 'windows.h'
+ */
+#else
+#if __STD_C
+void* memset(void*, int, size_t);
+void* memcpy(void*, const void*, size_t);
+void* memmove(void*, const void*, size_t);
+#else
+Void_t* memset();
+Void_t* memcpy();
+Void_t* memmove();
+#endif
+#endif
+#endif
+
+
+/*
+ MALLOC_FAILURE_ACTION is the action to take before "return 0" when
+ malloc fails to be able to return memory, either because memory is
+ exhausted or because of illegal arguments.
+
+ By default, sets errno if running on STD_C platform, else does nothing.
+*/
+
+#ifndef MALLOC_FAILURE_ACTION
+#if __STD_C
+#define MALLOC_FAILURE_ACTION \
+ errno = ENOMEM;
+
+#else
+
+#define MALLOC_FAILURE_ACTION
+#endif
+#endif
+
+/*
+ Define HAVE_MMAP as true to optionally make malloc() use mmap() to
+ allocate very large blocks. These will be returned to the
+ operating system immediately after a free(). Also, if mmap
+ is available, it is used as a backup strategy in cases where
+ MORECORE fails to provide space from system.
+
+ This malloc is best tuned to work with mmap for large requests.
+ If you do not have mmap, allocation of very large chunks (1MB
+ or so) may be slower than you'd like.
+*/
+
+#ifndef HAVE_MMAP
+#define HAVE_MMAP 1
+#endif
+
+/*
+ MMAP_AS_MORECORE_SIZE is the minimum mmap size argument to use if
+ sbrk fails, and mmap is used as a backup (which is done only if
+ HAVE_MMAP). The value must be a multiple of page size. This
+ backup strategy generally applies only when systems have "holes" in
+ address space, so sbrk cannot perform contiguous expansion, but
+ there is still space available on system. On systems for which
+ this is known to be useful (i.e. most linux kernels), this occurs
+ only when programs allocate huge amounts of memory. Between this,
+ and the fact that mmap regions tend to be limited, the size should
+ be large, to avoid too many mmap calls and thus avoid running out
+ of kernel resources.
+*/
+
+#ifndef MMAP_AS_MORECORE_SIZE
+#define MMAP_AS_MORECORE_SIZE (1024 * 1024)
+#endif
+
+
+
+/*
+ Define HAVE_MREMAP to make realloc() use mremap() to re-allocate
+ large blocks. This is currently only possible on Linux with
+ kernel versions newer than 1.3.77.
+*/
+
+#ifndef HAVE_MREMAP
+#ifdef linux
+#define HAVE_MREMAP 1
+#else
+#define HAVE_MREMAP 0
+#endif
+
+#endif /* HAVE_MMAP */
+
+
+/*
+
+ This version of malloc supports the standard SVID/XPG mallinfo
+ routine that returns a struct containing usage properties and
+ statistics. It should work on any SVID/XPG compliant system that has
+ a /usr/include/malloc.h defining struct mallinfo. (If you'd like to
+ install such a thing yourself, cut out the preliminary declarations
+ as described above and below and save them in a malloc.h file. But
+ there's no compelling reason to bother to do this.)
+
+ The main declaration needed is the mallinfo struct that is returned
+ (by-copy) by mallinfo(). The SVID/XPG malloinfo struct contains a
+ bunch of field that are not even meaningful in this version of
+ malloc. These fields are are instead filled by mallinfo() with
+ other numbers that might be of interest.
+
+ HAVE_USR_INCLUDE_MALLOC_H should be set if you have a
+ /usr/include/malloc.h file that includes a declaration of struct
+ mallinfo. If so, it is included; else an SVID2/XPG2 compliant
+ version is declared below. These must be precisely the same for
+ mallinfo() to work.
+
+*/
+
+/* #define HAVE_USR_INCLUDE_MALLOC_H */
+
+#ifdef HAVE_USR_INCLUDE_MALLOC_H
+#include "/usr/include/malloc.h"
+#else
+
+/* SVID2/XPG mallinfo structure */
+
+struct mallinfo {
+ int arena; /* non-mmapped space allocated from system */
+ int ordblks; /* number of free chunks */
+ int smblks; /* number of fastbin blocks */
+ int hblks; /* number of mmapped regions */
+ int hblkhd; /* space in mmapped regions */
+ int usmblks; /* maximum total allocated space */
+ int fsmblks; /* space available in freed fastbin blocks */
+ int uordblks; /* total allocated space */
+ int fordblks; /* total free space */
+ int keepcost; /* top-most, releasable (via malloc_trim) space */
+};
+
+/* SVID2/XPG mallopt options */
+
+#define M_MXFAST 1 /* Set maximum fastbin size */
+#define M_NLBLKS 2 /* UNUSED in this malloc */
+#define M_GRAIN 3 /* UNUSED in this malloc */
+#define M_KEEP 4 /* UNUSED in this malloc */
+
+
+#endif
+
+
+/* Additional mallopt options supported in this malloc */
+
+#ifndef M_TRIM_THRESHOLD
+#define M_TRIM_THRESHOLD -1
+#endif
+
+#ifndef M_TOP_PAD
+#define M_TOP_PAD -2
+#endif
+
+#ifndef M_MMAP_THRESHOLD
+#define M_MMAP_THRESHOLD -3
+#endif
+
+#ifndef M_MMAP_MAX
+#define M_MMAP_MAX -4
+#endif
+
+
+/*
+ MXFAST is the maximum request size used for "fastbins", special bins
+ that hold returned chunks without consolidating their spaces. This
+ enables future requests for chunks of the same size to be handled
+ very quickly, but can increase fragmentation, and thus increase the
+ overall memory footprint of a program.
+
+ This malloc manages fastbins very conservatively yet still
+ efficiently, so fragmentation is rarely a problem for values less
+ than or equal to the default. The maximum supported value of MXFAST
+ is 80. You wouldn't want it any higher than this anyway. Fastbins
+ are designed especially for use with many small structs, objects or
+ strings -- the default handles structs/objects/arrays with sizes up
+ to 8 4byte fields, or small strings representing words, tokens,
+ etc. Using fastbins for larger objects normally worsens
+ fragmentation without improving speed.
+
+ MXFAST is set in REQUEST size units. It is internally used in
+ chunksize units, which adds padding and alignment. You can reduce
+ MXFAST to 0 to disable all use of fastbins. This causes the malloc
+ algorithm to be a close approximation of fifo-best-fit in all cases,
+ not just for larger requests, but will generally cause it to be
+ slower.
+
+*/
+
+#ifndef DEFAULT_MXFAST
+#define DEFAULT_MXFAST 64
+#endif
+
+
+/*
+ M_TRIM_THRESHOLD is the maximum amount of unused top-most memory
+ to keep before releasing via malloc_trim in free().
+
+ Automatic trimming is mainly useful in long-lived programs.
+ Because trimming via sbrk can be slow on some systems, and can
+ sometimes be wasteful (in cases where programs immediately
+ afterward allocate more large chunks) the value should be high
+ enough so that your overall system performance would improve by
+ releasing.
+
+ The trim threshold and the mmap control parameters (see below)
+ can be traded off with one another. Trimming and mmapping are
+ two different ways of releasing unused memory back to the
+ system. Between these two, it is often possible to keep
+ system-level demands of a long-lived program down to a bare
+ minimum. For example, in one test suite of sessions measuring
+ the XF86 X server on Linux, using a trim threshold of 128K and a
+ mmap threshold of 192K led to near-minimal long term resource
+ consumption.
+
+ If you are using this malloc in a long-lived program, it should
+ pay to experiment with these values. As a rough guide, you
+ might set to a value close to the average size of a process
+ (program) running on your system. Releasing this much memory
+ would allow such a process to run in memory. Generally, it's
+ worth it to tune for trimming rather tham memory mapping when a
+ program undergoes phases where several large chunks are
+ allocated and released in ways that can reuse each other's
+ storage, perhaps mixed with phases where there are no such
+ chunks at all. And in well-behaved long-lived programs,
+ controlling release of large blocks via trimming versus mapping
+ is usually faster.
+
+ However, in most programs, these parameters serve mainly as
+ protection against the system-level effects of carrying around
+ massive amounts of unneeded memory. Since frequent calls to
+ sbrk, mmap, and munmap otherwise degrade performance, the default
+ parameters are set to relatively high values that serve only as
+ safeguards.
+
+ The default trim value is high enough to cause trimming only in
+ fairly extreme (by current memory consumption standards) cases.
+ It must be greater than page size to have any useful effect. To
+ disable trimming completely, you can set to (unsigned long)(-1);
+
+ Trim settings interact with fastbin (MXFAST) settings: Unless
+ TRIM_FASTBINS is defined, automatic trimming never takes place upon
+ freeing a chunk with size less than or equal to MXFAST. Trimming is
+ instead delayed until subsequent freeing of larger chunks. However,
+ you can still force an attempted trim by calling malloc_trim.
+
+ Also, trimming is not generally possible in cases where
+ the main arena is obtained via mmap.
+
+*/
+
+
+#ifndef DEFAULT_TRIM_THRESHOLD
+#define DEFAULT_TRIM_THRESHOLD (128 * 1024)
+#endif
+
+
+
+/*
+ M_TOP_PAD is the amount of extra `padding' space to allocate or
+ retain whenever sbrk is called. It is used in two ways internally:
+
+ * When sbrk is called to extend the top of the arena to satisfy
+ a new malloc request, this much padding is added to the sbrk
+ request.
+
+ * When malloc_trim is called automatically from free(),
+ it is used as the `pad' argument.
+
+ In both cases, the actual amount of padding is rounded
+ so that the end of the arena is always a system page boundary.
+
+ The main reason for using padding is to avoid calling sbrk so
+ often. Having even a small pad greatly reduces the likelihood
+ that nearly every malloc request during program start-up (or
+ after trimming) will invoke sbrk, which needlessly wastes
+ time.
+
+ Automatic rounding-up to page-size units is normally sufficient
+ to avoid measurable overhead, so the default is 0. However, in
+ systems where sbrk is relatively slow, it can pay to increase
+ this value, at the expense of carrying around more memory than
+ the program needs.
+
+*/
+
+#ifndef DEFAULT_TOP_PAD
+#define DEFAULT_TOP_PAD (0)
+#endif
+
+/*
+
+ M_MMAP_THRESHOLD is the request size threshold for using mmap()
+ to service a request. Requests of at least this size that cannot
+ be allocated using already-existing space will be serviced via mmap.
+ (If enough normal freed space already exists it is used instead.)
+
+ Using mmap segregates relatively large chunks of memory so that
+ they can be individually obtained and released from the host
+ system. A request serviced through mmap is never reused by any
+ other request (at least not directly; the system may just so
+ happen to remap successive requests to the same locations).
+
+ Segregating space in this way has the benefit that mmapped space
+ can ALWAYS be individually released back to the system, which
+ helps keep the system level memory demands of a long-lived
+ program low. Mapped memory can never become `locked' between
+ other chunks, as can happen with normally allocated chunks, which
+ means that even trimming via malloc_trim would not release them.
+
+ However, it has the disadvantages that:
+
+ 1. The space cannot be reclaimed, consolidated, and then
+ used to service later requests, as happens with normal chunks.
+ 2. It can lead to more wastage because of mmap page alignment
+ requirements
+ 3. It causes malloc performance to be more dependent on host
+ system memory management support routines which may vary in
+ implementation quality and may impose arbitrary
+ limitations. Generally, servicing a request via normal
+ malloc steps is faster than going through a system's mmap.
+
+ All together, these considerations should lead you to use mmap
+ only for relatively large requests.
+
+*/
+
+
+#ifndef DEFAULT_MMAP_THRESHOLD
+#define DEFAULT_MMAP_THRESHOLD (128 * 1024)
+#endif
+
+/*
+ M_MMAP_MAX is the maximum number of requests to simultaneously
+ service using mmap. This parameter exists because:
+
+ 1. Some systems have a limited number of internal tables for
+ use by mmap.
+ 2. In most systems, overreliance on mmap can degrade overall
+ performance.
+ 3. If a program allocates many large regions, it is probably
+ better off using normal sbrk-based allocation routines that
+ can reclaim and reallocate normal heap memory.
+
+ Setting to 0 disables use of mmap for servicing large requests. If
+ HAVE_MMAP is not set, the default value is 0, and attempts to set it
+ to non-zero values in mallopt will fail.
+*/
+
+
+
+#ifndef DEFAULT_MMAP_MAX
+#if HAVE_MMAP
+#define DEFAULT_MMAP_MAX (256)
+#else
+#define DEFAULT_MMAP_MAX (0)
+#endif
+#endif
+
+
+/*
+ TRIM_FASTBINS controls whether free() of a very small chunk can
+ immediately lead to trimming. Setting to true (1) can reduce memory
+ footprint, but will almost always slow down (by a few percent)
+ programs that use a lot of small chunks.
+
+ Define this only if you are willing to give up some speed to more
+ aggressively reduce system-level memory footprint when releasing
+ memory in programs that use many small chunks. You can get
+ essentially the same effect by setting MXFAST to 0, but this can
+ lead to even greater slowdowns in programs using many small chunks.
+ TRIM_FASTBINS is an in-between compile-time option, that disables
+ only those chunks bordering topmost memory from being placed in
+ fastbins.
+
+*/
+
+
+#ifndef TRIM_FASTBINS
+#define TRIM_FASTBINS 0
+#endif
+
+
+/*
+ MORECORE-related declarations. By default, rely on sbrk
+*/
+
+
+#ifdef LACKS_UNISTD_H
+#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
+#if __STD_C
+extern Void_t* sbrk(ptrdiff_t);
+#else
+extern Void_t* sbrk();
+#endif
+#endif
+#endif
+
+/*
+ MORECORE is the name of the routine to call to obtain more memory
+ from the system. See below for general guidance on writing
+ alternative MORECORE functions, as well as a version for WIN32 and a
+ sample version for pre-OSX macos.
+*/
+
+#ifndef MORECORE
+#define MORECORE sbrk
+#endif
+
+
+/*
+ MORECORE_FAILURE is the value returned upon failure of MORECORE
+ as well as mmap. Since it cannot be an otherwise valid memory address,
+ and must reflect values of standard sys calls, you probably ought not
+ try to redefine it.
+*/
+
+#ifndef MORECORE_FAILURE
+#define MORECORE_FAILURE (-1)
+#endif
+
+/*
+ If MORECORE_CONTIGUOUS is true, take advantage of fact that
+ consecutive calls to MORECORE with positive arguments always return
+ contiguous increasing addresses. This is true of unix sbrk. Even
+ if not defined, when regions happen to be contiguous, malloc will
+ permit allocations spanning regions obtained from different
+ calls. But defining this when applicable enables some stronger
+ consistency checks and space efficiencies.
+*/
+
+
+#ifndef MORECORE_CONTIGUOUS
+#define MORECORE_CONTIGUOUS 1
+#endif
+
+
+/*
+ The system page size. To the extent possible, this malloc manages
+ memory from the system in page-size units. Note that this value is
+ cached during initialization into a field of malloc_state. So even
+ if malloc_getpagesize is a function, it is only called once.
+
+ The following mechanics for getpagesize were adapted from bsd/gnu
+ getpagesize.h. If none of the system-probes here apply, a value of
+ 4096 is used, which should be OK: If they don't apply, then using
+ the actual value probably doesn't impact performance.
+*/
+
+#ifndef malloc_getpagesize
+
+#ifndef LACKS_UNISTD_H
+# include <unistd.h>
+#endif
+
+# ifdef _SC_PAGESIZE /* some SVR4 systems omit an underscore */
+# ifndef _SC_PAGE_SIZE
+# define _SC_PAGE_SIZE _SC_PAGESIZE
+# endif
+# endif
+
+# ifdef _SC_PAGE_SIZE
+# define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
+# else
+# if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
+ extern size_t getpagesize();
+# define malloc_getpagesize getpagesize()
+# else
+# ifdef WIN32 /* use supplied emulation of getpagesize */
+# define malloc_getpagesize getpagesize()
+# else
+# ifndef LACKS_SYS_PARAM_H
+# include <sys/param.h>
+# endif
+# ifdef EXEC_PAGESIZE
+# define malloc_getpagesize EXEC_PAGESIZE
+# else
+# ifdef NBPG
+# ifndef CLSIZE
+# define malloc_getpagesize NBPG
+# else
+# define malloc_getpagesize (NBPG * CLSIZE)
+# endif
+# else
+# ifdef NBPC
+# define malloc_getpagesize NBPC
+# else
+# ifdef PAGESIZE
+# define malloc_getpagesize PAGESIZE
+# else /* just guess */
+# define malloc_getpagesize (4096)
+# endif
+# endif
+# endif
+# endif
+# endif
+# endif
+# endif
+#endif
+
+
+/* Two-phase Name mangling */
+
+#ifndef USE_PUBLIC_MALLOC_WRAPPERS
+#define cALLOc public_cALLOc
+#define fREe public_fREe
+#define cFREe public_cFREe
+#define mALLOc public_mALLOc
+#define mEMALIGn public_mEMALIGn
+#define rEALLOc public_rEALLOc
+#define vALLOc public_vALLOc
+#define pVALLOc public_pVALLOc
+#define mALLINFo public_mALLINFo
+#define mALLOPt public_mALLOPt
+#define mTRIm public_mTRIm
+#define mSTATs public_mSTATs
+#define mUSABLe public_mUSABLe
+#endif
+
+#ifdef USE_DL_PREFIX
+#define public_cALLOc dlcalloc
+#define public_fREe dlfree
+#define public_cFREe dlcfree
+#define public_mALLOc dlmalloc
+#define public_mEMALIGn dlmemalign
+#define public_rEALLOc dlrealloc
+#define public_vALLOc dlvalloc
+#define public_pVALLOc dlpvalloc
+#define public_mALLINFo dlmallinfo
+#define public_mALLOPt dlmallopt
+#define public_mTRIm dlmalloc_trim
+#define public_mSTATs dlmalloc_stats
+#define public_mUSABLe dlmalloc_usable_size
+#else /* USE_DL_PREFIX */
+#define public_cALLOc calloc
+#define public_fREe free
+#define public_cFREe cfree
+#define public_mALLOc malloc
+#define public_mEMALIGn memalign
+#define public_rEALLOc realloc
+#define public_vALLOc valloc
+#define public_pVALLOc pvalloc
+#define public_mALLINFo mallinfo
+#define public_mALLOPt mallopt
+#define public_mTRIm malloc_trim
+#define public_mSTATs malloc_stats
+#define public_mUSABLe malloc_usable_size
+#endif /* USE_DL_PREFIX */
+
+#if __STD_C
+
+Void_t* public_mALLOc(size_t);
+void public_fREe(Void_t*);
+Void_t* public_rEALLOc(Void_t*, size_t);
+Void_t* public_mEMALIGn(size_t, size_t);
+Void_t* public_vALLOc(size_t);
+Void_t* public_pVALLOc(size_t);
+Void_t* public_cALLOc(size_t, size_t);
+void public_cFREe(Void_t*);
+int public_mTRIm(size_t);
+size_t public_mUSABLe(Void_t*);
+void public_mSTATs();
+int public_mALLOPt(int, int);
+struct mallinfo public_mALLINFo(void);
+#else
+Void_t* public_mALLOc();
+void public_fREe();
+Void_t* public_rEALLOc();
+Void_t* public_mEMALIGn();
+Void_t* public_vALLOc();
+Void_t* public_pVALLOc();
+Void_t* public_cALLOc();
+void public_cFREe();
+int public_mTRIm();
+size_t public_mUSABLe();
+void public_mSTATs();
+int public_mALLOPt();
+struct mallinfo public_mALLINFo();
+#endif
+
+
+#ifdef __cplusplus
+}; /* end of extern "C" */
+#endif
+
+
+
+/* ---------- To make a malloc.h, end cutting here ------------ */
+
+
+/* Declarations of internal utilities defined below */
+
+
+
+
+#ifdef USE_PUBLIC_MALLOC_WRAPPERS
+#if __STD_C
+
+static Void_t* mALLOc(size_t);
+static void fREe(Void_t*);
+static Void_t* rEALLOc(Void_t*, size_t);
+static Void_t* mEMALIGn(size_t, size_t);
+static Void_t* vALLOc(size_t);
+static Void_t* pVALLOc(size_t);
+static Void_t* cALLOc(size_t, size_t);
+static void cFREe(Void_t*);
+static int mTRIm(size_t);
+static size_t mUSABLe(Void_t*);
+static void mSTATs();
+static int mALLOPt(int, int);
+static struct mallinfo mALLINFo(void);
+#else
+static Void_t* mALLOc();
+static void fREe();
+static Void_t* rEALLOc();
+static Void_t* mEMALIGn();
+static Void_t* vALLOc();
+static Void_t* pVALLOc();
+static Void_t* cALLOc();
+static void cFREe();
+static int mTRIm();
+static size_t mUSABLe();
+static void mSTATs();
+static int mALLOPt();
+static struct mallinfo mALLINFo();
+#endif
+#endif
+
+
+
+/* ---------- public wrappers --------------- */
+
+#ifdef USE_PUBLIC_MALLOC_WRAPPERS
+
+/*
+ MALLOC_PREACTION and MALLOC_POSTACTION should be
+ defined to return 0 on success, and nonzero on failure.
+ The return value of MALLOC_POSTACTION is currently ignored
+ in wrapper functions since there is no reasonable default
+ action to take on failure.
+*/
+
+
+#ifdef USE_MALLOC_LOCK
+
+#ifdef WIN32
+
+static int mALLOC_MUTEx;
+
+#define MALLOC_PREACTION slwait(&mALLOC_MUTEx)
+#define MALLOC_POSTACTION slrelease(&mALLOC_MUTEx)
+
+#else
+
+#include <pthread.h>
+
+static pthread_mutex_t mALLOC_MUTEx = PTHREAD_MUTEX_INITIALIZER;
+
+#define MALLOC_PREACTION pthread_mutex_lock(&mALLOC_MUTEx)
+#define MALLOC_POSTACTION pthread_mutex_unlock(&mALLOC_MUTEx)
+
+#endif /* USE_MALLOC_LOCK */
+
+#else
+
+/* Substitute anything you like for these */
+
+#define MALLOC_PREACTION (0)
+#define MALLOC_POSTACTION (0)
+
+#endif
+
+Void_t* public_mALLOc(size_t bytes) {
+ Void_t* m;
+ if (MALLOC_PREACTION != 0) {
+ return 0;
+ }
+ m = mALLOc(bytes);
+ if (MALLOC_POSTACTION != 0) {
+ }
+ return m;
+}
+
+void public_fREe(Void_t* m) {
+ if (MALLOC_PREACTION != 0) {
+ return;
+ }
+ fREe(m);
+ if (MALLOC_POSTACTION != 0) {
+ }
+}
+
+Void_t* public_rEALLOc(Void_t* m, size_t bytes) {
+ if (MALLOC_PREACTION != 0) {
+ return 0;
+ }
+ m = rEALLOc(m, bytes);
+ if (MALLOC_POSTACTION != 0) {
+ }
+ return m;
+}
+
+Void_t* public_mEMALIGn(size_t alignment, size_t bytes) {
+ Void_t* m;
+ if (MALLOC_PREACTION != 0) {
+ return 0;
+ }
+ m = mEMALIGn(alignment, bytes);
+ if (MALLOC_POSTACTION != 0) {
+ }
+ return m;
+}
+
+Void_t* public_vALLOc(size_t bytes) {
+ Void_t* m;
+ if (MALLOC_PREACTION != 0) {
+ return 0;
+ }
+ m = vALLOc(bytes);
+ if (MALLOC_POSTACTION != 0) {
+ }
+ return m;
+}
+
+Void_t* public_pVALLOc(size_t bytes) {
+ Void_t* m;
+ if (MALLOC_PREACTION != 0) {
+ return 0;
+ }
+ m = pVALLOc(bytes);
+ if (MALLOC_POSTACTION != 0) {
+ }
+ return m;
+}
+
+Void_t* public_cALLOc(size_t n, size_t elem_size) {
+ Void_t* m;
+ if (MALLOC_PREACTION != 0) {
+ return 0;
+ }
+ m = cALLOc(n, elem_size);
+ if (MALLOC_POSTACTION != 0) {
+ }
+ return m;
+}
+
+void public_cFREe(Void_t* m) {
+ if (MALLOC_PREACTION != 0) {
+ return;
+ }
+ cFREe(m);
+ if (MALLOC_POSTACTION != 0) {
+ }
+}
+
+int public_mTRIm(size_t s) {
+ int result;
+ if (MALLOC_PREACTION != 0) {
+ return 0;
+ }
+ result = mTRIm(s);
+ if (MALLOC_POSTACTION != 0) {
+ }
+ return result;
+}
+
+
+size_t public_mUSABLe(Void_t* m) {
+ size_t result;
+ if (MALLOC_PREACTION != 0) {
+ return 0;
+ }
+ result = mUSABLe(m);
+ if (MALLOC_POSTACTION != 0) {
+ }
+ return result;
+}
+
+
+void public_mSTATs() {
+ if (MALLOC_PREACTION != 0) {
+ return;
+ }
+ mSTATs();
+ if (MALLOC_POSTACTION != 0) {
+ }
+}
+
+struct mallinfo public_mALLINFo() {
+ struct mallinfo m;
+ if (MALLOC_PREACTION != 0) {
+ return m;
+ }
+ m = mALLINFo();
+ if (MALLOC_POSTACTION != 0) {
+ }
+ return m;
+}
+
+int public_mALLOPt(int p, int v) {
+ int result;
+ if (MALLOC_PREACTION != 0) {
+ return 0;
+ }
+ result = mALLOPt(p, v);
+ if (MALLOC_POSTACTION != 0) {
+ }
+ return result;
+}
+
+#endif
+
+
+
+/* ------------- Optional versions of memcopy ---------------- */
+
+
+#if USE_MEMCPY
+
+#define MALLOC_COPY(dest, src, nbytes, overlap) \
+ ((overlap) ? memmove(dest, src, nbytes) : memcpy(dest, src, nbytes))
+#define MALLOC_ZERO(dest, nbytes) memset(dest, 0, nbytes)
+
+#else /* !USE_MEMCPY */
+
+/* Use Duff's device for good zeroing/copying performance. */
+
+#define MALLOC_ZERO(charp, nbytes) \
+do { \
+ INTERNAL_SIZE_T* mzp = (INTERNAL_SIZE_T*)(charp); \
+ long mctmp = (nbytes)/sizeof(INTERNAL_SIZE_T), mcn; \
+ if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp %= 8; } \
+ switch (mctmp) { \
+ case 0: for(;;) { *mzp++ = 0; \
+ case 7: *mzp++ = 0; \
+ case 6: *mzp++ = 0; \
+ case 5: *mzp++ = 0; \
+ case 4: *mzp++ = 0; \
+ case 3: *mzp++ = 0; \
+ case 2: *mzp++ = 0; \
+ case 1: *mzp++ = 0; if(mcn <= 0) break; mcn--; } \
+ } \
+} while(0)
+
+/* For overlapping case, dest is always _below_ src. */
+
+#define MALLOC_COPY(dest,src,nbytes,overlap) \
+do { \
+ INTERNAL_SIZE_T* mcsrc = (INTERNAL_SIZE_T*) src; \
+ INTERNAL_SIZE_T* mcdst = (INTERNAL_SIZE_T*) dest; \
+ long mctmp = (nbytes)/sizeof(INTERNAL_SIZE_T), mcn; \
+ if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp %= 8; } \
+ switch (mctmp) { \
+ case 0: for(;;) { *mcdst++ = *mcsrc++; \
+ case 7: *mcdst++ = *mcsrc++; \
+ case 6: *mcdst++ = *mcsrc++; \
+ case 5: *mcdst++ = *mcsrc++; \
+ case 4: *mcdst++ = *mcsrc++; \
+ case 3: *mcdst++ = *mcsrc++; \
+ case 2: *mcdst++ = *mcsrc++; \
+ case 1: *mcdst++ = *mcsrc++; if(mcn <= 0) break; mcn--; } \
+ } \
+} while(0)
+
+#endif
+
+/* ------------------ MMAP support ------------------ */
+
+
+#if HAVE_MMAP
+
+#include <fcntl.h>
+#ifndef LACKS_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
+#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+
+/*
+ Nearly all versions of mmap support MAP_ANONYMOUS,
+ so the following is unlikely to be needed, but is
+ supplied just in case.
+*/
+
+#ifndef MAP_ANONYMOUS
+
+static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */
+
+#define MMAP(addr, size, prot, flags) ((dev_zero_fd < 0) ? \
+ (dev_zero_fd = open("/dev/zero", O_RDWR), \
+ mmap((addr), (size), (prot), (flags), dev_zero_fd, 0)) : \
+ mmap((addr), (size), (prot), (flags), dev_zero_fd, 0))
+
+#else
+
+#define MMAP(addr, size, prot, flags) \
+ (mmap((addr), (size), (prot), (flags)|MAP_ANONYMOUS, -1, 0))
+
+#endif
+
+#endif /* HAVE_MMAP */
+
+
+/* ---------- Alternative MORECORE functions ------------ */
+
+
+/*
+ General Requirements for MORECORE.
+
+ The MORECORE function must have the following properties:
+
+ If MORECORE_CONTIGUOUS is false:
+
+ * MORECORE must allocate in multiples of pagesize. It will
+ only be called with arguments that are multiples of pagesize.
+
+ * MORECORE must page-align. That is, MORECORE(0) must
+ return an address at a page boundary.
+
+ else (i.e. If MORECORE_CONTIGUOUS is true):
+
+ * Consecutive calls to MORECORE with positive arguments
+ return increasing addresses, indicating that space has been
+ contiguously extended.
+
+ * MORECORE need not allocate in multiples of pagesize.
+ Calls to MORECORE need not have args of multiples of pagesize.
+
+ * MORECORE need not page-align.
+
+ In either case:
+
+ * MORECORE may allocate more memory than requested. (Or even less,
+ but this will generally result in a malloc failure.)
+
+ * MORECORE must not allocate memory when given argument zero, but
+ instead return one past the end address of memory from previous
+ nonzero call. This malloc does NOT call MORECORE(0)
+ until at least one call with positive arguments is made, so
+ the initial value returned is not important.
+
+ * Even though consecutive calls to MORECORE need not return contiguous
+ addresses, it must be OK for malloc'ed chunks to span multiple
+ regions in those cases where they do happen to be contiguous.
+
+ * MORECORE need not handle negative arguments -- it may instead
+ just return MORECORE_FAILURE when given negative arguments.
+ Negative arguments are always multiples of pagesize. MORECORE
+ must not misinterpret negative args as large positive unsigned
+ args.
+
+ There is some variation across systems about the type of the
+ argument to sbrk/MORECORE. If size_t is unsigned, then it cannot
+ actually be size_t, because sbrk supports negative args, so it is
+ normally the signed type of the same width as size_t (sometimes
+ declared as "intptr_t", and sometimes "ptrdiff_t"). It doesn't much
+ matter though. Internally, we use "long" as arguments, which should
+ work across all reasonable possibilities.
+
+ Additionally, if MORECORE ever returns failure for a positive
+ request, and HAVE_MMAP is true, then mmap is used as a noncontiguous
+ system allocator. This is a useful backup strategy for systems with
+ holes in address spaces -- in this case sbrk cannot contiguously
+ expand the heap, but mmap may be able to map noncontiguous space.
+ If you'd like mmap to ALWAYS be used, you can define MORECORE to be
+ a function that always returns MORECORE_FAILURE.
+
+ If you are using this malloc with something other than unix sbrk to
+ supply memory regions, you probably want to set MORECORE_CONTIGUOUS
+ as false. As an example, here is a custom allocator kindly
+ contributed for pre-OSX macOS. It uses virtually but not
+ necessarily physically contiguous non-paged memory (locked in,
+ present and won't get swapped out). You can use it by uncommenting
+ this section, adding some #includes, and setting up the appropriate
+ defines above:
+
+ #define MORECORE osMoreCore
+ #define MORECORE_CONTIGUOUS 0
+
+ There is also a shutdown routine that should somehow be called for
+ cleanup upon program exit.
+
+ #define MAX_POOL_ENTRIES 100
+ #define MINIMUM_MORECORE_SIZE (64 * 1024)
+ static int next_os_pool;
+ void *our_os_pools[MAX_POOL_ENTRIES];
+
+ void *osMoreCore(int size)
+ {
+ void *ptr = 0;
+ static void *sbrk_top = 0;
+
+ if (size > 0)
+ {
+ if (size < MINIMUM_MORECORE_SIZE)
+ size = MINIMUM_MORECORE_SIZE;
+ if (CurrentExecutionLevel() == kTaskLevel)
+ ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0);
+ if (ptr == 0)
+ {
+ return (void *) MORECORE_FAILURE;
+ }
+ // save ptrs so they can be freed during cleanup
+ our_os_pools[next_os_pool] = ptr;
+ next_os_pool++;
+ ptr = (void *) ((((unsigned long) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK);
+ sbrk_top = (char *) ptr + size;
+ return ptr;
+ }
+ else if (size < 0)
+ {
+ // we don't currently support shrink behavior
+ return (void *) MORECORE_FAILURE;
+ }
+ else
+ {
+ return sbrk_top;
+ }
+ }
+
+ // cleanup any allocated memory pools
+ // called as last thing before shutting down driver
+
+ void osCleanupMem(void)
+ {
+ void **ptr;
+
+ for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++)
+ if (*ptr)
+ {
+ PoolDeallocate(*ptr);
+ *ptr = 0;
+ }
+ }
+
+*/
+
+
+
+
+
+/*
+ ----------------------- Chunk representations -----------------------
+*/
+
+
+/*
+ This struct declaration is misleading (but accurate and necessary).
+ It declares a "view" into memory allowing access to necessary
+ fields at known offsets from a given base. See explanation below.
+*/
+
+struct malloc_chunk {
+
+ INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */
+ INTERNAL_SIZE_T size; /* Size in bytes, including overhead. */
+
+ struct malloc_chunk* fd; /* double links -- used only if free. */
+ struct malloc_chunk* bk;
+};
+
+
+typedef struct malloc_chunk* mchunkptr;
+
+/*
+
+ malloc_chunk details:
+
+ (The following includes lightly edited explanations by Colin Plumb.)
+
+ Chunks of memory are maintained using a `boundary tag' method as
+ described in e.g., Knuth or Standish. (See the paper by Paul
+ Wilson ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a
+ survey of such techniques.) Sizes of free chunks are stored both
+ in the front of each chunk and at the end. This makes
+ consolidating fragmented chunks into bigger chunks very fast. The
+ size fields also hold bits representing whether chunks are free or
+ in use.
+
+ An allocated chunk looks like this:
+
+
+ chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Size of previous chunk, if allocated | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Size of chunk, in bytes |P|
+ mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | User data starts here... .
+ . .
+ . (malloc_usable_space() bytes) .
+ . |
+nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Size of chunk |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+ Where "chunk" is the front of the chunk for the purpose of most of
+ the malloc code, but "mem" is the pointer that is returned to the
+ user. "Nextchunk" is the beginning of the next contiguous chunk.
+
+ Chunks always begin on even word boundries, so the mem portion
+ (which is returned to the user) is also on an even word boundary, and
+ thus double-word aligned.
+
+ Free chunks are stored in circular doubly-linked lists, and look like this:
+
+ chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Size of previous chunk |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ `head:' | Size of chunk, in bytes |P|
+ mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Forward pointer to next chunk in list |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Back pointer to previous chunk in list |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Unused space (may be 0 bytes long) .
+ . .
+ . |
+nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ `foot:' | Size of chunk, in bytes |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ The P (PREV_INUSE) bit, stored in the unused low-order bit of the
+ chunk size (which is always a multiple of two words), is an in-use
+ bit for the *previous* chunk. If that bit is *clear*, then the
+ word before the current chunk size contains the previous chunk
+ size, and can be used to find the front of the previous chunk.
+ The very first chunk allocated always has this bit set,
+ preventing access to non-existent (or non-owned) memory. If
+ prev_inuse is set for any given chunk, then you CANNOT determine
+ the size of the previous chunk, and might even get a memory
+ addressing fault when trying to do so.
+
+ Note that the `foot' of the current chunk is actually represented
+ as the prev_size of the NEXT chunk. (This makes it easier to
+ deal with alignments etc).
+
+ The two exceptions to all this are
+
+ 1. The special chunk `top' doesn't bother using the
+ trailing size field since there is no next contiguous chunk
+ that would have to index off it. After initialization, `top'
+ is forced to always exist. If it would become less than
+ MINSIZE bytes long, it is replenished.
+
+ 2. Chunks allocated via mmap, which have the second-lowest-order
+ bit (IS_MMAPPED) set in their size fields. Because they are
+ allocated one-by-one, each must contain its own trailing size field.
+
+*/
+
+
+
+/*
+ Size and alignment checks and conversions
+*/
+
+/* conversion from malloc headers to user pointers, and back */
+
+#define chunk2mem(p) ((Void_t*)((char*)(p) + 2*SIZE_SZ))
+#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ))
+
+/* The smallest possible chunk */
+#define MIN_CHUNK_SIZE (sizeof(struct malloc_chunk))
+
+/* The smallest size we can malloc is an aligned minimal chunk */
+
+#define MINSIZE ((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
+
+/* Check if m has acceptable alignment */
+
+#define aligned_OK(m) (((unsigned long)((m)) & (MALLOC_ALIGN_MASK)) == 0)
+
+/*
+ Check for negative/huge sizes.
+ This cannot just test for < 0 because argument might
+ be an unsigned type of uncertain width.
+*/
+
+#define IS_NEGATIVE(x) \
+ ((unsigned long)x >= \
+ (unsigned long)((((INTERNAL_SIZE_T)(1)) << ((SIZE_SZ)*8 - 1))))
+
+
+/* pad request bytes into a usable size -- internal version */
+
+#define request2size(req) \
+ (((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \
+ MINSIZE : \
+ ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
+
+
+/*
+ Same, except check for negative/huge arguments.
+ This lets through args that are positive but wrap into
+ negatives when padded. However, these are trapped
+ elsewhere.
+*/
+
+#define checked_request2size(req, sz) \
+ if (IS_NEGATIVE(req)) { \
+ MALLOC_FAILURE_ACTION; \
+ return 0; \
+ } \
+ (sz) = request2size(req);
+
+
+
+
+/*
+ Physical chunk operations
+*/
+
+
+/* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */
+
+#define PREV_INUSE 0x1
+
+
+/* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */
+
+#define IS_MMAPPED 0x2
+
+
+/* Bits to mask off when extracting size */
+
+#define SIZE_BITS (PREV_INUSE|IS_MMAPPED)
+
+
+/* Ptr to next physical malloc_chunk. */
+
+#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) ))
+
+
+/* Ptr to previous physical malloc_chunk */
+
+#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_size) ))
+
+
+/* Treat space at ptr + offset as a chunk */
+
+#define chunk_at_offset(p, s) ((mchunkptr)(((char*)(p)) + (s)))
+
+
+
+
+/*
+ Dealing with use bits
+
+ Note: IS_MMAPPED is intentionally not masked off from size field in
+ macros for which mmapped chunks should never be seen. This should
+ cause helpful core dumps to occur if it is tried by accident by
+ people extending or adapting this malloc.
+
+*/
+
+
+/* extract p's inuse bit */
+
+#define inuse(p)\
+((((mchunkptr)(((char*)(p))+((p)->size & ~PREV_INUSE)))->size) & PREV_INUSE)
+
+
+/* extract inuse bit of previous chunk */
+
+#define prev_inuse(p) ((p)->size & PREV_INUSE)
+
+
+/* check for mmap()'ed chunk */
+
+#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)
+
+
+/* set/clear chunk as being inuse without otherwise disturbing */
+
+#define set_inuse(p)\
+((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size |= PREV_INUSE
+
+#define clear_inuse(p)\
+((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size &= ~(PREV_INUSE)
+
+
+/* check/set/clear inuse bits in known places */
+
+#define inuse_bit_at_offset(p, s)\
+ (((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE)
+
+#define set_inuse_bit_at_offset(p, s)\
+ (((mchunkptr)(((char*)(p)) + (s)))->size |= PREV_INUSE)
+
+#define clear_inuse_bit_at_offset(p, s)\
+ (((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE))
+
+
+
+
+/*
+ Dealing with size fields
+*/
+
+/* Get size, ignoring use bits */
+
+#define chunksize(p) ((p)->size & ~(SIZE_BITS))
+
+/* Set size at head, without disturbing its use bit */
+
+#define set_head_size(p, s) ((p)->size = (((p)->size & PREV_INUSE) | (s)))
+
+/* Set size/use field */
+
+#define set_head(p, s) ((p)->size = (s))
+
+/* Set size at footer (only when chunk is not in use) */
+
+#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_size = (s))
+
+
+
+
+
+/*
+ ------------------ Internal data structures --------------------
+
+ All internal state is held in an instance of malloc_state defined
+ below. There are no other static variables, except in two optional
+ cases:
+ * If USE_MALLOC_LOCK is defined, the mALLOC_MUTEx declared
+ above.
+ * If HAVE_MMAP is true, but mmap doesn't support
+ MAP_ANONYMOUS, a dummy file descriptor for mmap.
+
+ Beware of lots of tricks that minimize the total space
+ requirements. The result is a little over 1K bytes (for 4byte
+ pointers and size_t.)
+
+*/
+
+/*
+
+ Bins
+
+ An array of bin headers for free chunks. Each bin is doubly
+ linked. The bins are approximately proportionally (log) spaced.
+ There are a lot of these bins (128). This may look excessive, but
+ works very well in practice. Most bins hold sizes that are
+ unusual as malloc request sizes, but are more usual for fragments
+ and consolidated sets of chunks, which is what these bins hold, so
+ they can be found quickly. All procedures maintain the invariant
+ that no consolidated chunk physically borders another one, so each
+ chunk in a list is known to be preceeded and followed by either
+ inuse chunks or the ends of memory.
+
+ Chunks in bins are kept in size order, with ties going to the
+ approximately least recently used chunk. Ordering is irrelevant
+ for the small bins, which all contain the same-sized chunks, but
+ facilitates best-fit allocation for larger chunks. (These lists
+ are just sequential. Keeping them in order almost never requires
+ enough traversal to warrant using fancier ordered data
+ structures.) Chunks of the same size are linked with the most
+ recently freed at the front, and allocations are taken from the
+ back. This results in LRU (FIFO) allocation order, which tends
+ to give each chunk an equal opportunity to be consolidated with
+ adjacent freed chunks, resulting in larger free chunks and less
+ fragmentation.
+
+ To simplify use in double-linked lists, each bin header acts
+ as a malloc_chunk. This avoids special-casing for headers.
+ But to conserve space and (mainly) improve locality, we allocate
+ only the fd/bk pointers of bins, and then use repositioning tricks
+ to treat these as the fields of a malloc_chunk*.
+*/
+
+typedef struct malloc_chunk* mbinptr;
+
+#define NBINS 128
+
+
+/* addressing -- note that bin_at(0) does not exist */
+
+#define bin_at(m, i) ((mbinptr)((char*)&((m)->bins[(i)<<1]) - (SIZE_SZ<<1)))
+
+
+/* analog of ++bin */
+
+#define next_bin(b) ((mbinptr)((char*)(b) + (sizeof(mchunkptr)<<1)))
+
+
+/* Reminders about list directionality within bins */
+
+#define first(b) ((b)->fd)
+#define last(b) ((b)->bk)
+
+/*
+ Take a chunk off a bin list
+*/
+
+#define unlink(P, BK, FD) { \
+ FD = P->fd; \
+ BK = P->bk; \
+ FD->bk = BK; \
+ BK->fd = FD; \
+}
+
+/*
+ Indexing bins
+
+ Bins for sizes < 512 bytes contain chunks of all the same size, spaced
+ 8 bytes apart. Larger bins are approximately logarithmically spaced:
+
+ 64 bins of size 8
+ 32 bins of size 64
+ 16 bins of size 512
+ 8 bins of size 4096
+ 4 bins of size 32768
+ 2 bins of size 262144
+ 1 bin of size what's left
+
+ There is actually a little bit of slop in the numbers in bin_index
+ for the sake of speed. This makes no difference elsewhere.
+
+ The bins top out at around 1mb because we expect to service large
+ chunks via mmap.
+
+*/
+
+/* The first NSMALLBIN bins (and fastbins) hold only one size */
+#define NSMALLBINS 64
+#define SMALLBIN_WIDTH 8
+#define MIN_LARGE_SIZE 512
+
+#define in_smallbin_range(sz) ((sz) < MIN_LARGE_SIZE)
+
+#define smallbin_index(sz) (((unsigned)(sz)) >> 3)
+
+#define largebin_index(sz) \
+(((((unsigned long)(sz)) >> 6) <= 32)? 56 + (((unsigned long)(sz)) >> 6): \
+ ((((unsigned long)(sz)) >> 9) <= 20)? 91 + (((unsigned long)(sz)) >> 9): \
+ ((((unsigned long)(sz)) >> 12) <= 10)? 110 + (((unsigned long)(sz)) >> 12): \
+ ((((unsigned long)(sz)) >> 15) <= 4)? 119 + (((unsigned long)(sz)) >> 15): \
+ ((((unsigned long)(sz)) >> 18) <= 2)? 124 + (((unsigned long)(sz)) >> 18): \
+ 126)
+
+#define bin_index(sz) \
+ ((in_smallbin_range(sz)) ? smallbin_index(sz) : largebin_index(sz))
+
+
+/*
+ Unsorted chunks
+
+ All remainders from chunk splits, as well as all returned chunks,
+ are first placed in the "unsorted" bin. They are then placed
+ in regular bins after malloc gives them ONE chance to be used before
+ binning. So, basically, the unsorted_chunks list acts as a queue,
+ with chunks being placed on it in free (and malloc_consolidate),
+ and taken off (to be either used or placed in bins) in malloc.
+
+*/
+
+
+/* The otherwise unindexable 1-bin is used to hold unsorted chunks. */
+
+#define unsorted_chunks(M) (bin_at(M, 1))
+
+
+/*
+ Top
+
+ The top-most available chunk (i.e., the one bordering the end of
+ available memory) is treated specially. It is never included in
+ any bin, is used only if no other chunk is available, and is
+ released back to the system if it is very large (see
+ M_TRIM_THRESHOLD). `top' is never properly linked to its bin
+ since it is always handled specially. Because top initially
+ points to its own bin with initial zero size, thus forcing
+ extension on the first malloc request, we avoid having any special
+ code in malloc to check whether it even exists yet. But we still
+ need to do so when getting memory from system, so we make
+ initial_top treat the bin as a legal but unusable chunk during the
+ interval between initialization and the first call to
+ sYSMALLOc. (This is somewhat delicate, since it relies on
+ the 2 preceding words to be zero during this interval as well.)
+*/
+
+
+/* Conveniently, the unsorted bin can be used as dummy top on first call */
+#define initial_top(M) (unsorted_chunks(M))
+
+/*
+ Binmap
+
+ To help compensate for the large number of bins, a one-level index
+ structure is used for bin-by-bin searching. `binmap' is a
+ bitvector recording whether bins are definitely empty so they can
+ be skipped over during during traversals. The bits are NOT always
+ cleared as soon as bins are empty, but instead only
+ when they are noticed to be empty during traversal in malloc.
+
+*/
+
+/* Conservatively use 32 bits per map word, even if on 64bit system */
+#define BINMAPSHIFT 5
+#define BITSPERMAP (1U << BINMAPSHIFT)
+#define BINMAPSIZE (NBINS / BITSPERMAP)
+
+#define idx2block(i) ((i) >> BINMAPSHIFT)
+#define idx2bit(i) ((1U << ((i) & ((1U << BINMAPSHIFT)-1))))
+
+#define mark_bin(m,i) ((m)->binmap[idx2block(i)] |= idx2bit(i))
+#define unmark_bin(m,i) ((m)->binmap[idx2block(i)] &= ~(idx2bit(i)))
+#define get_binmap(m,i) ((m)->binmap[idx2block(i)] & idx2bit(i))
+
+
+/*
+ Fastbins
+
+ An array of lists holding recently freed small chunks. Fastbins
+ are not doubly linked. It is faster to single-link them, and
+ since chunks are never removed from the middles of these lists,
+ double linking is not necessary.
+
+ Chunks in fastbins keep their inuse bit set, so they cannot
+ be consolidated with other free chunks. malloc_consolidate
+ releases all chunks in fastbins and consolidates them with
+ other free chunks.
+*/
+
+typedef struct malloc_chunk* mfastbinptr;
+
+/* offset 2 to use otherwise unindexable first 2 bins */
+#define fastbin_index(sz) ((((unsigned int)(sz)) >> 3) - 2)
+
+/* The maximum fastbin request size we support */
+#define MAX_FAST_SIZE 80
+
+#define NFASTBINS (fastbin_index(request2size(MAX_FAST_SIZE))+1)
+
+
+
+/*
+ Flag bit held in max_fast indicating that there probably are some
+ fastbin chunks . It is set true on entering a chunk into any fastbin,
+ and cleared only in malloc_consolidate.
+
+ The truth value is inverted so that have_fastchunks will be true
+ upon startup (since statics are zero-filled).
+*/
+
+
+#define have_fastchunks(M) (((M)->max_fast & 1U) == 0)
+#define clear_fastchunks(M) ((M)->max_fast |= 1U)
+#define set_fastchunks(M) ((M)->max_fast &= ~1U)
+
+/*
+ Initialization value of max_fast.
+ Use impossibly small value if 0.
+ Value also has flag bit clear.
+*/
+#define req2max_fast(s) (((((s) == 0)? SMALLBIN_WIDTH: request2size(s))) | 1U)
+
+
+/*
+ NONCONTIGUOUS_REGIONS is a special value for sbrk_base indicating that
+ MORECORE does not return contiguous regions. In this case, we do not check
+ or assume that the address of each chunk is at least sbrk_base. Otherwise,
+ contiguity is exploited in merging together, when possible, results
+ from consecutive MORECORE calls.
+
+ The possible values for sbrk_base are:
+ MORECORE_FAILURE:
+ MORECORE has not yet been called, but we expect contiguous space
+ NONCONTIGUOUS_REGIONS:
+ we don't expect or rely on contiguous space
+ any other legal address:
+ the first address returned by MORECORE when contiguous
+*/
+
+#define NONCONTIGUOUS_REGIONS ((char*)(-3))
+
+
+/*
+ ----------- Internal state representation and initialization -----------
+*/
+
+
+struct malloc_state {
+
+ /* The maximum chunk size to be eligible for fastbin */
+ INTERNAL_SIZE_T max_fast; /* low bit used as fastbin flag */
+
+ /* Base of the topmost chunk -- not otherwise kept in a bin */
+ mchunkptr top;
+
+ /* The remainder from the most recent split of a small request */
+ mchunkptr last_remainder;
+
+ /* Fastbins */
+ mfastbinptr fastbins[NFASTBINS];
+
+ /* Normal bins packed as described above */
+ mchunkptr bins[NBINS * 2];
+
+ /* Bitmap of bins */
+ unsigned int binmap[BINMAPSIZE];
+
+ /* Tunable parameters */
+ unsigned long trim_threshold;
+ INTERNAL_SIZE_T top_pad;
+ INTERNAL_SIZE_T mmap_threshold;
+
+ /* Memory map support */
+ int n_mmaps;
+ int n_mmaps_max;
+ int max_n_mmaps;
+
+ /* Bookkeeping for sbrk */
+ unsigned int pagesize; /* Cache malloc_getpagesize */
+ char* sbrk_base; /* first address returned by sbrk,
+ or NONCONTIGUOUS_REGIONS */
+ /* Statistics */
+
+ INTERNAL_SIZE_T mmapped_mem;
+ INTERNAL_SIZE_T sbrked_mem;
+
+ INTERNAL_SIZE_T max_sbrked_mem;
+ INTERNAL_SIZE_T max_mmapped_mem;
+ INTERNAL_SIZE_T max_total_mem;
+};
+
+typedef struct malloc_state *mstate;
+
+/*
+ There is exactly one instance of this struct in this malloc.
+
+ If you are adapting this malloc in a way that does NOT use a static
+ malloc_state, you MUST explicitly zero-fill it before using. This
+ malloc relies on the property that malloc_state is initialized to
+ all zeroes (as is true of C statics).
+
+*/
+
+static struct malloc_state av_; /* never directly referenced */
+
+/*
+ All uses of av_ are via get_malloc_state().
+ This simplifies construction of multithreaded, etc extensions.
+
+ At most one call to get_malloc_state is made per invocation of
+ the public versions of malloc, free, and all other routines
+ except realloc, valloc, and vpalloc. Also, it is called
+ in check* routines if DEBUG is set.
+*/
+
+#define get_malloc_state() (&(av_))
+
+/*
+ Initialize a malloc_state struct.
+
+ This is called only from within malloc_consolidate, which needs
+ be called in the same contexts anyway. It is never called directly
+ outside of malloc_consolidate because some optimizing compilers try
+ to inline it at all call points, which turns out not to be an
+ optimization at all. (Inlining it only in malloc_consolidate is fine though.)
+*/
+
+#if __STD_C
+static void malloc_init_state(mstate av)
+#else
+static void malloc_init_state(av) mstate av;
+#endif
+{
+ int i;
+ mbinptr bin;
+
+
+ /* Uncomment this if you are not using a static av */
+ /* MALLOC_ZERO(av, sizeof(struct malloc_state); */
+
+ /* Establish circular links for normal bins */
+ for (i = 1; i < NBINS; ++i) {
+ bin = bin_at(av,i);
+ bin->fd = bin->bk = bin;
+ }
+
+ av->max_fast = req2max_fast(DEFAULT_MXFAST);
+
+ av->top_pad = DEFAULT_TOP_PAD;
+ av->n_mmaps_max = DEFAULT_MMAP_MAX;
+ av->mmap_threshold = DEFAULT_MMAP_THRESHOLD;
+
+#if MORECORE_CONTIGUOUS
+ av->trim_threshold = DEFAULT_TRIM_THRESHOLD;
+ av->sbrk_base = (char*)MORECORE_FAILURE;
+#else
+ av->trim_threshold = (unsigned long)(-1);
+ av->sbrk_base = NONCONTIGUOUS_REGIONS;
+#endif
+
+ av->top = initial_top(av);
+ av->pagesize = malloc_getpagesize;
+}
+
+/*
+ Other internal utilities operating on mstates
+*/
+
+#if __STD_C
+static Void_t* sYSMALLOc(INTERNAL_SIZE_T, mstate);
+static int sYSTRIm(size_t, mstate);
+static void malloc_consolidate(mstate);
+#else
+static Void_t* sYSMALLOc();
+static int sYSTRIm();
+static void malloc_consolidate();
+#endif
+
+
+/*
+ Debugging support
+
+ These routines make a number of assertions about the states
+ of data structures that should be true at all times. If any
+ are not true, it's very likely that a user program has somehow
+ trashed memory. (It's also possible that there is a coding error
+ in malloc. In which case, please report it!)
+
+*/
+
+#if ! DEBUG
+
+#define check_chunk(P)
+#define check_free_chunk(P)
+#define check_inuse_chunk(P)
+#define check_remalloced_chunk(P,N)
+#define check_malloced_chunk(P,N)
+#define check_malloc_state()
+
+#else
+#define check_chunk(P) do_check_chunk(P)
+#define check_free_chunk(P) do_check_free_chunk(P)
+#define check_inuse_chunk(P) do_check_inuse_chunk(P)
+#define check_remalloced_chunk(P,N) do_check_remalloced_chunk(P,N)
+#define check_malloced_chunk(P,N) do_check_malloced_chunk(P,N)
+#define check_malloc_state() do_check_malloc_state()
+
+
+/*
+ Properties of all chunks
+*/
+
+#if __STD_C
+static void do_check_chunk(mchunkptr p)
+#else
+static void do_check_chunk(p) mchunkptr p;
+#endif
+{
+
+ mstate av = get_malloc_state();
+ unsigned long sz = chunksize(p);
+
+ if (!chunk_is_mmapped(p)) {
+
+ /* Has legal address ... */
+ if (av->sbrk_base != NONCONTIGUOUS_REGIONS) {
+ assert(((char*)p) >= ((char*)(av->sbrk_base)));
+ }
+
+ if (p != av->top) {
+ if (av->sbrk_base != NONCONTIGUOUS_REGIONS) {
+ assert(((char*)p + sz) <= ((char*)(av->top)));
+ }
+ }
+ else {
+ if (av->sbrk_base != NONCONTIGUOUS_REGIONS) {
+ assert(((char*)p + sz) <= ((char*)(av->sbrk_base) + av->sbrked_mem));
+ }
+ /* top size is always at least MINSIZE */
+ assert((long)(sz) >= (long)(MINSIZE));
+ /* top predecessor always marked inuse */
+ assert(prev_inuse(p));
+ }
+
+ }
+ else {
+#if HAVE_MMAP
+ /* address is outside main heap */
+ /* unless mmap has been used as sbrk backup */
+ if (av->sbrk_base != NONCONTIGUOUS_REGIONS) {
+ assert(! (((char*)p) >= ((char*)av->sbrk_base) &&
+ ((char*)p) < ((char*)(av->sbrk_base) + av->sbrked_mem)));
+ }
+ /* chunk is page-aligned */
+ assert(((p->prev_size + sz) & (av->pagesize-1)) == 0);
+ /* mem is aligned */
+ assert(aligned_OK(chunk2mem(p)));
+#else
+ /* force an appropriate assert violation if debug set */
+ assert(!chunk_is_mmapped(p));
+#endif
+ }
+
+}
+
+/*
+ Properties of free chunks
+*/
+
+
+#if __STD_C
+static void do_check_free_chunk(mchunkptr p)
+#else
+static void do_check_free_chunk(p) mchunkptr p;
+#endif
+{
+ mstate av = get_malloc_state();
+
+ INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
+ mchunkptr next = chunk_at_offset(p, sz);
+
+ do_check_chunk(p);
+
+ /* Chunk must claim to be free ... */
+ assert(!inuse(p));
+ assert (!chunk_is_mmapped(p));
+
+ /* Unless a special marker, must have OK fields */
+ if ((unsigned long)sz >= (unsigned long)MINSIZE)
+ {
+ assert((sz & MALLOC_ALIGN_MASK) == 0);
+ assert(aligned_OK(chunk2mem(p)));
+ /* ... matching footer field */
+ assert(next->prev_size == sz);
+ /* ... and is fully consolidated */
+ assert(prev_inuse(p));
+ assert (next == av->top || inuse(next));
+
+ /* ... and has minimally sane links */
+ assert(p->fd->bk == p);
+ assert(p->bk->fd == p);
+ }
+ else /* markers are always of size SIZE_SZ */
+ assert(sz == SIZE_SZ);
+}
+
+/*
+ Properties of inuse chunks
+*/
+
+
+#if __STD_C
+static void do_check_inuse_chunk(mchunkptr p)
+#else
+static void do_check_inuse_chunk(p) mchunkptr p;
+#endif
+{
+ mstate av = get_malloc_state();
+ mchunkptr next;
+ do_check_chunk(p);
+
+ if (chunk_is_mmapped(p))
+ return; /* mmapped chunks have no next/prev */
+
+ /* Check whether it claims to be in use ... */
+ assert(inuse(p));
+
+ next = next_chunk(p);
+
+ /* ... and is surrounded by OK chunks.
+ Since more things can be checked with free chunks than inuse ones,
+ if an inuse chunk borders them and debug is on, it's worth doing them.
+ */
+ if (!prev_inuse(p)) {
+ /* Note that we cannot even look at prev unless it is not inuse */
+ mchunkptr prv = prev_chunk(p);
+ assert(next_chunk(prv) == p);
+ do_check_free_chunk(prv);
+ }
+
+ if (next == av->top) {
+ assert(prev_inuse(next));
+ assert(chunksize(next) >= MINSIZE);
+ }
+ else if (!inuse(next))
+ do_check_free_chunk(next);
+
+}
+
+/*
+ Properties of chunks recycled from fastbins
+*/
+
+#if __STD_C
+static void do_check_remalloced_chunk(mchunkptr p, INTERNAL_SIZE_T s)
+#else
+static void do_check_remalloced_chunk(p, s) mchunkptr p; INTERNAL_SIZE_T s;
+#endif
+{
+
+ INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
+
+ do_check_inuse_chunk(p);
+
+ /* Legal size ... */
+ assert((sz & MALLOC_ALIGN_MASK) == 0);
+ assert((long)sz - (long)MINSIZE >= 0);
+ assert((long)sz - (long)s >= 0);
+ assert((long)sz - (long)(s + MINSIZE) < 0);
+
+ /* ... and alignment */
+ assert(aligned_OK(chunk2mem(p)));
+
+}
+
+/*
+ Properties of nonrecycled chunks at the point they are malloced
+*/
+
+#if __STD_C
+static void do_check_malloced_chunk(mchunkptr p, INTERNAL_SIZE_T s)
+#else
+static void do_check_malloced_chunk(p, s) mchunkptr p; INTERNAL_SIZE_T s;
+#endif
+{
+ /* same as recycled case ... */
+ do_check_remalloced_chunk(p, s);
+
+ /*
+ ... plus, must obey implementation invariant that prev_inuse is
+ always true of any allocated chunk; i.e., that each allocated
+ chunk borders either a previously allocated and still in-use
+ chunk, or the base of its memory arena. This is ensured
+ by making all allocations from the the `lowest' part of any found
+ chunk. This does not necessarily hold however for chunks
+ recycled via fastbins.
+ */
+
+ assert(prev_inuse(p));
+}
+
+
+/*
+ Properties of malloc_state.
+
+ This may be useful for debugging malloc, as well as detecting user
+ programmer errors that somehow write into malloc_state.
+*/
+
+static void do_check_malloc_state()
+{
+ mstate av = get_malloc_state();
+ int i;
+ mchunkptr p;
+ mchunkptr q;
+ mbinptr b;
+ unsigned int biton;
+ int empty;
+ unsigned int idx;
+ INTERNAL_SIZE_T size;
+ unsigned long total = 0;
+ int max_fast_bin;
+
+
+ /* internal size_t must be no wider than pointer type */
+ assert(sizeof(INTERNAL_SIZE_T) <= sizeof(char*));
+
+ /* alignment is a power of 2 */
+ assert((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-1)) == 0);
+
+ /* cannot run remaining checks until fully initialized */
+ if (av->top == 0 || av->top == initial_top(av))
+ return;
+
+ /* pagesize is a power of 2 */
+ assert((av->pagesize & (av->pagesize-1)) == 0);
+
+ /* properties of fastbins */
+
+ /* max_fast is in allowed range */
+
+ assert((av->max_fast & ~1) <= request2size(MAX_FAST_SIZE));
+
+ max_fast_bin = fastbin_index(av->max_fast);
+
+ for (i = 0; i < NFASTBINS; ++i) {
+ p = av->fastbins[i];
+
+ /* all bins past max_fast are empty */
+ if (i > max_fast_bin)
+ assert(p == 0);
+
+ while (p != 0) {
+ /* each chunk claims to be inuse */
+ do_check_inuse_chunk(p);
+ total += chunksize(p);
+ /* chunk belongs in this bin */
+ assert(fastbin_index(chunksize(p)) == i);
+ p = p->fd;
+ }
+ }
+
+ if (total != 0)
+ assert(have_fastchunks(av));
+
+ /* check normal bins */
+ for (i = 1; i < NBINS; ++i) {
+ b = bin_at(av,i);
+
+ /* binmap is accurate (except for bin 1 == unsorted_chunks) */
+ if (i >= 2) {
+ biton = get_binmap(av,i);
+ empty = last(b) == b;
+ if (!biton)
+ assert(empty);
+ else if (!empty)
+ assert(biton);
+ }
+
+ for (p = last(b); p != b; p = p->bk) {
+ /* each chunk claims to be free */
+ do_check_free_chunk(p);
+ size = chunksize(p);
+ total += size;
+ if (i >= 2) {
+ /* chunk belongs in bin */
+ idx = bin_index(size);
+ assert(idx == i);
+ /* lists are sorted */
+ assert(p->bk == b || chunksize(p->bk) >= chunksize(p));
+ }
+ /* chunk is followed by a legal chain of inuse chunks */
+ for (q = next_chunk(p);
+ q != av->top && inuse(q) && (long)(chunksize(q)) >= (long)MINSIZE;
+ q = next_chunk(q))
+ do_check_inuse_chunk(q);
+
+ }
+ }
+
+ /* top chunk is OK */
+ check_chunk(av->top);
+
+ /* sanity checks for statistics */
+
+ assert(total <= (unsigned long)(av->max_total_mem));
+ assert(av->n_mmaps >= 0);
+ assert(av->n_mmaps <= av->n_mmaps_max);
+ assert(av->n_mmaps <= av->max_n_mmaps);
+ assert(av->max_n_mmaps <= av->n_mmaps_max);
+
+ assert((unsigned long)(av->sbrked_mem) <=
+ (unsigned long)(av->max_sbrked_mem));
+
+ assert((unsigned long)(av->mmapped_mem) <=
+ (unsigned long)(av->max_mmapped_mem));
+
+ assert((unsigned long)(av->max_total_mem) >=
+ (unsigned long)(av->mmapped_mem) + (unsigned long)(av->sbrked_mem));
+
+}
+
+
+#endif
+
+
+
+
+
+/* ----------- Routines dealing with system allocation -------------- */
+
+/*
+ Handle malloc cases requiring more memory from system.
+ malloc relays to sYSMALLOc if it cannot allocate out of
+ existing memory.
+
+ On entry, it is assumed that av->top does not have enough
+ space to service request for nb bytes, thus requiring more meory
+ from system.
+*/
+
+#if __STD_C
+static Void_t* sYSMALLOc(INTERNAL_SIZE_T nb, mstate av)
+#else
+static Void_t* sYSMALLOc(nb, av) INTERNAL_SIZE_T nb; mstate av;
+#endif
+{
+ mchunkptr old_top; /* incoming value of av->top */
+ INTERNAL_SIZE_T old_size; /* its size */
+ char* old_end; /* its end address */
+
+ long size; /* arg to first MORECORE or mmap call */
+ char* brk; /* return value from MORECORE */
+ char* mm; /* return value from mmap call*/
+
+ long correction; /* arg to 2nd MORECORE call */
+ char* snd_brk; /* 2nd return val */
+
+ INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of new space */
+ INTERNAL_SIZE_T end_misalign; /* partial page left at end of new space */
+ char* aligned_brk; /* aligned offset into brk */
+
+ mchunkptr p; /* the allocated/returned chunk */
+ mchunkptr remainder; /* remainder from allocation */
+ long remainder_size; /* its size */
+
+ unsigned long sum; /* for updating stats */
+
+ size_t pagemask = av->pagesize - 1;
+
+ /*
+ If have mmap, and the request size meets the mmap threshold, and
+ the system supports mmap, and there are few enough currently
+ allocated mmapped regions, and a call to mmap succeeds, try to
+ directly map this request rather than expanding top.
+ */
+
+#if HAVE_MMAP
+ if ((unsigned long)nb >= (unsigned long)(av->mmap_threshold) &&
+ (av->n_mmaps < av->n_mmaps_max)) {
+
+ /*
+ Round up size to nearest page. For mmapped chunks, the overhead
+ is one SIZE_SZ unit larger than for normal chunks, because there
+ is no following chunk whose prev_size field could be used.
+ */
+ size = (nb + SIZE_SZ + MALLOC_ALIGN_MASK + pagemask) & ~pagemask;
+
+ mm = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE));
+
+ if (mm != (char*)(MORECORE_FAILURE)) {
+
+ /*
+ The offset to the start of the mmapped region is stored
+ in the prev_size field of the chunk. This allows us to adjust
+ returned start address to meet alignment requirements here
+ and in memalign(), and still be able to compute proper
+ address argument for later munmap in free() and realloc().
+ */
+
+ front_misalign = (INTERNAL_SIZE_T)chunk2mem(mm) & MALLOC_ALIGN_MASK;
+ if (front_misalign > 0) {
+ correction = MALLOC_ALIGNMENT - front_misalign;
+ p = (mchunkptr)(mm + correction);
+ p->prev_size = correction;
+ set_head(p, (size - correction) |IS_MMAPPED);
+ }
+ else {
+ p = (mchunkptr)mm;
+ set_head(p, size|IS_MMAPPED);
+ }
+
+ check_chunk(p);
+
+ /* update statistics */
+
+ if (++av->n_mmaps > av->max_n_mmaps)
+ av->max_n_mmaps = av->n_mmaps;
+
+ sum = av->mmapped_mem += size;
+ if (sum > (unsigned long)(av->max_mmapped_mem))
+ av->max_mmapped_mem = sum;
+ sum += av->sbrked_mem;
+ if (sum > (unsigned long)(av->max_total_mem))
+ av->max_total_mem = sum;
+
+ return chunk2mem(p);
+ }
+ }
+#endif
+
+ /* record incoming configuration of top */
+
+ old_top = av->top;
+ old_size = chunksize(old_top);
+ old_end = (char*)(chunk_at_offset(old_top, old_size));
+
+ brk = snd_brk = (char*)(MORECORE_FAILURE);
+
+ /*
+ If not the first time through, we require old_size to be
+ at least MINSIZE and to have prev_inuse set.
+ */
+
+ assert(old_top == initial_top(av) ||
+ ((unsigned long) (old_size) >= (unsigned long)(MINSIZE) &&
+ prev_inuse(old_top)));
+
+
+ /* Request enough space for nb + pad + overhead */
+
+ size = nb + av->top_pad + MINSIZE;
+
+ /*
+ If contiguous, we can subtract out existing space that we hope to
+ combine with new space. We add it back later only if
+ we don't actually get contiguous space.
+ */
+
+ if (av->sbrk_base != NONCONTIGUOUS_REGIONS)
+ size -= old_size;
+
+ /*
+ Round to a multiple of page size.
+ If MORECORE is not contiguous, this ensures that we only call it
+ with whole-page arguments. And if MORECORE is contiguous and
+ this is not first time through, this preserves page-alignment of
+ previous calls. Otherwise, we re-correct anyway to page-align below.
+ */
+
+ size = (size + pagemask) & ~pagemask;
+
+ /*
+ Don't try to call MORECORE if argument is so big as to appear
+ negative. Note that since mmap takes size_t arg, it may succeed
+ below even if we cannot call MORECORE.
+ */
+
+ if (size > 0)
+ brk = (char*)(MORECORE(size));
+
+ /*
+ If have mmap, try using it as a backup when MORECORE fails. This
+ is worth doing on systems that have "holes" in address space, so
+ sbrk cannot extend to give contiguous space, but space is available
+ elsewhere. Note that we ignore mmap max count and threshold limits,
+ since there is no reason to artificially limit use here.
+ */
+
+#if HAVE_MMAP
+ if (brk == (char*)(MORECORE_FAILURE)) {
+
+ /* Cannot merge with old top, so add its size back in */
+
+ if (av->sbrk_base != NONCONTIGUOUS_REGIONS)
+ size = (size + old_size + pagemask) & ~pagemask;
+
+ /* If we are relying on mmap as backup, then use larger units */
+
+ if ((unsigned long)size < (unsigned long)MMAP_AS_MORECORE_SIZE)
+ size = MMAP_AS_MORECORE_SIZE;
+
+ brk = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE));
+
+ if (brk != (char*)(MORECORE_FAILURE)) {
+
+ /* We do not need, and cannot use, another sbrk call to find end */
+ snd_brk = brk + size;
+
+ /*
+ Record that we no longer have a contiguous sbrk region.
+ After the first time mmap is used as backup, we cannot
+ ever rely on contiguous space.
+ */
+ av->sbrk_base = NONCONTIGUOUS_REGIONS;
+ }
+ }
+#endif
+
+ if (brk != (char*)(MORECORE_FAILURE)) {
+
+ av->sbrked_mem += size;
+
+ /*
+ If MORECORE extends previous space, we can likewise extend top size.
+ */
+
+ if (brk == old_end && snd_brk == (char*)(MORECORE_FAILURE)) {
+ set_head(old_top, (size + old_size) | PREV_INUSE);
+ }
+
+ /*
+ Otherwise, make adjustments guided by the special values of
+ av->sbrk_base (MORECORE_FAILURE or NONCONTIGUOUS_REGIONS):
+
+ * If the first time through or noncontiguous, we need to call sbrk
+ just to find out where the end of memory lies.
+
+ * We need to ensure that all returned chunks from malloc will meet
+ MALLOC_ALIGNMENT
+
+ * If there was an intervening foreign sbrk, we need to adjust sbrk
+ request size to account for fact that we will not be able to
+ combine new space with existing space in old_top.
+
+ * Almost all systems internally allocate whole pages at a time, in
+ which case we might as well use the whole last page of request.
+ So we allocate enough more memory to hit a page boundary now,
+ which in turn causes future contiguous calls to page-align.
+
+ */
+
+ else {
+ front_misalign = 0;
+ end_misalign = 0;
+ correction = 0;
+ aligned_brk = brk;
+
+ /* handle contiguous cases */
+ if (av->sbrk_base != NONCONTIGUOUS_REGIONS) {
+
+ /* Guarantee alignment of first new chunk made from this space */
+
+ front_misalign = (INTERNAL_SIZE_T)chunk2mem(brk) & MALLOC_ALIGN_MASK;
+ if (front_misalign > 0) {
+
+ /*
+ Skip over some bytes to arrive at an aligned position.
+ We don't need to specially mark these wasted front bytes.
+ They will never be accessed anyway because
+ prev_inuse of av->top (and any chunk created from its start)
+ is always true after initialization.
+ */
+
+ correction = MALLOC_ALIGNMENT - front_misalign;
+ aligned_brk += correction;
+ }
+
+ /*
+ If this isn't adjacent to a previous sbrk, then we will not
+ be able to merge with old_top space, so must add to 2nd request.
+ */
+
+ correction += old_size;
+
+ /* Pad out to hit a page boundary */
+
+ end_misalign = (INTERNAL_SIZE_T)(brk + size + correction);
+ correction += ((end_misalign + pagemask) & ~pagemask) - end_misalign;
+
+ assert(correction >= 0);
+
+ snd_brk = (char*)(MORECORE(correction));
+
+ /*
+ If can't allocate correction, try to at least find out current
+ brk. It might be enough to proceed without failing.
+
+ Note that if second sbrk did NOT fail, we assume that space
+ is contiguous with first sbrk. This is a safe assumption unless
+ program is multithreaded but doesn't use locks and a foreign sbrk
+ occurred between our first and second calls.
+ */
+
+ if (snd_brk == (char*)(MORECORE_FAILURE)) {
+ correction = 0;
+ snd_brk = (char*)(MORECORE(0));
+ }
+ }
+
+ /* handle non-contiguous cases */
+ else {
+
+ /* MORECORE/mmap must correctly align etc */
+ assert(((unsigned long)chunk2mem(brk) & MALLOC_ALIGN_MASK) == 0);
+
+ /* Find out current end of memory */
+ if (snd_brk == (char*)(MORECORE_FAILURE)) {
+ snd_brk = (char*)(MORECORE(0));
+ }
+
+ /* This must lie on a page boundary */
+ if (snd_brk != (char*)(MORECORE_FAILURE)) {
+ assert(((INTERNAL_SIZE_T)(snd_brk) & pagemask) == 0);
+ }
+ }
+
+ /* Adjust top based on results of second sbrk */
+ if (snd_brk != (char*)(MORECORE_FAILURE)) {
+
+ av->top = (mchunkptr)aligned_brk;
+ set_head(av->top, (snd_brk - aligned_brk + correction) | PREV_INUSE);
+
+ av->sbrked_mem += correction;
+
+ /* If first time through and contiguous, record base */
+ if (old_top == initial_top(av)) {
+ if (av->sbrk_base == (char*)(MORECORE_FAILURE))
+ av->sbrk_base = brk;
+ }
+
+ /*
+ Otherwise, we either have a gap due to foreign sbrk or a
+ non-contiguous region. Insert a double fencepost at old_top
+ to prevent consolidation with space we don't own. These
+ fenceposts are artificial chunks that are marked as inuse
+ and are in any case too small to use. We need two to make
+ sizes and alignments work out.
+ */
+
+ else {
+
+ /*
+ Shrink old_top to insert fenceposts, keeping size a
+ multiple of MALLOC_ALIGNMENT.
+ */
+ old_size = (old_size - 3*SIZE_SZ) & ~MALLOC_ALIGN_MASK;
+ set_head(old_top, old_size | PREV_INUSE);
+
+ /*
+ Note that the following assignments overwrite old_top when
+ old_size was previously MINSIZE. This is intentional. We
+ need the fencepost, even if old_top otherwise gets lost.
+ */
+ chunk_at_offset(old_top, old_size )->size =
+ SIZE_SZ|PREV_INUSE;
+
+ chunk_at_offset(old_top, old_size + SIZE_SZ)->size =
+ SIZE_SZ|PREV_INUSE;
+
+ /* If possible, release the rest. */
+ if (old_size >= MINSIZE)
+ fREe(chunk2mem(old_top));
+
+ }
+ }
+ }
+
+ /* Update statistics */
+
+ sum = av->sbrked_mem;
+ if (sum > (unsigned long)(av->max_sbrked_mem))
+ av->max_sbrked_mem = sum;
+
+ sum += av->mmapped_mem;
+ if (sum > (unsigned long)(av->max_total_mem))
+ av->max_total_mem = sum;
+
+ check_malloc_state();
+
+ /* finally, do the allocation */
+
+ p = av->top;
+ size = chunksize(p);
+ remainder_size = (long)size - (long)nb;
+
+ /* check that one of the above allocation paths succeeded */
+ if (remainder_size >= (long)MINSIZE) {
+ remainder = chunk_at_offset(p, nb);
+ av->top = remainder;
+ set_head(p, nb | PREV_INUSE);
+ set_head(remainder, remainder_size | PREV_INUSE);
+
+ check_malloced_chunk(p, nb);
+ return chunk2mem(p);
+ }
+ }
+
+ /* catch all failure paths */
+ MALLOC_FAILURE_ACTION;
+ return 0;
+}
+
+
+/*
+ sYSTRIm is an inverse of sorts to sYSMALLOc.
+ It gives memory back to the system (via negative
+ arguments to sbrk) if there is unused memory at the `high' end of
+ the malloc pool. It is called automatically by free()
+ when top space exceeds the trim threshold.
+ returns 1 if it actually released any memory, else 0.
+*/
+
+#if __STD_C
+static int sYSTRIm(size_t pad, mstate av)
+#else
+static int sYSTRIm(pad, av) size_t pad; mstate av;
+#endif
+{
+ long top_size; /* Amount of top-most memory */
+ long extra; /* Amount to release */
+ long released; /* Amount actually released */
+ char* current_brk; /* address returned by pre-check sbrk call */
+ char* new_brk; /* address returned by post-check sbrk call */
+ size_t pagesz;
+
+ /* Don't bother trying if sbrk doesn't provide contiguous regions */
+ if (av->sbrk_base != NONCONTIGUOUS_REGIONS) {
+
+ pagesz = av->pagesize;
+ top_size = chunksize(av->top);
+
+ /* Release in pagesize units, keeping at least one page */
+ extra = ((top_size - pad - MINSIZE + (pagesz-1)) / pagesz - 1) * pagesz;
+
+ if (extra > 0) {
+
+ /*
+ Only proceed if end of memory is where we last set it.
+ This avoids problems if there were foreign sbrk calls.
+ */
+ current_brk = (char*)(MORECORE(0));
+ if (current_brk == (char*)(av->top) + top_size) {
+
+ /*
+ Attempt to release memory. We ignore return value,
+ and instead call again to find out where new end of memory is.
+ This avoids problems if first call releases less than we asked,
+ of if failure somehow altered brk value. (We could still
+ encounter problems if it altered brk in some very bad way,
+ but the only thing we can do is adjust anyway, which will cause
+ some downstream failure.)
+ */
+
+ MORECORE(-extra);
+ new_brk = (char*)(MORECORE(0));
+
+ if (new_brk != (char*)MORECORE_FAILURE) {
+ released = (long)(current_brk - new_brk);
+
+ if (released != 0) {
+ /* Success. Adjust top. */
+ av->sbrked_mem -= released;
+ set_head(av->top, (top_size - released) | PREV_INUSE);
+ check_malloc_state();
+ return 1;
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* ----------------------- Main public routines ----------------------- */
+
+
+/*
+ Malloc routine. See running comments for algorithm description.
+*/
+
+#if __STD_C
+Void_t* mALLOc(size_t bytes)
+#else
+ Void_t* mALLOc(bytes) size_t bytes;
+#endif
+{
+ mstate av = get_malloc_state();
+
+ INTERNAL_SIZE_T nb; /* normalized request size */
+ unsigned int idx; /* associated bin index */
+ mbinptr bin; /* associated bin */
+ mfastbinptr* fb; /* associated fastbin */
+
+ mchunkptr victim; /* inspected/selected chunk */
+ INTERNAL_SIZE_T size; /* its size */
+ int victim_index; /* its bin index */
+
+ mchunkptr remainder; /* remainder from a split */
+ long remainder_size; /* its size */
+
+ unsigned int block; /* bit map traverser */
+ unsigned int bit; /* bit map traverser */
+ unsigned int map; /* current word of binmap */
+
+ mchunkptr fwd; /* misc temp for linking */
+ mchunkptr bck; /* misc temp for linking */
+
+
+ /*
+ Check request for legality and convert to internal form, nb.
+ This rejects negative arguments when size_t is treated as
+ signed. It also rejects arguments that are so large that the size
+ appears negative when aligned and padded. The converted form
+ adds SIZE_T bytes overhead plus possibly more to obtain necessary
+ alignment and/or to obtain a size of at least MINSIZE, the
+ smallest allocatable size.
+ */
+
+ checked_request2size(bytes, nb);
+
+ /*
+ If the size qualifies as a fastbin, first check corresponding bin.
+ This code is safe to execute even if av not yet initialized, so we
+ can try it first, which saves some time on this fast path.
+ */
+
+ if (nb <= av->max_fast) {
+ fb = &(av->fastbins[(fastbin_index(nb))]);
+ if ( (victim = *fb) != 0) {
+ *fb = victim->fd;
+ check_remalloced_chunk(victim, nb);
+ return chunk2mem(victim);
+ }
+ }
+
+ /*
+ If a small request, check regular bin. Since these "smallbins"
+ hold one size each, no searching within bins is necessary.
+
+ (If a large request, we need to wait until unsorted chunks are
+ processed to find best fit. But for small ones, fits are exact
+ anyway, so we can check now, which is faster.)
+ */
+
+ if (in_smallbin_range(nb)) {
+ idx = smallbin_index(nb);
+ bin = bin_at(av,idx);
+
+ if ( (victim = last(bin)) != bin) {
+ if (victim == 0) /* initialization check */
+ malloc_consolidate(av);
+ else {
+ bck = victim->bk;
+ set_inuse_bit_at_offset(victim, nb);
+ bin->bk = bck;
+ bck->fd = bin;
+
+ check_malloced_chunk(victim, nb);
+ return chunk2mem(victim);
+ }
+ }
+ }
+
+ /*
+ If a large request, consolidate fastbins before continuing.
+ While it might look excessive to kill all fastbins before
+ even seeing if there is space available, this avoids
+ fragmentation problems normally associated with fastbins.
+ Also, in practice, programs tend to have runs of either small or
+ large requests, but less often mixtures, so consolidation is not
+ usually invoked all that often.
+ */
+
+ else {
+ idx = largebin_index(nb);
+ if (have_fastchunks(av)) /* consolidation/initialization check */
+ malloc_consolidate(av);
+ }
+
+
+ /*
+ Process recently freed or remaindered chunks, taking one only if
+ it is exact fit, or, if a small request, it is the remainder from
+ the most recent non-exact fit. Place other traversed chunks in
+ bins. Note that this step is the only place in any routine where
+ chunks are placed in bins.
+
+ The outer loop here is needed because we might not realize until
+ near the end of malloc that we should have consolidated, so must
+ do so and retry. This happens at most once, and only when we would
+ otherwise need to expand memory to service a "small" request.
+ */
+
+
+ for(;;) {
+
+ while ( (victim = unsorted_chunks(av)->bk) != unsorted_chunks(av)) {
+ bck = victim->bk;
+ size = chunksize(victim);
+
+ /*
+ If a small request, try to use last remainder if it is the
+ only chunk in unsorted bin. This helps promote locality for
+ runs of consecutive small requests. This is the only
+ exception to best-fit.
+ */
+
+ if (in_smallbin_range(nb) &&
+ victim == av->last_remainder &&
+ bck == unsorted_chunks(av) &&
+ (remainder_size = (long)size - (long)nb) >= (long)MINSIZE) {
+
+ /* split and reattach remainder */
+ remainder = chunk_at_offset(victim, nb);
+ unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
+ av->last_remainder = remainder;
+ remainder->bk = remainder->fd = unsorted_chunks(av);
+
+ set_head(victim, nb | PREV_INUSE);
+ set_head(remainder, remainder_size | PREV_INUSE);
+ set_foot(remainder, remainder_size);
+
+ check_malloced_chunk(victim, nb);
+ return chunk2mem(victim);
+ }
+
+ /* remove from unsorted list */
+ unsorted_chunks(av)->bk = bck;
+ bck->fd = unsorted_chunks(av);
+
+ /* Take now instead of binning if exact fit */
+
+ if (size == nb) {
+ set_inuse_bit_at_offset(victim, size);
+ check_malloced_chunk(victim, nb);
+ return chunk2mem(victim);
+ }
+
+ /* place chunk in bin */
+
+ if (in_smallbin_range(size)) {
+ victim_index = smallbin_index(size);
+ bck = bin_at(av, victim_index);
+ fwd = bck->fd;
+ }
+ else {
+ victim_index = largebin_index(size);
+ bck = bin_at(av, victim_index);
+ fwd = bck->fd;
+
+ /* maintain large bins in sorted order */
+ if (fwd != bck) {
+ /* if smaller than smallest, bypass loop below */
+ if ((unsigned long)size <=
+ (unsigned long)(chunksize(bck->bk))) {
+ fwd = bck;
+ bck = bck->bk;
+ }
+ else {
+ while (fwd != bck &&
+ (unsigned long)size < (unsigned long)(chunksize(fwd))) {
+ fwd = fwd->fd;
+ }
+ bck = fwd->bk;
+ }
+ }
+ }
+
+ mark_bin(av, victim_index);
+ victim->bk = bck;
+ victim->fd = fwd;
+ fwd->bk = victim;
+ bck->fd = victim;
+ }
+
+ /*
+ If a large request, scan through the chunks of current bin in
+ sorted order to find smallest that fits. This is the only step
+ where an unbounded number of chunks might be scanned without doing
+ anything useful with them. However the lists tend to be very
+ short.
+ */
+
+ if (!in_smallbin_range(nb)) {
+ bin = bin_at(av, idx);
+
+ /* skip scan if largest chunk is too small */
+ if ((victim = last(bin)) != bin &&
+ (long)(chunksize(first(bin))) - (long)(nb) >= 0) {
+ do {
+ size = chunksize(victim);
+ remainder_size = (long)size - (long)nb;
+
+ if (remainder_size >= 0) {
+ unlink(victim, bck, fwd);
+
+ /* Exhaust */
+ if (remainder_size < (long)MINSIZE) {
+ set_inuse_bit_at_offset(victim, size);
+ check_malloced_chunk(victim, nb);
+ return chunk2mem(victim);
+ }
+ /* Split */
+ else {
+ remainder = chunk_at_offset(victim, nb);
+ unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
+ remainder->bk = remainder->fd = unsorted_chunks(av);
+ set_head(victim, nb | PREV_INUSE);
+ set_head(remainder, remainder_size | PREV_INUSE);
+ set_foot(remainder, remainder_size);
+ check_malloced_chunk(victim, nb);
+ return chunk2mem(victim);
+ }
+ }
+ } while ( (victim = victim->bk) != bin);
+ }
+ }
+
+ /*
+ Search for a chunk by scanning bins, starting with next largest
+ bin. This search is strictly by best-fit; i.e., the smallest
+ (with ties going to approximately the least recently used) chunk
+ that fits is selected.
+
+ The bitmap avoids needing to check that most blocks are nonempty.
+ The particular case of skipping all bins during warm-up phases
+ when no chunks have been returned yet is faster than it might look.
+ */
+
+ ++idx;
+ bin = bin_at(av,idx);
+ block = idx2block(idx);
+ map = av->binmap[block];
+ bit = idx2bit(idx);
+
+ for (;;) {
+ /*
+ Skip rest of block if there are no more set bits in this block.
+ */
+
+ if (bit > map || bit == 0) {
+ for (;;) {
+ if (++block >= BINMAPSIZE) /* out of bins */
+ break;
+
+ else if ( (map = av->binmap[block]) != 0) {
+ bin = bin_at(av, (block << BINMAPSHIFT));
+ bit = 1;
+ break;
+ }
+ }
+ /* Optimizers seem to like this double-break better than goto */
+ if (block >= BINMAPSIZE)
+ break;
+ }
+
+ /* Advance to bin with set bit. There must be one. */
+ while ((bit & map) == 0) {
+ bin = next_bin(bin);
+ bit <<= 1;
+ }
+
+ victim = last(bin);
+
+ /* False alarm -- the bin is empty. Clear the bit. */
+ if (victim == bin) {
+ av->binmap[block] = map &= ~bit; /* Write through */
+ bin = next_bin(bin);
+ bit <<= 1;
+ }
+
+ /* We know the first chunk in this bin is big enough to use. */
+ else {
+ size = chunksize(victim);
+ remainder_size = (long)size - (long)nb;
+
+ assert(remainder_size >= 0);
+
+ /* unlink */
+ bck = victim->bk;
+ bin->bk = bck;
+ bck->fd = bin;
+
+
+ /* Exhaust */
+ if (remainder_size < (long)MINSIZE) {
+ set_inuse_bit_at_offset(victim, size);
+ check_malloced_chunk(victim, nb);
+ return chunk2mem(victim);
+ }
+
+ /* Split */
+ else {
+ remainder = chunk_at_offset(victim, nb);
+
+ unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder;
+ remainder->bk = remainder->fd = unsorted_chunks(av);
+ /* advertise as last remainder */
+ if (in_smallbin_range(nb))
+ av->last_remainder = remainder;
+
+ set_head(victim, nb | PREV_INUSE);
+ set_head(remainder, remainder_size | PREV_INUSE);
+ set_foot(remainder, remainder_size);
+ check_malloced_chunk(victim, nb);
+ return chunk2mem(victim);
+ }
+ }
+ }
+
+ /*
+ If large enough, split off the chunk bordering the end of memory
+ ("top"). Note that this use of top is in accord with the best-fit search
+ rule. In effect, top is treated as larger (and thus less well
+ fitting) than any other available chunk since it can be extended
+ to be as large as necessary (up to system limitations).
+
+ We require that "top" always exists (i.e., has size >= MINSIZE)
+ after initialization, so if it would otherwise be exhuasted by
+ current request, it is replenished. (Among the reasons for
+ ensuring it exists is that we may need MINSIZE space to put in
+ fenceposts in sysmalloc.)
+ */
+
+ victim = av->top;
+ size = chunksize(victim);
+ remainder_size = (long)size - (long)nb;
+
+ if (remainder_size >= (long)MINSIZE) {
+ remainder = chunk_at_offset(victim, nb);
+ av->top = remainder;
+ set_head(victim, nb | PREV_INUSE);
+ set_head(remainder, remainder_size | PREV_INUSE);
+
+ check_malloced_chunk(victim, nb);
+ return chunk2mem(victim);
+ }
+
+ /*
+ If there is space available in fastbins, consolidate and retry,
+ to possibly avoid expanding memory. This can occur only if nb is
+ in smallbin range so we didn't consolidate upon entry.
+ */
+
+ else if (have_fastchunks(av)) {
+ assert(in_smallbin_range(nb));
+ idx = smallbin_index(nb); /* restore original bin index */
+ malloc_consolidate(av);
+ }
+
+ /*
+ Otherwise, relay to handle system-dependent cases
+ */
+ else
+ return sYSMALLOc(nb, av);
+ }
+}
+
+
+
+/*
+ Free routine. See running comments for algorithm description.
+*/
+
+#if __STD_C
+void fREe(Void_t* mem)
+#else
+void fREe(mem) Void_t* mem;
+#endif
+{
+ mstate av = get_malloc_state();
+
+ mchunkptr p; /* chunk corresponding to mem */
+ INTERNAL_SIZE_T size; /* its size */
+ mfastbinptr* fb; /* associated fastbin */
+ mchunkptr nextchunk; /* next contiguous chunk */
+ INTERNAL_SIZE_T nextsize; /* its size */
+ int nextinuse; /* true if nextchunk is used */
+ INTERNAL_SIZE_T prevsize; /* size of previous contiguous chunk */
+ mchunkptr bck; /* misc temp for linking */
+ mchunkptr fwd; /* misc temp for linking */
+
+
+ /* free(0) has no effect */
+ if (mem != 0) {
+
+ p = mem2chunk(mem);
+ check_inuse_chunk(p);
+
+ size = chunksize(p);
+
+ /*
+ If eligible, place chunk on a fastbin so it can be found
+ and used quickly in malloc.
+ */
+
+ if ((unsigned long)size <= (unsigned long)av->max_fast
+
+#if TRIM_FASTBINS
+ /*
+ If TRIM_FASTBINS set, don't place chunks
+ bordering top into fastbins
+ */
+ && (chunk_at_offset(p, size) != av->top)
+#endif
+ ) {
+
+ set_fastchunks(av);
+ fb = &(av->fastbins[fastbin_index(size)]);
+ p->fd = *fb;
+ *fb = p;
+ }
+
+ /*
+ Consolidate non-mmapped chunks as they arrive.
+ */
+
+ else if (!chunk_is_mmapped(p)) {
+
+ nextchunk = chunk_at_offset(p, size);
+
+ /* consolidate backward */
+ if (!prev_inuse(p)) {
+ prevsize = p->prev_size;
+ size += prevsize;
+ p = chunk_at_offset(p, -((long) prevsize));
+ unlink(p, bck, fwd);
+ }
+
+ nextsize = chunksize(nextchunk);
+
+ if (nextchunk != av->top) {
+
+ /* get and clear inuse bit */
+ nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
+ set_head(nextchunk, nextsize);
+
+ /* consolidate forward */
+ if (!nextinuse) {
+ unlink(nextchunk, bck, fwd);
+ size += nextsize;
+ }
+
+ /*
+ Place chunk in unsorted chunk list. Chunks are
+ not placed into regular bins until after they have
+ been given one chance to be used in malloc.
+ */
+
+ bck = unsorted_chunks(av);
+ fwd = bck->fd;
+ p->bk = bck;
+ p->fd = fwd;
+ bck->fd = p;
+ fwd->bk = p;
+
+ set_head(p, size | PREV_INUSE);
+ set_foot(p, size);
+ }
+
+ /*
+ If the chunk borders the current high end of memory,
+ consolidate into top
+ */
+
+ else {
+ size += nextsize;
+ set_head(p, size | PREV_INUSE);
+ av->top = p;
+
+ /*
+ If the total unused topmost memory exceeds trim
+ threshold, ask malloc_trim to reduce top.
+
+ Unless max_fast is 0, we don't know if there are fastbins
+ bordering top, so we cannot tell for sure whether threshold has
+ been reached unless fastbins are consolidated. But we don't
+ want to consolidate on each free. As a compromise,
+ consolidation is performed if half the threshold is
+ reached.
+
+ */
+
+ if ((unsigned long)(size) > (unsigned long)(av->trim_threshold / 2)) {
+ if (have_fastchunks(av)) {
+ malloc_consolidate(av);
+ size = chunksize(av->top);
+ }
+
+ if ((unsigned long)(size) > (unsigned long)(av->trim_threshold))
+ sYSTRIm(av->top_pad, av);
+ }
+ }
+ }
+
+ /*
+ If the chunk was allocated via mmap, release via munmap()
+ Note that if HAVE_MMAP is false but chunk_is_mmapped is
+ true, then user must have overwritten memory. There's nothing
+ we can do to catch this error unless DEBUG is set, in which case
+ check_inuse_chunk (above) will have triggered error.
+ */
+
+ else {
+#if HAVE_MMAP
+ int ret;
+ INTERNAL_SIZE_T offset = p->prev_size;
+ av->n_mmaps--;
+ av->mmapped_mem -= (size + offset);
+ ret = munmap((char*)p - offset, size + offset);
+ /* munmap returns non-zero on failure */
+ assert(ret == 0);
+#endif
+ }
+ }
+}
+
+
+
+/*
+ malloc_consolidate is a specialized version of free() that tears
+ down chunks held in fastbins. Free itself cannot be used for this
+ purpose since, among other things, it might place chunks back onto
+ fastbins. So, instead, we need to use a minor variant of the same
+ code.
+
+ Also, because this routine needs to be called the first time through
+ malloc anyway, it turns out to be the perfect place to bury
+ initialization code.
+*/
+
+#if __STD_C
+static void malloc_consolidate(mstate av)
+#else
+static void malloc_consolidate(av) mstate av;
+#endif
+{
+ mfastbinptr* fb;
+ mfastbinptr* maxfb;
+ mchunkptr p;
+ mchunkptr nextp;
+ mchunkptr unsorted_bin;
+ mchunkptr first_unsorted;
+
+ /* These have same use as in free() */
+ mchunkptr nextchunk;
+ INTERNAL_SIZE_T size;
+ INTERNAL_SIZE_T nextsize;
+ INTERNAL_SIZE_T prevsize;
+ int nextinuse;
+ mchunkptr bck;
+ mchunkptr fwd;
+
+ /*
+ If max_fast is 0, we know that malloc hasn't
+ yet been initialized, in which case do so.
+ */
+
+ if (av->max_fast == 0) {
+ malloc_init_state(av);
+ check_malloc_state();
+ }
+ else if (have_fastchunks(av)) {
+ clear_fastchunks(av);
+
+ unsorted_bin = unsorted_chunks(av);
+
+ /*
+ Remove each chunk from fast bin and consolidate it, placing it
+ then in unsorted bin. Among other reasons for doing this,
+ placing in unsorted bin avoids needing to calculate actual bins
+ until malloc is sure that chunks aren't immediately going to be
+ reused anyway.
+ */
+
+ maxfb = &(av->fastbins[fastbin_index(av->max_fast)]);
+ fb = &(av->fastbins[0]);
+ do {
+ if ( (p = *fb) != 0) {
+ *fb = 0;
+
+ do {
+ check_inuse_chunk(p);
+ nextp = p->fd;
+
+ /* Slightly streamlined version of consolidation code in free() */
+ size = p->size & ~PREV_INUSE;
+ nextchunk = chunk_at_offset(p, size);
+
+ if (!prev_inuse(p)) {
+ prevsize = p->prev_size;
+ size += prevsize;
+ p = chunk_at_offset(p, -((long) prevsize));
+ unlink(p, bck, fwd);
+ }
+
+ nextsize = chunksize(nextchunk);
+
+ if (nextchunk != av->top) {
+
+ nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
+ set_head(nextchunk, nextsize);
+
+ if (!nextinuse) {
+ size += nextsize;
+ unlink(nextchunk, bck, fwd);
+ }
+
+ first_unsorted = unsorted_bin->fd;
+ unsorted_bin->fd = p;
+ first_unsorted->bk = p;
+
+ set_head(p, size | PREV_INUSE);
+ p->bk = unsorted_bin;
+ p->fd = first_unsorted;
+ set_foot(p, size);
+ }
+
+ else {
+ size += nextsize;
+ set_head(p, size | PREV_INUSE);
+ av->top = p;
+ }
+
+ } while ( (p = nextp) != 0);
+
+ }
+ } while (fb++ != maxfb);
+ }
+}
+
+
+
+
+/*
+ Realloc algorithm cases:
+
+ * Chunks that were obtained via mmap cannot be extended or shrunk
+ unless HAVE_MREMAP is defined, in which case mremap is used.
+ Otherwise, if the reallocation is for additional space, they are
+ copied. If for less, they are just left alone.
+
+ * Otherwise, if the reallocation is for additional space, and the
+ chunk can be extended, it is, else a malloc-copy-free sequence is
+ taken. There are several different ways that a chunk could be
+ extended. All are tried:
+
+ * Extending forward into following adjacent free chunk.
+ * Shifting backwards, joining preceding adjacent space
+ * Both shifting backwards and extending forward.
+ * Extending into newly sbrked space
+
+ * If there is not enough memory available to realloc, realloc
+ returns null, but does NOT free the existing space.
+
+ * If the reallocation is for less space, the newly unused space is
+ lopped off and freed. Unless the #define REALLOC_ZERO_BYTES_FREES
+ is set, realloc with a size argument of zero (re)allocates a
+ minimum-sized chunk.
+
+
+ The old unix realloc convention of allowing the last-free'd chunk
+ to be used as an argument to realloc is no longer supported.
+ I don't know of any programs still relying on this feature,
+ and allowing it would also allow too many other incorrect
+ usages of realloc to be sensible.
+*/
+
+#if __STD_C
+Void_t* rEALLOc(Void_t* oldmem, size_t bytes)
+#else
+Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
+#endif
+{
+ mstate av = get_malloc_state();
+
+ INTERNAL_SIZE_T nb; /* padded request size */
+
+ mchunkptr oldp; /* chunk corresponding to oldmem */
+ INTERNAL_SIZE_T oldsize; /* its size */
+
+ mchunkptr newp; /* chunk to return */
+ INTERNAL_SIZE_T newsize; /* its size */
+ Void_t* newmem; /* corresponding user mem */
+
+ mchunkptr next; /* next contiguous chunk after oldp */
+ mchunkptr prev; /* previous contiguous chunk before oldp */
+
+ mchunkptr remainder; /* extra space at end of newp */
+ long remainder_size; /* its size */
+
+ mchunkptr bck; /* misc temp for linking */
+ mchunkptr fwd; /* misc temp for linking */
+
+ INTERNAL_SIZE_T copysize; /* bytes to copy */
+ int ncopies; /* INTERNAL_SIZE_T words to copy */
+ INTERNAL_SIZE_T* s; /* copy source */
+ INTERNAL_SIZE_T* d; /* copy destination */
+
+
+#ifdef REALLOC_ZERO_BYTES_FREES
+ if (bytes == 0) {
+ fREe(oldmem);
+ return 0;
+ }
+#endif
+
+ /* realloc of null is supposed to be same as malloc */
+ if (oldmem == 0) return mALLOc(bytes);
+
+ checked_request2size(bytes, nb);
+
+ oldp = mem2chunk(oldmem);
+ oldsize = chunksize(oldp);
+
+ check_inuse_chunk(oldp);
+
+ if (!chunk_is_mmapped(oldp)) {
+
+ if ((unsigned long)(oldsize) >= (unsigned long)(nb)) {
+ /* already big enough; split below */
+ newp = oldp;
+ newsize = oldsize;
+ }
+
+ else {
+ newp = 0;
+ newsize = 0;
+
+ next = chunk_at_offset(oldp, oldsize);
+
+ if (next == av->top) { /* Expand forward into top */
+ newsize = oldsize + chunksize(next);
+
+ if ((unsigned long)(newsize) >= (unsigned long)(nb + MINSIZE)) {
+ set_head_size(oldp, nb);
+ av->top = chunk_at_offset(oldp, nb);
+ set_head(av->top, (newsize - nb) | PREV_INUSE);
+ return chunk2mem(oldp);
+ }
+
+ else if (!prev_inuse(oldp)) { /* Shift backwards + top */
+ prev = prev_chunk(oldp);
+ newsize += chunksize(prev);
+
+ if ((unsigned long)(newsize) >= (unsigned long)(nb + MINSIZE)) {
+ newp = prev;
+ unlink(prev, bck, fwd);
+ av->top = chunk_at_offset(newp, nb);
+ set_head(av->top, (newsize - nb) | PREV_INUSE);
+ newsize = nb;
+ }
+ }
+ }
+
+ else if (!inuse(next)) { /* Forward into next chunk */
+ newsize = oldsize + chunksize(next);
+
+ if (((unsigned long)(newsize) >= (unsigned long)(nb))) {
+ newp = oldp;
+ unlink(next, bck, fwd);
+ }
+
+ else if (!prev_inuse(oldp)) { /* Forward + backward */
+ prev = prev_chunk(oldp);
+ newsize += chunksize(prev);
+
+ if (((unsigned long)(newsize) >= (unsigned long)(nb))) {
+ newp = prev;
+ unlink(prev, bck, fwd);
+ unlink(next, bck, fwd);
+ }
+ }
+ }
+
+ else if (!prev_inuse(oldp)) { /* Backward only */
+ prev = prev_chunk(oldp);
+ newsize = oldsize + chunksize(prev);
+
+ if ((unsigned long)(newsize) >= (unsigned long)(nb)) {
+ newp = prev;
+ unlink(prev, bck, fwd);
+ }
+ }
+
+ if (newp != 0) {
+ if (newp != oldp) {
+ /* Backward copies are not worth unrolling */
+ MALLOC_COPY(chunk2mem(newp), oldmem, oldsize - SIZE_SZ, 1);
+ }
+ }
+
+ /* Must allocate */
+ else {
+ newmem = mALLOc(nb - MALLOC_ALIGN_MASK);
+ if (newmem == 0)
+ return 0; /* propagate failure */
+
+ newp = mem2chunk(newmem);
+ newsize = chunksize(newp);
+
+ /*
+ Avoid copy if newp is next chunk after oldp.
+ */
+ if (newp == next) {
+ newsize += oldsize;
+ newp = oldp;
+ }
+ else {
+
+ /*
+ Unroll copy of <= 36 bytes (72 if 8byte sizes)
+ We know that contents have an odd number of
+ INTERNAL_SIZE_T-sized words; minimally 3.
+ */
+
+ copysize = oldsize - SIZE_SZ;
+ s = (INTERNAL_SIZE_T*)oldmem;
+ d = (INTERNAL_SIZE_T*)(chunk2mem(newp));
+ ncopies = copysize / sizeof(INTERNAL_SIZE_T);
+ assert(ncopies >= 3);
+
+ if (ncopies > 9)
+ MALLOC_COPY(d, s, copysize, 0);
+
+ else {
+ *(d+0) = *(s+0);
+ *(d+1) = *(s+1);
+ *(d+2) = *(s+2);
+ if (ncopies > 4) {
+ *(d+3) = *(s+3);
+ *(d+4) = *(s+4);
+ if (ncopies > 6) {
+ *(d+5) = *(s+5);
+ *(d+6) = *(s+6);
+ if (ncopies > 8) {
+ *(d+7) = *(s+7);
+ *(d+8) = *(s+8);
+ }
+ }
+ }
+ }
+
+ fREe(oldmem);
+ check_inuse_chunk(newp);
+ return chunk2mem(newp);
+ }
+ }
+ }
+
+
+ /* If possible, free extra space in old or extended chunk */
+
+ remainder_size = (long)newsize - (long)nb;
+ assert(remainder_size >= 0);
+
+ if (remainder_size >= (long)MINSIZE) { /* split remainder */
+ remainder = chunk_at_offset(newp, nb);
+ set_head_size(newp, nb);
+ set_head(remainder, remainder_size | PREV_INUSE);
+ /* Mark remainder as inuse so free() won't complain */
+ set_inuse_bit_at_offset(remainder, remainder_size);
+ fREe(chunk2mem(remainder));
+ }
+
+ else { /* not enough extra to split off */
+ set_head_size(newp, newsize);
+ set_inuse_bit_at_offset(newp, newsize);
+ }
+
+ check_inuse_chunk(newp);
+ return chunk2mem(newp);
+ }
+
+ /*
+ Handle mmap cases
+ */
+
+ else {
+#if HAVE_MMAP
+
+#if HAVE_MREMAP
+ INTERNAL_SIZE_T offset = oldp->prev_size;
+ size_t pagemask = av->pagesize - 1;
+ char *cp;
+ unsigned long sum;
+
+ /* Note the extra SIZE_SZ overhead */
+ newsize = (nb + offset + SIZE_SZ + pagemask) & ~pagemask;
+
+ /* don't need to remap if still within same page */
+ if (oldsize == newsize - offset)
+ return oldmem;
+
+ cp = (char*)mremap((char*)oldp - offset, oldsize + offset, newsize, 1);
+
+ if (cp != (char*)MORECORE_FAILURE) {
+
+ newp = (mchunkptr)(cp + offset);
+ set_head(newp, (newsize - offset)|IS_MMAPPED);
+
+ assert(aligned_OK(chunk2mem(newp)));
+ assert((newp->prev_size == offset));
+
+ /* update statistics */
+ sum = av->mmapped_mem += newsize - oldsize;
+ if (sum > (unsigned long)(av->max_mmapped_mem))
+ av->max_mmapped_mem = sum;
+ sum += av->sbrked_mem;
+ if (sum > (unsigned long)(av->max_total_mem))
+ av->max_total_mem = sum;
+
+ return chunk2mem(newp);
+ }
+
+#endif
+
+ /* Note the extra SIZE_SZ overhead. */
+ if ((long)oldsize - (long)SIZE_SZ >= (long)nb)
+ newmem = oldmem; /* do nothing */
+ else {
+ /* Must alloc, copy, free. */
+ newmem = mALLOc(nb - MALLOC_ALIGN_MASK);
+ if (newmem != 0) {
+ MALLOC_COPY(newmem, oldmem, oldsize - 2*SIZE_SZ, 0);
+ fREe(oldmem);
+ }
+ }
+ return newmem;
+
+#else
+ /* If !HAVE_MMAP, but chunk_is_mmapped, user must have overwritten mem */
+ check_malloc_state();
+ MALLOC_FAILURE_ACTION;
+ return 0;
+#endif
+ }
+
+}
+
+
+
+/*
+ memalign requests more than enough space from malloc, finds a spot
+ within that chunk that meets the alignment request, and then
+ possibly frees the leading and trailing space.
+
+ Alignments must be powers of two. If the argument is not a
+ power of two, the nearest greater power is used.
+
+ 8-byte alignment is guaranteed by normal malloc calls, so don't
+ bother calling memalign with an argument of 8 or less.
+
+ Overreliance on memalign is a sure way to fragment space.
+*/
+
+
+#if __STD_C
+Void_t* mEMALIGn(size_t alignment, size_t bytes)
+#else
+Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes;
+#endif
+{
+ INTERNAL_SIZE_T nb; /* padded request size */
+ char* m; /* memory returned by malloc call */
+ mchunkptr p; /* corresponding chunk */
+ char* brk; /* alignment point within p */
+ mchunkptr newp; /* chunk to return */
+ INTERNAL_SIZE_T newsize; /* its size */
+ INTERNAL_SIZE_T leadsize; /* leading space befor alignment point */
+ mchunkptr remainder; /* spare room at end to split off */
+ long remainder_size; /* its size */
+
+
+ /* If need less alignment than we give anyway, just relay to malloc */
+
+ if (alignment <= MALLOC_ALIGNMENT) return mALLOc(bytes);
+
+ /* Otherwise, ensure that it is at least a minimum chunk size */
+
+ if (alignment < MINSIZE) alignment = MINSIZE;
+
+ /* Make sure alignment is power of 2 (in case MINSIZE is not). */
+ if ((alignment & (alignment - 1)) != 0) {
+ size_t a = MALLOC_ALIGNMENT * 2;
+ while ((unsigned long)a < (unsigned long)alignment) a <<= 1;
+ alignment = a;
+ }
+
+ checked_request2size(bytes, nb);
+
+ /* Call malloc with worst case padding to hit alignment. */
+
+ m = (char*)(mALLOc(nb + alignment + MINSIZE));
+
+ if (m == 0) return 0; /* propagate failure */
+
+ p = mem2chunk(m);
+
+ if ((((unsigned long)(m)) % alignment) != 0) { /* misaligned */
+
+ /*
+ Find an aligned spot inside chunk. Since we need to give back
+ leading space in a chunk of at least MINSIZE, if the first
+ calculation places us at a spot with less than MINSIZE leader,
+ we can move to the next aligned spot -- we've allocated enough
+ total room so that this is always possible.
+ */
+
+ brk = (char*)mem2chunk(((unsigned long)(m + alignment - 1)) &
+ -((signed long) alignment));
+ if ((long)(brk - (char*)(p)) < (long)MINSIZE)
+ brk = brk + alignment;
+
+ newp = (mchunkptr)brk;
+ leadsize = brk - (char*)(p);
+ newsize = chunksize(p) - leadsize;
+
+ /* For mmapped chunks, just adjust offset */
+ if (chunk_is_mmapped(p)) {
+ newp->prev_size = p->prev_size + leadsize;
+ set_head(newp, newsize|IS_MMAPPED);
+ return chunk2mem(newp);
+ }
+
+ /* Otherwise, give back leader, use the rest */
+
+ set_head(newp, newsize | PREV_INUSE);
+ set_inuse_bit_at_offset(newp, newsize);
+ set_head_size(p, leadsize);
+ fREe(chunk2mem(p));
+ p = newp;
+
+ assert (newsize >= nb &&
+ (((unsigned long)(chunk2mem(p))) % alignment) == 0);
+ }
+
+ /* Also give back spare room at the end */
+ if (!chunk_is_mmapped(p)) {
+
+ remainder_size = (long)(chunksize(p)) - (long)nb;
+
+ if (remainder_size >= (long)MINSIZE) {
+ remainder = chunk_at_offset(p, nb);
+ set_head(remainder, remainder_size | PREV_INUSE);
+ set_head_size(p, nb);
+ fREe(chunk2mem(remainder));
+ }
+ }
+
+ check_inuse_chunk(p);
+ return chunk2mem(p);
+
+}
+
+
+
+
+/*
+ calloc calls malloc, then zeroes out the allocated chunk.
+*/
+
+#if __STD_C
+Void_t* cALLOc(size_t n_elements, size_t elem_size)
+#else
+Void_t* cALLOc(n_elements, elem_size) size_t n_elements; size_t elem_size;
+#endif
+{
+ mchunkptr p;
+ INTERNAL_SIZE_T clearsize;
+ int nclears;
+ INTERNAL_SIZE_T* d;
+
+ Void_t* mem = mALLOc(n_elements * elem_size);
+
+ if (mem != 0) {
+ p = mem2chunk(mem);
+ if (!chunk_is_mmapped(p)) { /* don't need to clear mmapped space */
+
+ /*
+ Unroll clear of <= 36 bytes (72 if 8byte sizes)
+ We know that contents have an odd number of
+ INTERNAL_SIZE_T-sized words; minimally 3.
+ */
+
+ d = (INTERNAL_SIZE_T*)mem;
+ clearsize = chunksize(p) - SIZE_SZ;
+ nclears = clearsize / sizeof(INTERNAL_SIZE_T);
+ assert(nclears >= 3);
+
+ if (nclears > 9)
+ MALLOC_ZERO(d, clearsize);
+
+ else {
+ *(d+0) = 0;
+ *(d+1) = 0;
+ *(d+2) = 0;
+ if (nclears > 4) {
+ *(d+3) = 0;
+ *(d+4) = 0;
+ if (nclears > 6) {
+ *(d+5) = 0;
+ *(d+6) = 0;
+ if (nclears > 8) {
+ *(d+7) = 0;
+ *(d+8) = 0;
+ }
+ }
+ }
+ }
+ }
+ }
+ return mem;
+}
+
+
+/*
+ cfree just calls free. It is needed/defined on some systems
+ that pair it with calloc, presumably for odd historical reasons
+ (such as: cfree is used in example code in first edition of K&R).
+*/
+
+#if __STD_C
+void cFREe(Void_t *mem)
+#else
+void cFREe(mem) Void_t *mem;
+#endif
+{
+ fREe(mem);
+}
+
+
+
+
+
+/*
+ valloc just invokes memalign with alignment argument equal
+ to the page size of the system (or as near to this as can
+ be figured out from all the includes/defines above.)
+*/
+
+#if __STD_C
+Void_t* vALLOc(size_t bytes)
+#else
+Void_t* vALLOc(bytes) size_t bytes;
+#endif
+{
+ /* Ensure initialization/consolidation */
+ mstate av = get_malloc_state();
+ malloc_consolidate(av);
+ return mEMALIGn(av->pagesize, bytes);
+}
+
+/*
+ pvalloc just invokes valloc for the nearest pagesize
+ that will accommodate request
+*/
+
+
+#if __STD_C
+Void_t* pVALLOc(size_t bytes)
+#else
+Void_t* pVALLOc(bytes) size_t bytes;
+#endif
+{
+ mstate av = get_malloc_state();
+ size_t pagesz;
+
+ /* Ensure initialization/consolidation */
+ malloc_consolidate(av);
+
+ pagesz = av->pagesize;
+ return mEMALIGn(pagesz, (bytes + pagesz - 1) & ~(pagesz - 1));
+}
+
+
+/*
+ Malloc_Trim gives memory back to the system (via negative
+ arguments to sbrk) if there is unused memory at the `high' end of
+ the malloc pool. You can call this after freeing large blocks of
+ memory to potentially reduce the system-level memory requirements
+ of a program. However, it cannot guarantee to reduce memory. Under
+ some allocation patterns, some large free blocks of memory will be
+ locked between two used chunks, so they cannot be given back to
+ the system.
+
+ The `pad' argument to malloc_trim represents the amount of free
+ trailing space to leave untrimmed. If this argument is zero,
+ only the minimum amount of memory to maintain internal data
+ structures will be left (one page or less). Non-zero arguments
+ can be supplied to maintain enough trailing space to service
+ future expected allocations without having to re-obtain memory
+ from the system.
+
+ Malloc_trim returns 1 if it actually released any memory, else 0.
+*/
+
+#if __STD_C
+int mTRIm(size_t pad)
+#else
+int mTRIm(pad) size_t pad;
+#endif
+{
+ mstate av = get_malloc_state();
+ /* Ensure initialization/consolidation */
+ malloc_consolidate(av);
+
+ return sYSTRIm(pad, av);
+}
+
+/*
+ malloc_usable_size tells you how many bytes you can actually use in
+ an allocated chunk, which may be more than you requested (although
+ often not). You can use this many bytes without worrying about
+ overwriting other allocated objects. Not a particularly great
+ programming practice, but still sometimes useful.
+*/
+
+#if __STD_C
+size_t mUSABLe(Void_t* mem)
+#else
+size_t mUSABLe(mem) Void_t* mem;
+#endif
+{
+ mchunkptr p;
+ if (mem != 0) {
+ p = mem2chunk(mem);
+ if (chunk_is_mmapped(p))
+ return chunksize(p) - 2*SIZE_SZ;
+ else if (inuse(p))
+ return chunksize(p) - SIZE_SZ;
+ }
+ return 0;
+}
+
+
+
+
+/*
+ mallinfo returns a copy of updated current mallinfo.
+*/
+
+struct mallinfo mALLINFo()
+{
+ mstate av = get_malloc_state();
+ struct mallinfo mi;
+ int i;
+ mbinptr b;
+ mchunkptr p;
+ INTERNAL_SIZE_T avail;
+ int navail;
+ int nfastblocks;
+ int fastbytes;
+
+ /* Ensure initialization */
+ if (av->top == 0) malloc_consolidate(av);
+
+ check_malloc_state();
+
+ /* Account for top */
+ avail = chunksize(av->top);
+ navail = 1; /* top always exists */
+
+ /* traverse fastbins */
+ nfastblocks = 0;
+ fastbytes = 0;
+
+ for (i = 0; i < NFASTBINS; ++i) {
+ for (p = av->fastbins[i]; p != 0; p = p->fd) {
+ ++nfastblocks;
+ fastbytes += chunksize(p);
+ }
+ }
+
+ avail += fastbytes;
+
+ /* traverse regular bins */
+ for (i = 1; i < NBINS; ++i) {
+ b = bin_at(av, i);
+ for (p = last(b); p != b; p = p->bk) {
+ avail += chunksize(p);
+ navail++;
+ }
+ }
+
+ mi.smblks = nfastblocks;
+ mi.ordblks = navail;
+ mi.fordblks = avail;
+ mi.uordblks = av->sbrked_mem - avail;
+ mi.arena = av->sbrked_mem;
+ mi.hblks = av->n_mmaps;
+ mi.hblkhd = av->mmapped_mem;
+ mi.fsmblks = fastbytes;
+ mi.keepcost = chunksize(av->top);
+ mi.usmblks = av->max_total_mem;
+ return mi;
+}
+
+
+
+/*
+ malloc_stats prints on stderr the amount of space obtained from the
+ system (both via sbrk and mmap), the maximum amount (which may be
+ more than current if malloc_trim and/or munmap got called), and the
+ current number of bytes allocated via malloc (or realloc, etc) but
+ not yet freed. Note that this is the number of bytes allocated, not
+ the number requested. It will be larger than the number requested
+ because of alignment and bookkeeping overhead. Because it includes
+ alignment wastage as being in use, this figure may be greater than zero
+ even when no user-level chunks are allocated.
+
+ The reported current and maximum system memory can be inaccurate if
+ a program makes other calls to system memory allocation functions
+ (normally sbrk) outside of malloc.
+
+ malloc_stats prints only the most commonly interesting statistics.
+ More information can be obtained by calling mallinfo.
+*/
+
+void mSTATs()
+{
+ struct mallinfo mi = mALLINFo();
+
+#ifdef WIN32
+ {
+ unsigned long free, reserved, committed;
+ vminfo (&free, &reserved, &committed);
+ fprintf(stderr, "free bytes = %10lu\n",
+ free);
+ fprintf(stderr, "reserved bytes = %10lu\n",
+ reserved);
+ fprintf(stderr, "committed bytes = %10lu\n",
+ committed);
+ }
+#endif
+
+
+ fprintf(stderr, "max system bytes = %10lu\n",
+ (unsigned long)(mi.usmblks));
+ fprintf(stderr, "system bytes = %10lu\n",
+ (unsigned long)(mi.arena + mi.hblkhd));
+ fprintf(stderr, "in use bytes = %10lu\n",
+ (unsigned long)(mi.uordblks + mi.hblkhd));
+
+#ifdef WIN32
+ {
+ unsigned long kernel, user;
+ if (cpuinfo (TRUE, &kernel, &user)) {
+ fprintf(stderr, "kernel ms = %10lu\n",
+ kernel);
+ fprintf(stderr, "user ms = %10lu\n",
+ user);
+ }
+ }
+#endif
+}
+
+
+
+/*
+ mallopt is the general SVID/XPG interface to tunable parameters.
+ The format is to provide a (parameter-number, parameter-value)
+ pair. mallopt then sets the corresponding parameter to the
+ argument value if it can (i.e., so long as the value is
+ meaningful), and returns 1 if successful else 0. See descriptions
+ of tunable parameters above for meanings.
+*/
+
+#if __STD_C
+int mALLOPt(int param_number, int value)
+#else
+int mALLOPt(param_number, value) int param_number; int value;
+#endif
+{
+ mstate av = get_malloc_state();
+ /* Ensure initialization/consolidation */
+ malloc_consolidate(av);
+
+ switch(param_number) {
+ case M_MXFAST:
+ if (value >= 0 && value <= MAX_FAST_SIZE) {
+ av->max_fast = req2max_fast(value);
+ return 1;
+ }
+ else
+ return 0;
+
+ case M_TRIM_THRESHOLD:
+ av->trim_threshold = value;
+ return 1;
+
+ case M_TOP_PAD:
+ av->top_pad = value;
+ return 1;
+
+ case M_MMAP_THRESHOLD:
+ av->mmap_threshold = value;
+ return 1;
+
+ case M_MMAP_MAX:
+#if HAVE_MMAP
+ av->n_mmaps_max = value;
+ return 1;
+#else
+ if (value != 0)
+ return 0;
+ else {
+ av->n_mmaps_max = value;
+ return 1;
+ }
+#endif
+
+ default:
+ return 0;
+ }
+}
+
+
+/* -------------------------------------------------------------- */
+
+/*
+ Emulation of sbrk for win32.
+ Donated by J. Walter <Walter@GeNeSys-e.de>.
+ For additional information about this code, and malloc on Win32, see
+ http://www.genesys-e.de/jwalter/
+
+*/
+
+
+#ifdef WIN32
+
+#ifdef _DEBUG
+/* #define TRACE */
+#endif
+
+/* Support for USE_MALLOC_LOCK */
+#ifdef USE_MALLOC_LOCK
+
+/* Wait for spin lock */
+static int slwait (int *sl) {
+ while (InterlockedCompareExchange ((void **) sl, (void *) 1, (void *) 0) != 0)
+ Sleep (0);
+ return 0;
+}
+
+/* Release spin lock */
+static int slrelease (int *sl) {
+ InterlockedExchange (sl, 0);
+ return 0;
+}
+
+#ifdef NEEDED
+/* Spin lock for emulation code */
+static int g_sl;
+#endif
+
+#endif /* USE_MALLOC_LOCK */
+
+/* getpagesize for windows */
+static long getpagesize (void) {
+ static long g_pagesize = 0;
+ if (! g_pagesize) {
+ SYSTEM_INFO system_info;
+ GetSystemInfo (&system_info);
+ g_pagesize = system_info.dwPageSize;
+ }
+ return g_pagesize;
+}
+static long getregionsize (void) {
+ static long g_regionsize = 0;
+ if (! g_regionsize) {
+ SYSTEM_INFO system_info;
+ GetSystemInfo (&system_info);
+ g_regionsize = system_info.dwAllocationGranularity;
+ }
+ return g_regionsize;
+}
+
+/* A region list entry */
+typedef struct _region_list_entry {
+ void *top_allocated;
+ void *top_committed;
+ void *top_reserved;
+ long reserve_size;
+ struct _region_list_entry *previous;
+} region_list_entry;
+
+/* Allocate and link a region entry in the region list */
+static int region_list_append (region_list_entry **last, void *base_reserved, long reserve_size) {
+ region_list_entry *next = HeapAlloc (GetProcessHeap (), 0, sizeof (region_list_entry));
+ if (! next)
+ return FALSE;
+ next->top_allocated = (char *) base_reserved;
+ next->top_committed = (char *) base_reserved;
+ next->top_reserved = (char *) base_reserved + reserve_size;
+ next->reserve_size = reserve_size;
+ next->previous = *last;
+ *last = next;
+ return TRUE;
+}
+/* Free and unlink the last region entry from the region list */
+static int region_list_remove (region_list_entry **last) {
+ region_list_entry *previous = (*last)->previous;
+ if (! HeapFree (GetProcessHeap (), sizeof (region_list_entry), *last))
+ return FALSE;
+ *last = previous;
+ return TRUE;
+}
+
+#define CEIL(size,to) (((size)+(to)-1)&~((to)-1))
+#define FLOOR(size,to) ((size)&~((to)-1))
+
+#define SBRK_SCALE 0
+/* #define SBRK_SCALE 1 */
+/* #define SBRK_SCALE 2 */
+/* #define SBRK_SCALE 4 */
+
+/* sbrk for windows */
+static void *sbrk (long size) {
+ static long g_pagesize, g_my_pagesize;
+ static long g_regionsize, g_my_regionsize;
+ static region_list_entry *g_last;
+ void *result = (void *) MORECORE_FAILURE;
+#ifdef TRACE
+ printf ("sbrk %d\n", size);
+#endif
+#if defined (USE_MALLOC_LOCK) && defined (NEEDED)
+ /* Wait for spin lock */
+ slwait (&g_sl);
+#endif
+ /* First time initialization */
+ if (! g_pagesize) {
+ g_pagesize = getpagesize ();
+ g_my_pagesize = g_pagesize << SBRK_SCALE;
+ }
+ if (! g_regionsize) {
+ g_regionsize = getregionsize ();
+ g_my_regionsize = g_regionsize << SBRK_SCALE;
+ }
+ if (! g_last) {
+ if (! region_list_append (&g_last, 0, 0))
+ goto sbrk_exit;
+ }
+ /* Assert invariants */
+ assert (g_last);
+ assert ((char *) g_last->top_reserved - g_last->reserve_size <= (char *) g_last->top_allocated &&
+ g_last->top_allocated <= g_last->top_committed);
+ assert ((char *) g_last->top_reserved - g_last->reserve_size <= (char *) g_last->top_committed &&
+ g_last->top_committed <= g_last->top_reserved &&
+ (unsigned) g_last->top_committed % g_pagesize == 0);
+ assert ((unsigned) g_last->top_reserved % g_regionsize == 0);
+ assert ((unsigned) g_last->reserve_size % g_regionsize == 0);
+ /* Allocation requested? */
+ if (size >= 0) {
+ /* Allocation size is the requested size */
+ long allocate_size = size;
+ /* Compute the size to commit */
+ long to_commit = (char *) g_last->top_allocated + allocate_size - (char *) g_last->top_committed;
+ /* Do we reach the commit limit? */
+ if (to_commit > 0) {
+ /* Round size to commit */
+ long commit_size = CEIL (to_commit, g_my_pagesize);
+ /* Compute the size to reserve */
+ long to_reserve = (char *) g_last->top_committed + commit_size - (char *) g_last->top_reserved;
+ /* Do we reach the reserve limit? */
+ if (to_reserve > 0) {
+ /* Compute the remaining size to commit in the current region */
+ long remaining_commit_size = (char *) g_last->top_reserved - (char *) g_last->top_committed;
+ if (remaining_commit_size > 0) {
+ /* Assert preconditions */
+ assert ((unsigned) g_last->top_committed % g_pagesize == 0);
+ assert (0 < remaining_commit_size && remaining_commit_size % g_pagesize == 0); {
+ /* Commit this */
+ void *base_committed = VirtualAlloc (g_last->top_committed, remaining_commit_size,
+ MEM_COMMIT, PAGE_READWRITE);
+ /* Check returned pointer for consistency */
+ if (base_committed != g_last->top_committed)
+ goto sbrk_exit;
+ /* Assert postconditions */
+ assert ((unsigned) base_committed % g_pagesize == 0);
+#ifdef TRACE
+ printf ("Commit %p %d\n", base_committed, remaining_commit_size);
+#endif
+ /* Adjust the regions commit top */
+ g_last->top_committed = (char *) base_committed + remaining_commit_size;
+ }
+ } {
+ /* Now we are going to search and reserve. */
+ int contiguous = -1;
+ int found = FALSE;
+ MEMORY_BASIC_INFORMATION memory_info;
+ void *base_reserved;
+ long reserve_size;
+ do {
+ /* Assume contiguous memory */
+ contiguous = TRUE;
+ /* Round size to reserve */
+ reserve_size = CEIL (to_reserve, g_my_regionsize);
+ /* Start with the current region's top */
+ memory_info.BaseAddress = g_last->top_reserved;
+ /* Assert preconditions */
+ assert ((unsigned) memory_info.BaseAddress % g_pagesize == 0);
+ assert (0 < reserve_size && reserve_size % g_regionsize == 0);
+ while (VirtualQuery (memory_info.BaseAddress, &memory_info, sizeof (memory_info))) {
+ /* Assert postconditions */
+ assert ((unsigned) memory_info.BaseAddress % g_pagesize == 0);
+#ifdef TRACE
+ printf ("Query %p %d %s\n", memory_info.BaseAddress, memory_info.RegionSize,
+ memory_info.State == MEM_FREE ? "FREE":
+ (memory_info.State == MEM_RESERVE ? "RESERVED":
+ (memory_info.State == MEM_COMMIT ? "COMMITTED": "?")));
+#endif
+ /* Region is free, well aligned and big enough: we are done */
+ if (memory_info.State == MEM_FREE &&
+ (unsigned) memory_info.BaseAddress % g_regionsize == 0 &&
+ memory_info.RegionSize >= (unsigned) reserve_size) {
+ found = TRUE;
+ break;
+ }
+ /* From now on we can't get contiguous memory! */
+ contiguous = FALSE;
+ /* Recompute size to reserve */
+ reserve_size = CEIL (allocate_size, g_my_regionsize);
+ memory_info.BaseAddress = (char *) memory_info.BaseAddress + memory_info.RegionSize;
+ /* Assert preconditions */
+ assert ((unsigned) memory_info.BaseAddress % g_pagesize == 0);
+ assert (0 < reserve_size && reserve_size % g_regionsize == 0);
+ }
+ /* Search failed? */
+ if (! found)
+ goto sbrk_exit;
+ /* Assert preconditions */
+ assert ((unsigned) memory_info.BaseAddress % g_regionsize == 0);
+ assert (0 < reserve_size && reserve_size % g_regionsize == 0);
+ /* Try to reserve this */
+ base_reserved = VirtualAlloc (memory_info.BaseAddress, reserve_size,
+ MEM_RESERVE, PAGE_NOACCESS);
+ if (! base_reserved) {
+ int rc = GetLastError ();
+ if (rc != ERROR_INVALID_ADDRESS)
+ goto sbrk_exit;
+ }
+ /* A null pointer signals (hopefully) a race condition with another thread. */
+ /* In this case, we try again. */
+ } while (! base_reserved);
+ /* Check returned pointer for consistency */
+ if (memory_info.BaseAddress && base_reserved != memory_info.BaseAddress)
+ goto sbrk_exit;
+ /* Assert postconditions */
+ assert ((unsigned) base_reserved % g_regionsize == 0);
+#ifdef TRACE
+ printf ("Reserve %p %d\n", base_reserved, reserve_size);
+#endif
+ /* Did we get contiguous memory? */
+ if (contiguous) {
+ long start_size = (char *) g_last->top_committed - (char *) g_last->top_allocated;
+ /* Adjust allocation size */
+ allocate_size -= start_size;
+ /* Adjust the regions allocation top */
+ g_last->top_allocated = g_last->top_committed;
+ /* Recompute the size to commit */
+ to_commit = (char *) g_last->top_allocated + allocate_size - (char *) g_last->top_committed;
+ /* Round size to commit */
+ commit_size = CEIL (to_commit, g_my_pagesize);
+ }
+ /* Append the new region to the list */
+ if (! region_list_append (&g_last, base_reserved, reserve_size))
+ goto sbrk_exit;
+ /* Didn't we get contiguous memory? */
+ if (! contiguous) {
+ /* Recompute the size to commit */
+ to_commit = (char *) g_last->top_allocated + allocate_size - (char *) g_last->top_committed;
+ /* Round size to commit */
+ commit_size = CEIL (to_commit, g_my_pagesize);
+ }
+ }
+ }
+ /* Assert preconditions */
+ assert ((unsigned) g_last->top_committed % g_pagesize == 0);
+ assert (0 < commit_size && commit_size % g_pagesize == 0); {
+ /* Commit this */
+ void *base_committed = VirtualAlloc (g_last->top_committed, commit_size,
+ MEM_COMMIT, PAGE_READWRITE);
+ /* Check returned pointer for consistency */
+ if (base_committed != g_last->top_committed)
+ goto sbrk_exit;
+ /* Assert postconditions */
+ assert ((unsigned) base_committed % g_pagesize == 0);
+#ifdef TRACE
+ printf ("Commit %p %d\n", base_committed, commit_size);
+#endif
+ /* Adjust the regions commit top */
+ g_last->top_committed = (char *) base_committed + commit_size;
+ }
+ }
+ /* Adjust the regions allocation top */
+ g_last->top_allocated = (char *) g_last->top_allocated + allocate_size;
+ result = (char *) g_last->top_allocated - size;
+ /* Deallocation requested? */
+ } else if (size < 0) {
+ long deallocate_size = - size;
+ /* As long as we have a region to release */
+ while ((char *) g_last->top_allocated - deallocate_size < (char *) g_last->top_reserved - g_last->reserve_size) {
+ /* Get the size to release */
+ long release_size = g_last->reserve_size;
+ /* Get the base address */
+ void *base_reserved = (char *) g_last->top_reserved - release_size;
+ /* Assert preconditions */
+ assert ((unsigned) base_reserved % g_regionsize == 0);
+ assert (0 < release_size && release_size % g_regionsize == 0); {
+ /* Release this */
+ int rc = VirtualFree (base_reserved, 0,
+ MEM_RELEASE);
+ /* Check returned code for consistency */
+ if (! rc)
+ goto sbrk_exit;
+#ifdef TRACE
+ printf ("Release %p %d\n", base_reserved, release_size);
+#endif
+ }
+ /* Adjust deallocation size */
+ deallocate_size -= (char *) g_last->top_allocated - (char *) base_reserved;
+ /* Remove the old region from the list */
+ if (! region_list_remove (&g_last))
+ goto sbrk_exit;
+ } {
+ /* Compute the size to decommit */
+ long to_decommit = (char *) g_last->top_committed - ((char *) g_last->top_allocated - deallocate_size);
+ if (to_decommit >= g_my_pagesize) {
+ /* Compute the size to decommit */
+ long decommit_size = FLOOR (to_decommit, g_my_pagesize);
+ /* Compute the base address */
+ void *base_committed = (char *) g_last->top_committed - decommit_size;
+ /* Assert preconditions */
+ assert ((unsigned) base_committed % g_pagesize == 0);
+ assert (0 < decommit_size && decommit_size % g_pagesize == 0); {
+ /* Decommit this */
+ int rc = VirtualFree ((char *) base_committed, decommit_size,
+ MEM_DECOMMIT);
+ /* Check returned code for consistency */
+ if (! rc)
+ goto sbrk_exit;
+#ifdef TRACE
+ printf ("Decommit %p %d\n", base_committed, decommit_size);
+#endif
+ }
+ /* Adjust deallocation size and regions commit and allocate top */
+ deallocate_size -= (char *) g_last->top_allocated - (char *) base_committed;
+ g_last->top_committed = base_committed;
+ g_last->top_allocated = base_committed;
+ }
+ }
+ /* Adjust regions allocate top */
+ g_last->top_allocated = (char *) g_last->top_allocated - deallocate_size;
+ /* Check for underflow */
+ if ((char *) g_last->top_reserved - g_last->reserve_size > (char *) g_last->top_allocated ||
+ g_last->top_allocated > g_last->top_committed) {
+ /* Adjust regions allocate top */
+ g_last->top_allocated = (char *) g_last->top_reserved - g_last->reserve_size;
+ goto sbrk_exit;
+ }
+ result = g_last->top_allocated;
+ }
+ /* Assert invariants */
+ assert (g_last);
+ assert ((char *) g_last->top_reserved - g_last->reserve_size <= (char *) g_last->top_allocated &&
+ g_last->top_allocated <= g_last->top_committed);
+ assert ((char *) g_last->top_reserved - g_last->reserve_size <= (char *) g_last->top_committed &&
+ g_last->top_committed <= g_last->top_reserved &&
+ (unsigned) g_last->top_committed % g_pagesize == 0);
+ assert ((unsigned) g_last->top_reserved % g_regionsize == 0);
+ assert ((unsigned) g_last->reserve_size % g_regionsize == 0);
+
+sbrk_exit:
+#if defined (USE_MALLOC_LOCK) && defined (NEEDED)
+ /* Release spin lock */
+ slrelease (&g_sl);
+#endif
+ return result;
+}
+
+/* mmap for windows */
+static void *mmap (void *ptr, long size, long prot, long type, long handle, long arg) {
+ static long g_pagesize;
+ static long g_regionsize;
+#ifdef TRACE
+ printf ("mmap %d\n", size);
+#endif
+#if defined (USE_MALLOC_LOCK) && defined (NEEDED)
+ /* Wait for spin lock */
+ slwait (&g_sl);
+#endif
+ /* First time initialization */
+ if (! g_pagesize)
+ g_pagesize = getpagesize ();
+ if (! g_regionsize)
+ g_regionsize = getregionsize ();
+ /* Assert preconditions */
+ assert ((unsigned) ptr % g_regionsize == 0);
+ assert (size % g_pagesize == 0);
+ /* Allocate this */
+ ptr = VirtualAlloc (ptr, size,
+ MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE);
+ if (! ptr) {
+ ptr = (void *) MORECORE_FAILURE;
+ goto mmap_exit;
+ }
+ /* Assert postconditions */
+ assert ((unsigned) ptr % g_regionsize == 0);
+#ifdef TRACE
+ printf ("Commit %p %d\n", ptr, size);
+#endif
+mmap_exit:
+#if defined (USE_MALLOC_LOCK) && defined (NEEDED)
+ /* Release spin lock */
+ slrelease (&g_sl);
+#endif
+ return ptr;
+}
+
+/* munmap for windows */
+static long munmap (void *ptr, long size) {
+ static long g_pagesize;
+ static long g_regionsize;
+ int rc = MUNMAP_FAILURE;
+#ifdef TRACE
+ printf ("munmap %p %d\n", ptr, size);
+#endif
+#if defined (USE_MALLOC_LOCK) && defined (NEEDED)
+ /* Wait for spin lock */
+ slwait (&g_sl);
+#endif
+ /* First time initialization */
+ if (! g_pagesize)
+ g_pagesize = getpagesize ();
+ if (! g_regionsize)
+ g_regionsize = getregionsize ();
+ /* Assert preconditions */
+ assert ((unsigned) ptr % g_regionsize == 0);
+ assert (size % g_pagesize == 0);
+ /* Free this */
+ if (! VirtualFree (ptr, 0,
+ MEM_RELEASE))
+ goto munmap_exit;
+ rc = 0;
+#ifdef TRACE
+ printf ("Release %p %d\n", ptr, size);
+#endif
+munmap_exit:
+#if defined (USE_MALLOC_LOCK) && defined (NEEDED)
+ /* Release spin lock */
+ slrelease (&g_sl);
+#endif
+ return rc;
+}
+
+static void vminfo (unsigned long *free, unsigned long *reserved, unsigned long *committed) {
+ MEMORY_BASIC_INFORMATION memory_info;
+ memory_info.BaseAddress = 0;
+ *free = *reserved = *committed = 0;
+ while (VirtualQuery (memory_info.BaseAddress, &memory_info, sizeof (memory_info))) {
+ switch (memory_info.State) {
+ case MEM_FREE:
+ *free += memory_info.RegionSize;
+ break;
+ case MEM_RESERVE:
+ *reserved += memory_info.RegionSize;
+ break;
+ case MEM_COMMIT:
+ *committed += memory_info.RegionSize;
+ break;
+ }
+ memory_info.BaseAddress = (char *) memory_info.BaseAddress + memory_info.RegionSize;
+ }
+}
+
+static int cpuinfo (int whole, unsigned long *kernel, unsigned long *user) {
+ if (whole) {
+ __int64 creation64, exit64, kernel64, user64;
+ int rc = GetProcessTimes (GetCurrentProcess (),
+ (FILETIME *) &creation64,
+ (FILETIME *) &exit64,
+ (FILETIME *) &kernel64,
+ (FILETIME *) &user64);
+ if (! rc) {
+ *kernel = 0;
+ *user = 0;
+ return FALSE;
+ }
+ *kernel = (unsigned long) (kernel64 / 10000);
+ *user = (unsigned long) (user64 / 10000);
+ return TRUE;
+ } else {
+ __int64 creation64, exit64, kernel64, user64;
+ int rc = GetThreadTimes (GetCurrentThread (),
+ (FILETIME *) &creation64,
+ (FILETIME *) &exit64,
+ (FILETIME *) &kernel64,
+ (FILETIME *) &user64);
+ if (! rc) {
+ *kernel = 0;
+ *user = 0;
+ return FALSE;
+ }
+ *kernel = (unsigned long) (kernel64 / 10000);
+ *user = (unsigned long) (user64 / 10000);
+ return TRUE;
+ }
+}
+
+#endif /* WIN32 */
+
+/*
+
+History:
+
+ V2.7.0
+ * new WIN32 sbrk, mmap, munmap, lock code from <Walter@GeNeSys-e.de>.
+ * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for
+ helping test this.)
+ * memalign: check alignment arg
+ * realloc: use memmove when regions may overlap.
+ * Collect all cases in malloc requiring system memory into sYSMALLOc
+ * Use mmap as backup to sbrk, if available; fold these mmap-related
+ operations into others.
+ * Place all internal state in malloc_state
+ * Introduce fastbins (although similar to 2.5.1)
+ * Many minor tunings and cosmetic improvements
+ * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK
+ * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS
+ Thanks to Tony E. Bennett <tbennett@nvidia.com> and others.
+ * Adjust request2size to fit with MALLOC_FAILURE_ACTION.
+ * Include errno.h to support default failure action.
+ * Further improve WIN32 'sbrk()' emulation's 'findRegion()' routine
+ to avoid infinite loop when allocating initial memory larger
+ than RESERVED_SIZE and/or subsequent memory larger than
+ NEXT_SIZE. Thanks to Andreas Mueller <a.mueller at paradatec.de>
+ for finding this one.
+
+ V2.6.6 Sun Dec 5 07:42:19 1999 Doug Lea (dl at gee)
+ * return null for negative arguments
+ * Added Several WIN32 cleanups from Martin C. Fong <mcfong at yahoo.com>
+ * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h'
+ (e.g. WIN32 platforms)
+ * Cleanup header file inclusion for WIN32 platforms
+ * Cleanup code to avoid Microsoft Visual C++ compiler complaints
+ * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
+ memory allocation routines
+ * Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
+ * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
+ usage of 'assert' in non-WIN32 code
+ * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
+ avoid infinite loop
+ * Always call 'fREe()' rather than 'free()'
+
+ V2.6.5 Wed Jun 17 15:57:31 1998 Doug Lea (dl at gee)
+ * Fixed ordering problem with boundary-stamping
+
+ V2.6.3 Sun May 19 08:17:58 1996 Doug Lea (dl at gee)
+ * Added pvalloc, as recommended by H.J. Liu
+ * Added 64bit pointer support mainly from Wolfram Gloger
+ * Added anonymously donated WIN32 sbrk emulation
+ * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
+ * malloc_extend_top: fix mask error that caused wastage after
+ foreign sbrks
+ * Add linux mremap support code from HJ Liu
+
+ V2.6.2 Tue Dec 5 06:52:55 1995 Doug Lea (dl at gee)
+ * Integrated most documentation with the code.
+ * Add support for mmap, with help from
+ Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
+ * Use last_remainder in more cases.
+ * Pack bins using idea from colin@nyx10.cs.du.edu
+ * Use ordered bins instead of best-fit threshhold
+ * Eliminate block-local decls to simplify tracing and debugging.
+ * Support another case of realloc via move into top
+ * Fix error occuring when initial sbrk_base not word-aligned.
+ * Rely on page size for units instead of SBRK_UNIT to
+ avoid surprises about sbrk alignment conventions.
+ * Add mallinfo, mallopt. Thanks to Raymond Nijssen
+ (raymond@es.ele.tue.nl) for the suggestion.
+ * Add `pad' argument to malloc_trim and top_pad mallopt parameter.
+ * More precautions for cases where other routines call sbrk,
+ courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
+ * Added macros etc., allowing use in linux libc from
+ H.J. Lu (hjl@gnu.ai.mit.edu)
+ * Inverted this history list
+
+ V2.6.1 Sat Dec 2 14:10:57 1995 Doug Lea (dl at gee)
+ * Re-tuned and fixed to behave more nicely with V2.6.0 changes.
+ * Removed all preallocation code since under current scheme
+ the work required to undo bad preallocations exceeds
+ the work saved in good cases for most test programs.
+ * No longer use return list or unconsolidated bins since
+ no scheme using them consistently outperforms those that don't
+ given above changes.
+ * Use best fit for very large chunks to prevent some worst-cases.
+ * Added some support for debugging
+
+ V2.6.0 Sat Nov 4 07:05:23 1995 Doug Lea (dl at gee)
+ * Removed footers when chunks are in use. Thanks to
+ Paul Wilson (wilson@cs.texas.edu) for the suggestion.
+
+ V2.5.4 Wed Nov 1 07:54:51 1995 Doug Lea (dl at gee)
+ * Added malloc_trim, with help from Wolfram Gloger
+ (wmglo@Dent.MED.Uni-Muenchen.DE).
+
+ V2.5.3 Tue Apr 26 10:16:01 1994 Doug Lea (dl at g)
+
+ V2.5.2 Tue Apr 5 16:20:40 1994 Doug Lea (dl at g)
+ * realloc: try to expand in both directions
+ * malloc: swap order of clean-bin strategy;
+ * realloc: only conditionally expand backwards
+ * Try not to scavenge used bins
+ * Use bin counts as a guide to preallocation
+ * Occasionally bin return list chunks in first scan
+ * Add a few optimizations from colin@nyx10.cs.du.edu
+
+ V2.5.1 Sat Aug 14 15:40:43 1993 Doug Lea (dl at g)
+ * faster bin computation & slightly different binning
+ * merged all consolidations to one part of malloc proper
+ (eliminating old malloc_find_space & malloc_clean_bin)
+ * Scan 2 returns chunks (not just 1)
+ * Propagate failure in realloc if malloc returns 0
+ * Add stuff to allow compilation on non-ANSI compilers
+ from kpv@research.att.com
+
+ V2.5 Sat Aug 7 07:41:59 1993 Doug Lea (dl at g.oswego.edu)
+ * removed potential for odd address access in prev_chunk
+ * removed dependency on getpagesize.h
+ * misc cosmetics and a bit more internal documentation
+ * anticosmetics: mangled names in macros to evade debugger strangeness
+ * tested on sparc, hp-700, dec-mips, rs6000
+ with gcc & native cc (hp, dec only) allowing
+ Detlefs & Zorn comparison study (in SIGPLAN Notices.)
+
+ Trial version Fri Aug 28 13:14:29 1992 Doug Lea (dl at g.oswego.edu)
+ * Based loosely on libg++-1.2X malloc. (It retains some of the overall
+ structure of old version, but most details differ.)
+
+*/
+
+
diff --git a/src/libs/xpcom18a4/xpcom/build/nsOS2VACLegacy.cpp b/src/libs/xpcom18a4/xpcom/build/nsOS2VACLegacy.cpp
new file mode 100644
index 00000000..c9c04b30
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/nsOS2VACLegacy.cpp
@@ -0,0 +1,753 @@
+/* -*- 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 the Mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * innotek GmbH.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * innotek GmbH / Knut St. Osmundsen
+ *
+ * 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 ***** */
+
+/*
+ * This module contains wrappers for a handful of XPCOM methods which someone
+ * have been so kind as to link their plugins against. This module will only
+ * provide the minimum of what necessary to make legacy plugins work with
+ * the GCC based mozilla. Luckily this only means the IBM oji JAVA plugins.
+ *
+ * Actually, I haven't seen npoji6 calling any of these yet.
+ */
+
+/*******************************************************************************
+* Defined Constants And Macros *
+*******************************************************************************/
+/** @group Visual Age for C++ v3.6.5 target (OS/2). */
+/* @{ */
+/** Indicate Visual Age for C++ v3.6.5 target */
+#define VFT_VAC365 1
+/** VFTable/Interface Calling Convention for Win32. */
+#define VFTCALL _Optlink
+/** First Entry which VAC uses. */
+#define VFTFIRST_DECL unsigned uFirst[2]
+#define VFTFIRST_VAL() {0, 0},
+/** This deltas which VAC uses. */
+#define VFTDELTA_DECL(n) unsigned uDelta##n
+#define VFTDELTA_VAL() 0,
+/** @} */
+
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include "nscore.h"
+#include "nsIServiceManagerUtils.h"
+
+
+/*******************************************************************************
+* Structures and Typedefs *
+*******************************************************************************/
+#ifndef __cplusplus
+typedef struct nsID
+{
+ PRUint32 m0;
+ PRUint16 m1;
+ PRUint16 m2;
+ PRUint8 m3[8];
+} nsID, nsCID, nsIID;
+#define REFNSIID const nsIID *
+
+typedef PRUint32 nsrefcnt;
+#endif
+
+
+/**
+ * nsISupports vftable.
+ */
+typedef struct vftable_nsISupports
+{
+ VFTFIRST_DECL;
+ nsresult (*VFTCALL QueryInterface)(void *pvThis, REFNSIID aIID, void** aInstancePtr);
+ VFTDELTA_DECL(QueryInterface);
+ nsrefcnt (*VFTCALL AddRef)(void *pvThis);
+ VFTDELTA_DECL(AddRef);
+ nsrefcnt (*VFTCALL Release)(void *pvThis);
+ VFTDELTA_DECL(Release);
+} VFTnsISupports;
+
+/**
+ * nsGetServiceByCID::nsCOMPtr_helper vftable.
+ */
+typedef struct vftable_nsGetServiceByCID_nsCOMPtr_helper
+{
+ VFTFIRST_DECL;
+ /* virtual nsresult operator()( const nsIID&, void** ) const; */
+ nsresult (*VFTCALL __operator_paratheses)(void *pvThis, REFNSIID aIID, void** aInstancePtr);
+ VFTDELTA_DECL(__operator_paratheses);
+ void * (*VFTCALL __destructor)(void *pvThis, unsigned __dtorFlags, unsigned __vtt);
+ VFTDELTA_DECL(__destructor);
+} VFTnsGetServiceByCID_nsCOMPtr_helper;
+
+/**
+ * nsQueryInterface::nsCOMPtr_helper vftable.
+ */
+typedef struct vftable_nsQueryInterface_nsCOMPtr_helper
+{
+ VFTFIRST_DECL;
+ nsresult (*VFTCALL __operator_paratheses)(void *pvThis, REFNSIID aIID, void** aInstancePtr);
+ VFTDELTA_DECL(__operator_paratheses);
+} VFTnsQueryInterface_nsCOMPtr_helper;
+
+
+
+
+/**
+ * nsISupport object.
+ */
+typedef struct obj_nsISupports
+{
+ VFTnsISupports *pVFT;
+} obj_nsISupports;
+
+/**
+ * nsCOMPtr_base object.
+ */
+typedef struct obj_nsCOMPtr_base
+{
+ obj_nsISupports *mRawPtr;
+} obj_nsCOMPtr_base;
+
+/**
+ * nsGetServiceByCID_nsCOMPtr_helper object.
+ */
+typedef struct obj_nsGetServiceByCID_nsCOMPtr_helper
+{
+ VFTnsGetServiceByCID_nsCOMPtr_helper *pVFT; /* ?? */
+ nsID *mCID; /* const nsCID& */
+ void *mServiceManager;/* nsCOMPtr<nsIServiceManager> */
+ nsresult *mErrorPtr;
+} obj_nsGetServiceByCID_nsCOMPtr_helper;
+
+/**
+ * nsQueryInterface_nsCOMPtr_helper object.
+ */
+typedef struct obj_nsQueryInterface_nsCOMPtr_helper
+{
+ VFTnsQueryInterface_nsCOMPtr_helper *pVFT; /* ?? */
+ obj_nsISupports *mRawPtr; /* const nsCID& */
+ nsresult *mErrorPtr;
+} obj_nsQueryInterface_nsCOMPtr_helper;
+
+
+
+
+/**
+ * nsCOMPtr_base::~nsCOMPtr_base()
+ *
+ * @remark This guys doing the oji plugin have been very unfortunate to link in this
+ * without any similar new operator. The object is thus created in the plugin
+ * but freed by xpcom.dll. As the plugin and mozilla have different CRTs this
+ * is a good way of asking for trouble. But, they guys've been lucky, the VAC
+ * CRT might just handle this ok.
+ * However, we cannot perform this delete as we have no VAC CRT around, and
+ * hence we will leak this object.
+ * ----
+ * assembly:
+ public __dt__13nsCOMPtr_baseFv
+__dt__13nsCOMPtr_baseFv proc
+ push ebp
+ mov ebp,esp
+ sub esp,08h
+ mov [ebp+08h],eax; this
+ mov [ebp+0ch],edx; __dtorFlags
+
+; 63 if ( mRawPtr )
+ mov eax,[ebp+08h]; this
+ cmp dword ptr [eax],0h
+ je @BLBL4
+
+; 64 NSCAP_RELEASE(this, mRawPtr);
+ mov ecx,[ebp+08h]; this
+ mov ecx,[ecx]
+ mov ecx,[ecx]
+ mov eax,[ebp+08h]; this
+ mov eax,[eax]
+ add eax,[ecx+01ch]
+ mov ecx,[ebp+08h]; this
+ mov ecx,[ecx]
+ mov ecx,[ecx]
+ call dword ptr [ecx+018h]
+@BLBL4:
+
+; 65 }
+ test byte ptr [ebp+0ch],01h; __dtorFlags
+ je @BLBL6
+ mov eax,[ebp+08h]; this
+ call __dl__FPv
+@BLBL6:
+ mov eax,[ebp+08h]; this
+ add esp,08h
+ pop ebp
+ ret
+__dt__13nsCOMPtr_baseFv endp
+*/
+extern "C" void * VFTCALL __dt__13nsCOMPtr_baseFv(void *pvThis, unsigned __dtorFlags)
+{
+ obj_nsCOMPtr_base *pThis = (obj_nsCOMPtr_base*)pvThis;
+//asm("int $3");
+ if (pThis->mRawPtr)
+ {
+ /* NSCAP_RELEASE(this, mRawPtr); */
+ pThis->mRawPtr->pVFT->Release((char*)pThis->mRawPtr + pThis->mRawPtr->pVFT->uDeltaRelease);
+ }
+
+ /*
+ * Delete the object...
+ * (As memtioned before we'll rather leak this.)
+ */
+ #if 0
+ if (!(__dtorFlags & 1))
+ __dl__FPv(this)
+ #endif
+
+ return pvThis;
+}
+
+/** workaround for _Optlink bug.. */
+extern "C" void * VFTCALL _dt__13nsCOMPtr_baseFv(void *pvThis, unsigned __dtorFlags)
+{
+ return __dt__13nsCOMPtr_baseFv(pvThis, __dtorFlags);
+}
+
+
+
+/**
+ *
+ * -----
+ * assembly:
+; 92 nsGetServiceByCID::operator()( const nsIID& aIID, void** aInstancePtr ) const
+ align 010h
+
+ public __cl__17nsGetServiceByCIDCFRC4nsIDPPv
+__cl__17nsGetServiceByCIDCFRC4nsIDPPv proc
+ push ebp
+ mov ebp,esp
+ sub esp,014h
+ push ebx
+ sub esp,08h
+ mov [ebp+08h],eax; this
+ mov [ebp+0ch],edx; aIID
+ mov [ebp+010h],ecx; aInstancePtr
+
+; 94 nsresult status = NS_ERROR_FAILURE;
+ mov dword ptr [ebp-04h],080004005h; status
+
+; 95 if ( mServiceManager ) {
+ mov eax,[ebp+08h]; this
+ add eax,08h
+ call __opP13nsDerivedSafeXT17nsIServiceManager___8nsCOMPtrXT17nsIServiceManager_CFv
+ test eax,eax
+ je @BLBL13
+
+; 96 status = mServiceManager->GetService(mCID, aIID, (void**)aInstancePtr);
+ mov eax,[ebp+08h]; this
+ add eax,08h
+ call __rf__8nsCOMPtrXT17nsIServiceManager_CFv
+ mov [ebp-08h],eax; __212
+ mov eax,[ebp+010h]; aInstancePtr
+ push eax
+ mov ecx,[ebp+0ch]; aIID
+ mov edx,[ebp+08h]; this
+ mov edx,[edx+04h]
+ mov ebx,[ebp-08h]; __212
+ mov ebx,[ebx]
+ mov eax,[ebp-08h]; __212
+ add eax,[ebx+024h]
+ sub esp,0ch
+ mov ebx,[ebp-08h]; __212
+ mov ebx,[ebx]
+ call dword ptr [ebx+020h]
+ add esp,010h
+ mov [ebp-04h],eax; status
+
+; 97 } else {
+ jmp @BLBL14
+ align 010h
+@BLBL13:
+
+; 95 if ( mServiceManager ) {
+
+; 98 nsCOMPtr<nsIServiceManager> mgr;
+ lea eax,[ebp-0ch]; mgr
+ call __ct__8nsCOMPtrXT17nsIServiceManager_Fv
+
+; 99 NS_GetServiceManager(getter_AddRefs(mgr));
+ lea edx,[ebp-0ch]; mgr
+ lea eax,[ebp-010h]; __216
+ call getter_AddRefs__FR8nsCOMPtrXT17nsIServiceManager_
+ sub esp,04h
+ lea eax,[ebp-010h]; __216
+ sub esp,04h
+ call __opPP17nsIServiceManager__15nsGetterAddRefsXT17nsIServiceManager_Fv
+ add esp,08h
+ call NS_GetServiceManager
+ mov edx,02h
+ lea eax,[ebp-010h]; __216
+ call __dt__15nsGetterAddRefsXT17nsIServiceManager_Fv
+
+; 100 if (mgr)
+ lea eax,[ebp-0ch]; mgr
+ call __opP13nsDerivedSafeXT17nsIServiceManager___8nsCOMPtrXT17nsIServiceManager_CFv
+ test eax,eax
+ je @BLBL15
+
+; 101 status = mgr->GetService(mCID, aIID, (void**)aInstancePtr);
+ lea eax,[ebp-0ch]; mgr
+ call __rf__8nsCOMPtrXT17nsIServiceManager_CFv
+ mov [ebp-014h],eax; __217
+ mov eax,[ebp+010h]; aInstancePtr
+ push eax
+ mov ecx,[ebp+0ch]; aIID
+ mov edx,[ebp+08h]; this
+ mov edx,[edx+04h]
+ mov ebx,[ebp-014h]; __217
+ mov ebx,[ebx]
+ mov eax,[ebp-014h]; __217
+ add eax,[ebx+024h]
+ sub esp,0ch
+ mov ebx,[ebp-014h]; __217
+ mov ebx,[ebx]
+ call dword ptr [ebx+020h]
+ add esp,010h
+ mov [ebp-04h],eax; status
+@BLBL15:
+
+; 102 }
+ mov edx,02h
+ lea eax,[ebp-0ch]; mgr
+ call __dt__8nsCOMPtrXT17nsIServiceManager_Fv
+@BLBL14:
+
+; 103 if ( NS_FAILED(status) )
+ test byte ptr [ebp-01h],080h; status
+ je @BLBL16
+
+; 104 *aInstancePtr = 0;
+ mov eax,[ebp+010h]; aInstancePtr
+ mov dword ptr [eax],0h
+@BLBL16:
+
+; 106 if ( mErrorPtr )
+ mov eax,[ebp+08h]; this
+ cmp dword ptr [eax+0ch],0h
+ je @BLBL17
+
+; 107 *mErrorPtr = status;
+ mov eax,[ebp+08h]; this
+ mov eax,[eax+0ch]
+ mov ebx,[ebp-04h]; status
+ mov [eax],ebx
+@BLBL17:
+
+; 108 return status;
+ mov eax,[ebp-04h]; status
+ add esp,08h
+ pop ebx
+ mov esp,ebp
+ pop ebp
+ ret
+__cl__17nsGetServiceByCIDCFRC4nsIDPPv endp
+
+ * -----
+ * C++ Code:
+nsresult
+nsGetServiceByCID::operator()( const nsIID& aIID, void** aInstancePtr ) const
+{
+ nsresult status = NS_ERROR_FAILURE;
+ if ( mServiceManager ) {
+ status = mServiceManager->GetService(mCID, aIID, (void**)aInstancePtr);
+ } else {
+ nsCOMPtr<nsIServiceManager> mgr;
+ NS_GetServiceManager(getter_AddRefs(mgr));
+ if (mgr)
+ status = mgr->GetService(mCID, aIID, (void**)aInstancePtr);
+ }
+ if ( NS_FAILED(status) )
+ *aInstancePtr = 0;
+
+ if ( mErrorPtr )
+ *mErrorPtr = status;
+ return status;
+}
+ */
+extern "C" nsresult VFTCALL GSBC_COM__operator_paratheses(void *pvThis, REFNSIID aIID, void** aInstancePtr)
+{
+ obj_nsGetServiceByCID_nsCOMPtr_helper *pThis = (obj_nsGetServiceByCID_nsCOMPtr_helper *)pvThis;
+ nsresult status = NS_ERROR_FAILURE;
+//asm("int $3");
+
+ /* For convenience we don't use mServiceManager here because it's a wrapped object.
+ * We ASSUME that there is only one service manager floating around....
+ */
+ nsCOMPtr<nsIServiceManager> mgr;
+ NS_GetServiceManager(getter_AddRefs(mgr));
+ if (mgr)
+ status = mgr->GetService(*pThis->mCID, aIID, (void**)aInstancePtr);
+
+ if (NS_FAILED(status))
+ *aInstancePtr = 0;
+
+ if (pThis->mErrorPtr)
+ *pThis->mErrorPtr = status;
+ return status;
+}
+
+/**
+ * Just a destructor.
+ * -----
+ * assembly:
+; 59 virtual ~nsGetServiceByCID() {};
+ align 010h
+
+__dt__17nsGetServiceByCIDFv proc
+ push ebp
+ mov ebp,esp
+ sub esp,08h
+ mov [ebp+08h],eax; this
+ mov [ebp+0ch],edx; __dtorFlags
+ mov [ebp+010h],ecx; __vtt
+ mov eax,[ebp+08h]; this
+ mov dword ptr [eax],offset FLAT:__vft17nsGetServiceByCID15nsCOMPtr_helper
+ mov edx,02h
+ mov eax,[ebp+08h]; this
+ add eax,08h
+ call __dt__8nsCOMPtrXT17nsIServiceManager_Fv
+ test byte ptr [ebp+0ch],01h; __dtorFlags
+ je @BLBL24
+ mov eax,[ebp+08h]; this
+ call __dl__FPv
+@BLBL24:
+ mov eax,[ebp+08h]; this
+ add esp,08h
+ pop ebp
+ ret
+__dt__17nsGetServiceByCIDFv endp
+ */
+extern "C" void * VFTCALL GSBC_COM__destructor(void *pvThis, unsigned __dtorFlags, unsigned __vtt)
+{
+ obj_nsGetServiceByCID_nsCOMPtr_helper *pThis = (obj_nsGetServiceByCID_nsCOMPtr_helper *)pvThis;
+//asm("int $3");
+
+ /*
+ * Because previously mentioned issues with VAC heaps, we'll
+ * not do anything in here.
+ * (We will then skip destruction of all parents and such, but
+ * I don't think that will hurt anyone.)
+ */
+ __dtorFlags = __dtorFlags;
+ __vtt = __vtt;
+ return pThis;
+}
+
+
+/**
+ * VFT for nsGetServiceByCID::nsCOMPtr_helper or something like that.
+ * It's just implementing an operator() and the destructor.
+ *
+ * @remark We need to skip an underscore to get the name right.
+ * ----
+ * assembly:
+__vft17nsGetServiceByCID15nsCOMPtr_helper dd 0
+ db 0h,0h,0h,0h
+ dd offset FLAT:__cl__17nsGetServiceByCIDCFRC4nsIDPPv
+ db 0h,0h,0h,0h
+ dd offset FLAT:__dt__17nsGetServiceByCIDFv
+ db 0h,0h,0h,0h
+ */
+extern const VFTnsGetServiceByCID_nsCOMPtr_helper _vft17nsGetServiceByCID15nsCOMPtr_helper =
+{
+ VFTFIRST_VAL()
+ GSBC_COM__operator_paratheses, VFTDELTA_VAL()
+ GSBC_COM__destructor, VFTDELTA_VAL()
+};
+
+
+
+/**
+ *
+ * -----
+ * assembly
+; 42 nsQueryInterface::operator()( const nsIID& aIID, void** answer ) const
+ align 010h
+
+ public __cl__16nsQueryInterfaceCFRC4nsIDPPv
+__cl__16nsQueryInterfaceCFRC4nsIDPPv proc
+ push ebp
+ mov ebp,esp
+ sub esp,08h
+ push ebx
+ sub esp,0ch
+ mov [ebp+08h],eax; this
+ mov [ebp+0ch],edx; aIID
+ mov [ebp+010h],ecx; answer
+
+; 45 if ( mRawPtr )
+ mov eax,[ebp+08h]; this
+ cmp dword ptr [eax+04h],0h
+ je @BLBL1
+
+; 46 {
+; 47 status = mRawPtr->QueryInterface(aIID, answer);
+ mov ecx,[ebp+010h]; answer
+ mov edx,[ebp+0ch]; aIID
+ mov ebx,[ebp+08h]; this
+ mov ebx,[ebx+04h]
+ mov ebx,[ebx]
+ mov eax,[ebp+08h]; this
+ mov eax,[eax+04h]
+ add eax,[ebx+0ch]
+ mov ebx,[ebp+08h]; this
+ mov ebx,[ebx+04h]
+ mov ebx,[ebx]
+ call dword ptr [ebx+08h]
+ mov [ebp-04h],eax; status
+
+; 48 #ifdef NSCAP_FEATURE_TEST_NONNULL_QUERY_SUCCEEDS
+; 49 NS_WARN_IF_FALSE(NS_SUCCEEDED(status), "interface not found---were you expecting that?");
+; 50 #endif
+; 51 }
+ jmp @BLBL2
+ align 010h
+@BLBL1:
+
+; 45 if ( mRawPtr )
+
+; 53 status = NS_ERROR_NULL_POINTER;
+ mov dword ptr [ebp-04h],080004003h; status
+@BLBL2:
+
+; 55 if ( mErrorPtr )
+ mov eax,[ebp+08h]; this
+ cmp dword ptr [eax+08h],0h
+ je @BLBL3
+
+; 56 *mErrorPtr = status;
+ mov eax,[ebp+08h]; this
+ mov eax,[eax+08h]
+ mov ebx,[ebp-04h]; status
+ mov [eax],ebx
+@BLBL3:
+
+; 57 return status;
+ mov eax,[ebp-04h]; status
+ add esp,0ch
+ pop ebx
+ mov esp,ebp
+ pop ebp
+ ret
+__cl__16nsQueryInterfaceCFRC4nsIDPPv endp
+
+ * -----
+ * C++ Code:
+nsresult
+nsQueryInterface::operator()( const nsIID& aIID, void** answer ) const
+ {
+ nsresult status;
+ if ( mRawPtr )
+ {
+ status = mRawPtr->QueryInterface(aIID, answer);
+#ifdef NSCAP_FEATURE_TEST_NONNULL_QUERY_SUCCEEDS
+ NS_WARN_IF_FALSE(NS_SUCCEEDED(status), "interface not found---were you expecting that?");
+#endif
+ }
+ else
+ status = NS_ERROR_NULL_POINTER;
+
+ if ( mErrorPtr )
+ *mErrorPtr = status;
+ return status;
+ }
+ */
+extern "C" nsresult VFTCALL QI_COM__operator_paratheses(void *pvThis, REFNSIID aIID, void** aInstancePtr)
+{
+ obj_nsQueryInterface_nsCOMPtr_helper *pThis = (obj_nsQueryInterface_nsCOMPtr_helper *)pvThis;
+ nsresult status = NS_ERROR_NULL_POINTER;
+//asm("int $3");
+
+ if (pThis->mRawPtr)
+ {
+ status = pThis->mRawPtr->pVFT->QueryInterface(pThis->mRawPtr, aIID, aInstancePtr);
+ /* don't care about warnings, do we? */
+ }
+
+ if (pThis->mErrorPtr)
+ *pThis->mErrorPtr = status;
+ return status;
+}
+
+
+
+/**
+ * VFT for nsQueryInterface::nsCOMPtr_helper or something like that.
+ * No destructor, only an operator().
+ *
+ * @remark We need to skip an underscore to get the name right.
+ * -----
+ * assembly:
+__vft16nsQueryInterface15nsCOMPtr_helper dd 0
+ db 0h,0h,0h,0h
+ dd offset FLAT:__cl__16nsQueryInterfaceCFRC4nsIDPPv
+ db 0h,0h,0h,0h
+ */
+extern const VFTnsQueryInterface_nsCOMPtr_helper _vft16nsQueryInterface15nsCOMPtr_helper =
+{
+ VFTFIRST_VAL()
+ QI_COM__operator_paratheses, VFTDELTA_VAL()
+};
+
+/**
+ *
+ * -----
+ * C++ Code:
+void
+assign_assuming_AddRef( nsISupports* newPtr )
+{
+ / *
+ |AddRef()|ing the new value (before entering this function) before
+ |Release()|ing the old lets us safely ignore the self-assignment case.
+ We must, however, be careful only to |Release()| _after_ doing the
+ assignment, in case the |Release()| leads to our _own_ destruction,
+ which would, in turn, cause an incorrect second |Release()| of our old
+ pointer. Thank <waterson@netscape.com> for discovering this.
+ * /
+ nsISupports* oldPtr = mRawPtr;
+ mRawPtr = newPtr;
+ NSCAP_LOG_ASSIGNMENT(this, newPtr);
+ NSCAP_LOG_RELEASE(this, oldPtr);
+ if ( oldPtr )
+ NSCAP_RELEASE(this, oldPtr);
+}
+ */
+extern "C" void VFTCALL assign_assuming_AddRef__13nsCOMPtr_baseFP11nsISupports(void *pvThis, obj_nsISupports *newPtr)
+{
+ obj_nsCOMPtr_base *pThis = (obj_nsCOMPtr_base *)pvThis;
+ obj_nsISupports *oldPtr;
+
+ oldPtr = pThis->mRawPtr;
+ pThis->mRawPtr = newPtr;
+ if (oldPtr)
+ {
+ /* NSCAP_RELEASE(this, oldPtr); */
+ pThis->mRawPtr->pVFT->Release(oldPtr + oldPtr->pVFT->uDeltaRelease);
+ }
+}
+
+
+
+
+/**
+ *
+ * -----
+ * Assembly:
+; 77 nsCOMPtr_base::assign_from_helper( const nsCOMPtr_helper& helper, const nsIID& iid )
+ align 010h
+
+ public assign_from_helper__13nsCOMPtr_baseFRC15nsCOMPtr_helperRC4nsID
+assign_from_helper__13nsCOMPtr_baseFRC15nsCOMPtr_helperRC4nsID proc
+ push ebp
+ mov ebp,esp
+ sub esp,08h
+ push ebx
+ sub esp,0ch
+ mov [ebp+08h],eax; this
+ mov [ebp+0ch],edx; helper
+ mov [ebp+010h],ecx; iid
+
+; 80 if ( NS_FAILED( helper(iid, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
+ lea ecx,[ebp-04h]; newRawPtr
+ mov edx,[ebp+010h]; iid
+ mov ebx,[ebp+0ch]; helper
+ mov ebx,[ebx]
+ mov eax,[ebp+0ch]; helper
+ add eax,[ebx+0ch]
+ mov ebx,[ebp+0ch]; helper
+ mov ebx,[ebx]
+ call dword ptr [ebx+08h]
+ test eax,080000000h
+ je @BLBL8
+
+; 81 newRawPtr = 0;
+ mov dword ptr [ebp-04h],0h; newRawPtr
+@BLBL8:
+
+; 82 assign_assuming_AddRef(newRawPtr);
+ mov edx,[ebp-04h]; newRawPtr
+ mov eax,[ebp+08h]; this
+ call assign_assuming_AddRef__13nsCOMPtr_baseFP11nsISupports
+ add esp,0ch
+ pop ebx
+ mov esp,ebp
+ pop ebp
+ ret
+assign_from_helper__13nsCOMPtr_baseFRC15nsCOMPtr_helperRC4nsID endp
+
+ * -----
+ * C Code:
+void
+nsCOMPtr_base::assign_from_helper( const nsCOMPtr_helper& helper, const nsIID& iid )
+ {
+ nsISupports* newRawPtr;
+ if ( NS_FAILED( helper(iid, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
+ newRawPtr = 0;
+ assign_assuming_AddRef(newRawPtr);
+ }
+ */
+extern "C" void VFTCALL assign_from_helper__13nsCOMPtr_baseFRC15nsCOMPtr_helperRC4nsID(
+ void *pvThis, void * helper, REFNSIID iid)
+{
+ obj_nsCOMPtr_base *pThis = (obj_nsCOMPtr_base *)pvThis;
+ obj_nsISupports* newRawPtr = NULL;
+ nsresult status = NS_ERROR_FAILURE;
+//asm("int $3");
+
+ /* this may or may not be correct but the layout is the same. */
+ obj_nsQueryInterface_nsCOMPtr_helper * pHelper = (obj_nsQueryInterface_nsCOMPtr_helper*)helper;
+
+ /* if ( NS_FAILED( helper(iid, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) ) */
+ status = pHelper->pVFT->__operator_paratheses((char*)pHelper + pHelper->pVFT->uDelta__operator_paratheses,
+ iid, (void**)&newRawPtr);
+ if (NS_FAILED(status))
+ newRawPtr = 0;
+
+ /* assign_assuming_AddRef(newRawPtr); */
+ assign_assuming_AddRef__13nsCOMPtr_baseFP11nsISupports(pThis, newRawPtr);
+}
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/build/nsStringAPI.cpp b/src/libs/xpcom18a4/xpcom/build/nsStringAPI.cpp
new file mode 100644
index 00000000..ca9a76e4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/nsStringAPI.cpp
@@ -0,0 +1,261 @@
+/* vim:set ts=2 sw=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "nsString.h"
+#include "nsCharTraits.h"
+
+#define NS_STRINGAPI_IMPL
+#include "nsStringAPI.h"
+#include "nsNativeCharsetUtils.h"
+
+/* ------------------------------------------------------------------------- */
+
+NS_STRINGAPI(nsresult)
+NS_StringContainerInit(nsStringContainer &aContainer)
+{
+ NS_ASSERTION(sizeof(nsStringContainer) >= sizeof(nsString),
+ "nsStringContainer is not large enough");
+
+ // use placement new to avoid heap allocating nsString object
+ new (&aContainer) nsString();
+
+ return NS_OK;
+}
+
+NS_STRINGAPI(void)
+NS_StringContainerFinish(nsStringContainer &aContainer)
+{
+ // call the nsString dtor
+ NS_REINTERPRET_CAST(nsString *, &aContainer)->~nsString();
+}
+
+/* ------------------------------------------------------------------------- */
+
+NS_STRINGAPI(PRUint32)
+NS_StringGetData(const nsAString &aStr, const PRUnichar **aData,
+ PRBool *aTerminated)
+{
+ if (aTerminated)
+ *aTerminated = aStr.IsTerminated();
+
+ nsAString::const_iterator begin;
+ aStr.BeginReading(begin);
+ *aData = begin.get();
+ return begin.size_forward();
+}
+
+NS_STRINGAPI(PRUnichar *)
+NS_StringCloneData(const nsAString &aStr)
+{
+ return ToNewUnicode(aStr);
+}
+
+NS_STRINGAPI(nsresult)
+NS_StringSetData(nsAString &aStr, const PRUnichar *aData, PRUint32 aDataLength)
+{
+ aStr.Assign(aData, aDataLength);
+ return NS_OK; // XXX report errors
+}
+
+NS_STRINGAPI(nsresult)
+NS_StringSetDataRange(nsAString &aStr,
+ PRUint32 aCutOffset, PRUint32 aCutLength,
+ const PRUnichar *aData, PRUint32 aDataLength)
+{
+ if (aCutOffset == PR_UINT32_MAX)
+ {
+ // append case
+ if (aData)
+ aStr.Append(aData, aDataLength);
+ return NS_OK; // XXX report errors
+ }
+
+ if (aCutLength == PR_UINT32_MAX)
+ aCutLength = aStr.Length() - aCutOffset;
+
+ if (aData)
+ {
+ if (aDataLength == PR_UINT32_MAX)
+ aStr.Replace(aCutOffset, aCutLength, nsDependentString(aData));
+ else
+ aStr.Replace(aCutOffset, aCutLength, Substring(aData, aData + aDataLength));
+ }
+ else
+ aStr.Cut(aCutOffset, aCutLength);
+
+ return NS_OK; // XXX report errors
+}
+
+NS_STRINGAPI(nsresult)
+NS_StringCopy(nsAString &aDest, const nsAString &aSrc)
+{
+ aDest.Assign(aSrc);
+ return NS_OK; // XXX report errors
+}
+
+/* ------------------------------------------------------------------------- */
+
+NS_STRINGAPI(nsresult)
+NS_CStringContainerInit(nsCStringContainer &aContainer)
+{
+ NS_ASSERTION(sizeof(nsCStringContainer) >= sizeof(nsCString),
+ "nsCStringContainer is not large enough");
+
+ // use placement new to avoid heap allocating nsCString object
+ new (&aContainer) nsCString();
+
+ return NS_OK;
+}
+
+NS_STRINGAPI(void)
+NS_CStringContainerFinish(nsCStringContainer &aContainer)
+{
+ // call the nsCString dtor
+ NS_REINTERPRET_CAST(nsCString *, &aContainer)->~nsCString();
+}
+
+/* ------------------------------------------------------------------------- */
+
+NS_STRINGAPI(PRUint32)
+NS_CStringGetData(const nsACString &aStr, const char **aData,
+ PRBool *aTerminated)
+{
+ if (aTerminated)
+ *aTerminated = aStr.IsTerminated();
+
+ nsACString::const_iterator begin;
+ aStr.BeginReading(begin);
+ *aData = begin.get();
+ return begin.size_forward();
+}
+
+NS_STRINGAPI(char *)
+NS_CStringCloneData(const nsACString &aStr)
+{
+ return ToNewCString(aStr);
+}
+
+NS_STRINGAPI(nsresult)
+NS_CStringSetData(nsACString &aStr, const char *aData, PRUint32 aDataLength)
+{
+ aStr.Assign(aData, aDataLength);
+ return NS_OK; // XXX report errors
+}
+
+NS_STRINGAPI(nsresult)
+NS_CStringSetDataRange(nsACString &aStr,
+ PRUint32 aCutOffset, PRUint32 aCutLength,
+ const char *aData, PRUint32 aDataLength)
+{
+ if (aCutOffset == PR_UINT32_MAX)
+ {
+ // append case
+ if (aData)
+ aStr.Append(aData, aDataLength);
+ return NS_OK; // XXX report errors
+ }
+
+ if (aCutLength == PR_UINT32_MAX)
+ aCutLength = aStr.Length() - aCutOffset;
+
+ if (aData)
+ {
+ if (aDataLength == PR_UINT32_MAX)
+ aStr.Replace(aCutOffset, aCutLength, nsDependentCString(aData));
+ else
+ aStr.Replace(aCutOffset, aCutLength, Substring(aData, aData + aDataLength));
+ }
+ else
+ aStr.Cut(aCutOffset, aCutLength);
+
+ return NS_OK; // XXX report errors
+}
+
+NS_STRINGAPI(nsresult)
+NS_CStringCopy(nsACString &aDest, const nsACString &aSrc)
+{
+ aDest.Assign(aSrc);
+ return NS_OK; // XXX report errors
+}
+
+/* ------------------------------------------------------------------------- */
+
+NS_STRINGAPI(nsresult)
+NS_CStringToUTF16(const nsACString &aSrc,
+ nsCStringEncoding aSrcEncoding,
+ nsAString &aDest)
+{
+ switch (aSrcEncoding)
+ {
+ case NS_CSTRING_ENCODING_ASCII:
+ CopyASCIItoUTF16(aSrc, aDest);
+ break;
+ case NS_CSTRING_ENCODING_UTF8:
+ CopyUTF8toUTF16(aSrc, aDest);
+ break;
+ case NS_CSTRING_ENCODING_NATIVE_FILESYSTEM:
+ NS_CopyNativeToUnicode(aSrc, aDest);
+ break;
+ default:
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ return NS_OK; // XXX report errors
+}
+
+NS_STRINGAPI(nsresult)
+NS_UTF16ToCString(const nsAString &aSrc,
+ nsCStringEncoding aDestEncoding,
+ nsACString &aDest)
+{
+ switch (aDestEncoding)
+ {
+ case NS_CSTRING_ENCODING_ASCII:
+ LossyCopyUTF16toASCII(aSrc, aDest);
+ break;
+ case NS_CSTRING_ENCODING_UTF8:
+ CopyUTF16toUTF8(aSrc, aDest);
+ break;
+ case NS_CSTRING_ENCODING_NATIVE_FILESYSTEM:
+ NS_CopyUnicodeToNative(aSrc, aDest);
+ break;
+ default:
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ return NS_OK; // XXX report errors
+}
diff --git a/src/libs/xpcom18a4/xpcom/build/nsXPCOM.h b/src/libs/xpcom18a4/xpcom/build/nsXPCOM.h
new file mode 100644
index 00000000..4e60c74e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/nsXPCOM.h
@@ -0,0 +1,217 @@
+/* -*- 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 ***** */
+
+#ifndef nsXPCOM_h__
+#define nsXPCOM_h__
+
+#include "nscore.h"
+#include "nsXPCOMCID.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define NS_InitXPCOM2 VBoxNsxpNS_InitXPCOM2
+#define NS_ShutdownXPCOM VBoxNsxpNS_ShutdownXPCOM
+#define NS_NewNativeLocalFile VBoxNsxpNS_NewNativeLocalFile
+#define NS_GetServiceManager VBoxNsxpNS_GetServiceManager
+#define NS_GetComponentManager VBoxNsxpNS_GetComponentManager
+#define NS_GetComponentRegistrar VBoxNsxpNS_GetComponentRegistrar
+#define NS_GetDebug VBoxNsxpNS_GetDebug
+#define NS_GetMemoryManager VBoxNsxpNS_GetMemoryManager
+#define NS_GetTraceRefcnt VBoxNsxpNS_GetTraceRefcnt
+#define NS_NewLocalFile VBoxNsxpNS_NewLocalFile
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+class nsAString;
+class nsACString;
+
+class nsIComponentManager;
+class nsIComponentRegistrar;
+class nsIServiceManager;
+class nsIFile;
+class nsILocalFile;
+class nsIDirectoryServiceProvider;
+class nsIMemory;
+class nsIDebug;
+class nsITraceRefcnt;
+
+/**
+ * Initialises XPCOM. You must call this method before proceeding
+ * to use xpcom. The one exception is that you may call
+ * NS_NewLocalFile to create a nsIFile.
+ *
+ * @status FROZEN
+ *
+ * @note Use <CODE>NS_NewLocalFile</CODE> or <CODE>NS_NewNativeLocalFile</CODE>
+ * to create the file object you supply as the bin directory path in this
+ * call. The function may be safely called before the rest of XPCOM or
+ * embedding has been initialised.
+ *
+ * @param result The service manager. You may pass null.
+ *
+ * @param binDirectory The directory containing the component
+ * registry and runtime libraries;
+ * or use <CODE>nsnull</CODE> to use the working
+ * directory.
+ *
+ * @param appFileLocationProvider The object to be used by Gecko that specifies
+ * to Gecko where to find profiles, the component
+ * registry preferences and so on; or use
+ * <CODE>nsnull</CODE> for the default behaviour.
+ *
+ * @see NS_NewLocalFile
+ * @see nsILocalFile
+ * @see nsIDirectoryServiceProvider
+ *
+ * @return NS_OK for success;
+ * NS_ERROR_NOT_INITIALIZED if static globals were not initialied, which
+ * can happen if XPCOM is reloaded, but did not completly shutdown.
+ * other error codes indicate a failure during initialisation.
+ *
+ */
+extern "C" NS_COM nsresult
+NS_InitXPCOM2(nsIServiceManager* *result,
+ nsIFile* binDirectory,
+ nsIDirectoryServiceProvider* appFileLocationProvider);
+/**
+ * Shutdown XPCOM. You must call this method after you are finished
+ * using xpcom.
+ *
+ * @status FROZEN
+ *
+ * @param servMgr The service manager which was returned by NS_InitXPCOM2.
+ * This will release servMgr. You may pass null.
+ *
+ * @return NS_OK for success;
+ * other error codes indicate a failure during initialisation.
+ *
+ */
+extern "C" NS_COM nsresult
+NS_ShutdownXPCOM(nsIServiceManager* servMgr);
+
+
+/**
+ * Public Method to access to the service manager.
+ *
+ * @status FROZEN
+ * @param result Interface pointer to the service manager
+ *
+ * @return NS_OK for success;
+ * other error codes indicate a failure during initialisation.
+ *
+ */
+extern "C" NS_COM nsresult
+NS_GetServiceManager(nsIServiceManager* *result);
+
+/**
+ * Public Method to access to the component manager.
+ *
+ * @status FROZEN
+ * @param result Interface pointer to the service
+ *
+ * @return NS_OK for success;
+ * other error codes indicate a failure during initialisation.
+ *
+ */
+extern "C" NS_COM nsresult
+NS_GetComponentManager(nsIComponentManager* *result);
+
+/**
+ * Public Method to access to the component registration manager.
+ *
+ * @status FROZEN
+ * @param result Interface pointer to the service
+ *
+ * @return NS_OK for success;
+ * other error codes indicate a failure during initialisation.
+ *
+ */
+extern "C" NS_COM nsresult
+NS_GetComponentRegistrar(nsIComponentRegistrar* *result);
+
+/**
+ * Public Method to access to the memory manager. See nsIMemory
+ *
+ * @status FROZEN
+ * @param result Interface pointer to the memory manager
+ *
+ * @return NS_OK for success;
+ * other error codes indicate a failure during initialisation.
+ *
+ */
+extern "C" NS_COM nsresult
+NS_GetMemoryManager(nsIMemory* *result);
+
+/**
+ * Public Method to create an instance of a nsILocalFile. This function
+ * may be called prior to NS_InitXPCOM2.
+ *
+ * @status FROZEN
+ *
+ * @param path
+ * A string which specifies a full file path to a
+ * location. Relative paths will be treated as an
+ * error (NS_ERROR_FILE_UNRECOGNIZED_PATH).
+ * |NS_NewNativeLocalFile|'s path must be in the
+ * filesystem charset.
+ * @param followLinks
+ * This attribute will determine if the nsLocalFile will auto
+ * resolve symbolic links. By default, this value will be false
+ * on all non unix systems. On unix, this attribute is effectively
+ * a noop.
+ * @param result Interface pointer to a new instance of an nsILocalFile
+ *
+ * @return NS_OK for success;
+ * other error codes indicate a failure.
+ */
+
+extern "C" NS_COM nsresult
+NS_NewLocalFile(const nsAString &path,
+ PRBool followLinks,
+ nsILocalFile* *result);
+
+extern "C" NS_COM nsresult
+NS_NewNativeLocalFile(const nsACString &path,
+ PRBool followLinks,
+ nsILocalFile* *result);
+
+
+extern "C" NS_COM nsresult
+NS_GetDebug(nsIDebug* *result);
+
+extern "C" NS_COM nsresult
+NS_GetTraceRefcnt(nsITraceRefcnt* *result);
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/build/nsXPCOMCID.h b/src/libs/xpcom18a4/xpcom/build/nsXPCOMCID.h
new file mode 100644
index 00000000..d5bd039c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/nsXPCOMCID.h
@@ -0,0 +1,174 @@
+/* -*- 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 ***** */
+
+#ifndef nsXPCOMCID_h__
+#define nsXPCOMCID_h__
+
+/**
+ * XPCOM Directory Service Contract ID
+ * The directory service provides ways to obtain file system locations. The
+ * directory service is a singleton.
+ *
+ * This contract supports the nsIDirectoryService and the nsIProperties
+ * interfaces.
+ *
+ */
+#define NS_DIRECTORY_SERVICE_CONTRACTID "@mozilla.org/file/directory_service;1"
+
+/**
+ * XPCOM File
+ * The file abstraction provides ways to obtain and access files and
+ * directories located on the local system.
+ *
+ * This contract supports the nsIFile interface and the nsILocalFile interface.
+ * This contract may also support platform specific interfaces such as
+ * nsILocalFileMac on platforms where additional interfaces are required.
+ *
+ */
+#define NS_LOCAL_FILE_CONTRACTID "@mozilla.org/file/local;1"
+
+/**
+ * XPCOM Category Manager Contract ID
+ * The contract supports the nsICategoryManager interface. The
+ * category manager is a singleton.
+ */
+#define NS_CATEGORYMANAGER_CONTRACTID "@mozilla.org/categorymanager;1"
+
+/**
+ * XPCOM Properties Object Contract ID
+ * Simple mapping object which supports the nsIProperties interface.
+ */
+#define NS_PROPERTIES_CONTRACTID "@mozilla.org/properties;1"
+
+/**
+ * XPCOM Array Object ContractID
+ * Simple array implementation which supports the nsIArray and
+ * nsIMutableArray interfaces.
+ */
+#define NS_ARRAY_CONTRACTID "@mozilla.org/array;1"
+
+/**
+ * The following are the CIDs and Contract IDs of the nsISupports wrappers for
+ * primative types.
+ */
+#define NS_SUPPORTS_ID_CID \
+{ 0xacf8dc40, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_ID_CONTRACTID "@mozilla.org/supports-id;1"
+
+#define NS_SUPPORTS_CSTRING_CID \
+{ 0xacf8dc41, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_CSTRING_CONTRACTID "@mozilla.org/supports-cstring;1"
+
+#define NS_SUPPORTS_STRING_CID \
+{ 0xacf8dc42, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_STRING_CONTRACTID "@mozilla.org/supports-string;1"
+
+#define NS_SUPPORTS_PRBOOL_CID \
+{ 0xacf8dc43, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_PRBOOL_CONTRACTID "@mozilla.org/supports-PRBool;1"
+
+#define NS_SUPPORTS_PRUINT8_CID \
+{ 0xacf8dc44, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_PRUINT8_CONTRACTID "@mozilla.org/supports-PRUint8;1"
+
+#define NS_SUPPORTS_PRUINT16_CID \
+{ 0xacf8dc46, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_PRUINT16_CONTRACTID "@mozilla.org/supports-PRUint16;1"
+
+#define NS_SUPPORTS_PRUINT32_CID \
+{ 0xacf8dc47, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_PRUINT32_CONTRACTID "@mozilla.org/supports-PRUint32;1"
+
+#define NS_SUPPORTS_PRUINT64_CID \
+{ 0xacf8dc48, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_PRUINT64_CONTRACTID "@mozilla.org/supports-PRUint64;1"
+
+#define NS_SUPPORTS_PRTIME_CID \
+{ 0xacf8dc49, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_PRTIME_CONTRACTID "@mozilla.org/supports-PRTime;1"
+
+#define NS_SUPPORTS_CHAR_CID \
+{ 0xacf8dc4a, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_CHAR_CONTRACTID "@mozilla.org/supports-char;1"
+
+#define NS_SUPPORTS_PRINT16_CID \
+{ 0xacf8dc4b, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_PRINT16_CONTRACTID "@mozilla.org/supports-PRInt16;1"
+
+#define NS_SUPPORTS_PRINT32_CID \
+{ 0xacf8dc4c, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_PRINT32_CONTRACTID "@mozilla.org/supports-PRInt32;1"
+
+#define NS_SUPPORTS_PRINT64_CID \
+{ 0xacf8dc4d, 0x4a25, 0x11d3, \
+{ 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+#define NS_SUPPORTS_PRINT64_CONTRACTID "@mozilla.org/supports-PRInt64;1"
+
+#define NS_SUPPORTS_FLOAT_CID \
+{ 0xcbf86870, 0x4ac0, 0x11d3, \
+{ 0xba, 0xea, 0x0, 0x80, 0x5f, 0x8a, 0x5d, 0xd7 } }
+#define NS_SUPPORTS_FLOAT_CONTRACTID "@mozilla.org/supports-float;1"
+
+#define NS_SUPPORTS_DOUBLE_CID \
+{ 0xcbf86871, 0x4ac0, 0x11d3, \
+{ 0xba, 0xea, 0x0, 0x80, 0x5f, 0x8a, 0x5d, 0xd7 } }
+#define NS_SUPPORTS_DOUBLE_CONTRACTID "@mozilla.org/supports-double;1"
+
+#define NS_SUPPORTS_VOID_CID \
+{ 0xaf10f3e0, 0x568d, 0x11d3, \
+{ 0xba, 0xf8, 0x0, 0x80, 0x5f, 0x8a, 0x5d, 0xd7 } }
+#define NS_SUPPORTS_VOID_CONTRACTID "@mozilla.org/supports-void;1"
+
+#define NS_SUPPORTS_INTERFACE_POINTER_CID \
+{ 0xA99FEBBA, 0x1DD1, 0x11B2, \
+{ 0xA9, 0x43, 0xB0, 0x23, 0x34, 0xA6, 0xD0, 0x83 } }
+#define NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID "@mozilla.org/supports-interface-pointer;1"
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/build/nsXPCOMPrivate.h b/src/libs/xpcom18a4/xpcom/build/nsXPCOMPrivate.h
new file mode 100644
index 00000000..cd526ba3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/nsXPCOMPrivate.h
@@ -0,0 +1,228 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:set ts=4 sw=4 et cindent: */
+/* ***** 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 nsXPComPrivate_h__
+#define nsXPComPrivate_h__
+
+#include "nscore.h"
+#include "nsXPCOM.h"
+
+class nsStringContainer;
+class nsCStringContainer;
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define NS_GetFrozenFunctions VBoxNsxpNS_GetFrozenFunctions
+#define NS_RegisterXPCOMExitRoutine VBoxNsxpNS_RegisterXPCOMExitRoutine
+#define NS_UnregisterXPCOMExitRoutine VBoxNsxpNS_UnregisterXPCOMExitRoutine
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+/**
+ * Private Method to register an exit routine. This method
+ * allows you to setup a callback that will be called from
+ * the NS_ShutdownXPCOM function after all services and
+ * components have gone away.
+ *
+ * This API is for the exclusive use of the xpcom glue library.
+ *
+ * Note that these APIs are NOT threadsafe and must be called on the
+ * main thread.
+ *
+ * @status FROZEN
+ * @param exitRoutine pointer to user defined callback function
+ * of type XPCOMExitRoutine.
+ * @param priority higher priorities are called before lower
+ * priorities.
+ *
+ * @return NS_OK for success;
+ * other error codes indicate a failure.
+ *
+ */
+typedef NS_CALLBACK(XPCOMExitRoutine)(void);
+
+extern "C" NS_COM nsresult
+NS_RegisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine, PRUint32 priority);
+
+extern "C" NS_COM nsresult
+NS_UnregisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine);
+
+
+// PUBLIC
+typedef nsresult (* InitFunc)(nsIServiceManager* *result, nsIFile* binDirectory, nsIDirectoryServiceProvider* appFileLocationProvider);
+typedef nsresult (* ShutdownFunc)(nsIServiceManager* servMgr);
+typedef nsresult (* GetServiceManagerFunc)(nsIServiceManager* *result);
+typedef nsresult (* GetComponentManagerFunc)(nsIComponentManager* *result);
+typedef nsresult (* GetComponentRegistrarFunc)(nsIComponentRegistrar* *result);
+typedef nsresult (* GetMemoryManagerFunc)(nsIMemory* *result);
+typedef nsresult (* NewLocalFileFunc)(const nsAString &path, PRBool followLinks, nsILocalFile* *result);
+typedef nsresult (* NewNativeLocalFileFunc)(const nsACString &path, PRBool followLinks, nsILocalFile* *result);
+
+typedef nsresult (* GetDebugFunc)(nsIDebug* *result);
+typedef nsresult (* GetTraceRefcntFunc)(nsITraceRefcnt* *result);
+
+typedef nsresult (* StringContainerInitFunc)(nsStringContainer&);
+typedef void (* StringContainerFinishFunc)(nsStringContainer&);
+typedef PRUint32 (* StringGetDataFunc)(const nsAString&, const PRUnichar**, PRBool*);
+typedef PRUnichar* (* StringCloneDataFunc)(const nsAString&);
+typedef nsresult (* StringSetDataFunc)(nsAString&, const PRUnichar*, PRUint32);
+typedef nsresult (* StringSetDataRangeFunc)(nsAString&, PRUint32, PRUint32, const PRUnichar*, PRUint32);
+typedef nsresult (* StringCopyFunc)(nsAString &, const nsAString &);
+
+typedef nsresult (* CStringContainerInitFunc)(nsCStringContainer&);
+typedef void (* CStringContainerFinishFunc)(nsCStringContainer&);
+typedef PRUint32 (* CStringGetDataFunc)(const nsACString&, const char**, PRBool*);
+typedef char* (* CStringCloneDataFunc)(const nsACString&);
+typedef nsresult (* CStringSetDataFunc)(nsACString&, const char*, PRUint32);
+typedef nsresult (* CStringSetDataRangeFunc)(nsACString&, PRUint32, PRUint32, const char*, PRUint32);
+typedef nsresult (* CStringCopyFunc)(nsACString &, const nsACString &);
+
+typedef nsresult (* CStringToUTF16)(const nsACString &, PRUint32, const nsAString &);
+typedef nsresult (* UTF16ToCString)(const nsAString &, PRUint32, const nsACString &);
+
+// PRIVATE
+typedef nsresult (* RegisterXPCOMExitRoutineFunc)(XPCOMExitRoutine exitRoutine, PRUint32 priority);
+typedef nsresult (* UnregisterXPCOMExitRoutineFunc)(XPCOMExitRoutine exitRoutine);
+
+typedef struct XPCOMFunctions{
+ PRUint32 version;
+ PRUint32 size;
+
+ InitFunc init;
+ ShutdownFunc shutdown;
+ GetServiceManagerFunc getServiceManager;
+ GetComponentManagerFunc getComponentManager;
+ GetComponentRegistrarFunc getComponentRegistrar;
+ GetMemoryManagerFunc getMemoryManager;
+ NewLocalFileFunc newLocalFile;
+ NewNativeLocalFileFunc newNativeLocalFile;
+
+ RegisterXPCOMExitRoutineFunc registerExitRoutine;
+ UnregisterXPCOMExitRoutineFunc unregisterExitRoutine;
+
+ // Added for Mozilla 1.5
+ GetDebugFunc getDebug;
+ GetTraceRefcntFunc getTraceRefcnt;
+
+ // Added for Mozilla 1.7
+ StringContainerInitFunc stringContainerInit;
+ StringContainerFinishFunc stringContainerFinish;
+ StringGetDataFunc stringGetData;
+ StringSetDataFunc stringSetData;
+ StringSetDataRangeFunc stringSetDataRange;
+ StringCopyFunc stringCopy;
+ CStringContainerInitFunc cstringContainerInit;
+ CStringContainerFinishFunc cstringContainerFinish;
+ CStringGetDataFunc cstringGetData;
+ CStringSetDataFunc cstringSetData;
+ CStringSetDataRangeFunc cstringSetDataRange;
+ CStringCopyFunc cstringCopy;
+ CStringToUTF16 cstringToUTF16;
+ UTF16ToCString utf16ToCString;
+ StringCloneDataFunc stringCloneData;
+ CStringCloneDataFunc cstringCloneData;
+
+} XPCOMFunctions;
+
+typedef nsresult (PR_CALLBACK *GetFrozenFunctionsFunc)(XPCOMFunctions *entryPoints, const char* libraryPath);
+extern "C" NS_COM nsresult
+NS_GetFrozenFunctions(XPCOMFunctions *entryPoints, const char* libraryPath);
+
+// think hard before changing this
+#define XPCOM_GLUE_VERSION 1
+
+
+/* XPCOM Specific Defines
+ *
+ * XPCOM_DLL - name of the loadable xpcom library on disk.
+ * XPCOM_SEARCH_KEY - name of the environment variable that can be
+ * modified to include additional search paths.
+ * GRE_CONF_NAME - Name of the GRE Configuration file
+ */
+
+#ifdef XPCOM_DLL_BASE
+#define XPCOM_DLL XPCOM_DLL_BASE MOZ_DLL_SUFFIX
+#endif
+
+#if defined(XP_WIN32) || defined(XP_OS2)
+
+#define XPCOM_SEARCH_KEY "PATH"
+#define GRE_CONF_NAME "gre.config"
+#define GRE_WIN_REG_LOC "Software\\mozilla.org\\GRE\\"
+#ifndef XPCOM_DLL
+#define XPCOM_DLL "xpcom"MOZ_DLL_SUFFIX
+#endif
+
+#elif defined(XP_BEOS)
+
+#define XPCOM_SEARCH_KEY "ADDON_PATH"
+#define GRE_CONF_NAME ".gre.config"
+#define GRE_CONF_PATH "/boot/home/config/settings/GRE/gre.conf"
+#ifndef XPCOM_DLL
+#define XPCOM_DLL "libxpcom"MOZ_DLL_SUFFIX
+#endif
+
+#else // Unix
+
+#ifndef XPCOM_DLL
+#define XPCOM_DLL "libxpcom"MOZ_DLL_SUFFIX
+#endif
+
+// you have to love apple..
+#ifdef XP_MACOSX
+#define XPCOM_SEARCH_KEY "DYLD_LIBRARY_PATH"
+#else
+#define XPCOM_SEARCH_KEY "LD_LIBRARY_PATH"
+#endif
+
+#define GRE_CONF_NAME ".gre.config"
+#define GRE_CONF_PATH "/etc/gre.conf"
+#define GRE_CONF_DIR "/etc/gre.d/"
+#endif
+
+#if defined(XP_WIN) || defined(XP_OS2)
+ #define XPCOM_FILE_PATH_SEPARATOR "\\"
+ #define XPCOM_ENV_PATH_SEPARATOR ";"
+#elif defined(XP_UNIX) || defined(XP_BEOS)
+ #define XPCOM_FILE_PATH_SEPARATOR "/"
+ #define XPCOM_ENV_PATH_SEPARATOR ":"
+#else
+ #error need_to_define_your_file_path_separator_and_illegal_characters
+#endif
+
+#endif
+
+
diff --git a/src/libs/xpcom18a4/xpcom/build/nsXPComInit.cpp b/src/libs/xpcom18a4/xpcom/build/nsXPComInit.cpp
new file mode 100644
index 00000000..65d84b6b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/nsXPComInit.cpp
@@ -0,0 +1,1079 @@
+/* -*- 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 "nsXPCOM.h"
+#include "nsXPCOMPrivate.h"
+#include "nscore.h"
+#include "prlink.h"
+#include "nsCOMPtr.h"
+#include "nsObserverList.h"
+#include "nsObserverService.h"
+#include "nsProperties.h"
+#include "nsIProperties.h"
+#include "nsPersistentProperties.h"
+#include "nsScriptableInputStream.h"
+#include "nsBinaryStream.h"
+#include "nsStorageStream.h"
+
+#include "nsMemoryImpl.h"
+#include "nsDebugImpl.h"
+#include "nsTraceRefcntImpl.h"
+#include "nsErrorService.h"
+#include "nsByteBuffer.h"
+
+#include "nsSupportsArray.h"
+#include "nsArray.h"
+#include "nsSupportsPrimitives.h"
+#include "nsConsoleService.h"
+#include "nsExceptionService.h"
+
+#include "nsComponentManager.h"
+#include "nsCategoryManagerUtils.h"
+#include "nsIServiceManager.h"
+#include "nsGenericFactory.h"
+
+#include "nsEventQueueService.h"
+#include "nsEventQueue.h"
+#ifdef VBOX
+# include "nsEventQueueUtils.h"
+# include "nsProxyRelease.h"
+#endif /* VBOX */
+
+#include "nsIProxyObjectManager.h"
+#include "nsProxyEventPrivate.h" // access to the impl of nsProxyObjectManager for the generic factory registration.
+
+#include "xptinfo.h"
+#include "nsIInterfaceInfoManager.h"
+
+#include "nsTimerImpl.h"
+#include "TimerThread.h"
+
+#include "nsThread.h"
+#include "nsProcess.h"
+#include "nsEnvironment.h"
+
+#include "nsEmptyEnumerator.h"
+
+#include "nsILocalFile.h"
+#include "nsLocalFile.h"
+#if defined(XP_UNIX) || defined(XP_OS2)
+#include "nsNativeCharsetUtils.h"
+#endif
+#include "nsDirectoryService.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsCategoryManager.h"
+#include "nsICategoryManager.h"
+#include "nsStringStream.h"
+#include "nsMultiplexInputStream.h"
+
+#include "nsFastLoadService.h"
+
+#include "nsAtomService.h"
+#include "nsAtomTable.h"
+#include "nsTraceRefcnt.h"
+#include "nsTimelineService.h"
+
+#include "nsVariant.h"
+
+#ifdef GC_LEAK_DETECTOR
+#include "nsLeakDetector.h"
+#endif
+#include "nsRecyclingAllocator.h"
+
+#include "SpecialSystemDirectory.h"
+
+#include "ipcdclient.h"
+#include "ipcService.h"
+#include "ipcConfig.h"
+#include "ipcCID.h"
+#include "ipcLockService.h"
+#include "ipcLockCID.h"
+#include "tmTransactionService.h"
+#include "ipcDConnectService.h"
+
+#include <locale.h>
+
+// Registry Factory creation function defined in nsRegistry.cpp
+// We hook into this function locally to create and register the registry
+// Since noone outside xpcom needs to know about this and nsRegistry.cpp
+// does not have a local include file, we are putting this definition
+// here rather than in nsIRegistry.h
+extern nsresult NS_RegistryGetFactory(nsIFactory** aFactory);
+extern nsresult NS_CategoryManagerGetFactory( nsIFactory** );
+
+#ifdef DEBUG
+extern void _FreeAutoLockStatics();
+#endif
+
+static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
+static NS_DEFINE_CID(kMemoryCID, NS_MEMORY_CID);
+static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsProcess)
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsEventQueueServiceImpl, Init)
+
+#define NS_ENVIRONMENT_CLASSNAME "Environment Service"
+
+#include "nsXPCOM.h"
+// ds/nsISupportsPrimitives
+#define NS_SUPPORTS_ID_CLASSNAME "Supports ID"
+#define NS_SUPPORTS_CSTRING_CLASSNAME "Supports String"
+#define NS_SUPPORTS_STRING_CLASSNAME "Supports WString"
+#define NS_SUPPORTS_PRBOOL_CLASSNAME "Supports PRBool"
+#define NS_SUPPORTS_PRUINT8_CLASSNAME "Supports PRUint8"
+#define NS_SUPPORTS_PRUINT16_CLASSNAME "Supports PRUint16"
+#define NS_SUPPORTS_PRUINT32_CLASSNAME "Supports PRUint32"
+#define NS_SUPPORTS_PRUINT64_CLASSNAME "Supports PRUint64"
+#define NS_SUPPORTS_PRTIME_CLASSNAME "Supports PRTime"
+#define NS_SUPPORTS_CHAR_CLASSNAME "Supports Char"
+#define NS_SUPPORTS_PRINT16_CLASSNAME "Supports PRInt16"
+#define NS_SUPPORTS_PRINT32_CLASSNAME "Supports PRInt32"
+#define NS_SUPPORTS_PRINT64_CLASSNAME "Supports PRInt64"
+#define NS_SUPPORTS_FLOAT_CLASSNAME "Supports float"
+#define NS_SUPPORTS_DOUBLE_CLASSNAME "Supports double"
+#define NS_SUPPORTS_VOID_CLASSNAME "Supports void"
+#define NS_SUPPORTS_INTERFACE_POINTER_CLASSNAME "Supports interface pointer"
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsIDImpl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsStringImpl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsCStringImpl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRBoolImpl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint8Impl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint16Impl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint32Impl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint64Impl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRTimeImpl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsCharImpl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRInt16Impl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRInt32Impl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRInt64Impl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsFloatImpl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsDoubleImpl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsVoidImpl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsInterfacePointerImpl)
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsArray)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsConsoleService)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsAtomService)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsExceptionService)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsTimerImpl)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsTimerManager)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsBinaryOutputStream)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsBinaryInputStream)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsStorageStream)
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsVariant)
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsRecyclingAllocatorImpl)
+
+#ifdef MOZ_TIMELINE
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsTimelineService)
+#endif
+
+static NS_METHOD
+nsXPTIInterfaceInfoManagerGetSingleton(nsISupports* outer,
+ const nsIID& aIID,
+ void* *aInstancePtr)
+{
+ NS_ENSURE_ARG_POINTER(aInstancePtr);
+ NS_ENSURE_TRUE(!outer, NS_ERROR_NO_AGGREGATION);
+
+ nsCOMPtr<nsIInterfaceInfoManager> iim(dont_AddRef(XPTI_GetInterfaceInfoManager()));
+ if (!iim) {
+ return NS_ERROR_FAILURE;
+ }
+
+ return iim->QueryInterface(aIID, aInstancePtr);
+}
+
+
+PR_STATIC_CALLBACK(nsresult)
+RegisterGenericFactory(nsIComponentRegistrar* registrar,
+ const nsModuleComponentInfo *info)
+{
+ nsresult rv;
+ nsIGenericFactory* fact;
+ rv = NS_NewGenericFactory(&fact, info);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = registrar->RegisterFactory(info->mCID,
+ info->mDescription,
+ info->mContractID,
+ fact);
+ NS_RELEASE(fact);
+ return rv;
+}
+
+// In order to support the installer, we need
+// to be told out of band if we should cause
+// an autoregister. If the file ".autoreg" exists in the binary
+// directory, we check its timestamp against the timestamp of the
+// compreg.dat file. If the .autoreg file is newer, we autoregister.
+static PRBool CheckUpdateFile()
+{
+ nsresult rv;
+ nsCOMPtr<nsIProperties> directoryService;
+ nsDirectoryService::Create(nsnull,
+ NS_GET_IID(nsIProperties),
+ getter_AddRefs(directoryService));
+
+ if (!directoryService)
+ return PR_FALSE;
+
+ nsCOMPtr<nsIFile> file;
+ rv = directoryService->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
+ NS_GET_IID(nsIFile),
+ getter_AddRefs(file));
+
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Getting NS_XPCOM_CURRENT_PROCESS_DIR failed");
+ return PR_FALSE;
+ }
+
+ file->AppendNative(nsDependentCString(".autoreg"));
+
+ PRBool exists;
+ file->Exists(&exists);
+ if (!exists)
+ return PR_FALSE;
+
+ nsCOMPtr<nsIFile> compregFile;
+ rv = directoryService->Get(NS_XPCOM_COMPONENT_REGISTRY_FILE,
+ NS_GET_IID(nsIFile),
+ getter_AddRefs(compregFile));
+
+
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Getting NS_XPCOM_COMPONENT_REGISTRY_FILE failed");
+ return PR_FALSE;
+ }
+
+ // Don't need to check whether compreg exists; if it doesn't
+ // we won't even be here.
+
+ PRInt64 compregModTime, autoregModTime;
+ compregFile->GetLastModifiedTime(&compregModTime);
+ file->GetLastModifiedTime(&autoregModTime);
+
+ return LL_CMP(autoregModTime, >, compregModTime);
+}
+
+#if 0 /// @todo later
+NS_GENERIC_FACTORY_CONSTRUCTOR(ipcService)
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(ipcLockService, Init)
+NS_GENERIC_FACTORY_CONSTRUCTOR(tmTransactionService)
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(ipcDConnectService, Init)
+
+// enable this code to make the IPC DCONNECT service auto-start.
+NS_METHOD
+ipcDConnectServiceRegisterProc(nsIComponentManager *aCompMgr,
+ nsIFile *aPath,
+ const char *registryLocation,
+ const char *componentType,
+ const nsModuleComponentInfo *info)
+{
+ //
+ // add ipcService to the XPCOM startup category
+ //
+ nsCOMPtr<nsICategoryManager> catman(do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
+ if (catman) {
+ nsXPIDLCString prevEntry;
+ catman->AddCategoryEntry(NS_XPCOM_STARTUP_OBSERVER_ID, "ipcDConnectService",
+ IPC_DCONNECTSERVICE_CONTRACTID, PR_TRUE, PR_TRUE,
+ getter_Copies(prevEntry));
+ }
+ return NS_OK;
+}
+
+NS_METHOD
+ipcDConnectServiceUnregisterProc(nsIComponentManager *aCompMgr,
+ nsIFile *aPath,
+ const char *registryLocation,
+ const nsModuleComponentInfo *info)
+{
+ nsCOMPtr<nsICategoryManager> catman(do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
+ if (catman)
+ catman->DeleteCategoryEntry(NS_XPCOM_STARTUP_OBSERVER_ID,
+ IPC_DCONNECTSERVICE_CONTRACTID, PR_TRUE);
+ return NS_OK;
+}
+#endif
+
+nsComponentManagerImpl* nsComponentManagerImpl::gComponentManager = NULL;
+nsIProperties *gDirectoryService = NULL;
+PRBool gXPCOMShuttingDown = PR_FALSE;
+
+// For each class that wishes to support nsIClassInfo, add a line like this
+// NS_DECL_CLASSINFO(nsMyClass)
+
+#define COMPONENT(NAME, Ctor) \
+ { NS_##NAME##_CLASSNAME, NS_##NAME##_CID, NS_##NAME##_CONTRACTID, Ctor }
+
+#define COMPONENT_CI(NAME, Ctor, Class) \
+ { NS_##NAME##_CLASSNAME, NS_##NAME##_CID, NS_##NAME##_CONTRACTID, Ctor, \
+ NULL, NULL, NULL, NS_CI_INTERFACE_GETTER_NAME(Class), NULL, \
+ &NS_CLASSINFO_NAME(Class) }
+
+static const nsModuleComponentInfo components[] = {
+ COMPONENT(MEMORY, nsMemoryImpl::Create),
+ COMPONENT(DEBUG, nsDebugImpl::Create),
+#define NS_ERRORSERVICE_CLASSNAME NS_ERRORSERVICE_NAME
+ COMPONENT(ERRORSERVICE, nsErrorService::Create),
+
+ COMPONENT(BYTEBUFFER, ByteBufferImpl::Create),
+ COMPONENT(SCRIPTABLEINPUTSTREAM, nsScriptableInputStream::Create),
+ COMPONENT(BINARYINPUTSTREAM, nsBinaryInputStreamConstructor),
+ COMPONENT(BINARYOUTPUTSTREAM, nsBinaryOutputStreamConstructor),
+ COMPONENT(STORAGESTREAM, nsStorageStreamConstructor),
+
+#define NS_PROPERTIES_CLASSNAME "Properties"
+ COMPONENT(PROPERTIES, nsProperties::Create),
+
+#define NS_PERSISTENTPROPERTIES_CID NS_IPERSISTENTPROPERTIES_CID /* sigh */
+ COMPONENT(PERSISTENTPROPERTIES, nsPersistentProperties::Create),
+
+ COMPONENT(SUPPORTSARRAY, nsSupportsArray::Create),
+ COMPONENT(ARRAY, nsArrayConstructor),
+ COMPONENT(CONSOLESERVICE, nsConsoleServiceConstructor),
+ COMPONENT(EXCEPTIONSERVICE, nsExceptionServiceConstructor),
+ COMPONENT(ATOMSERVICE, nsAtomServiceConstructor),
+#ifdef MOZ_TIMELINE
+ COMPONENT(TIMELINESERVICE, nsTimelineServiceConstructor),
+#endif
+ COMPONENT(OBSERVERSERVICE, nsObserverService::Create),
+ COMPONENT(GENERICFACTORY, nsGenericFactory::Create),
+ COMPONENT(EVENTQUEUESERVICE, nsEventQueueServiceImplConstructor),
+ COMPONENT(EVENTQUEUE, nsEventQueueImpl::Create),
+ COMPONENT(THREAD, nsThread::Create),
+
+#define NS_XPCOMPROXY_CID NS_PROXYEVENT_MANAGER_CID
+ COMPONENT(XPCOMPROXY, nsProxyObjectManager::Create),
+
+ COMPONENT(TIMER, nsTimerImplConstructor),
+ COMPONENT(TIMERMANAGER, nsTimerManagerConstructor),
+
+#define COMPONENT_SUPPORTS(TYPE, Type) \
+ COMPONENT(SUPPORTS_##TYPE, nsSupports##Type##ImplConstructor)
+
+ COMPONENT_SUPPORTS(ID, ID),
+ COMPONENT_SUPPORTS(STRING, String),
+ COMPONENT_SUPPORTS(CSTRING, CString),
+ COMPONENT_SUPPORTS(PRBOOL, PRBool),
+ COMPONENT_SUPPORTS(PRUINT8, PRUint8),
+ COMPONENT_SUPPORTS(PRUINT16, PRUint16),
+ COMPONENT_SUPPORTS(PRUINT32, PRUint32),
+ COMPONENT_SUPPORTS(PRUINT64, PRUint64),
+ COMPONENT_SUPPORTS(PRTIME, PRTime),
+ COMPONENT_SUPPORTS(CHAR, Char),
+ COMPONENT_SUPPORTS(PRINT16, PRInt16),
+ COMPONENT_SUPPORTS(PRINT32, PRInt32),
+ COMPONENT_SUPPORTS(PRINT64, PRInt64),
+ COMPONENT_SUPPORTS(FLOAT, Float),
+ COMPONENT_SUPPORTS(DOUBLE, Double),
+ COMPONENT_SUPPORTS(VOID, Void),
+ COMPONENT_SUPPORTS(INTERFACE_POINTER, InterfacePointer),
+
+#undef COMPONENT_SUPPORTS
+#define NS_LOCAL_FILE_CLASSNAME "Local File Specification"
+ COMPONENT(LOCAL_FILE, nsLocalFile::nsLocalFileConstructor),
+#define NS_DIRECTORY_SERVICE_CLASSNAME "nsIFile Directory Service"
+ COMPONENT(DIRECTORY_SERVICE, nsDirectoryService::Create),
+ COMPONENT(PROCESS, nsProcessConstructor),
+ COMPONENT(ENVIRONMENT, nsEnvironment::Create),
+
+ COMPONENT(STRINGINPUTSTREAM, nsStringInputStreamConstructor),
+ COMPONENT(MULTIPLEXINPUTSTREAM, nsMultiplexInputStreamConstructor),
+
+ COMPONENT(FASTLOADSERVICE, nsFastLoadService::Create),
+ COMPONENT(VARIANT, nsVariantConstructor),
+ COMPONENT(INTERFACEINFOMANAGER_SERVICE, nsXPTIInterfaceInfoManagerGetSingleton),
+
+ COMPONENT(RECYCLINGALLOCATOR, nsRecyclingAllocatorImplConstructor),
+
+#if 0 /// @todo later
+ { IPC_SERVICE_CLASSNAME,
+ IPC_SERVICE_CID,
+ IPC_SERVICE_CONTRACTID,
+ ipcServiceConstructor },
+ /*
+ ipcServiceRegisterProc,
+ ipcServiceUnregisterProc },
+ */
+ //
+ // extensions go here:
+ //
+ { IPC_LOCKSERVICE_CLASSNAME,
+ IPC_LOCKSERVICE_CID,
+ IPC_LOCKSERVICE_CONTRACTID,
+ ipcLockServiceConstructor },
+ { IPC_TRANSACTIONSERVICE_CLASSNAME,
+ IPC_TRANSACTIONSERVICE_CID,
+ IPC_TRANSACTIONSERVICE_CONTRACTID,
+ tmTransactionServiceConstructor },
+
+#ifdef BUILD_DCONNECT
+ { IPC_DCONNECTSERVICE_CLASSNAME,
+ IPC_DCONNECTSERVICE_CID,
+ IPC_DCONNECTSERVICE_CONTRACTID,
+ ipcDConnectServiceConstructor,
+ ipcDConnectServiceRegisterProc,
+ ipcDConnectServiceUnregisterProc },
+#endif
+#endif
+};
+
+#undef COMPONENT
+
+const int components_length = sizeof(components) / sizeof(components[0]);
+
+// gMemory will be freed during shutdown.
+static nsIMemory* gMemory = nsnull;
+nsresult NS_COM NS_GetMemoryManager(nsIMemory* *result)
+{
+ nsresult rv = NS_OK;
+ if (!gMemory)
+ {
+ rv = nsMemoryImpl::Create(nsnull,
+ NS_GET_IID(nsIMemory),
+ (void**)&gMemory);
+ }
+ NS_IF_ADDREF(*result = gMemory);
+ return rv;
+}
+
+// gDebug will be freed during shutdown.
+static nsIDebug* gDebug = nsnull;
+nsresult NS_COM NS_GetDebug(nsIDebug** result)
+{
+ nsresult rv = NS_OK;
+ if (!gDebug)
+ {
+ rv = nsDebugImpl::Create(nsnull,
+ NS_GET_IID(nsIDebug),
+ (void**)&gDebug);
+ }
+ NS_IF_ADDREF(*result = gDebug);
+ return rv;
+}
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+// gTraceRefcnt will be freed during shutdown.
+static nsITraceRefcnt* gTraceRefcnt = nsnull;
+#endif
+
+nsresult NS_COM NS_GetTraceRefcnt(nsITraceRefcnt** result)
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+ nsresult rv = NS_OK;
+ if (!gTraceRefcnt)
+ {
+ rv = nsTraceRefcntImpl::Create(nsnull,
+ NS_GET_IID(nsITraceRefcnt),
+ (void**)&gTraceRefcnt);
+ }
+ NS_IF_ADDREF(*result = gTraceRefcnt);
+ return rv;
+#else
+ return NS_ERROR_NOT_INITIALIZED;
+#endif
+}
+
+nsresult NS_COM NS_InitXPCOM(nsIServiceManager* *result,
+ nsIFile* binDirectory)
+{
+ return NS_InitXPCOM2(result, binDirectory, nsnull);
+}
+
+nsresult NS_COM NS_InitXPCOM2(nsIServiceManager* *result,
+ nsIFile* binDirectory,
+ nsIDirectoryServiceProvider* appFileLocationProvider)
+{
+ nsresult rv = NS_OK;
+
+ // We are not shutting down
+ gXPCOMShuttingDown = PR_FALSE;
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+ nsTraceRefcntImpl::Startup();
+#endif
+
+ // Establish the main thread here.
+ rv = nsIThread::SetMainThread();
+ if (NS_FAILED(rv)) return rv;
+
+ // Set up the timer globals/timer thread
+ rv = nsTimerImpl::Startup();
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Startup the memory manager
+ rv = nsMemoryImpl::Startup();
+ if (NS_FAILED(rv)) return rv;
+
+ // If the locale hasn't already been setup by our embedder,
+ // get us out of the "C" locale and into the system
+ if (strcmp(setlocale(LC_ALL, NULL), "C") == 0)
+ setlocale(LC_ALL, "");
+
+#if defined(XP_UNIX) || defined(XP_OS2)
+ NS_StartupNativeCharsetUtils();
+#endif
+ NS_StartupLocalFile();
+
+ StartupSpecialSystemDirectory();
+
+ // Start the directory service so that the component manager init can use it.
+ rv = nsDirectoryService::Create(nsnull,
+ NS_GET_IID(nsIProperties),
+ (void**)&gDirectoryService);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCOMPtr<nsIDirectoryService> dirService = do_QueryInterface(gDirectoryService, &rv);
+ if (NS_FAILED(rv))
+ return rv;
+ rv = dirService->Init();
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Create the Component/Service Manager
+ nsComponentManagerImpl *compMgr = NULL;
+
+ if (nsComponentManagerImpl::gComponentManager == NULL)
+ {
+ compMgr = new nsComponentManagerImpl();
+ if (compMgr == NULL)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(compMgr);
+
+ nsCOMPtr<nsIFile> xpcomLib;
+
+ PRBool value;
+ if (binDirectory)
+ {
+ rv = binDirectory->IsDirectory(&value);
+
+ if (NS_SUCCEEDED(rv) && value) {
+ gDirectoryService->Set(NS_XPCOM_INIT_CURRENT_PROCESS_DIR, binDirectory);
+ binDirectory->Clone(getter_AddRefs(xpcomLib));
+ }
+ }
+ else {
+ gDirectoryService->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
+ NS_GET_IID(nsIFile),
+ getter_AddRefs(xpcomLib));
+ }
+
+ if (xpcomLib) {
+ xpcomLib->AppendNative(nsDependentCString(XPCOM_DLL));
+ gDirectoryService->Set(NS_XPCOM_LIBRARY_FILE, xpcomLib);
+ }
+
+ if (appFileLocationProvider) {
+ rv = dirService->RegisterProvider(appFileLocationProvider);
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ rv = compMgr->Init();
+ if (NS_FAILED(rv))
+ {
+ NS_RELEASE(compMgr);
+ return rv;
+ }
+
+ nsComponentManagerImpl::gComponentManager = compMgr;
+
+ if (result) {
+ nsIServiceManager *serviceManager =
+ NS_STATIC_CAST(nsIServiceManager*, compMgr);
+
+ NS_ADDREF(*result = serviceManager);
+ }
+ }
+
+ nsCOMPtr<nsIMemory> memory;
+ NS_GetMemoryManager(getter_AddRefs(memory));
+ // dougt - these calls will be moved into a new interface when nsIComponentManager is frozen.
+ rv = compMgr->RegisterService(kMemoryCID, memory);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = compMgr->RegisterService(kComponentManagerCID, NS_STATIC_CAST(nsIComponentManager*, compMgr));
+ if (NS_FAILED(rv)) return rv;
+
+#ifdef GC_LEAK_DETECTOR
+ rv = NS_InitLeakDetector();
+ if (NS_FAILED(rv)) return rv;
+#endif
+
+ // 2. Register the global services with the component manager so that
+ // clients can create new objects.
+
+ // Category Manager
+ {
+ nsCOMPtr<nsIFactory> categoryManagerFactory;
+ if ( NS_FAILED(rv = NS_CategoryManagerGetFactory(getter_AddRefs(categoryManagerFactory))) )
+ return rv;
+
+ NS_DEFINE_CID(kCategoryManagerCID, NS_CATEGORYMANAGER_CID);
+
+ rv = compMgr->RegisterFactory(kCategoryManagerCID,
+ NS_CATEGORYMANAGER_CLASSNAME,
+ NS_CATEGORYMANAGER_CONTRACTID,
+ categoryManagerFactory,
+ PR_TRUE);
+ if ( NS_FAILED(rv) ) return rv;
+ }
+
+ // what I want to do here is QI for a Component Registration Manager. Since this
+ // has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(
+ NS_STATIC_CAST(nsIComponentManager*,compMgr), &rv);
+ if (registrar) {
+ for (int i = 0; i < components_length; i++)
+ RegisterGenericFactory(registrar, &components[i]);
+ }
+ rv = nsComponentManagerImpl::gComponentManager->ReadPersistentRegistry();
+#ifdef DEBUG
+ if (NS_FAILED(rv)) {
+ printf("No Persistent Registry Found.\n");
+ }
+#endif
+
+#if 0 /// @todo later
+ rv = IPC_Init();
+ if (NS_FAILED(rv))
+ return rv;
+#endif
+
+ if ( NS_FAILED(rv) || CheckUpdateFile()) {
+ // if we find no persistent registry, we will try to autoregister
+ // the default components directory.
+ nsComponentManagerImpl::gComponentManager->AutoRegister(nsnull);
+
+ // If the application is using a GRE, then,
+ // auto register components in the GRE directory as well.
+ //
+ // The application indicates that it's using an GRE by
+ // returning a valid nsIFile when queried (via appFileLocProvider)
+ // for the NS_GRE_DIR atom as shown below
+ //
+
+ if ( appFileLocationProvider ) {
+ nsCOMPtr<nsIFile> greDir;
+ PRBool persistent = PR_TRUE;
+
+ appFileLocationProvider->GetFile(NS_GRE_DIR, &persistent, getter_AddRefs(greDir));
+
+ if (greDir) {
+#ifdef DEBUG_dougt
+ printf("start - Registering GRE components\n");
+#endif
+ rv = gDirectoryService->Get(NS_GRE_COMPONENT_DIR,
+ NS_GET_IID(nsIFile),
+ getter_AddRefs(greDir));
+ if (NS_FAILED(rv)) {
+ NS_ERROR("Could not get GRE components directory!");
+ return rv;
+ }
+
+ // If the GRE contains any loaders, we want to know about it so that we can cause another
+ // autoregistration of the applications component directory.
+ int loaderCount = nsComponentManagerImpl::gComponentManager->GetLoaderCount();
+ rv = nsComponentManagerImpl::gComponentManager->AutoRegister(greDir);
+
+ if (loaderCount != nsComponentManagerImpl::gComponentManager->GetLoaderCount())
+ nsComponentManagerImpl::gComponentManager->AutoRegisterNonNativeComponents(nsnull);
+
+#ifdef DEBUG_dougt
+ printf("end - Registering GRE components\n");
+#endif
+ if (NS_FAILED(rv)) {
+ NS_ERROR("Could not AutoRegister GRE components");
+ return rv;
+ }
+ }
+ }
+
+ //
+ // If additional component directories have been specified, then
+ // register them as well.
+ //
+
+ nsCOMPtr<nsISimpleEnumerator> dirList;
+ gDirectoryService->Get(NS_XPCOM_COMPONENT_DIR_LIST,
+ NS_GET_IID(nsISimpleEnumerator),
+ getter_AddRefs(dirList));
+ if (dirList) {
+ PRBool hasMore;
+ while (NS_SUCCEEDED(dirList->HasMoreElements(&hasMore)) && hasMore) {
+ nsCOMPtr<nsISupports> elem;
+ dirList->GetNext(getter_AddRefs(elem));
+ if (elem) {
+ nsCOMPtr<nsIFile> dir = do_QueryInterface(elem);
+ if (dir)
+ nsComponentManagerImpl::gComponentManager->AutoRegister(dir);
+
+ // XXX should we worry about new component loaders being
+ // XXX defined by this process?
+ }
+ }
+ }
+
+
+ // Make sure the compreg file's mod time is current.
+ nsCOMPtr<nsIFile> compregFile;
+ rv = gDirectoryService->Get(NS_XPCOM_COMPONENT_REGISTRY_FILE,
+ NS_GET_IID(nsIFile),
+ getter_AddRefs(compregFile));
+ compregFile->SetLastModifiedTime(PR_Now() / 1000);
+ }
+
+ // Pay the cost at startup time of starting this singleton.
+ nsIInterfaceInfoManager* iim = XPTI_GetInterfaceInfoManager();
+ NS_IF_RELEASE(iim);
+#ifdef VBOX
+ // Must initialize the EventQueueService singleton before anyone is
+ // using it. The notification below creates a thread which races creating
+ // the EventQueueService creation otherwise, no matter what.
+ nsCOMPtr<nsIEventQueue> eventQ;
+ rv = NS_GetMainEventQ(getter_AddRefs(eventQ));
+ if (NS_FAILED(rv)) {
+ NS_ERROR("Could not create event queue for main thread");
+ /* this is just a build-time hack, to reference NS_ProxyRelease */
+ if (rv == 666)
+ NS_ProxyRelease(nsnull, nsnull);
+ return rv;
+ }
+#endif /* VBOX */
+
+ // Notify observers of xpcom autoregistration start
+ NS_CreateServicesFromCategory(NS_XPCOM_STARTUP_OBSERVER_ID,
+ nsnull,
+ NS_XPCOM_STARTUP_OBSERVER_ID);
+
+ return NS_OK;
+}
+
+
+static nsVoidArray* gExitRoutines;
+
+static void CallExitRoutines()
+{
+ if (!gExitRoutines)
+ return;
+
+ PRInt32 count = gExitRoutines->Count();
+ for (PRInt32 i = 0; i < count; i++) {
+ XPCOMExitRoutine func = (XPCOMExitRoutine) gExitRoutines->ElementAt(i);
+ func();
+ }
+ gExitRoutines->Clear();
+ delete gExitRoutines;
+ gExitRoutines = nsnull;
+}
+
+nsresult NS_COM
+NS_RegisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine, PRUint32 priority)
+{
+ // priority are not used right now. It will need to be implemented as more
+ // classes are moved into the glue library --dougt
+ if (!gExitRoutines) {
+ gExitRoutines = new nsVoidArray();
+ if (!gExitRoutines) {
+ NS_WARNING("Failed to allocate gExitRoutines");
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ PRBool okay = gExitRoutines->AppendElement((void*)exitRoutine);
+ return okay ? NS_OK : NS_ERROR_FAILURE;
+}
+
+nsresult NS_COM
+NS_UnregisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine)
+{
+ if (!gExitRoutines)
+ return NS_ERROR_FAILURE;
+
+ PRBool okay = gExitRoutines->RemoveElement((void*)exitRoutine);
+ return okay ? NS_OK : NS_ERROR_FAILURE;
+}
+
+
+//
+// NS_ShutdownXPCOM()
+//
+// The shutdown sequence for xpcom would be
+//
+// - Release the Global Service Manager
+// - Release all service instances held by the global service manager
+// - Release the Global Service Manager itself
+// - Release the Component Manager
+// - Release all factories cached by the Component Manager
+// - Unload Libraries
+// - Release Contractid Cache held by Component Manager
+// - Release dll abstraction held by Component Manager
+// - Release the Registry held by Component Manager
+// - Finally, release the component manager itself
+//
+nsresult NS_COM NS_ShutdownXPCOM(nsIServiceManager* servMgr)
+{
+
+ // Notify observers of xpcom shutting down
+ nsresult rv = NS_OK;
+ {
+ // Block it so that the COMPtr will get deleted before we hit
+ // servicemanager shutdown
+ nsCOMPtr<nsIObserverService> observerService =
+ do_GetService("@mozilla.org/observer-service;1", &rv);
+ if (NS_SUCCEEDED(rv))
+ {
+ nsCOMPtr<nsIServiceManager> mgr;
+ rv = NS_GetServiceManager(getter_AddRefs(mgr));
+ if (NS_SUCCEEDED(rv))
+ {
+ (void) observerService->NotifyObservers(mgr,
+ NS_XPCOM_SHUTDOWN_OBSERVER_ID,
+ nsnull);
+ }
+ }
+ }
+
+ // grab the event queue so that we can process events one last time before exiting
+ nsCOMPtr <nsIEventQueue> currentQ;
+ {
+ nsCOMPtr<nsIEventQueueService> eventQService =
+ do_GetService(kEventQueueServiceCID, &rv);
+
+ if (eventQService) {
+ eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(currentQ));
+ }
+ }
+ // XPCOM is officially in shutdown mode NOW
+ // Set this only after the observers have been notified as this
+ // will cause servicemanager to become inaccessible.
+ gXPCOMShuttingDown = PR_TRUE;
+
+#ifdef DEBUG_dougt
+ fprintf(stderr, "* * * * XPCOM shutdown. Access will be denied * * * * \n");
+#endif
+
+#if 0 /// @todo later
+ IPC_Shutdown();
+#endif
+
+ // We may have AddRef'd for the caller of NS_InitXPCOM, so release it
+ // here again:
+ NS_IF_RELEASE(servMgr);
+
+ // Shutdown global servicemanager
+ if (nsComponentManagerImpl::gComponentManager) {
+ nsComponentManagerImpl::gComponentManager->FreeServices();
+ }
+ nsServiceManager::ShutdownGlobalServiceManager(nsnull);
+
+ if (currentQ) {
+ currentQ->ProcessPendingEvents();
+ currentQ = 0;
+ }
+
+ nsProxyObjectManager::Shutdown();
+
+ // Release the directory service
+ NS_IF_RELEASE(gDirectoryService);
+
+ // Shutdown nsLocalFile string conversion
+ NS_ShutdownLocalFile();
+#ifdef XP_UNIX
+ NS_ShutdownNativeCharsetUtils();
+#endif
+
+ // Shutdown the timer thread and all timers that might still be alive before
+ // shutting down the component manager
+ nsTimerImpl::Shutdown();
+
+ CallExitRoutines();
+
+ // Shutdown xpcom. This will release all loaders and cause others holding
+ // a refcount to the component manager to release it.
+ if (nsComponentManagerImpl::gComponentManager) {
+ rv = (nsComponentManagerImpl::gComponentManager)->Shutdown();
+ NS_ASSERTION(NS_SUCCEEDED(rv), "Component Manager shutdown failed.");
+ } else
+ NS_WARNING("Component Manager was never created ...");
+
+ // Release our own singletons
+ // Do this _after_ shutting down the component manager, because the
+ // JS component loader will use XPConnect to call nsIModule::canUnload,
+ // and that will spin up the InterfaceInfoManager again -- bad mojo
+ XPTI_FreeInterfaceInfoManager();
+
+ // Finally, release the component manager last because it unloads the
+ // libraries:
+ if (nsComponentManagerImpl::gComponentManager) {
+ nsrefcnt cnt;
+ NS_RELEASE2(nsComponentManagerImpl::gComponentManager, cnt);
+ NS_WARN_IF_FALSE(cnt == 0, "Component Manager being held past XPCOM shutdown.");
+ }
+ nsComponentManagerImpl::gComponentManager = nsnull;
+
+#ifdef DEBUG
+ _FreeAutoLockStatics();
+#endif
+
+ ShutdownSpecialSystemDirectory();
+
+ EmptyEnumeratorImpl::Shutdown();
+ nsMemoryImpl::Shutdown();
+ NS_IF_RELEASE(gMemory);
+
+ nsThread::Shutdown();
+ NS_PurgeAtomTable();
+
+ NS_IF_RELEASE(gDebug);
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+ nsTraceRefcntImpl::DumpStatistics();
+ nsTraceRefcntImpl::ResetStatistics();
+ nsTraceRefcntImpl::Shutdown();
+#endif
+
+#ifdef GC_LEAK_DETECTOR
+ // Shutdown the Leak detector.
+ NS_ShutdownLeakDetector();
+#endif
+
+ return NS_OK;
+}
+
+#define GET_FUNC(_tag, _decl, _name) \
+ functions->_tag = (_decl) PR_FindSymbol(xpcomLib, _name); \
+ if (!functions->_tag) goto end
+
+nsresult NS_COM PR_CALLBACK
+NS_GetFrozenFunctions(XPCOMFunctions *functions, const char* libraryPath)
+{
+ if (!functions)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (functions->version != XPCOM_GLUE_VERSION)
+ return NS_ERROR_FAILURE;
+
+ PRLibrary *xpcomLib = PR_LoadLibrary(libraryPath);
+ if (!xpcomLib)
+ return NS_ERROR_FAILURE;
+
+ nsresult rv = NS_ERROR_FAILURE;
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+ GET_FUNC(init, InitFunc, "VBoxNsxpNS_InitXPCOM2");
+ GET_FUNC(shutdown, ShutdownFunc, "VBoxNsxpNS_ShutdownXPCOM");
+ GET_FUNC(getServiceManager, GetServiceManagerFunc, "VBoxNsxpNS_GetServiceManager");
+ GET_FUNC(getComponentManager, GetComponentManagerFunc, "VBoxNsxpNS_GetComponentManager");
+ GET_FUNC(getComponentRegistrar, GetComponentRegistrarFunc, "VBoxNsxpNS_GetComponentRegistrar");
+ GET_FUNC(getMemoryManager, GetMemoryManagerFunc, "VBoxNsxpNS_GetMemoryManager");
+ GET_FUNC(newLocalFile, NewLocalFileFunc, "VBoxNsxpNS_NewLocalFile");
+ GET_FUNC(newNativeLocalFile, NewNativeLocalFileFunc, "VBoxNsxpNS_NewNativeLocalFile");
+ GET_FUNC(registerExitRoutine, RegisterXPCOMExitRoutineFunc, "VBoxNsxpNS_RegisterXPCOMExitRoutine");
+ GET_FUNC(unregisterExitRoutine, UnregisterXPCOMExitRoutineFunc, "VBoxNsxpNS_UnregisterXPCOMExitRoutine");
+#else /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+ GET_FUNC(init, InitFunc, "NS_InitXPCOM2");
+ GET_FUNC(shutdown, ShutdownFunc, "NS_ShutdownXPCOM");
+ GET_FUNC(getServiceManager, GetServiceManagerFunc, "NS_GetServiceManager");
+ GET_FUNC(getComponentManager, GetComponentManagerFunc, "NS_GetComponentManager");
+ GET_FUNC(getComponentRegistrar, GetComponentRegistrarFunc, "NS_GetComponentRegistrar");
+ GET_FUNC(getMemoryManager, GetMemoryManagerFunc, "NS_GetMemoryManager");
+ GET_FUNC(newLocalFile, NewLocalFileFunc, "NS_NewLocalFile");
+ GET_FUNC(newNativeLocalFile, NewNativeLocalFileFunc, "NS_NewNativeLocalFile");
+ GET_FUNC(registerExitRoutine, RegisterXPCOMExitRoutineFunc, "NS_RegisterXPCOMExitRoutine");
+ GET_FUNC(unregisterExitRoutine, UnregisterXPCOMExitRoutineFunc, "NS_UnregisterXPCOMExitRoutine");
+#endif /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+ // these functions were added post 1.4 (need to check size of |functions|)
+ if (functions->size > offsetof(XPCOMFunctions, getTraceRefcnt)) {
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+ GET_FUNC(getDebug, GetDebugFunc, "VBoxNsxpNS_GetDebug");
+ GET_FUNC(getTraceRefcnt, GetTraceRefcntFunc, "VBoxNsxpNS_GetTraceRefcnt");
+#else /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+ GET_FUNC(getDebug, GetDebugFunc, "NS_GetDebug");
+ GET_FUNC(getTraceRefcnt, GetTraceRefcntFunc, "NS_GetTraceRefcnt");
+#endif /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+ }
+
+ // these functions were added post 1.6 (need to check size of |functions|)
+ if (functions->size > offsetof(XPCOMFunctions, cstringCloneData)) {
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+ GET_FUNC(stringContainerInit, StringContainerInitFunc, "VBoxNsxpNS_StringContainerInit");
+ GET_FUNC(stringContainerFinish, StringContainerFinishFunc, "VBoxNsxpNS_StringContainerFinish");
+ GET_FUNC(stringGetData, StringGetDataFunc, "VBoxNsxpNS_StringGetData");
+ GET_FUNC(stringSetData, StringSetDataFunc, "VBoxNsxpNS_StringSetData");
+ GET_FUNC(stringSetDataRange, StringSetDataRangeFunc, "VBoxNsxpNS_StringSetDataRange");
+ GET_FUNC(stringCopy, StringCopyFunc, "VBoxNsxpNS_StringCopy");
+ GET_FUNC(cstringContainerInit, CStringContainerInitFunc, "VBoxNsxpNS_CStringContainerInit");
+ GET_FUNC(cstringContainerFinish, CStringContainerFinishFunc, "VBoxNsxpNS_CStringContainerFinish");
+ GET_FUNC(cstringGetData, CStringGetDataFunc, "VBoxNsxpNS_CStringGetData");
+ GET_FUNC(cstringSetData, CStringSetDataFunc, "VBoxNsxpNS_CStringSetData");
+ GET_FUNC(cstringSetDataRange, CStringSetDataRangeFunc, "VBoxNsxpNS_CStringSetDataRange");
+ GET_FUNC(cstringCopy, CStringCopyFunc, "VBoxNsxpNS_CStringCopy");
+ GET_FUNC(cstringToUTF16, CStringToUTF16, "VBoxNsxpNS_CStringToUTF16");
+ GET_FUNC(utf16ToCString, UTF16ToCString, "VBoxNsxpNS_UTF16ToCString");
+ GET_FUNC(stringCloneData, StringCloneDataFunc, "VBoxNsxpNS_StringCloneData");
+ GET_FUNC(cstringCloneData, CStringCloneDataFunc, "VBoxNsxpNS_CStringCloneData");
+#else /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+ GET_FUNC(stringContainerInit, StringContainerInitFunc, "NS_StringContainerInit");
+ GET_FUNC(stringContainerFinish, StringContainerFinishFunc, "NS_StringContainerFinish");
+ GET_FUNC(stringGetData, StringGetDataFunc, "NS_StringGetData");
+ GET_FUNC(stringSetData, StringSetDataFunc, "NS_StringSetData");
+ GET_FUNC(stringSetDataRange, StringSetDataRangeFunc, "NS_StringSetDataRange");
+ GET_FUNC(stringCopy, StringCopyFunc, "NS_StringCopy");
+ GET_FUNC(cstringContainerInit, CStringContainerInitFunc, "NS_CStringContainerInit");
+ GET_FUNC(cstringContainerFinish, CStringContainerFinishFunc, "NS_CStringContainerFinish");
+ GET_FUNC(cstringGetData, CStringGetDataFunc, "NS_CStringGetData");
+ GET_FUNC(cstringSetData, CStringSetDataFunc, "NS_CStringSetData");
+ GET_FUNC(cstringSetDataRange, CStringSetDataRangeFunc, "NS_CStringSetDataRange");
+ GET_FUNC(cstringCopy, CStringCopyFunc, "NS_CStringCopy");
+ GET_FUNC(cstringToUTF16, CStringToUTF16, "NS_CStringToUTF16");
+ GET_FUNC(utf16ToCString, UTF16ToCString, "NS_UTF16ToCString");
+ GET_FUNC(stringCloneData, StringCloneDataFunc, "NS_StringCloneData");
+ GET_FUNC(cstringCloneData, CStringCloneDataFunc, "NS_CStringCloneData");
+#endif /* !VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+ }
+
+ rv = NS_OK;
+end:
+ PR_UnloadLibrary(xpcomLib); // the library is refcnt'ed above by the caller.
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/build/win32.order b/src/libs/xpcom18a4/xpcom/build/win32.order
new file mode 100644
index 00000000..ce6856ba
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/win32.order
@@ -0,0 +1,1514 @@
+??1nsCOMPtr_base@@QAE@XZ ; 33017395
+?ElementAt@nsVoidArray@@QBEPAXH@Z ; 14120786
+?AddRef@nsEventQueueServiceImpl@@UAGKXZ ; 13612685
+?Release@AtomImpl@@UAGKXZ ; 13067618
+?Initialize@nsStr@@SAXAAU1@W4eCharSize@@@Z ; 9860800
+?Reference@nsCWeakProxy@@QAEPAXXZ ; 9283082
+?Free@nsStr@@CAHAAU1@@Z ; 8492496
+?Destroy@nsStr@@SAXAAU1@@Z ; 8159980
+??1nsString@@UAE@XZ ; 7681847
+??0nsString@@QAE@XZ ; 7538998
+?GetWritableFragment@nsString@@MAEPAGAAU?$nsWritableFragment@G@@W4nsFragmentRequest@@I@Z ; 7387979
+?Initialize@nsStr@@SAXAAU1@PADIIW4eCharSize@@H@Z ; 7301440
+??1nsAutoString@@UAE@XZ ; 6828894
+??0nsAutoString@@QAE@XZ ; 6681318
+?normalize_forward@?$nsReadingIterator@G@@QAEXXZ ; 6469200
+?normalize_forward@?$nsWritingIterator@D@@QAEXXZ ; 4717355
+?StrTruncate@nsStr@@SAXAAU1@I@Z ; 4534497
+?assign_from_helper@nsCOMPtr_base@@QAEXABVnsCOMPtr_helper@@ABUnsID@@@Z ; 4516612
+??0nsHashKey@@IAE@XZ ; 4270805
+??1nsHashKey@@UAE@XZ ; 4268636
+??RnsQueryInterface@@UBEIABUnsID@@PAPAX@Z ; 4148520
+?SetLength@nsCString@@UAEXI@Z ; 4098410
+?Get@nsHashtable@@QAEPAXPAVnsHashKey@@@Z ; 3790063
+?GetFlatBufferHandle@nsLocalString@@UBEPBV?$nsBufferHandle@G@@XZ ; 3747888
+?BeginReading@nsACString@@QBEAAV?$nsReadingIterator@D@@AAV2@@Z ; 3649883
+?FindChar1@@YAHPBDIHGHH@Z ; 2533672
+?BeginWriting@nsACString@@QAEAAV?$nsWritingIterator@D@@AAV2@@Z ; 2226534
+?advance@?$nsWritingIterator@G@@QAEAAV1@H@Z ; 2049632
+?advance@?$nsReadingIterator@G@@QAEAAV1@H@Z ; 1995545
+?GetReadableFragment@nsAFlatCString@@MBEPBDAAU?$nsReadableFragment@D@@W4nsFragmentRequest@@I@Z ; 1948988
+?Count@nsSupportsArray@@UAGIPAI@Z ; 1839978
+?readable_distance@?$nsCharSourceTraits@V?$nsReadingIterator@G@@@@SAIABV?$nsReadingIterator@G@@0@Z ; 1802375
+?GetReadableFragment@nsCString@@MBEPBDAAU?$nsReadableFragment@D@@W4nsFragmentRequest@@I@Z ; 1763345
+??0nsQueryInterface@@QAE@PAVnsISupports@@PAI@Z ; 1655422
+?copy_string@@YAAAV?$nsWritingIterator@G@@AAV?$nsReadingIterator@G@@ABV2@AAV1@@Z ; 1487171
+?GetWritableFragment@nsAFlatString@@MAEPAGAAU?$nsWritableFragment@G@@W4nsFragmentRequest@@I@Z ; 1391163
+?advance@?$nsWritingIterator@D@@QAEAAV1@H@Z ; 1335661
+?Equals@nsAString@@QBEHABV1@@Z ; 1318787
+?move@?$nsCharTraits@G@@SAPAGPAGPBGI@Z ; 1315826
+?assign_with_AddRef@nsCOMPtr_base@@QAEXPAVnsISupports@@@Z ; 1259090
+?write@?$nsWritingIterator@G@@QAEIPBGI@Z ; 1243674
+?Get@nsSupportsHashtable@@QAEPAVnsISupports@@PAVnsHashKey@@@Z ; 1199544
+?GetUnicode@nsString@@QBEPBGXZ ; 1141413
+?StrAppend@nsStr@@SAXAAU1@ABU1@IH@Z ; 1102413
+?FindChar@nsString@@QBEHGHHH@Z ; 1090463
+?FindChar@nsStr@@SAHABU1@GHHH@Z ; 1090463
+?FindChar2@@YAHPBDIHGHH@Z ; 1056090
+?ElementAt@nsSupportsArray@@UAGPAVnsISupports@@I@Z ; 1055798
+?InsertElementAt@nsVoidArray@@QAEHPAXH@Z ; 926721
+?Compare2To2@@YAHPBD0IH@Z ; 920121
+?EnumerateForwards@nsSupportsArray@@UAGHP6AHPAVnsISupports@@PAX@Z1@Z ; 908730
+?strncasecmp@nsCRT@@SAHPBG0I@Z ; 896894
+?StrCompare@nsStr@@SAHABU1@0HH@Z ; 886450
+?Free@nsMemoryImpl@@UAGXPAX@Z ; 842646
+?Free@nsMemory@@SAXPAX@Z ; 832569
+?Distance@@YAIABV?$nsReadingIterator@G@@0@Z ; 801833
+?copy_string@@YAAAV?$CalculateLength@G@@AAV?$nsReadingIterator@G@@ABV2@AAV1@@Z ; 801833
+?Compare2To1@@YAHPBD0IH@Z ; 797802
+?Alloc@nsMemoryImpl@@UAGPAXI@Z ; 795063
+?Length@nsAFlatString@@UBEIXZ ; 789895
+?advance@?$nsReadingIterator@D@@QAEAAV1@H@Z ; 778072
+?copy_string@@YAAAV?$nsWritingIterator@D@@AAV?$nsReadingIterator@D@@ABV2@AAV1@@Z ; 738318
+?Alloc@nsMemory@@SAPAXI@Z ; 731916
+?write@?$nsWritingIterator@D@@QAEIPBDI@Z ; 724438
+?EqualsWithConversion@nsString@@QBEHABV1@HH@Z ; 680848
+?EqualsIgnoreCase@nsString@@QBEHABV1@@Z ; 680848
+?Length@nsAFlatCString@@UBEIXZ ; 674814
+?GetReadableFragment@nsSlidingSubstring@@MBEPBGAAU?$nsReadableFragment@G@@W4nsFragmentRequest@@I@Z ; 671287
+?do_AppendFromReadable@nsAString@@MAEXABV1@@Z ; 657779
+?Compare@@YAHABVnsAString@@0@Z ; 630913
+?do_AssignFromReadable@nsAString@@MAEXABV1@@Z ; 630139
+?CopyChars2To2@@YAXPADHPBDII@Z ; 615216
+?do_AppendFromReadable@nsACString@@MAEXABV1@@Z ; 584996
+?ObjectAt@nsDeque@@QBEPAXH@Z ; 568869
+?InsertElementAt@nsSupportsArray@@UAGHPAVnsISupports@@I@Z ; 548718
+?AssignFromReadable@nsACString@@IAEXABV1@@Z ; 534684
+??0nsLocalCString@@QAE@PBD@Z ; 525422
+?strlen@nsCRT@@SAIPBG@Z ; 517372
+?get@nsString@@UBEPBGXZ ; 500471
+?GrowCapacity@nsStr@@SAHAAU1@I@Z ; 493115
+?Realloc@nsStr@@CAHAAU1@I@Z ; 493115
+?Alloc@nsStr@@CAHAAU1@I@Z ; 493115
+?EnsureCapacity@nsStr@@SAHAAU1@I@Z ; 493115
+??0nsVoidArray@@QAE@XZ ; 490358
+?strncmp@nsCRT@@SAHPBGPBDI@Z ; 489334
+??1nsVoidArray@@UAE@XZ ; 481308
+??1nsCString@@UAE@XZ ; 478019
+?RemoveElementAt@nsVoidArray@@QAEHH@Z ; 473592
+?AppendElement@nsSupportsArray@@UAGIPAVnsISupports@@@Z ; 464186
+?AppendWithConversion@nsCString@@QAEXG@Z ; 452063
+??0nsCString@@QAE@XZ ; 449721
+?do_AppendFromElementPtr@nsACString@@MAEXPBD@Z ; 427640
+?SetArraySize@nsVoidArray@@IAEXH@Z ; 425906
+?get@nsPromiseFlatCString@@UBEPBDXZ ; 413903
+?Alloc@nsFixedSizeAllocator@@QAEPAXI@Z ; 411293
+??0nsPromiseFlatString@@IAE@ABVnsAString@@@Z ; 410015
+?Free@nsFixedSizeAllocator@@SAXPAXI@Z ; 401028
+?strcmp@nsCRT@@SAHPBG0@Z ; 400500
+??1nsPromiseFlatString@@UAE@XZ ; 398346
+??1nsCAutoString@@UAE@XZ ; 391273
+?GetFlatBufferHandle@nsCString@@MBEPBV?$nsBufferHandle@D@@XZ ; 385981
+?Push@nsDeque@@QAEAAV1@PAX@Z ; 367628
+?Equals@nsIDKey@@UBEHPBVnsHashKey@@@Z ; 358933
+?Clear@nsSupportsArray@@UAGIXZ ; 352217
+?AppendFromReadable@nsAString@@IAEXABV1@@Z ; 352181
+?strncasecmp@nsCRT@@SAHPBGPBDI@Z ; 330906
+?IsAsciiAlpha@nsCRT@@SAHG@Z ; 327047
+??0nsCAutoString@@QAE@XZ ; 311314
+?Clear@nsVoidArray@@QAEXXZ ; 287750
+?Compare1To1@@YAHPBD0IH@Z ; 276525
+?Length@nsSlidingSubstring@@UBEIXZ ; 264724
+?PopFront@nsDeque@@QAEPAXXZ ; 260861
+?AcquireNonOwningReference@Buffer@nsSharedBufferList@@QBEXXZ ; 256259
+?Distance@Position@nsSharedBufferList@@SAHABU12@0@Z ; 254042
+?DiscardUnreferencedPrefix@nsSlidingSharedBufferList@@QAEXPAVBuffer@nsSharedBufferList@@@Z ; 254040
+?ReleaseNonOwningReference@Buffer@nsSharedBufferList@@QBEXXZ ; 254040
+??1nsCStringKey@@UAE@XZ ; 253255
+?HashCode@nsCRT@@SAIPBDPAI@Z ; 251093
+?HashCode@nsCStringKey@@UBEIXZ ; 250679
+?NS_GetGlobalComponentManager@@YAIPAPAVnsIComponentManager@@@Z ; 250625
+??1nsAFlatString@@UAE@XZ ; 249908
+??0nsAFlatString@@QAE@XZ ; 243174
+?Equals@nsCStringKey@@UBEHPBVnsHashKey@@@Z ; 238528
+?IsAsciiSpace@nsCRT@@SAHG@Z ; 238314
+?CopyChars1To2@@YAXPADHPBDII@Z ; 237716
+??0nsLocalString@@QAE@PBGI@Z ; 236845
+?NS_NewAtom@@YAPAVnsIAtom@@ABVnsAString@@@Z ; 235384
+?Release@nsSupportsArray@@UAGKXZ ; 229149
+?GetParameterCount@nsProxyObjectCallInfo@@QBEIXZ ; 228843
+??0nsAutoVoidArray@@QAE@XZ ; 223605
+?do_AppendFromElementPtrLength@nsAString@@MAEXPBGI@Z ; 221664
+?AppendWithConversion@nsString@@QAEXPBDH@Z ; 216212
+?ChangeCase@nsStr@@SAXAAU1@H@Z ; 211594
+?length@?$nsCharTraits@G@@SAIPBG@Z ; 206064
+??0nsLocalString@@QAE@PBG@Z ; 205367
+?SetArrayOwner@nsVoidArray@@IAEXH@Z ; 202301
+?GetFactoryEntry@nsComponentManagerImpl@@IAEPAVnsFactoryEntry@@ABUnsID@@H@Z ; 198436
+?FindFactory@nsComponentManagerImpl@@UAGIABUnsID@@PAPAVnsIFactory@@@Z ; 198385
+?GetFactory@nsFactoryEntry@@QAEIPAPAVnsIFactory@@PAVnsComponentManagerImpl@@@Z ; 198384
+?CreateInstance@nsComponentManagerImpl@@UAGIABUnsID@@PAVnsISupports@@0PAPAX@Z ; 198351
+?ToLowerCase@nsString@@QAEXXZ ; 198180
+?Remove@nsHashtable@@QAEPAXPAVnsHashKey@@@Z ; 191685
+?ToString@AtomImpl@@UAGIAAVnsAString@@@Z ; 189337
+?First@nsAString@@QBEGXZ ; 189245
+?release_ownership_of_buffer_list@nsSlidingSubstring@@AAEXXZ ; 188763
+?IndexOf@nsVoidArray@@QBEHPAX@Z ; 175677
+?StartAssignmentByValue@nsXPIDLString@@AAEPAPAGXZ ; 173850
+?SetCapacity@nsString@@UAEXI@Z ; 170493
+?CopyChars2To1@@YAXPADHPBDII@Z ; 168065
+?Put@nsHashtable@@QAEPAXPAVnsHashKey@@PAX@Z ; 160536
+?DiscardPrefix@nsSlidingString@@QAEXABV?$nsReadingIterator@G@@@Z ; 159450
+?StrAssign@nsStr@@SAXAAU1@ABU1@IH@Z ; 154324
+?Trim@nsStr@@SAXAAU1@PBDHH@Z ; 154152
+?SetCapacity@nsCString@@UAEXI@Z ; 151535
+?GetGlobalServiceManager@nsServiceManager@@SAIPAPAVnsIServiceManager@@@Z ; 148522
+?GetService@nsServiceManagerImpl@@UAGIABUnsID@@0PAPAVnsISupports@@PAVnsIShutdownListener@@@Z ; 146024
+?AddListener@nsServiceEntry@@QAEIPAVnsIShutdownListener@@@Z ; 146022
+?GetUnicode@AtomImpl@@UAGIPAPBG@Z ; 143965
+?Pop@nsDeque@@QAEPAXXZ ; 143309
+??RnsQueryReferent@@UBEIABUnsID@@PAPAX@Z ; 142474
+?normalize_backward@?$nsReadingIterator@G@@QAEXXZ ; 142302
+?QueryReferent@nsWeakReference@@UAGIABUnsID@@PAPAX@Z ; 142237
+?AddRef@nsStorageStream@@UAGKXZ ; 141846
+?Assign@nsACString@@QAEXPBD@Z ; 141606
+?FindCharInSet@nsStr@@SAHABU1@0HH@Z ; 138161
+?FindCharInSet@nsCString@@QBEHPBDH@Z ; 138161
+?CreateInstance@nsComponentManager@@SAIABUnsID@@PAVnsISupports@@0PAPAX@Z ; 137059
+??0nsCStringKey@@QAE@PBDHW4Ownership@0@@Z ; 136293
+??1nsXPIDLCString@@UAE@XZ ; 134911
+??0nsString@@QAE@ABV0@@Z ; 134194
+?do_AssignFromReadable@nsACString@@MAEXABV1@@Z ; 128929
+?ConvertCase1@@YAHPADIH@Z ; 128876
+?AssignWithConversion@nsCString@@QAEXPBGH@Z ; 122216
+?do_AppendFromElement@nsACString@@MAEXD@Z ; 120364
+?Write@FileImpl@@UAGIPBDIPAI@Z ; 120089
+?AssignWithConversion@nsCString@@QAEXABVnsString@@@Z ; 119962
+?AddRef@nsSupportsStringImpl@@UAGKXZ ; 118646
+??0nsCStringKey@@QAE@ABVnsCString@@@Z ; 117124
+?GetResolveState@xptiInterfaceInfo@@QBEEXZ ; 117066
+?AppendUnicodeTo@@YAXABV?$nsReadingIterator@G@@0AAVnsAString@@@Z ; 115792
+?AssignWithConversion@nsString@@QAEXPBD@Z ; 115695
+?Last@nsAString@@QBEGXZ ; 115018
+?ContractIDToClassID@nsComponentManagerImpl@@UAGIPBDPAUnsID@@@Z ; 112973
+?ToNewCString@nsCString@@QBEPADXZ ; 110413
+?LookupLowercasedKeyword@@YAHABVnsCString@@PAVnsHashtable@@@Z ; 110405
+?IsAsciiDigit@nsCRT@@SAHG@Z ; 107530
+?Remove@nsSupportsHashtable@@QAEHPAVnsHashKey@@PAPAVnsISupports@@@Z ; 106325
+??0nsAutoString@@QAE@ABVnsString@@@Z ; 103799
+?CompareWithConversion@nsString@@QBEHPBDHH@Z ; 102438
+?EqualsWithConversion@nsString@@QBEHPBDHH@Z ; 101441
+?Lookup@nsStaticCaseInsensitiveNameTable@@QAEHABVnsString@@@Z ; 101178
+?Trim@nsString@@QAEXPBDHHH@Z ; 100923
+?Release@nsWeakReference@@UAGKXZ ; 100809
+?GetReadableFragment@nsPromiseSubstring@@MBEPBGAAU?$nsReadableFragment@G@@W4nsFragmentRequest@@I@Z ; 98711
+?GetService@nsServiceManager@@SAIABUnsID@@0PAPAVnsISupports@@PAVnsIShutdownListener@@@Z ; 97630
+?write@nsOutputStream@@QAEHPBXH@Z ; 96747
+?Init@nsXPTCVariant@@QAEXABUnsXPTCMiniVariant@@ABVnsXPTType@@E@Z ; 95698
+?acquire_ownership_of_buffer_list@nsSlidingString@@ABEXXZ ; 94592
+?ReleaseReference@nsSlidingSharedBufferList@@QAEXXZ ; 94590
+??1nsSlidingSubstring@@UAE@XZ ; 94580
+??0nsSlidingSubstring@@QAE@XZ ; 94173
+?RemoveElement@nsVoidArray@@QAEHPAX@Z ; 91746
+??RnsGetServiceByCID@@UBEIABUnsID@@PAPAX@Z ; 91521
+??0nsGetServiceByCID@@QAE@ABUnsID@@PAVnsISupports@@PAI@Z ; 91521
+?Release@nsEventQueueImpl@@UAGKXZ ; 87880
+?EqualsIgnoreCase@nsString@@QBEHPBDH@Z ; 86030
+?Init@NS_ConvertUTF8toUCS2@@IAEXPBDI@Z ; 85607
+?Rebind@nsSlidingSubstring@@QAEXABVnsSlidingString@@ABV?$nsReadingIterator@G@@1@Z ; 83943
+?do_AppendFromElementPtr@nsAString@@MAEXPBG@Z ; 83867
+??0nsSupportsArray@@QAE@XZ ; 83106
+?ConvertCase2@@YAHPADIH@Z ; 82718
+?DeleteArray@nsSupportsArray@@IAEXXZ ; 82548
+??1nsSupportsArray@@UAE@XZ ; 82548
+?QueryInterface@nsSupportsArray@@UAGIABUnsID@@PAPAX@Z ; 81918
+?Create@nsSupportsArray@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 81725
+?NS_NewISupportsArray@@YAIPAPAVnsISupportsArray@@@Z ; 81666
+?CopyChars1To1@@YAXPADHPBDII@Z ; 81524
+??_EnsSupportsArray@@UAEPAXI@Z ; 81168
+?GetMethodInfo@xptiInterfaceInfo@@UAGIGPAPBVnsXPTMethodInfo@@@Z ; 78229
+?Release@xptiInterfaceInfo@@UAGKXZ ; 76117
+?do_AssignFromElementPtr@nsAString@@MAEXPBG@Z ; 73811
+?copy_string@@YAAAPAGAAV?$nsReadingIterator@G@@ABV1@AAPAG@Z ; 71847
+?GetReadableFragment@nsPromiseCSubstring@@MBEPBDAAU?$nsReadableFragment@D@@W4nsFragmentRequest@@I@Z ; 71331
+?GetBuffer@ByteBufferImpl@@UBGPADXZ ; 71201
+?Read@ConverterInputStream@@UAGIPAGIIPAI@Z ; 70839
+?Read@nsPersistentProperties@@QAEHXZ ; 70367
+?do_AssignFromElementPtr@nsACString@@MAEXPBD@Z ; 62916
+?Length@nsPromiseCSubstring@@UBEIXZ ; 62793
+?CompareWithConversion@nsCString@@QBEHPBDHH@Z ; 62172
+??0NS_ConvertASCIItoUCS2@@QAE@PBD@Z ; 61750
+?CreateInstanceByContractID@nsComponentManagerImpl@@UAGIPBDPAVnsISupports@@ABUnsID@@PAPAX@Z ; 61075
+?CreateInstance@nsComponentManager@@SAIPBDPAVnsISupports@@ABUnsID@@PAPAX@Z ; 61075
+?Exit@nsAutoMonitor@@QAEXXZ ; 59293
+?Enter@nsAutoMonitor@@QAEXXZ ; 59293
+PL_GetEventOwner ; 55295
+?RefCountInInterfacePointers@nsProxyObjectCallInfo@@AAEXH@Z ; 55218
+?Clone@nsMemory@@SAPAXPBXI@Z ; 53069
+?Promises@nsAString@@UBEHABV1@@Z ; 52421
+?Promises@nsPromiseSubstring@@UBEHABVnsAString@@@Z ; 52287
+?ContractIDToClassID@nsComponentManager@@SAIPBDPAUnsID@@@Z ; 51898
+?GetStringValue@nsStaticCaseInsensitiveNameTable@@QAEABVnsCString@@H@Z ; 51863
+?CopyUnicodeTo@@YAXABV?$nsReadingIterator@G@@0AAVnsAString@@@Z ; 51424
+??RnsGetInterface@@UBEIABUnsID@@PAPAX@Z ; 51014
+?GetService@nsServiceManager@@SAIPBDABUnsID@@PAPAVnsISupports@@PAVnsIShutdownListener@@@Z ; 50614
+?GetService@nsServiceManagerImpl@@UAGIPBDABUnsID@@PAPAVnsISupports@@PAVnsIShutdownListener@@@Z ; 50608
+?GetElementAt@nsSupportsArray@@UAGIIPAPAVnsISupports@@@Z ; 50421
+??0nsCAutoString@@QAE@PBD@Z ; 50288
+?Release@nsGenericFactory@@UAGKXZ ; 48967
+?Release@nsLocalFile@@UAGKXZ ; 48924
+?CreateInstance@nsGenericFactory@@UAGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 47807
+?ToNewUnicode@@YAPAGABVnsAString@@@Z ; 47476
+?Equals@nsSupportsArray@@UAGHPBVnsISupportsArray@@@Z ; 47394
+?QueryInterface@nsWeakReference@@UAGIABUnsID@@PAPAX@Z ; 47232
+?ToInteger@nsString@@QBEHPAHI@Z ; 46397
+??0nsGetServiceByContractID@@QAE@PBDPAVnsISupports@@PAI@Z ; 45960
+??RnsGetServiceByContractID@@UBEIABUnsID@@PAPAX@Z ; 45960
+?Reset@nsHashtable@@QAEXP6AHPAVnsHashKey@@PAX1@Z1@Z ; 45160
+?Reset@nsHashtable@@QAEXXZ ; 44779
+?strdup@nsCRT@@SAPAGPBG@Z ; 44542
+?strndup@nsCRT@@SAPAGPBGI@Z ; 44542
+PL_InitEvent ; 42216
+PL_DestroyEvent ; 42216
+?Release@nsProxyObject@@UAGKXZ ; 42053
+?HashCode@nsCRT@@SAIPBGPAI@Z ; 41515
+?MakeDirty@nsLocalFile@@AAEXXZ ; 40921
+?CompressSet@nsStr@@SAXAAU1@PBDHH@Z ; 40756
+?FindSubstr@nsStr@@SAHABU1@0HHH@Z ; 40557
+XPTC_InvokeByIndex ; 40446
+?QueryInterface@nsEventQueueImpl@@UAGIABUnsID@@PAPAX@Z ; 40010
+?Peek@nsDeque@@QAEPAXXZ ; 39695
+?ToUpper@nsCRT@@SAGG@Z ; 39657
+?CopyStrings@nsProxyObjectCallInfo@@AAEXH@Z ; 39492
+PL_DHashTableOperate ; 39446
+??0nsDeque@@QAE@PAVnsDequeFunctor@@@Z ; 38500
+?Empty@nsDeque@@QAEAAV1@XZ ; 38489
+??1nsDeque@@QAE@XZ ; 38489
+?Erase@nsDeque@@QAEAAV1@XZ ; 38489
+?GetSegmentCount@nsSegmentedBuffer@@QAEIXZ ; 38168
+?Release@nsProxyEventObject@@UAGKXZ ; 37461
+?ReplaceElementAt@nsVoidArray@@QAEHPAXH@Z ; 37379
+??0nsAutoString@@QAE@PBG@Z ; 35740
+PL_GetEvent ; 34422
+PL_HandleEvent ; 34415
+PL_PostEvent ; 34415
+?PostEvent@nsEventQueueImpl@@UAG?AW4PRStatus@@PAUPLEvent@@@Z ; 34353
+?strncmp@nsCRT@@SAHPBG0I@Z ; 34311
+?Cut@nsAString@@UAEXII@Z ; 33933
+?Release@nsThread@@UAGKXZ ; 32675
+?GetInstance@nsProxyObjectManager@@SAPAV1@XZ ; 31747
+?EqualsWithConversion@nsCString@@QBEHPBGHH@Z ; 31327
+?CompareWithConversion@nsCString@@QBEHPBGHH@Z ; 31327
+?GetRealObject@nsProxyObject@@QBEPAVnsISupports@@XZ ; 30180
+PL_DHashStringKey ; 29743
+?QueryInterface@nsEventQueueServiceImpl@@UAGIABUnsID@@PAPAX@Z ; 29645
+?GetReadSegment@nsPipe@@QAEIIPAPBDPAI@Z ; 29618
+??1nsXPIDLString@@UAE@XZ ; 29310
+?Release@nsProxyEventClass@@UAGKXZ ; 29259
+??0nsPromiseSubstring@@QAE@ABVnsAString@@II@Z ; 29232
+?Compact@nsSupportsArray@@UAGIXZ ; 28635
+?Mid@nsAString@@QBEIAAV1@II@Z ; 28616
+?AssignFromPromise@nsAString@@IAEXABV1@@Z ; 28510
+?get@nsAFlatString@@UBEPBGXZ ; 28400
+?Equals@nsACString@@QBEHABV1@@Z ; 28339
+?convertMiniVariantToVariant@nsProxyObject@@AAEIPAVnsXPTMethodInfo@@PAUnsXPTCMiniVariant@@PAPAUnsXPTCVariant@@PAE@Z ; 27609
+??_EnsProxyObjectCallInfo@@UAEPAXI@Z ; 27609
+?Post@nsProxyObject@@QAEIIPAVnsXPTMethodInfo@@PAUnsXPTCMiniVariant@@PAVnsIInterfaceInfo@@@Z ; 27609
+??1nsProxyObjectCallInfo@@UAE@XZ ; 27609
+?CallMethod@nsProxyEventObject@@UAGIGPBVnsXPTMethodInfo@@PAUnsXPTCMiniVariant@@@Z ; 27609
+??0nsProxyObjectCallInfo@@QAE@PAVnsProxyObject@@PAVnsXPTMethodInfo@@IPAUnsXPTCVariant@@IPAUPLEvent@@@Z ; 27609
+?Append@NS_ConvertUCS2toUTF8@@IAEXPBGI@Z ; 27265
+?ReplaceChar@nsString@@QAEXPBDG@Z ; 26980
+?CompressSet@nsString@@QAEXPBDGHH@Z ; 26980
+?CompressChars2@@YAHPADIPBD@Z ; 26980
+?CompressWhitespace@nsString@@QAEXHH@Z ; 26980
+?assign_assuming_AddRef@nsCOMPtr_base@@IAEXPAVnsISupports@@@Z ; 26695
+?do_AssignFromElement@nsAString@@MAEXG@Z ; 25781
+??0nsCAutoString@@QAE@ABVCBufDescriptor@@@Z ; 25669
+??0CBufDescriptor@@QAE@PADHIH@Z ; 25623
+?RemoveElementAt@nsSupportsArray@@UAGHI@Z ; 25489
+PL_IsQueueOnCurrentThread ; 25382
+?GetInterfaceInfo@nsProxyEventObject@@UAGIPAPAVnsIInterfaceInfo@@@Z ; 25038
+?Equals@nsACString@@QBEHPBD@Z ; 24972
+?ReadSegments@nsPipeInputStream@nsPipe@@UAGIP6GIPAVnsIInputStream@@PAXPBDIIPAI@Z1I3@Z ; 24934
+?Cut@nsACString@@UAEXII@Z ; 24343
+?RemoveElement@nsSupportsArray@@UAGHPBVnsISupports@@I@Z ; 24174
+?RemoveElement@nsSupportsArray@@UAGIPAVnsISupports@@@Z ; 24174
+??0nsPromiseCSubstring@@QAE@ABVnsACString@@II@Z ; 23764
+?Mid@nsACString@@QBEIAAV1@II@Z ; 23764
+?AssignFromPromise@nsACString@@IAEXABV1@@Z ; 23764
+?ToNewUnicode@nsString@@QBEPAGXZ ; 23688
+?Last@nsACString@@QBEDXZ ; 22996
+?AssignWithConversion@nsCString@@QAEXABVnsAString@@@Z ; 22923
+?IsQueueOnCurrentThread@nsEventQueueImpl@@UAGIPAH@Z ; 22307
+?AppendWithConversion@nsString@@QAEXD@Z ; 22276
+?Compare1To2@@YAHPBD0IH@Z ; 22272
+?GetIID@xptiInterfaceInfo@@UAGIPAPAUnsID@@@Z ; 21683
+?Find@nsString@@QBEHPBDHHH@Z ; 21620
+?AppendFromReadable@nsACString@@IAEXABV1@@Z ; 21546
+??0nsLocalCString@@QAE@PBDI@Z ; 21266
+??0nsAString@@QAE@XZ ; 20650
+?HashCode@nsProxyEventKey@@UBEIXZ ; 20409
+?QueryInterface@nsLocalFile@@UAGIABUnsID@@PAPAX@Z ; 19832
+?QueryElementAt@nsSupportsArray@@UAGIIABUnsID@@PAPAX@Z ; 19439
+?HashCode@nsStringKey@@UBEIXZ ; 19128
+??1nsStringKey@@UAE@XZ ; 18271
+??RnsCreateInstanceByContractID@@UBEIABUnsID@@PAPAX@Z ; 17842
+?GetTypelibGuts@xptiWorkingSet@@QAEPAVxptiTypelibGuts@@ABVxptiTypelib@@@Z ; 17499
+?GetInfoAtNoAddRef@xptiTypelibGuts@@QAEPAVxptiInterfaceInfo@@G@Z ; 17499
+?GetInfoForParam@xptiInterfaceInfo@@UAGIGPBVnsXPTParamInfo@@PAPAVnsIInterfaceInfo@@@Z ; 17441
+?GetIIDForParam@xptiInterfaceInfo@@UAGIGPBVnsXPTParamInfo@@PAPAUnsID@@@Z ; 17381
+?Find@nsString@@QBEHABV1@HHH@Z ; 17158
+?NS_NewAtom@@YAPAVnsIAtom@@PBG@Z ; 17124
+?Delete@nsStr@@SAXAAU1@II@Z ; 17080
+?QueryInterface@nsProxyEventObject@@UAGIABUnsID@@PAPAX@Z ; 17047
+?StripChars@nsStr@@SAXAAU1@PBD@Z ; 16392
+?StripChars@nsCString@@QAEXPBD@Z ; 16392
+?Equals@nsVoidKey@@UBEHPBVnsHashKey@@@Z ; 15797
+?StripChar@nsString@@QAEXGH@Z ; 15611
+?do_AppendFromElementPtrLength@nsACString@@MAEXPBDI@Z ; 15433
+?NS_NewAtom@@YAPAVnsIAtom@@PBD@Z ; 14915
+?strcasecmp@nsCRT@@SAHPBG0@Z ; 14605
+?GetNewOrUsedClass@nsProxyEventClass@@SAPAV1@ABUnsID@@@Z ; 14587
+?do_GetService@@YA?BVnsGetServiceByCID@@ABUnsID@@PAI@Z ; 14568
+??0nsProxyEventObject@@QAE@PAVnsIEventQueue@@HPAVnsISupports@@PAVnsProxyEventClass@@PAV0@@Z ; 14476
+??0nsProxyObject@@QAE@PAVnsIEventQueue@@HPAVnsISupports@@@Z ; 14476
+??1nsProxyEventObject@@UAE@XZ ; 14444
+??_EnsProxyObject@@UAEPAXI@Z ; 14444
+??_EnsProxyEventObject@@UAEPAXI@Z ; 14444
+??1nsProxyObject@@UAE@XZ ; 14444
+?ReleaseData@nsSimpleCharString@@IAEXXZ ; 14127
+??1?$nsSharedBufferHandle@G@@QAE@XZ ; 13784
+?CompressChars1@@YAHPADIPBD@Z ; 13776
+?CompressSet@nsCString@@QAEXPBDGHH@Z ; 13776
+?ReplaceChar@nsCString@@QAEXPBDG@Z ; 13776
+??0NS_ConvertUCS2toUTF8@@QAE@ABVnsAString@@@Z ; 13501
+??0nsCString@@QAE@ABVnsACString@@@Z ; 13490
+?Compact@nsVoidArray@@QAEXXZ ; 13069
+?ResolveAndStat@nsLocalFile@@AAEIH@Z ; 13042
+?Trim@nsCString@@QAEXPBDHHH@Z ; 12473
+?ToCString@nsString@@QBEPADPADII@Z ; 12467
+?Copy@nsXPIDLCString@@SAPADPBD@Z ; 12345
+?StripChars1@@YAHPADIPBD@Z ; 12243
+PL_ProcessPendingEvents ; 11979
+?copy_string@@YAAAV?$LossyConvertEncoding@GD@@AAV?$nsReadingIterator@G@@ABV2@AAV1@@Z ; 11800
+?ToNewCString@@YAPADABVnsAString@@@Z ; 11800
+?ToNewUTF8String@@YAPADABVnsAString@@@Z ; 11776
+?Release@nsProxyObjectManager@@UAGKXZ ; 11736
+??1nsCommonString@@UAE@XZ ; 11669
+?UnlinkBuffer@nsSharedBufferList@@QAEPAVBuffer@1@PAV21@@Z ; 11567
+?FindItem@nsAVLTree@@QBEPAXPAX@Z ; 11472
+?ReallocData@nsSimpleCharString@@IAEXI@Z ; 11366
+?ShiftCharsLeft@@YAXPADIII@Z ; 11222
+?GetYoungest@nsEventQueueImpl@@UAGIPAPAVnsIEventQueue@@@Z ; 10964
+?SetFollowLinks@nsLocalFile@@UAGIH@Z ; 10936
+?GetYoungestEventQueue@nsEventQueueServiceImpl@@AAEIPAVnsIEventQueue@@PAPAV2@@Z ; 10928
+?GetThreadEventQueue@nsEventQueueServiceImpl@@UAGIPAUPRThread@@PAPAVnsIEventQueue@@@Z ; 10925
+??0nsSharedBufferList@@QAE@PAVBuffer@0@@Z ; 10649
+?init_range_from_buffer_list@nsSlidingSubstring@@AAEXXZ ; 10649
+?DestroyBuffers@nsSharedBufferList@@IAEXXZ ; 10647
+??_EnsSlidingSharedBufferList@@UAEPAXI@Z ; 10647
+??1nsSharedBufferList@@UAE@XZ ; 10647
+??RnsCreateInstanceByCID@@UBEIABUnsID@@PAPAX@Z ; 10636
+?Put@nsSupportsHashtable@@QAEHPAVnsHashKey@@PAVnsISupports@@PAPAV3@@Z ; 10605
+?ToLowerCase@nsString@@QBEXAAV1@@Z ; 10514
+?GetPath@nsLocalFile@@UAGIPAPAD@Z ; 10449
+??0nsStringKey@@QAE@PBGHW4Ownership@0@@Z ; 10430
+?AddRef@nsPipeInputStream@nsPipe@@UAGKXZ ; 10377
+?Release@nsPipeInputStream@nsPipe@@UAGKXZ ; 10375
+?Rebind@nsSlidingSubstring@@QAEXABVnsAString@@@Z ; 10240
+?PeekFront@nsDeque@@QAEPAXXZ ; 10192
+??2AtomImpl@@SAPAXIABVnsAString@@@Z ; 10144
+??0AtomImpl@@QAE@XZ ; 10144
+?ResolveEventQueue@nsEventQueueServiceImpl@@UAGIPAVnsIEventQueue@@PAPAV2@@Z ; 10065
+?ToNewUTF8String@nsString@@QBEPADXZ ; 10047
+PL_DHashTableEnumerate ; 9813
+?AddBucket@nsFixedSizeAllocator@@IAEII@Z ; 9776
+?AppendWithConversion@nsCString@@QAEXABVnsString@@H@Z ; 9758
+?Right@nsACString@@QBEIAAV1@I@Z ; 9591
+?Lookup@nsStaticCaseInsensitiveNameTable@@QAEHABVnsCString@@@Z ; 9227
+?Enumerate@nsHashtable@@QAEXP6AHPAVnsHashKey@@PAX1@Z1@Z ; 9133
+?GetParent@xptiInterfaceInfo@@UAGIPAPAVnsIInterfaceInfo@@@Z ; 9105
+_md_EventReceiverProc@16 ; 9061
+?InitWithPath@nsLocalFile@@UAGIPBD@Z ; 8986
+??0nsLocalFile@@QAE@XZ ; 8981
+??_EnsLocalFile@@UAEPAXI@Z ; 8977
+??1nsLocalFile@@UAE@XZ ; 8977
+NS_NewLocalFile ; 8952
+?GetWriteSegment@nsPipe@@QAEIPAPADPAI@Z ; 8809
+?GetProxyForObject@nsProxyObjectManager@@UAGIPAVnsIEventQueue@@ABUnsID@@PAVnsISupports@@HPAPAX@Z ; 8762
+?GetNewOrUsedProxy@nsProxyEventObject@@SAPAV1@PAVnsIEventQueue@@HPAVnsISupports@@ABUnsID@@@Z ; 8762
+?Equals@nsProxyEventKey@@UBEHPBVnsHashKey@@@Z ; 8745
+?AddRef@nsPipeOutputStream@nsPipe@@UAGKXZ ; 8650
+?Release@nsPipeOutputStream@nsPipe@@UAGKXZ ; 8649
+?Read@nsPipeInputStream@nsPipe@@UAGIPADIPAI@Z ; 8617
+??4nsXPIDLCString@@QAEAAV0@PBD@Z ; 8570
+??1nsSimpleCharString@@QAE@XZ ; 8555
+?Equals@nsStringKey@@UBEHPBVnsHashKey@@@Z ; 8497
+?AddRefData@nsSimpleCharString@@IAEXXZ ; 8367
+?Init@nsFixedSizeAllocator@@QAEIPBDPBIHHH@Z ; 7954
+??0nsStringKey@@QAE@ABVnsAString@@@Z ; 7944
+?Release@nsArrayEnumerator@@UAGKXZ ; 7923
+?PostCompleted@nsProxyObjectCallInfo@@QAEXXZ ; 7863
+?SetCompleted@nsProxyObjectCallInfo@@QAEXXZ ; 7863
+??0nsCString@@QAE@ABV0@@Z ; 7622
+?AppendNewSegment@nsSegmentedBuffer@@QAEPADXZ ; 7622
+??_GAtomImpl@@UAEPAXI@Z ; 7566
+??1AtomImpl@@UAE@XZ ; 7566
+??0nsCString@@QAE@PBD@Z ; 7541
+??0nsAutoString@@QAE@ABVCBufDescriptor@@@Z ; 7529
+??0NS_ConvertASCIItoUCS2@@QAE@PBDI@Z ; 7452
+??0nsString@@QAE@ABVnsAString@@@Z ; 7419
+??0CBufDescriptor@@QAE@PAGHIH@Z ; 7406
+??0nsCreateInstanceByContractID@@QAE@PBDPAVnsISupports@@PAI@Z ; 7402
+?EnumerateForwards@nsVoidArray@@QAEHP6AHPAX0@Z0@Z ; 7195
+?AppendInt@nsCString@@QAEXHH@Z ; 7047
+??RnsGetWeakReference@@UBEIABUnsID@@PAPAX@Z ; 7028
+?NS_GetWeakReference@@YAPAVnsIWeakReference@@PAVnsISupports@@PAI@Z ; 7022
+?Clone@nsLocalFile@@UAGIPAPAVnsIFile@@@Z ; 6960
+?AppendRelativePath@nsLocalFile@@UAGIPBD@Z ; 6927
+?Empty@nsSegmentedBuffer@@QAEXXZ ; 6878
+??_EnsIDKey@@UAEPAXI@Z ; 6876
+?Append@nsLocalFile@@UAGIPBD@Z ; 6818
+?RFindChar@nsStr@@SAHABU1@GHHH@Z ; 6753
+?RFindChar@nsString@@QBEHGHHH@Z ; 6753
+?GetWeakReference@nsSupportsWeakReference@@UAGIPAPAVnsIWeakReference@@@Z ; 6751
+?Release@nsMemoryImpl@@UAGKXZ ; 6468
+??1nsSupportsWeakReference@@UAE@XZ ; 6428
+?SetNonBlocking@nsPipeInputStream@nsPipe@@UAGIH@Z ; 6306
+PL_DHashTableRawRemove ; 6270
+?GetNext@nsArrayEnumerator@@UAGIPAPAVnsISupports@@@Z ; 6180
+?ReleaseService@nsServiceManagerImpl@@UAGIABUnsID@@PAVnsISupports@@PAVnsIShutdownListener@@@Z ; 6156
+?RFindSubstr@nsStr@@SAHABU1@0HHH@Z ; 6056
+?RFind@nsCString@@QBEHPBDHHH@Z ; 6052
+?HasMoreElements@nsDirEnumerator@@UAGIPAH@Z ; 5962
+?QueryInterface@nsProxyObjectManager@@UAGIABUnsID@@PAPAX@Z ; 5920
+?GetReadableFragment@nsSlidingString@@MBEPBGAAU?$nsReadableFragment@G@@W4nsFragmentRequest@@I@Z ; 5909
+?ShiftDoubleCharsLeft@@YAXPADIII@Z ; 5858
+?Clone@nsProxyEventKey@@UBEPAVnsHashKey@@XZ ; 5832
+?IsManagerShutdown@nsProxyObjectManager@@SAHXZ ; 5823
+?ReleaseService@nsServiceManager@@SAIABUnsID@@PAVnsISupports@@PAVnsIShutdownListener@@@Z ; 5681
+??4nsSimpleCharString@@QAEXABV0@@Z ; 5572
+?Copy@nsXPIDLString@@SAPAGPBG@Z ; 5526
+??0nsString@@QAE@PBG@Z ; 5504
+?Find@nsProxyEventObject@@QAEPAV1@ABUnsID@@@Z ; 5501
+?WriteSegments@nsPipeOutputStream@nsPipe@@UAGIP6GIPAVnsIOutputStream@@PAXPADIIPAI@Z1I3@Z ; 5497
+?Read@StringUnicharInputStream@@UAGIPAGIIPAI@Z ; 5482
+?WriteFrom@nsPipeOutputStream@nsPipe@@UAGIPAVnsIInputStream@@IPAI@Z ; 5388
+?ToNewCString@nsString@@QBEPADXZ ; 5351
+?Release@nsInputStreamTee@@UAGKXZ ; 5341
+?IndexOf@nsSupportsArray@@UAGHPBVnsISupports@@@Z ; 5281
+?IndexOfStartingAt@nsSupportsArray@@UAGHPBVnsISupports@@I@Z ; 5281
+??6nsOutputStream@@QAEAAV0@PBD@Z ; 5112
+?ToInteger@nsCString@@QBEHPAHI@Z ; 5109
+?do_AssignFromElementPtrLength@nsACString@@MAEXPBDI@Z ; 5103
+?Exists@nsLocalFile@@UAGIPAH@Z ; 5085
+?PL_HashTableInit@@YA?AW4PRStatus@@PAUPLHashTable@@IP6AIPBX@ZP6AH11@Z3PBUPLHashAllocOps@@PAX@Z ; 4964
+??0nsHashtable@@QAE@IH@Z ; 4964
+?Get@nsInt2StrHashtable@@QAEPADI@Z ; 4864
+??BnsSimpleCharString@@QAEPADXZ ; 4785
+?GetConstant@xptiInterfaceInfo@@UAGIGPAPBVnsXPTConstant@@@Z ; 4716
+?PL_HashTableFinalize@@YAXPAUPLHashTable@@@Z ; 4596
+??1nsHashtable@@UAE@XZ ; 4596
+?do_AssignFromElementPtrLength@nsAString@@MAEXPBGI@Z ; 4541
+?Error@nsFileSpec@@QBEIXZ ; 4535
+?GetSpecialEventQueue@nsEventQueueServiceImpl@@UAGIHPAPAVnsIEventQueue@@@Z ; 4454
+?GetStringProperty@nsPersistentProperties@@UAGIABVnsString@@AAV2@@Z ; 4441
+?DumpStatistics@nsTraceRefcnt@@SAIW4StatisticsType@1@PAU_iobuf@@@Z ; 4434
+?GetBufferHandle@nsPrivateSharableString@@UBEPBV?$nsBufferHandle@G@@XZ ; 4434
+?Release@xptiInterfaceInfoManager@@UAGKXZ ; 4417
+?Clone@nsCStringKey@@UBEPAVnsHashKey@@XZ ; 4332
+?normalize_backward@?$nsWritingIterator@D@@QAEXXZ ; 4288
+??1nsFileSpec@@UAE@XZ ; 4256
+?AddRef@BasicStringImpl@@UAGKXZ ; 4185
+??_EnsCStringKey@@UAEPAXI@Z ; 4173
+?ToCString@nsCString@@QBEPADPADII@Z ; 4056
+?First@nsDequeIterator@@QAEAAV1@XZ ; 4049
+??_EnsSubsumeStr@@UAEPAXI@Z ; 4048
+?InsertStringAt@nsStringArray@@QAEHABVnsAString@@H@Z ; 4026
+?Release@BasicStringImpl@@UAGKXZ ; 3967
+?ReleaseValues@nsProperties@@SAHPAVnsHashKey@@PAX1@Z ; 3966
+?StripChars2@@YAHPADIPBD@Z ; 3927
+?ToFloat@nsString@@QBEMPAH@Z ; 3910
+?Release@nsThreadPool@@UAGKXZ ; 3896
+??0nsPromiseFlatCString@@IAE@ABVnsACString@@@Z ; 3888
+??1nsPromiseFlatCString@@UAE@XZ ; 3878
+?Clone@nsStringKey@@UBEPAVnsHashKey@@XZ ; 3824
+?RFindChar2@@YAHPBDIHGHH@Z ; 3738
+??_EnsStringKey@@UAEPAXI@Z ; 3721
+?Alloc@ArenaImpl@@UAGPAXI@Z ; 3688
+?DeleteFirstSegment@nsSegmentedBuffer@@QAEHXZ ; 3646
+?OpenANSIFileDesc@nsLocalFile@@UAGIPBDPAPAU_iobuf@@@Z ; 3547
+?EqualsWithConversion@nsCString@@QBEHPBDHH@Z ; 3544
+?EqualsIgnoreCase@nsCString@@QBEHPBDH@Z ; 3544
+?ResolvePath@nsLocalFile@@AAEIPBDHPAPAD@Z ; 3539
+?CopyFrom@nsSimpleCharString@@QAEXPBDI@Z ; 3498
+?FindCharInReadable@@YAHGAAV?$nsReadingIterator@G@@ABV1@@Z ; 3480
+??0nsPromiseSubstring@@QAE@ABV?$nsReadingIterator@G@@0@Z ; 3431
+?GetStringUTF8@nsRegistry@@UAGIIPBDPAPAD@Z ; 3345
+??0nsSegmentedBuffer@@QAE@XZ ; 3334
+??1nsSegmentedBuffer@@QAE@XZ ; 3333
+?GetInfoForName@xptiInterfaceInfoManager@@UAGIPBDPAPAVnsIInterfaceInfo@@@Z ; 3332
+?Init@nsSegmentedBuffer@@QAEIIIPAVnsIMemory@@@Z ; 3307
+?HasInterfaceRecord@xptiInterfaceInfo@@QBEHXZ ; 3300
+?Compare@@YAHABVnsACString@@0@Z ; 3236
+?vsmprintf@nsTextFormatter@@SAPAGPBGPAD@Z ; 3228
+?smprintf@nsTextFormatter@@SAPAGPBGZZ ; 3228
+?QueryInterface@nsMemoryImpl@@UAGIABUnsID@@PAPAX@Z ; 3156
+??0nsPipe@@QAE@XZ ; 3153
+?Close@nsPipeOutputStream@nsPipe@@UAGIXZ ; 3153
+?SetObserver@nsPipeInputStream@nsPipe@@UAGIPAVnsIInputStreamObserver@@@Z ; 3153
+?Initialize@nsPipe@@UAGIIIHHPAVnsIMemory@@@Z ; 3153
+?NS_NewPipe@@YAIPAPAVnsIInputStream@@PAPAVnsIOutputStream@@IIHHPAVnsIMemory@@@Z ; 3153
+?Close@nsPipeInputStream@nsPipe@@UAGIXZ ; 3152
+??1nsPipe@@UAE@XZ ; 3152
+??_GnsPipe@@UAEPAXI@Z ; 3152
+?GetLeafName@nsLocalFile@@UAGIPAPAD@Z ; 3138
+?Parse@nsID@@QAEHPBD@Z ; 3088
+?GetLeaf@nsSimpleCharString@@QBEPADD@Z ; 3070
+?GetLeafName@nsFileSpec@@QBEPADXZ ; 3070
+?Flush@nsPipeOutputStream@nsPipe@@UAGIXZ ; 3043
+?CheckForDeactivation@nsEventQueueImpl@@AAEXXZ ; 3018
+?RFindChar1@@YAHPBDIHGHH@Z ; 3015
+??0nsCAutoString@@QAE@ABVnsACString@@@Z ; 3014
+?GetNext@nsDirEnumerator@@UAGIPAPAVnsISupports@@@Z ; 2976
+?ProcessPendingEvents@nsEventQueueImpl@@UAGIXZ ; 2951
+?GetInterfaceInfoManagerNoAddRef@xptiInterfaceInfoManager@@SAPAV1@XZ ; 2948
+?CountChar@nsAString@@QBEIG@Z ; 2937
+?AppendInt@nsString@@QAEXHH@Z ; 2922
+?ToUpperCase@nsString@@QAEXXZ ; 2900
+nsUnescapeCount ; 2828
+nsUnescape ; 2828
+??0nsSimpleCharString@@QAE@ABV0@@Z ; 2795
+??4nsFileSpec@@QAEXABV0@@Z ; 2739
+??0nsFileSpec@@QAE@ABV0@@Z ; 2731
+?StripWhitespace@nsString@@QAEXXZ ; 2714
+XPTI_GetInterfaceInfoManager ; 2696
+?StringAt@nsStringArray@@QBEPAVnsString@@H@Z ; 2681
+??0nsArrayEnumerator@@QAE@PAVnsISupportsArray@@@Z ; 2637
+??1nsArrayEnumerator@@UAE@XZ ; 2637
+?GetPRThread@nsThread@@UAGIPAPAUPRThread@@@Z ; 2623
+?GetMainThread@nsIThread@@SAIPAPAV1@@Z ; 2622
+NS_NewArrayEnumerator ; 2582
+??_EnsArrayEnumerator@@UAEPAXI@Z ; 2582
+?CallQueryInterfaceOnProxy@nsProxyEventClass@@AAEIPAVnsProxyEventObject@@ABUnsID@@PAPAV2@@Z ; 2571
+?GetQueue@nsProxyEventObject@@QBEPAVnsIEventQueue@@XZ ; 2571
+?DelegatedQueryInterface@nsProxyEventClass@@UAGIPAVnsProxyEventObject@@ABUnsID@@PAPAX@Z ; 2571
+?GetRealObject@nsProxyEventObject@@QBEPAVnsISupports@@XZ ; 2571
+??_EnsWeakReference@@EAEPAXI@Z ; 2556
+?ReadSegments@ConstCharImpl@@MAGIP6GIPAVnsIInputStream@@PAXPBDIIPAI@Z1I3@Z ; 2520
+?IsDone@nsRegSubtreeEnumerator@@UAGIXZ ; 2490
+?Next@nsRegSubtreeEnumerator@@UAGIXZ ; 2490
+?advance@nsRegSubtreeEnumerator@@MAGIXZ ; 2451
+?GetErrorStringBundleKey@nsErrorService@@UAGIIPAPAD@Z ; 2432
+?GetErrorStringBundle@nsErrorService@@UAGIFPAPAD@Z ; 2432
+?GetIndexOf@nsSupportsArray@@UAGIPAVnsISupports@@PAH@Z ; 2409
+?ToNewUnicode@nsCString@@QBEPAGXZ ; 2376
+?ToNewCString@@YAPADABVnsACString@@@Z ; 2364
+?copy_string@@YAAAPADAAV?$nsReadingIterator@D@@ABV1@AAPAD@Z ; 2364
+?WriteSegmentFun@nsInputStreamTee@@CGIPAVnsIInputStream@@PAXPBDIIPAI@Z ; 2346
+?CurrentItemInPlaceUTF8@nsRegSubtreeEnumerator@@UAGIPAIPAPBD@Z ; 2320
+PL_DHashAllocTable ; 2253
+?Release@nsFileSpecImpl@@UAGKXZ ; 2241
+?GetSharedBufferHandle@nsCommonCString@@MBEPBV?$nsSharedBufferHandle@D@@XZ ; 2217
+?assign@nsCommonString@@IAEXABVnsAString@@@Z ; 2217
+?ReleaseReference@?$nsSharedBufferHandle@G@@QBEXXZ ; 2217
+?NS_AllocateContiguousHandleWithData@@YAPAV?$nsSharedBufferHandle@G@@PBV1@ABVnsAString@@I@Z ; 2217
+?QueryInterface@nsFileSpecImpl@@UAGIABUnsID@@PAPAX@Z ; 2172
+?GetRequest@nsThreadPool@@QAEPAVnsIRunnable@@PAVnsIThread@@@Z ; 2147
+PL_DHashFreeTable ; 2125
+?Clear@nsCStringArray@@QAEXXZ ; 2122
+?ReadSegments@nsInputStreamTee@@UAGIP6GIPAVnsIInputStream@@PAXPBDIIPAI@Z1I3@Z ; 2115
+?TeeSegment@nsInputStreamTee@@AAEIPBDI@Z ; 2045
+?DispatchRequest@nsThreadPool@@UAGIPAVnsIRunnable@@@Z ; 2038
+??1nsThreadPoolBusyBody@@QAE@XZ ; 2038
+??0nsThreadPoolBusyBody@@QAE@PAVnsThreadPool@@@Z ; 2038
+??0nsCreateInstanceByCID@@QAE@ABUnsID@@PAVnsISupports@@PAI@Z ; 2029
+?ReplaceChar@nsCString@@QAEXGG@Z ; 2022
+?CloseStream@nsFileSpecImpl@@UAGIXZ ; 1968
+?do_InsertFromReadable@nsACString@@MAEXABV1@I@Z ; 1965
+?do_InsertFromElement@nsACString@@MAEXDI@Z ; 1965
+??_EnsFileSpecImpl@@UAEPAXI@Z ; 1955
+??1nsFileSpecImpl@@UAE@XZ ; 1955
+??0nsSimpleCharString@@QAE@PBD@Z ; 1936
+?RFindCharInSet@nsCString@@QBEHPBDH@Z ; 1913
+?RFindCharInSet@nsStr@@SAHABU1@0HH@Z ; 1913
+?Release@ByteBufferImpl@@UAGKXZ ; 1905
+?SkipWhiteSpace@nsPersistentProperties@@QAEHH@Z ; 1898
+?First@nsACString@@QBEDXZ ; 1881
+??0nsVoidArray@@QAE@H@Z ; 1876
+?copy_string_backward@@YAAAV?$nsWritingIterator@D@@ABV?$nsReadingIterator@D@@AAV2@AAV1@@Z ; 1834
+?QueryInterface@nsPipeInputStream@nsPipe@@UAGIABUnsID@@PAPAX@Z ; 1782
+?QueryInterface@nsPipe@@UAGIABUnsID@@PAPAX@Z ; 1782
+?CountCharInReadable@@YAIABVnsAString@@G@Z ; 1767
+?IsDirectory@nsLocalFile@@UAGIPAH@Z ; 1765
+?GetFileSpec@nsFileSpecImpl@@UAGIPAVnsFileSpec@@@Z ; 1765
+?CopyUnicodeTo@@YAPAGABVnsAString@@IPAGI@Z ; 1749
+NS_QuickSort ; 1729
+??1nsStringArray@@UAE@XZ ; 1709
+??0nsStringArray@@QAE@XZ ; 1709
+?IsScriptable@xptiInterfaceInfo@@UAGIPAH@Z ; 1690
+?Find@nsCString@@QBEHPBGHHH@Z ; 1674
+?SetLeafName@nsFileSpec@@QAEXPBD@Z ; 1670
+?LeafReplace@nsSimpleCharString@@QAEXDPBD@Z ; 1670
+?NextLine@ManifestLineReader@@QAEHXZ ; 1658
+??0nsFileSpec@@QAE@XZ ; 1656
+PL_DHashTableInit ; 1622
+??4nsSimpleCharString@@QAEXPBD@Z ; 1598
+?GetInterfaceIsArgNumberForParam@xptiInterfaceInfo@@UAGIGPBVnsXPTParamInfo@@PAE@Z ; 1555
+?Init@nsInputStreamTee@@UAGIPAVnsIInputStream@@PAVnsIOutputStream@@@Z ; 1550
+?QueryInterface@nsInputStreamTee@@UAGIABUnsID@@PAPAX@Z ; 1550
+?Right@nsAString@@QBEIAAV1@I@Z ; 1518
+PL_DHashTableFinish ; 1494
+??0nsFileSpecImpl@@QAE@ABVnsFileSpec@@@Z ; 1446
+?MakeInterface@nsFileSpecImpl@@SAIABVnsFileSpec@@PAPAVnsIFileSpec@@@Z ; 1446
+?NS_NewFileSpecWithSpec@@YAIABVnsFileSpec@@PAPAVnsIFileSpec@@@Z ; 1437
+??0xptiInterfaceInfo@@QAE@PBDABUnsID@@ABVxptiTypelib@@PAVxptiWorkingSet@@@Z ; 1434
+?CopyName@xptiInterfaceInfo@@AAEXPBDPAVxptiWorkingSet@@@Z ; 1434
+?SetScriptableFlag@xptiInterfaceInfo@@QAEXH@Z ; 1434
+??1xptiInterfaceInfo@@UAE@XZ ; 1427
+??_GxptiInterfaceInfo@@UAEPAXI@Z ; 1427
+??1nsSupportsHashtable@@UAE@XZ ; 1406
+??0nsACString@@QAE@XZ ; 1361
+?Exists@nsHashtable@@QAEHPAVnsHashKey@@@Z ; 1348
+?SetData@nsSupportsVoidImpl@@UAGIPAX@Z ; 1337
+??0BasicStringImpl@@QAE@XZ ; 1319
+?QueryInterface@BasicStringImpl@@UAGIABUnsID@@PAPAX@Z ; 1319
+??0ConstCharImpl@@QAE@PBDH@Z ; 1319
+?NewMonitor@nsAutoMonitor@@SAPAUPRMonitor@@PBD@Z ; 1312
+??1BasicStringImpl@@UAE@XZ ; 1309
+?DestroyMonitor@nsAutoMonitor@@SAXPAUPRMonitor@@@Z ; 1309
+??_EBasicStringImpl@@UAEPAXI@Z ; 1309
+?Enter@nsAutoCMonitor@@QAEXXZ ; 1307
+?Exit@nsAutoCMonitor@@QAEXXZ ; 1307
+?StringAllocator_wchar_t@@YAAAV?$nsStringAllocator@G@@XZ ; 1306
+?get_allocator@?$nsSharedBufferHandle@G@@IBEAAV?$nsStringAllocator@G@@XZ ; 1306
+?Deallocate@?$XPCOM_StringAllocator@G@@UBEXPAG@Z ; 1306
+NS_NewCharInputStream ; 1303
+?Release@nsRegSubtreeEnumerator@@UAGKXZ ; 1289
+??0nsDequeIterator@@QAE@ABVnsDeque@@H@Z ; 1284
+??FnsDequeIterator@@QAEPAXXZ ; 1284
+?End@nsDeque@@QBE?AVnsDequeIterator@@XZ ; 1284
+?OpenNSPRFileDesc@nsLocalFile@@UAGIHHPAPAUPRFileDesc@@@Z ; 1275
+?StrInsert@nsStr@@SAXAAU1@IABU1@IH@Z ; 1266
+?InsertWithConversion@nsString@@QAEXPBDIH@Z ; 1266
+?ShiftDoubleCharsRight@@YAXPADIII@Z ; 1266
+??0nsSupportsVoidImpl@@QAE@XZ ; 1260
+??_GnsSupportsVoidImpl@@UAEPAXI@Z ; 1260
+??1nsSupportsVoidImpl@@UAE@XZ ; 1260
+?QueryInterface@nsSupportsVoidImpl@@UAGIABUnsID@@PAPAX@Z ; 1260
+?QueryInterface@ConverterInputStream@@UAGIABUnsID@@PAPAX@Z ; 1258
+?get_at_eof@nsRandomAccessInputStream@@MBEHXZ ; 1241
+?GetAtEOF@FileImpl@@UAGIPAH@Z ; 1241
+?get_at_eof@nsRandomAccessStoreClient@@MBEHXZ ; 1241
+?GetTargetArraySize@nsObserverListEnumerator@@ABEIXZ ; 1208
+??YnsSimpleCharString@@QAEXPBD@Z ; 1187
+??_EStringUnicharInputStream@@UAEPAXI@Z ; 1178
+??1StringUnicharInputStream@@UAE@XZ ; 1178
+??0StringUnicharInputStream@@QAE@PAVnsString@@@Z ; 1178
+?NS_NewStringUnicharInputStream@@YAIPAPAVnsIUnicharInputStream@@PAVnsString@@@Z ; 1178
+??0nsInputStreamTee@@QAE@XZ ; 1164
+??_GnsInputStreamTee@@UAEPAXI@Z ; 1164
+??1nsInputStreamTee@@UAE@XZ ; 1164
+?NS_NewInputStreamTee@@YAIPAPAVnsIInputStream@@PAV1@PAVnsIOutputStream@@@Z ; 1164
+?GetTypelibRecord@xptiInterfaceInfo@@QBEABVxptiTypelib@@XZ ; 1156
+?Write@nsStorageStream@@UAGIPBDIPAI@Z ; 1138
+?GetObserverList@nsObserverService@@EAGIPBGPAPAVnsIObserverList@@@Z ; 1119
+?HasMoreElements@nsArrayEnumerator@@UAGIPAH@Z ; 1100
+?GetCString@nsFileSpec@@QBEPBDXZ ; 1098
+PL_DHashVoidPtrKeyStub ; 1098
+?strtok@nsCRT@@SAPADPADPBDPAPAD@Z ; 1084
+?GetInfoForIID@xptiInterfaceInfoManager@@UAGIPBUnsID@@PAPAVnsIInterfaceInfo@@@Z ; 1081
+??_EnsSupportsArrayEnumerator@@UAEPAXI@Z ; 1065
+??0nsSupportsArrayEnumerator@@QAE@PAVnsISupportsArray@@@Z ; 1065
+??1nsSupportsArrayEnumerator@@UAE@XZ ; 1065
+?Enumerate@nsSupportsArray@@UAGIPAPAVnsIEnumerator@@@Z ; 1065
+?First@nsSupportsArrayEnumerator@@UAGIXZ ; 1065
+?WriteFully@nsBinaryOutputStream@@QAEIPBDI@Z ; 1055
+?CurrentItem@nsSupportsArrayEnumerator@@UAGIPAPAVnsISupports@@@Z ; 1053
+?GetConstantCount@xptiInterfaceInfo@@UAGIPAG@Z ; 1040
+?Clone@nsIDKey@@UBEPAVnsHashKey@@XZ ; 1035
+?SetStringProperty@nsPersistentProperties@@UAGIABVnsString@@AAV2@1@Z ; 1006
+?Next@nsSupportsArrayEnumerator@@UAGIXZ ; 993
+?Release@nsStorageInputStream@@UAGKXZ ; 981
+?GetMethodCount@xptiInterfaceInfo@@UAGIPAG@Z ; 970
+?QueryInterface@nsObserverService@@UAGIABUnsID@@PAPAX@Z ; 948
+?FindChar@nsAString@@QBEHGI@Z ; 941
+?LinkBuffer@nsSharedBufferList@@QAEXPAVBuffer@1@00@Z ; 920
+?IsIID@xptiInterfaceInfo@@UAGIPBUnsID@@PAH@Z ; 918
+?AppendBuffer@nsSlidingString@@QAEXPAG00@Z ; 900
+??1nsFilePath@@UAE@XZ ; 886
+?NativeToUnix@nsFileSpecHelpers@@YAXAAVnsSimpleCharString@@@Z ; 886
+?SetDeallocator@nsDeque@@QAEXPAVnsDequeFunctor@@@Z ; 885
+?IsASCII@@YAHABVnsAString@@@Z ; 875
+?SkipLine@nsPersistentProperties@@QAEHH@Z ; 862
+?EnumerateObserverList@nsObserverService@@UAGIPBGPAPAVnsIEnumerator@@@Z ; 855
+?EnumerateObserverList@nsObserverList@@UAGIPAPAVnsIEnumerator@@@Z ; 855
+??4nsPersistentFileDescriptor@@QAEXABVnsFileSpec@@@Z ; 849
+??1nsPersistentFileDescriptor@@UAE@XZ ; 849
+??0nsPersistentFileDescriptor@@QAE@ABVnsFileSpec@@@Z ; 849
+?GetData@nsPersistentFileDescriptor@@QBEXAAVnsSimpleCharString@@@Z ; 849
+?GetPersistentDescriptorString@nsFileSpecImpl@@UAGIPAPAD@Z ; 849
+?FindInReadable@@YAHABVnsAString@@AAV?$nsReadingIterator@G@@1@Z ; 819
+?nsCID_Destroy@@YAHPAVnsHashKey@@PAX1@Z ; 773
+?Read@nsInputStreamTee@@UAGIPADIPAI@Z ; 769
+??1nsFactoryEntry@@QAE@XZ ; 737
+?nsFactoryEntry_Destroy@@YAHPAVnsHashKey@@PAX1@Z ; 733
+??0nsFileSpecImpl@@QAE@XZ ; 726
+?NS_NewFileSpec@@YAIPAPAVnsIFileSpec@@@Z ; 726
+?Create@nsFileSpecImpl@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 726
+?UnixToNative@nsFileSpecHelpers@@YAXAAVnsSimpleCharString@@@Z ; 719
+?Invalidate@xptiInterfaceInfo@@QAEXXZ ; 717
+?AppendWithConversion@nsCString@@QAEXPBGH@Z ; 697
+??0nsFactoryEntry@@QAE@ABUnsID@@PBD1PAVnsIComponentLoader@@@Z ; 695
+?SetInfoAt@xptiTypelibGuts@@QAEIGPAVxptiInterfaceInfo@@@Z ; 683
+PL_DHashGetKeyStub ; 678
+PL_DHashMoveEntryStub ; 678
+?GrowCapacity@nsDeque@@AAEAAV1@XZ ; 673
+?AssignWithConversion@nsString@@QAEXPBDH@Z ; 665
+??4nsFilePath@@QAEXABVnsFileSpec@@@Z ; 659
+??0nsFilePath@@QAE@ABVnsFileSpec@@@Z ; 659
+?Canonify@nsFileSpecHelpers@@YAXAAVnsSimpleCharString@@H@Z ; 653
+?FromFileSpec@nsFileSpecImpl@@UAGIPBVnsIFileSpec@@@Z ; 652
+?GetValueType@nsRegistry@@UAGIIPBDPAI@Z ; 652
+?GetBytesUTF8@nsRegistry@@UAGIIPBDPAIPAPAE@Z ; 651
+?Write32@nsBinaryOutputStream@@UAGII@Z ; 649
+?EnumerateBackwards@nsSupportsArray@@UAGHP6AHPAVnsISupports@@PAX@Z1@Z ; 648
+?SetFromFileSpec@nsFileSpecImpl@@UAGIABVnsFileSpec@@@Z ; 634
+?smprintf_free@nsTextFormatter@@SAXPAG@Z ; 623
+?nsEndl@@YAAAVnsOutputStream@@AAV1@@Z ; 615
+?QueryInterface@nsGenericFactory@@UAGIABUnsID@@PAPAX@Z ; 606
+?Equals@nsAString@@QBEHPBG@Z ; 599
+?strcasecmp@nsCRT@@SAHPBGPBD@Z ; 585
+?put@nsOutputStream@@QAEXD@Z ; 572
+?IsFile@nsLocalFile@@UAGIPAH@Z ; 570
+?ForEach@nsDeque@@QBEXAAVnsDequeFunctor@@@Z ; 558
+?Release@EmptyEnumeratorImpl@@UAGKXZ ; 553
+NS_NewEmptyEnumerator ; 553
+?HasMoreElements@EmptyEnumeratorImpl@@UAGIPAH@Z ; 552
+?AddRef@FileImpl@@UAGKXZ ; 549
+?Release@FileImpl@@UAGKXZ ; 542
+?snprintf@nsTextFormatter@@SAIPAGIPBGZZ ; 534
+?vsnprintf@nsTextFormatter@@SAIPAGIPBGPAD@Z ; 534
+?Available@nsPipeInputStream@nsPipe@@UAGIPAI@Z ; 533
+?PushFront@nsDeque@@QAEAAV1@PAX@Z ; 522
+?AddItem@nsAVLTree@@QAE?AW4eAVLStatus@@PAX@Z ; 518
+??0nsAutoString@@QAE@PBGH@Z ; 509
+?IsDone@nsObserverListEnumerator@@UAGIXZ ; 479
+?MoveToIndex@nsObserverListEnumerator@@AAEII@Z ; 479
+?ReleaseService@nsServiceManager@@SAIPBDPAVnsISupports@@PAVnsIShutdownListener@@@Z ; 477
+?ReleaseService@nsServiceManagerImpl@@UAGIPBDPAVnsISupports@@PAVnsIShutdownListener@@@Z ; 477
+?AppendWithConversion@nsCString@@QAEXABVnsAString@@@Z ; 467
+?CreateDll@nsNativeComponentLoader@@AAEIPAVnsIFile@@PBDPA_J2PAPAVnsDll@@@Z ; 466
+?Flush@FileImpl@@UAGIXZ ; 455
+??1nsNSPRPath@@UAE@XZ ; 444
+??BnsNSPRPath@@QBEPBDXZ ; 444
+??0nsByteArrayInputStream@@QAE@PADI@Z ; 443
+??_EnsByteArrayInputStream@@UAEPAXI@Z ; 443
+??1nsByteArrayInputStream@@UAE@XZ ; 443
+?QueryInterface@nsByteArrayInputStream@@UAGIABUnsID@@PAPAX@Z ; 443
+?NS_NewByteArrayInputStream@@YAIPAPAVnsIByteArrayInputStream@@PADK@Z ; 443
+PL_DHashMatchEntryStub ; 442
+?ScriptableFlagIsValid@xptiInterfaceInfo@@ABEHXZ ; 439
+?PartiallyResolveLocked@xptiInterfaceInfo@@QAEHPAUXPTInterfaceDescriptor@@PAVxptiWorkingSet@@@Z ; 439
+??1xptiInterfaceGuts@@QAE@XZ ; 439
+?QueryInterface@FileImpl@@UAGIABUnsID@@PAPAX@Z ; 433
+??1xptiFile@@QAE@XZ ; 424
+?QueryInterface@nsSupportsStringImpl@@UAGIABUnsID@@PAPAX@Z ; 422
+?ReplaceChar@nsString@@QAEXGG@Z ; 421
+?Notify@nsObserverService@@UAGIPAVnsISupports@@PBG1@Z ; 416
+??0nsSlidingString@@QAE@PAG00@Z ; 408
+?NewWrappingBuffer@nsSharedBufferList@@SAPAVBuffer@1@PAG00@Z ; 408
+??0nsSlidingSubstring@@IAE@PAVnsSlidingSharedBufferList@@@Z ; 408
+??0nsCStringArray@@QAE@XZ ; 394
+??1nsCStringArray@@UAE@XZ ; 393
+??EnsDirectoryIterator@@QAEAAV0@XZ ; 377
+?Reset@nsSupportsHashtable@@QAEXXZ ; 370
+?ReadSegments@nsByteArrayInputStream@@UAGIP6GIPAVnsIInputStream@@PAXPBDIIPAI@Z1I3@Z ; 356
+?GetFileSize@nsLocalFile@@UAGIPA_J@Z ; 354
+?SetDataWithLength@nsSupportsStringImpl@@UAGIIPBD@Z ; 344
+??0nsSupportsStringImpl@@QAE@XZ ; 344
+??1nsSupportsStringImpl@@UAE@XZ ; 337
+??_EnsSupportsStringImpl@@UAEPAXI@Z ; 337
+?GetModule@nsDll@@QAEIPAVnsISupports@@PAPAVnsIModule@@@Z ; 331
+?Release@nsStorageStream@@UAGKXZ ; 328
+?Release@nsSupportsIDImpl@@UAGKXZ ; 327
+?CopyASCIItoUCS2@@YAXABVnsACString@@AAVnsAString@@@Z ; 327
+?copy_string@@YAAAV?$LossyConvertEncoding@DG@@AAV?$nsReadingIterator@D@@ABV2@AAV1@@Z ; 327
+??_EnsCString@@UAEPAXI@Z ; 324
+?StringAt@nsStringArray@@QBEXHAAVnsAString@@@Z ; 321
+?ToString@nsID@@QBEPADXZ ; 319
+?GetLength@UnicharBufferImpl@@UBGHXZ ; 316
+?Fill@ByteBufferImpl@@UAGHPAIPAVnsIInputStream@@I@Z ; 316
+?Fill@ConverterInputStream@@IAEHPAI@Z ; 316
+?copy_string_backward@@YAAAV?$nsWritingIterator@G@@ABV?$nsReadingIterator@G@@AAV2@AAV1@@Z ; 310
+?do_InsertFromReadable@nsAString@@MAEXABV1@I@Z ; 310
+??0nsFileSpec@@QAE@PBDH@Z ; 307
+?SetData@nsSupportsStringImpl@@UAGIPBD@Z ; 295
+?InsertCStringAt@nsCStringArray@@QAEHABVnsCString@@H@Z ; 288
+??YnsFileSpec@@QAEXPBD@Z ; 281
+?CompressWhitespace@nsCString@@QAEXHH@Z ; 278
+?GetFactory@nsNativeComponentLoader@@UAGIABUnsID@@PBD1PAPAVnsIFactory@@@Z ; 273
+?GetFactoryFromModule@nsNativeComponentLoader@@AAEIPAVnsDll@@ABUnsID@@PAPAVnsIFactory@@@Z ; 273
+?GetReadableFragment@nsPromiseConcatenation@@MBEPBGAAU?$nsReadableFragment@G@@W4nsFragmentRequest@@I@Z ; 268
+?Load@nsDll@@QAEHXZ ; 254
+?HasMoreElements@nsAdapterEnumerator@@UAGIPAH@Z ; 251
+?Next@nsObserverListEnumerator@@UAGIXZ ; 250
+??0nsSubsumeStr@@QAE@XZ ; 250
+?Subsume@nsSubsumeStr@@QAEHPAGHH@Z ; 250
+?CurrentItem@nsObserverListEnumerator@@UAGIPAPAVnsISupports@@@Z ; 250
+?Release@nsRegistryNode@@UAGKXZ ; 245
+?PrepareEncoder@nsFSStringConversion@@CAIXZ ; 241
+?UCSToNewFS@nsFSStringConversion@@SAIPBGPAPAD@Z ; 241
+?Write@nsBinaryOutputStream@@UAGIPBDIPAI@Z ; 238
+?IsDirectory@nsFileSpec@@QBEHXZ ; 236
+?QueryInterface@nsConjoiningEnumerator@@UAGIABUnsID@@PAPAX@Z ; 236
+_DllMain@12 ; 235
+??_GnsObserverListEnumerator@@UAEPAXI@Z ; 229
+?First@nsObserverListEnumerator@@UAGIXZ ; 229
+??0nsObserverListEnumerator@@QAE@PAVnsISupportsArray@@@Z ; 229
+?SetComponentInfo@nsGenericFactory@@UAGIPAUnsModuleComponentInfo@@@Z ; 228
+?NS_NewGenericFactory@@YAIPAPAVnsIGenericFactory@@PAUnsModuleComponentInfo@@@Z ; 228
+?Create@nsGenericFactory@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 228
+??0nsGenericFactory@@QAE@PAUnsModuleComponentInfo@@@Z ; 228
+?do_InsertFromElementPtrLength@nsAString@@MAEXPBGII@Z ; 227
+??1nsGenericFactory@@UAE@XZ ; 226
+?GetBufferSize@ByteBufferImpl@@UBGIXZ ; 226
+??_EnsGenericFactory@@UAEPAXI@Z ; 226
+??4nsFileSpec@@QAEXABVnsFilePath@@@Z ; 219
+?GetLastModifiedTime@nsLocalFile@@UAGIPA_J@Z ; 217
+?RFindInReadable@@YAHABVnsAString@@AAV?$nsReadingIterator@G@@1@Z ; 217
+?GetTarget@nsLocalFile@@UAGIPAPAD@Z ; 216
+?CopyFields@xptiFile@@AAEXABV1@@Z ; 212
+??0xptiFile@@QAE@XZ ; 212
+?ConvertStringLineBreaks@nsLinebreakConverter@@SAIAAVnsString@@W4ELinebreakType@1@1@Z ; 212
+??0xptiFile@@QAE@ABVnsInt64@@0PBDPAVxptiWorkingSet@@PAUXPTHeader@@@Z ; 212
+?QueryInterface@nsDirectoryService@@UAGIABUnsID@@PAPAX@Z ; 211
+?ReplaceSubstring@nsString@@QAEXABV1@0@Z ; 210
+?GetLongLong@nsRegistry@@UAGIIPBDPA_J@Z ; 210
+??0nsSimpleCharString@@QAE@ABVnsString@@@Z ; 209
+PL_DHashClearEntryStub ; 209
+??4nsSimpleCharString@@QAEXABVnsString@@@Z ; 209
+?Release@nsDirectoryService@@UAGKXZ ; 208
+?GetType@xptiFileType@@SA?AW4Type@1@PBD@Z ; 208
+?AutoRegisterComponent@nsNativeComponentLoader@@UAGIHPAVnsIFile@@PAH@Z ; 208
+?SetLeafName@nsFileSpecImpl@@UAGIPBD@Z ; 207
+?SetLeafName@nsFileSpec@@QAEXABVnsString@@@Z ; 203
+??0nsFilePath@@QAE@ABVnsString@@H@Z ; 203
+nsEscapeHTML ; 200
+?SetActivityIsLegal@nsTraceRefcnt@@SAXH@Z ; 198
+?GetProxy@nsCWeakReferent@@QAEPAVnsCWeakProxy@@XZ ; 196
+??0nsCWeakProxy@@QAE@PAXPAVnsCWeakReferent@@@Z ; 196
+??0nsCWeakReferent@@QAE@PAX@Z ; 196
+?ReleaseReference@nsCWeakProxy@@QAEXXZ ; 195
+??_EnsCWeakProxy@@UAEPAXI@Z ; 195
+??1nsCWeakProxy@@UAE@XZ ; 195
+??1nsCWeakReferent@@UAE@XZ ; 195
+nsEscape ; 178
+nsEscapeCount ; 178
+?GetIsOpen@FileImpl@@UAGIPAH@Z ; 177
+?Exists@nsFileSpec@@QBEHXZ ; 173
+?read@nsInputStream@@QAEHPAXH@Z ; 171
+?Read@FileImpl@@UAGIPADIPAI@Z ; 171
+??0nsAutoString@@QAE@G@Z ; 170
+?GetClassObject@nsGenericModule@@UAGIPAVnsIComponentManager@@ABUnsID@@1PAPAX@Z ; 169
+?Get@nsDirectoryService@@UAGIPBDABUnsID@@PAPAX@Z ; 165
+?Seek@nsStorageStream@@AAGIH@Z ; 164
+?SetLength@nsStorageStream@@UAGII@Z ; 164
+?Close@FileImpl@@UAGIXZ ; 163
+?WriteStringZ@nsBinaryOutputStream@@UAGIPBD@Z ; 163
+?AppendElements@nsSupportsArray@@UAGHPAVnsISupportsArray@@@Z ; 162
+?Write8@nsBinaryOutputStream@@UAGIE@Z ; 162
+?AddObserver@nsObserverService@@UAGIPAVnsIObserver@@PBG@Z ; 158
+?AddObserver@nsObserverList@@UAGIPAVnsIObserver@@@Z ; 158
+?read@ConstCharImpl@@MAEHPADI@Z ; 156
+?Read@BasicStringImpl@@UAGIPADIPAI@Z ; 156
+?GetGlobalMemoryService@nsMemory@@SAPAVnsIMemory@@XZ ; 155
+?GetData@nsSupportsStringImpl@@UAGIPAPAD@Z ; 153
+??0nsCAutoString@@QAE@PBDH@Z ; 152
+??0nsObjectHashtable@@QAE@P6APAXPAVnsHashKey@@PAX1@Z1P6AH011@Z1IH@Z ; 140
+??0ArenaImpl@@QAE@XZ ; 139
+?Init@ArenaImpl@@UAGII@Z ; 139
+?Create@ArenaImpl@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 139
+?NS_NewHeapArena@@YAIPAPAVnsIArena@@I@Z ; 139
+?QueryInterface@ArenaImpl@@UAGIABUnsID@@PAPAX@Z ; 139
+??1nsObjectHashtable@@UAE@XZ ; 138
+?Reset@nsObjectHashtable@@QAEXXZ ; 138
+?ResolveLocked@xptiInterfaceInfo@@AAEHPAVxptiWorkingSet@@@Z ; 129
+?GetNext@nsAdapterEnumerator@@UAGIPAPAVnsISupports@@@Z ; 129
+?GetCompleted@nsProxyObjectCallInfo@@QAEHXZ ; 124
+??0CBufDescriptor@@QAE@PBGHIH@Z ; 123
+??0nsServiceEntry@@QAE@ABUnsID@@PAVnsISupports@@@Z ; 122
+?NotifyListeners@nsServiceEntry@@QAEIXZ ; 122
+??1nsServiceEntry@@QAE@XZ ; 122
+?Resolve@xptiInterfaceInfo@@AAEHPAVxptiWorkingSet@@@Z ; 122
+??4nsFileSpec@@QAEXPBD@Z ; 121
+?QueryInterface@nsRegistryNode@@UAGIABUnsID@@PAPAX@Z ; 114
+?RegisterThreadSelf@nsThread@@QAEIXZ ; 114
+?FindSymbol@nsDll@@QAEPAXPBD@Z ; 114
+??_GnsRegistryNode@@UAEPAXI@Z ; 114
+??0nsThread@@QAE@XZ ; 114
+??0nsRegistryNode@@QAE@PAXPADJ@Z ; 114
+?CurrentItem@nsRegSubtreeEnumerator@@UAGIPAPAVnsISupports@@@Z ; 114
+??1nsRegistryNode@@UAE@XZ ; 114
+?Init@nsThread@@UAGIPAVnsIRunnable@@IW4PRThreadPriority@@W4PRThreadScope@@W4PRThreadState@@@Z ; 113
+?NS_NewThread@@YAIPAPAVnsIThread@@PAVnsIRunnable@@IW4PRThreadState@@W4PRThreadPriority@@W4PRThreadScope@@@Z ; 113
+?WaitUntilReadyToStartMain@nsThread@@QAEXXZ ; 113
+?Main@nsThread@@SAXPAX@Z ; 113
+??1ArenaImpl@@UAE@XZ ; 112
+??_GArenaImpl@@UAEPAXI@Z ; 112
+?GetKey@nsRegistryNode@@UAGIPAI@Z ; 112
+?Exit@nsThread@@SAXPAX@Z ; 111
+??1nsThread@@UAE@XZ ; 110
+?GetCurrent@nsIThread@@SAIPAPAV1@@Z ; 110
+??_GnsThread@@UAEPAXI@Z ; 110
+?WriteToLog@xptiInterfaceInfoManager@@SAXPBDZZ ; 110
+?GetIThread@nsIThread@@SAIPAUPRThread@@PAPAV1@@Z ; 110
+?Write@nsPipeOutputStream@nsPipe@@UAGIPBDIPAI@Z ; 109
+?AddThread@nsThreadPool@@IAEIXZ ; 109
+?Run@nsThreadPoolRunnable@@UAGIXZ ; 109
+??0nsThreadPoolRunnable@@QAE@PAVnsThreadPool@@@Z ; 109
+?DeleteLastElement@nsSupportsArray@@UAGIPAVnsISupports@@@Z ; 108
+??_GnsThreadPoolRunnable@@UAEPAXI@Z ; 108
+?RemoveLastElement@nsSupportsArray@@UAGHPBVnsISupports@@@Z ; 108
+?RemoveThread@nsThreadPool@@IAEIPAVnsIThread@@@Z ; 108
+??1nsThreadPoolRunnable@@UAE@XZ ; 108
+?GetNameUTF8@nsRegistryNode@@UAGIPAPAD@Z ; 108
+?RemoveObserver@nsObserverService@@UAGIPAVnsIObserver@@PBG@Z ; 106
+?RemoveObserver@nsObserverList@@UAGIPAVnsIObserver@@@Z ; 106
+?Contains@nsLocalFile@@UAGIPAVnsIFile@@HPAH@Z ; 104
+?RegistryLocationForSpec@nsComponentManagerImpl@@UAGIPAVnsIFile@@PAPAD@Z ; 104
+?Close@ConverterInputStream@@UAGIXZ ; 103
+??1nsDll@@QAE@XZ ; 103
+?Init@nsDll@@AAEXPAVnsIFile@@@Z ; 100
+??0nsDll@@QAE@PAVnsIFile@@PBDPA_J2@Z ; 100
+?SpecForRegistryLocation@nsComponentManagerImpl@@UAGIPBDPAPAVnsIFile@@@Z ; 100
+?UnescapeKey@nsRegistry@@UAGIPAEIPAIPAPAE@Z ; 99
+?GetRegistryDllInfo@nsNativeComponentLoader@@AAEIIPA_J0@Z ; 99
+NS_NewIOFileStream ; 98
+?Open@FileImpl@@UAGIABVnsFileSpec@@HH@Z ; 98
+??1FileImpl@@UAE@XZ ; 98
+??_GFileImpl@@UAEPAXI@Z ; 98
+??0FileImpl@@QAE@ABVnsFileSpec@@HH@Z ; 98
+?HasChanged@nsDll@@QAEHXZ ; 94
+?Read@nsByteArrayInputStream@@UAGIPADIPAI@Z ; 87
+PL_DHashGetStubOps ; 86
+??0nsStorageStream@@QAE@XZ ; 83
+?NS_NewStorageStream@@YAIIIPAPAVnsIStorageStream@@@Z ; 83
+??1nsStorageStream@@UAE@XZ ; 83
+?Init@nsStorageStream@@QAGIIIPAVnsIMemory@@@Z ; 83
+??_EnsStorageStream@@UAEPAXI@Z ; 83
+?GetOutputStream@nsStorageStream@@UAGIHPAPAVnsIOutputStream@@@Z ; 82
+?WriteBytes@nsBinaryOutputStream@@UAGIPBDI@Z ; 82
+??0nsBinaryOutputStream@@QAE@PAVnsIOutputStream@@@Z ; 81
+?Write16@nsBinaryOutputStream@@UAGIG@Z ; 81
+??1nsStorageInputStream@@UAE@XZ ; 81
+?Available@nsStorageInputStream@@UAGIPAI@Z ; 81
+?NewInputStream@nsStorageStream@@UAGIHPAPAVnsIInputStream@@@Z ; 81
+??_EnsStorageInputStream@@UAEPAXI@Z ; 81
+?WriteFloat@nsBinaryOutputStream@@UAGIM@Z ; 81
+?NS_NewBinaryOutputStream@@YAIPAPAVnsIBinaryOutputStream@@PAVnsIOutputStream@@@Z ; 81
+?Release@nsBinaryOutputStream@@UAGKXZ ; 81
+??_EnsBinaryOutputStream@@UAEPAXI@Z ; 81
+?Read@nsStorageInputStream@@UAGIPADIPAI@Z ; 81
+??0nsStorageInputStream@@QAE@PAVnsStorageStream@@I@Z ; 81
+??_EConverterInputStream@@UAEPAXI@Z ; 80
+??0ByteBufferImpl@@QAE@XZ ; 80
+?QueryInterface@nsSupportsPRInt32Impl@@UAGIABUnsID@@PAPAX@Z ; 80
+?NS_NewUnicharBuffer@@YAIPAPAVnsIUnicharBuffer@@PAVnsISupports@@I@Z ; 80
+?NS_NewB2UConverter@@YAIPAPAVnsIUnicodeDecoder@@PAVnsISupports@@PAVnsString@@@Z ; 80
+?QueryInterface@UnicharBufferImpl@@UAGIABUnsID@@PAPAX@Z ; 80
+??1ByteBufferImpl@@UAE@XZ ; 80
+?Init@UnicharBufferImpl@@UAGII@Z ; 80
+??0UnicharBufferImpl@@QAE@XZ ; 80
+?Create@UnicharBufferImpl@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 80
+?NS_NewByteBuffer@@YAIPAPAVnsIByteBuffer@@PAVnsISupports@@I@Z ; 80
+?Init@ByteBufferImpl@@UAGII@Z ; 80
+?QueryInterface@ByteBufferImpl@@UAGIABUnsID@@PAPAX@Z ; 80
+??0ConverterInputStream@@QAE@PAVnsIInputStream@@PAVnsIUnicodeDecoder@@I@Z ; 80
+??1UnicharBufferImpl@@UAE@XZ ; 80
+??_EUnicharBufferImpl@@UAEPAXI@Z ; 80
+?NS_NewConverterStream@@YAIPAPAVnsIUnicharInputStream@@PAVnsISupports@@PAVnsIInputStream@@HPAVnsString@@@Z ; 80
+??_EByteBufferImpl@@UAEPAXI@Z ; 80
+??1ConverterInputStream@@UAE@XZ ; 80
+?Create@ByteBufferImpl@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 80
+?is_open@nsFileClient@@QBEHXZ ; 79
+?GetData@nsSupportsPRBoolImpl@@UAGIPAH@Z ; 78
+??0nsSupportsPRInt32Impl@@QAE@XZ ; 77
+?SetNativePath@nsFileSpecImpl@@UAGIPBD@Z ; 74
+?InsertFromReadable@nsAString@@IAEXABV1@I@Z ; 74
+?ToString@nsSupportsStringImpl@@UAGIPAPAD@Z ; 74
+?IsDone@nsSupportsArrayEnumerator@@UAGIXZ ; 73
+?AllocateBuffers@FileImpl@@IAEIII@Z ; 71
+??1nsOutputStream@@UAE@XZ ; 71
+??_EnsSupportsPRInt32Impl@@UAEPAXI@Z ; 70
+??1nsOutputFileStream@@UAE@XZ ; 70
+?AssignFrom@nsOutputFileStream@@IAEXPAVnsISupports@@@Z ; 70
+??0nsRandomAccessOutputStream@@IAE@XZ ; 70
+??0nsOutputStream@@QAE@PAVnsIOutputStream@@@Z ; 70
+??1nsRandomAccessOutputStream@@UAE@XZ ; 70
+??1nsSupportsPRInt32Impl@@UAE@XZ ; 70
+??0nsDirectoryIterator@@QAE@ABVnsFileSpec@@H@Z ; 68
+??1nsDirectoryIterator@@UAE@XZ ; 68
+?Promises@nsPromiseCConcatenation@@UBEHABVnsACString@@@Z ; 67
+?Length@nsPromiseConcatenation@@UBEIXZ ; 67
+?AppendFromPromise@nsAString@@IAEXABV1@@Z ; 67
+?IndexOf@nsStringArray@@QBEHABVnsAString@@@Z ; 67
+??0nsOutputFileStream@@QAE@ABVnsFileSpec@@HH@Z ; 67
+?Available@nsInputStreamTee@@UAGIPAI@Z ; 66
+?HashContractID@nsComponentManagerImpl@@IAEIPBDABUnsID@@@Z ; 65
+??0nsSubsumeCStr@@QAE@PADHH@Z ; 65
+?close@nsInputStream@@QAEIXZ ; 65
+?HandleEvent@nsEventQueueImpl@@UAGIPAUPLEvent@@@Z ; 62
+?PostAndWait@nsProxyObject@@QAEIPAVnsProxyObjectCallInfo@@@Z ; 62
+?WaitForEvent@nsEventQueueImpl@@UAGIPAPAUPLEvent@@@Z ; 62
+?SetCallersQueue@nsProxyObjectCallInfo@@QAEXPAVnsIEventQueue@@@Z ; 62
+PL_PostSynchronousEvent ; 62
+?PostSynchronousEvent@nsEventQueueImpl@@UAGIPAUPLEvent@@PAPAX@Z ; 62
+PL_WaitForEvent ; 62
+?strcmp@nsCRT@@SAHPBGPBD@Z ; 60
+?ns_file_convert_result@@YAIH@Z ; 60
+?Load@nsLocalFile@@UAGIPAPAUPRLibrary@@@Z ; 54
+?hash_enumerator@@YAHPAVnsHashKey@@PAX1@Z ; 53
+?Shutdown@nsDll@@QAEIXZ ; 53
+??1nsAdapterEnumerator@@UAE@XZ ; 51
+?IsDone@nsHashtableEnumerator@@UAGIXZ ; 51
+?CurrentItem@nsHashtableEnumerator@@UAGIPAPAVnsISupports@@@Z ; 51
+?Next@nsHashtableEnumerator@@UAGIXZ ; 51
+??0nsAdapterEnumerator@@QAE@PAVnsIEnumerator@@@Z ; 51
+??HnsFileSpec@@QBE?AV0@PBD@Z ; 50
+?Read32@nsBinaryInputStream@@UAGIPAI@Z ; 50
+?Available@nsByteArrayInputStream@@UAGIPAI@Z ; 50
+?flush@nsOutputFileStream@@UAEIXZ ; 49
+?RegisterComponentCommon@nsComponentManagerImpl@@IAEIABUnsID@@PBD11HH1@Z ; 48
+??0nsString@@QAE@AAVnsSubsumeStr@@@Z ; 47
+??0nsSubsumeStr@@QAE@PAGHH@Z ; 47
+??0CBufDescriptor@@QAE@PBDHIH@Z ; 46
+?Initialize@nsGenericModule@@IAEIXZ ; 45
+??0nsGenericModule@@QAE@PBDIPAUnsModuleComponentInfo@@P6AXPAVnsIModule@@@Z@Z ; 45
+?CanUnload@nsGenericModule@@UAGIPAVnsIComponentManager@@PAH@Z ; 45
+?Shutdown@nsGenericModule@@IAEXXZ ; 45
+?NS_NewGenericModule@@YAIPBDIPAUnsModuleComponentInfo@@P6AXPAVnsIModule@@@ZPAPAV2@@Z ; 45
+?GetLoaderForType@nsComponentManagerImpl@@IAEIPBDPAPAVnsIComponentLoader@@@Z ; 45
+?QueryInterface@nsGenericModule@@UAGIABUnsID@@PAPAX@Z ; 45
+??_EnsGenericModule@@UAEPAXI@Z ; 45
+??1nsGenericModule@@UAE@XZ ; 45
+?OnRegister@nsNativeComponentLoader@@UAGIABUnsID@@PBD111HH@Z ; 44
+?GetLeafName@nsFileSpecImpl@@UAGIPAPAD@Z ; 44
+?QueryInterface@AtomImpl@@UAGIABUnsID@@PAPAX@Z ; 44
+?find_category@nsCategoryManager@@AAEPAVCategoryNode@@PBD@Z ; 44
+?RegistryNameForLib@nsComponentManagerImpl@@IAEIPBDPAPAD@Z ; 44
+?RegisterComponentLib@nsComponentManager@@SAIABUnsID@@PBD11HH@Z ; 44
+?RegisterComponentLib@nsComponentManagerImpl@@UAGIABUnsID@@PBD11HH@Z ; 44
+?RegisterFactory@nsComponentManagerImpl@@UAGIABUnsID@@PBD1PAVnsIFactory@@H@Z ; 42
+??0nsFactoryEntry@@QAE@ABUnsID@@PAVnsIFactory@@@Z ; 42
+?copy_string@@YAAAV?$ConvertToUpperCase@G@@AAV?$nsWritingIterator@G@@ABV2@AAV1@@Z ; 40
+?ResolveSymlink@nsFileSpec@@QAEIAAH@Z ; 40
+?ToUpperCase@@YAXAAVnsAString@@@Z ; 40
+?advance@nsRegValueEnumerator@@UAGIXZ ; 39
+?Release@nsPersistentProperties@@UAGKXZ ; 39
+?ToNewString@nsString@@QBEPAV1@XZ ; 38
+?IsValid@xptiWorkingSet@@QBEHXZ ; 38
+?GetComponentsDir@xptiInterfaceInfoManager@@QAEHPAPAVnsILocalFile@@@Z ; 37
+??1xptiTypelibGuts@@QAE@XZ ; 36
+??0xptiTypelibGuts@@QAE@PAUXPTHeader@@@Z ; 36
+?LoadFile@xptiInterfaceInfoManager@@QAEHABVxptiTypelib@@PAVxptiWorkingSet@@@Z ; 36
+?SetHeader@xptiFile@@QAEHPAUXPTHeader@@@Z ; 36
+?ReadXPTFile@xptiInterfaceInfoManager@@AAEPAUXPTHeader@@PAVnsILocalFile@@PAVxptiWorkingSet@@@Z ; 36
+?ConvertBreaks@@YAPAGPBGAAHPBD2@Z ; 35
+?ConvertUnicharLineBreaksInSitu@nsLinebreakConverter@@SAIPAPAGW4ELinebreakType@1@1HPAH@Z ; 35
+?CountLinebreaks@@YAHPBGHPBD@Z ; 35
+?FindFactory@nsComponentManager@@SAIABUnsID@@PAPAVnsIFactory@@@Z ; 34
+??1nsRegistryValue@@UAE@XZ ; 32
+??_GnsRegistryValue@@UAEPAXI@Z ; 32
+?getInfo@nsRegistryValue@@IAEIXZ ; 32
+?find_leaf@CategoryNode@@QAEPAVnsCString@@PBD@Z ; 32
+??0nsRegistryValue@@QAE@PAXJK@Z ; 32
+?QueryInterface@nsRegistryValue@@UAGIABUnsID@@PAPAX@Z ; 32
+?GetNameUTF8@nsRegistryValue@@UAGIPAPAD@Z ; 32
+?AddCategoryEntry@nsCategoryManager@@UAGIPBD00HHPAPAD@Z ; 32
+?CurrentItem@nsRegValueEnumerator@@UAGIPAPAVnsISupports@@@Z ; 32
+??1nsInputFileStream@@UAE@XZ ; 29
+??YnsFileSpec@@QAEXABVnsString@@@Z ; 29
+?Release@nsAppFileLocationProvider@@UAGKXZ ; 29
+??0nsInputStream@@QAE@PAVnsIInputStream@@@Z ; 29
+??1nsRandomAccessInputStream@@UAE@XZ ; 29
+??1nsInputStream@@UAE@XZ ; 29
+?IsLowMemory@nsMemoryImpl@@UAGIPAH@Z ; 29
+??8nsFileSpec@@QBEHABV0@@Z ; 28
+?QueryInterface@nsAppFileLocationProvider@@UAGIABUnsID@@PAPAX@Z ; 27
+?copy_string@@YAAAV?$CalculateLength@D@@AAV?$nsReadingIterator@D@@ABV2@AAV1@@Z ; 26
+?Distance@@YAIABV?$nsReadingIterator@D@@0@Z ; 26
+?GetFile@nsAppFileLocationProvider@@UAGIPBDPAHPAPAVnsIFile@@@Z ; 26
+?nsLocalFileConstructor@nsLocalFile@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 26
+?GetFactoryFromNSGetFactory@nsNativeComponentLoader@@AAEIPAVnsDll@@ABUnsID@@PAVnsIServiceManager@@PAPAVnsIFactory@@@Z ; 25
+?Release@nsRegistry@@UAGKXZ ; 25
+?First@nsRegSubtreeEnumerator@@UAGIXZ ; 24
+??1nsRegSubtreeEnumerator@@UAE@XZ ; 24
+??0nsRegSubtreeEnumerator@@QAE@PAXJH@Z ; 24
+?Set@nsDirectoryService@@UAGIPBDPAVnsISupports@@@Z ; 24
+??_GnsRegSubtreeEnumerator@@UAEPAXI@Z ; 24
+??0nsPersistentProperties@@QAE@XZ ; 23
+?Load@nsPersistentProperties@@UAGIPAVnsIInputStream@@@Z ; 23
+?Create@nsPersistentProperties@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 23
+?QueryInterface@nsPersistentProperties@@UAGIABUnsID@@PAPAX@Z ; 23
+??1nsFileURL@@UAE@XZ ; 20
+?SetPersistentDescriptor@nsLocalFile@@UAGIPBD@Z ; 20
+?Close@BasicStringImpl@@UAGIXZ ; 20
+??4nsFileURL@@QAEXABVnsFilePath@@@Z ; 20
+?ReplaceElementAt@nsSupportsArray@@UAGHPAVnsISupports@@I@Z ; 20
+?NS_AllocateContiguousHandleWithData@@YAPAVBuffer@nsSharedBufferList@@PBV12@ABVnsLocalString@@I@Z ; 20
+?QueryInterface@nsRegistry@@UAGIABUnsID@@PAPAX@Z ; 19
+?SetCharAt@nsCString@@QAEHGI@Z ; 19
+??0nsSpecialSystemDirectory@@QAE@W4SystemDirectories@0@@Z ; 18
+?GetFileSize@nsFileSpec@@QBEIXZ ; 18
+?Exists@nsFileSpecImpl@@UAGIPAH@Z ; 18
+?GetSubtree@nsRegistry@@UAGIIPBDPAI@Z ; 18
+??4nsSpecialSystemDirectory@@QAEXW4SystemDirectories@0@@Z ; 18
+??1nsSpecialSystemDirectory@@UAE@XZ ; 18
+??0nsRandomAccessInputStream@@IAE@XZ ; 17
+??0nsObserverList@@QAE@XZ ; 17
+??1nsObserverList@@UAE@XZ ; 17
+?EnumerateSubtrees@nsRegistry@@UAGIIPAPAVnsIEnumerator@@@Z ; 17
+?NS_NewObserverList@@YAIPAPAVnsIObserverList@@@Z ; 17
+?AssignFrom@nsInputFileStream@@IAEXPAVnsISupports@@@Z ; 17
+??0nsInputFileStream@@QAE@ABVnsFileSpec@@HH@Z ; 17
+?QueryInterface@nsObserverList@@UAGIABUnsID@@PAPAX@Z ; 17
+??_GnsObserverList@@UAEPAXI@Z ; 17
+?Unescape@nsSimpleCharString@@QAEXXZ ; 16
+?SetCharAt@nsString@@QAEHGI@Z ; 16
+??1nsOpaqueKey@@UAE@XZ ; 16
+??1nsPersistentProperties@@UAE@XZ ; 16
+??_EnsPersistentProperties@@UAEPAXI@Z ; 16
+??0nsFilePath@@QAE@PBDH@Z ; 16
+??0nsOpaqueKey@@QAE@PBDIW4Ownership@0@@Z ; 16
+?AppendRelativeUnixPath@nsFileSpecImpl@@UAGIPBD@Z ; 15
+??0nsCString@@QAE@PBDH@Z ; 15
+?GetString@nsRegistry@@UAGIIPBGPAPAG@Z ; 15
+?SetStringUTF8@nsRegistry@@UAGIIPBD0@Z ; 15
+?SetString@nsRegistry@@UAGIIPBG0@Z ; 15
+?ReleaseElements@nsHashtableEnumerator@@EAGIXZ ; 14
+PL_GetEventQueueMonitor ; 14
+?ReadStringZ@nsBinaryInputStream@@UAGIPAPAD@Z ; 14
+?EscapeKey@nsRegistry@@UAGIPAEIPAIPAPAE@Z ; 14
+?AppendFromPromise@nsACString@@IAEXABV1@@Z ; 13
+?FindCharInReadable@@YAHDAAV?$nsReadingIterator@D@@ABV1@@Z ; 13
+??0nsPromiseCSubstring@@QAE@ABV?$nsReadingIterator@D@@0@Z ; 13
+?GetName@xptiInterfaceInfo@@UAGIPAPAD@Z ; 12
+?StartAssignmentByReference@nsXPIDLCString@@AAEPAPBDXZ ; 12
+??0nsFileURL@@QAE@ABVnsFileSpec@@@Z ; 12
+?ConvertFromFileSystemCharset@nsFileSpec@@IAEPAGPBD@Z ; 12
+?Read8@nsBinaryInputStream@@UAGIPAE@Z ; 12
+?IsHidden@nsLocalFile@@UAGIPAH@Z ; 12
+?BufferHashCode@nsCRT@@SAIPBDI@Z ; 12
+?GetFileSystemCharset@nsFileSpec@@KAXAAVnsString@@@Z ; 12
+??0nsRandomAccessStoreClient@@QAE@ABV?$nsCOMPtr@VnsIRandomAccessStore@@@@@Z ; 12
+??0nsFileClient@@QAE@ABV?$nsCOMPtr@VnsIOpenFile@@@@@Z ; 12
+?SetLongLong@nsRegistry@@UAGIIPBDPA_J@Z ; 12
+??0nsInputFileStream@@QAE@PAVnsIInputStream@@@Z ; 12
+?HashCode@nsOpaqueKey@@UBEIXZ ; 12
+??0nsRandomAccessInputStream@@QAE@PAVnsIInputStream@@@Z ; 12
+??4nsFileURL@@QAEXABVnsFileSpec@@@Z ; 12
+?AddRef@nsCategoryManager@@UAGKXZ ; 11
+?Release@nsCategoryManager@@UAGKXZ ; 11
+?GetFile@nsDirectoryService@@UAGIPBDPAHPAPAVnsIFile@@@Z ; 11
+??0nsProxyEventClass@@IAE@ABUnsID@@PAVnsIInterfaceInfo@@@Z ; 11
+?Read@nsFileSpecImpl@@UAGIPAPADHPAH@Z ; 11
+?InsertReadable@nsSlidingString@@IAEXABVnsAString@@ABV?$nsReadingIterator@G@@@Z ; 10
+NS_NewTypicalInputFileStream ; 10
+??1nsCommonCString@@UAE@XZ ; 10
+?SplitBuffer@nsSharedBufferList@@QAEXABUPosition@1@W4SplitDisposition@1@@Z ; 10
+?OpenStreamForReading@nsFileSpecImpl@@UAGIXZ ; 10
+PL_IsQueueNative ; 10
+?Release@nsRegistryFactory@@UAGKXZ ; 10
+??0ConstStringImpl@@QAE@ABVnsCString@@@Z ; 10
+?ResolveSymlink@nsFileSpecImpl@@UAGIXZ ; 10
+?IsQueueNative@nsEventQueueImpl@@UAGIPAH@Z ; 10
+??1nsACString@@UAE@XZ ; 10
+?Clone@nsVoidKey@@UBEPAVnsHashKey@@XZ ; 10
+NS_NewCStringInputStream ; 10
+?QueryInterface@nsRegSubtreeEnumerator@@UAGIABUnsID@@PAPAX@Z ; 9
+?GetFileSize@nsFileSpecImpl@@UAGIPAI@Z ; 9
+?GetTypeForParam@xptiInterfaceInfo@@UAGIGPBVnsXPTParamInfo@@GPAVnsXPTType@@@Z ; 9
+?Exists@nsDirectoryIteratorImpl@@UAGIPAH@Z ; 9
+?do_InsertFromElement@nsAString@@MAEXGI@Z ; 9
+?Create@nsDirectoryService@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 9
+?QueryInterface@nsCategoryManager@@UAGIABUnsID@@PAPAX@Z ; 9
+?GetFileContents@nsFileSpecImpl@@UAGIPAPAD@Z ; 9
+?GetTypeInArray@xptiInterfaceInfo@@EAGIPBVnsXPTParamInfo@@GPAPBUXPTTypeDescriptor@@@Z ; 9
+?IsOpen@nsRegistry@@UAGIPAH@Z ; 9
+?set_at_eof@nsRandomAccessStoreClient@@MAEXH@Z ; 8
+??0nsFilePath@@QAE@ABVnsFileURL@@@Z ; 8
+?GetLengthIsArgNumberForParam@xptiInterfaceInfo@@UAGIGPBVnsXPTParamInfo@@GPAE@Z ; 8
+?SetAtEOF@FileImpl@@UAGIH@Z ; 8
+?GetSubtreeRaw@nsRegistry@@UAGIIPBDPAI@Z ; 8
+?Delete@nsFileSpec@@QBEXH@Z ; 8
+??_EnsDirEnumerator@@UAEPAXI@Z ; 8
+??_EnsHashtable@@UAEPAXI@Z ; 8
+?ReadBytes@nsBinaryInputStream@@UAGIPAPADI@Z ; 8
+?Next@nsDirectoryIteratorImpl@@UAGIXZ ; 8
+?GetDirectoryEntries@nsLocalFile@@UAGIPAPAVnsISimpleEnumerator@@@Z ; 8
+??0nsFileURL@@QAE@PBDH@Z ; 8
+?EnumerateCategory@nsCategoryManager@@UAGIPBDPAPAVnsISimpleEnumerator@@@Z ; 8
+??0nsDirEnumerator@@QAE@XZ ; 8
+?Put@nsInt2StrHashtable@@QAEIIPBD@Z ; 8
+??0nsFileSpec@@QAE@ABVnsFileURL@@@Z ; 8
+?GetCurrentSpec@nsDirectoryIteratorImpl@@UAGIPAPAVnsIFileSpec@@@Z ; 8
+?Init@nsDirEnumerator@@QAEIPAVnsILocalFile@@@Z ; 8
+??1nsDirEnumerator@@UAE@XZ ; 8
+?MakeAllDirectories@nsFileSpecHelpers@@YAXPBDH@Z ; 8
+?NotifyObservers@nsEventQueueImpl@@AAEXPBD@Z ; 8
+?Reset@nsHashtableEnumerator@@EAGIPAVnsHashtable@@P6GIPAVnsHashKey@@PAX2PAPAVnsISupports@@@Z2@Z ; 7
+NS_NewHashtableEnumerator ; 7
+?GetLeafName@nsFileSpec@@QAEXAAVnsString@@@Z ; 7
+??1nsHashtableEnumerator@@UAE@XZ ; 7
+??0CategoryNode@@QAE@XZ ; 7
+?IsASCII@nsString@@QAEHPBG@Z ; 7
+NS_NewAdapterEnumerator ; 7
+??0nsRegValueEnumerator@@QAE@PAXJ@Z ; 7
+??1nsProxyEventClass@@MAE@XZ ; 7
+?Realloc@nsMemoryImpl@@UAGPAXPAXI@Z ; 7
+?EnterMonitor@nsEventQueueImpl@@UAGIXZ ; 7
+??_EnsHashtableEnumerator@@UAEPAXI@Z ; 7
+?First@nsHashtableEnumerator@@UAGIXZ ; 7
+?RegisterErrorStringBundleKey@nsErrorService@@UAGIIPBD@Z ; 7
+?EnumerateValues@nsRegistry@@UAGIIPAPAVnsIEnumerator@@@Z ; 7
+?GetSizeIsArgNumberForParam@xptiInterfaceInfo@@UAGIGPBVnsXPTParamInfo@@GPAE@Z ; 7
+??0nsHashtableEnumerator@@QAE@PAVnsHashtable@@P6GIPAVnsHashKey@@PAX2PAPAVnsISupports@@@Z2@Z ; 7
+??_EnsAdapterEnumerator@@UAEPAXI@Z ; 7
+?Release@nsComponentManagerImpl@@UAGKXZ ; 7
+??_GCategoryNode@@UAEPAXI@Z ; 7
+?Delete@nsLocalFile@@UAGIH@Z ; 7
+??_GnsProxyEventClass@@MAEPAXI@Z ; 7
+?ExitMonitor@nsEventQueueImpl@@UAGIXZ ; 7
+??0nsBinaryInputStream@@QAE@PAVnsIInputStream@@@Z ; 6
+?OpenWellKnownRegistry@nsRegistry@@UAGIH@Z ; 6
+??0nsStaticCaseInsensitiveNameTable@@QAE@XZ ; 6
+??0nsXPIDLString@@QAE@XZ ; 6
+?NS_NewBinaryInputStream@@YAIPAPAVnsIBinaryInputStream@@PAVnsIInputStream@@@Z ; 6
+?SetYounger@nsEventQueueImpl@@UAGIPAVnsPIEventQueueChain@@@Z ; 6
+?MakeUnique@nsFileSpec@@QAEXXZ ; 6
+?Release@nsBinaryInputStream@@UAGKXZ ; 6
+??_GnsBinaryInputStream@@UAEPAXI@Z ; 6
+?ConvertUnknownBreaks@@YAPADPBDAAH0@Z ; 6
+?Read16@nsBinaryInputStream@@UAGIPAG@Z ; 6
+?AddSubtreeRaw@nsRegistry@@UAGIIPBDPAI@Z ; 6
+?Init@nsStaticCaseInsensitiveNameTable@@QAEHQAPBDH@Z ; 6
+?IsFile@nsFileSpec@@QBEHXZ ; 6
+??0nsFileSpec@@QAE@ABVnsString@@H@Z ; 6
+?ConvertLineBreaks@nsLinebreakConverter@@SAPADPBDW4ELinebreakType@1@1HPAH@Z ; 6
+NS_NewByteInputStream ; 6
+?ReadFloat@nsBinaryInputStream@@UAGIPAM@Z ; 6
+?Realloc@nsMemory@@SAPAXPAXI@Z ; 6
+??1nsStaticCaseInsensitiveNameTable@@QAE@XZ ; 6
+?GetLength@nsStorageStream@@UAGIPAI@Z ; 6
+??_GnsRegistry@@UAEPAXI@Z ; 5
+??_EnsObjectHashtable@@UAEPAXI@Z ; 5
+?CloneMozBinDirectory@nsAppFileLocationProvider@@IAGIPAPAVnsILocalFile@@@Z ; 5
+?StripWhitespace@nsCString@@QAEXXZ ; 5
+??0nsRegistry@@QAE@XZ ; 5
+?MakeNewQueue@nsEventQueueServiceImpl@@EAGIPAUPRThread@@HPAPAVnsIEventQueue@@@Z ; 5
+?StopAcceptingEvents@nsEventQueueImpl@@UAGIXZ ; 5
+??1nsRegistry@@UAE@XZ ; 5
+?Create@nsEventQueueImpl@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 5
+?Close@nsRegistry@@MAGIXZ ; 5
+?CreateInstance@nsRegistryFactory@@UAGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 5
+?InitFromPRThread@nsEventQueueImpl@@UAGIPAUPRThread@@H@Z ; 5
+??4nsFileSpec@@QAEXABVnsString@@@Z ; 5
+?NS_FileSpecToIFile@@YAIPAVnsFileSpec@@PAPAVnsILocalFile@@@Z ; 5
+?QueryInterface@nsComponentManagerImpl@@UAGIABUnsID@@PAPAX@Z ; 5
+?GetNativePathString@nsFileSpec@@QAEXAAVnsString@@@Z ; 5
+??0nsEventQueueImpl@@QAE@XZ ; 5
+?do_GetService@@YA?BVnsGetServiceByContractID@@PBDPAI@Z ; 5
+PL_EventAvailable ; 4
+?RFind@nsString@@QBEHABV1@HHH@Z ; 4
+?RegisterComponentSpec@nsComponentManagerImpl@@UAGIABUnsID@@PBD1PAVnsIFile@@HH@Z ; 4
+?FSToNewUCS@nsFSStringConversion@@SAIPBDPAPAG@Z ; 4
+?GetCategoryEntry@nsCategoryManager@@UAGIPBD0PAPAD@Z ; 4
+?RegisterComponentWithType@nsComponentManagerImpl@@UAGIABUnsID@@PBD1PAVnsIFile@@1HH1@Z ; 4
+PL_CreateNativeEventQueue ; 4
+?RemoveStringAt@nsStringArray@@QAEHH@Z ; 4
+?PrepareDecoder@nsFSStringConversion@@CAIXZ ; 4
+?GetName@nsRegistryNode@@UAGIPAPAG@Z ; 4
+?Clone@nsOpaqueKey@@UBEPAVnsHashKey@@XZ ; 4
+?SetBufferSize@nsRegistry@@QAEHH@Z ; 4
+?GetCategoryEntryRaw@nsCategoryManager@@UAGIPBD0PAPAD@Z ; 4
+?AddSubtree@nsRegistry@@UAGIIPBDPAI@Z ; 4
+??_EnsOpaqueKey@@UAEPAXI@Z ; 4
+?GetOutputStream@nsFileSpecImpl@@UAGIPAPAVnsIOutputStream@@@Z ; 3
+NS_NewTypicalOutputFileStream ; 3
+?PushThreadEventQueue@nsEventQueueServiceImpl@@UAGIPAPAVnsIEventQueue@@@Z ; 3
+?QueryInterface@nsConsoleService@@UAGIABUnsID@@PAPAX@Z ; 3
+?PopThreadEventQueue@nsEventQueueServiceImpl@@UAGIPAVnsIEventQueue@@@Z ; 3
+PL_MapEvents ; 3
+?Unlink@nsEventQueueImpl@@UAGIXZ ; 3
+?SetElder@nsEventQueueImpl@@UAGIPAVnsPIEventQueueChain@@@Z ; 3
+?AppendQueue@nsEventQueueImpl@@UAGIPAVnsIEventQueue@@@Z ; 3
+??1nsEventQueueImpl@@UAE@XZ ; 3
+?OpenStreamForWriting@nsFileSpecImpl@@UAGIXZ ; 3
+??0nsOutputFileStream@@QAE@PAVnsIFileSpec@@@Z ; 3
+?LogMessage@nsConsoleService@@UAGIPAVnsIConsoleMessage@@@Z ; 3
+PL_DestroyEventQueue ; 3
+?IsRegistered@nsComponentManagerImpl@@UAGIABUnsID@@PAH@Z ; 3
+?GetCurrentProcessDirectory@nsDirectoryService@@AAEIPAPAVnsILocalFile@@@Z ; 3
+??_EnsEventQueueImpl@@UAEPAXI@Z ; 3
+?CreateDirectory@nsFileSpec@@QAEXH@Z ; 3
+??0nsDll@@QAE@PBDH@Z ; 3
+??1nsAVLTree@@QAE@XZ ; 2
+?NewFileArray@xptiWorkingSet@@QAEHI@Z ; 2
+?ToUpper@nsCRT@@SADD@Z ; 2
+??1nsInt2StrHashtable@@UAE@XZ ; 2
+?GetUnicodeLeafName@nsLocalFile@@UAGIPAPAG@Z ; 2
+?CompareWithConversion@nsString@@QBEHABV1@HH@Z ; 2
+?Read@xptiManifest@@SAHPAVxptiInterfaceInfoManager@@PAVxptiWorkingSet@@@Z ; 2
+??0nsMemoryImpl@@QAE@XZ ; 2
+??1xptiWorkingSet@@QAE@XZ ; 2
+?Create@nsMemoryImpl@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 2
+??0nsRegistryFactory@@QAE@XZ ; 2
+?NS_ErrorAccordingToNSPR@@YAIXZ ; 2
+?ClearHashTables@xptiWorkingSet@@QAEXXZ ; 2
+??_ExptiFile@@QAEPAXI@Z ; 2
+?AppendUnicode@nsLocalFile@@UAGIPBG@Z ; 2
+?Release@MemoryFlusher@@UAGKXZ ; 2
+??_EnsSupportsHashtable@@UAEPAXI@Z ; 2
+?CreateEventQueue@nsEventQueueServiceImpl@@EAGIPAUPRThread@@H@Z ; 2
+??1xptiAutoLog@@QAE@XZ ; 2
+NS_RegistryGetFactory ; 2
+?ClearFiles@xptiWorkingSet@@QAEXXZ ; 2
+??0xptiWorkingSet@@QAE@XZ ; 2
+?Tell@FileImpl@@UAGIPAH@Z ; 2
+?RegisterProvider@nsDirectoryService@@UAGIPAVnsIDirectoryServiceProvider@@@Z ; 2
+?GetKey@nsRegistry@@UAGIIPBGPAI@Z ; 2
+?ClearZipItems@xptiWorkingSet@@QAEXXZ ; 2
+?readline@nsRandomAccessInputStream@@QAEHPADH@Z ; 2
+??0nsAVLTree@@QAE@AAVnsAVLNodeComparitor@@PAVnsAVLNodeFunctor@@@Z ; 2
+?GetManifestDir@xptiInterfaceInfoManager@@QAEHPAPAVnsILocalFile@@@Z ; 2
+??0xptiAutoLog@@QAE@PAVxptiInterfaceInfoManager@@PAVnsILocalFile@@H@Z ; 2
+?tell@nsRandomAccessStoreClient@@QAEHXZ ; 2
+NS_NewUnicodeLocalFile ; 2
+??0nsInt2StrHashtable@@QAE@XZ ; 2
+?seek@nsRandomAccessStoreClient@@QAEXW4PRSeekWhence@@H@Z ; 2
+?Open@nsRegistry@@UAGIPBD@Z ; 2
+?QueryInterface@nsErrorService@@UAGIABUnsID@@PAPAX@Z ; 2
+?RegisterService@nsServiceManagerImpl@@UAGIABUnsID@@PAVnsISupports@@@Z ; 2
+?Seek@FileImpl@@UAGIW4PRSeekWhence@@H@Z ; 2
+?GetUnicodePath@nsLocalFile@@UAGIPAPAG@Z ; 2
+?AddRef@MemoryFlusher@@UAGKXZ ; 2
+?PrepareFSCharset@nsFSStringConversion@@CAIXZ ; 2
+??_EnsDirectoryService@@UAEPAXI@Z ; 1
+?NS_ShutdownXPCOM@@YAIPAVnsIServiceManager@@@Z ; 1
+?AutoRegister@nsComponentManagerImpl@@UAGIHPAVnsIFile@@@Z ; 1
+?OnShutdown@HandleCaseConversionShutdown3@@UAGIABUnsID@@PAVnsISupports@@@Z ; 1
+?GetParent@nsFileSpec@@QBEXAAV1@@Z ; 1
+??1nsConsoleService@@UAE@XZ ; 1
+??0nsComponentManagerImpl@@QAE@XZ ; 1
+?PlatformVersionCheck@nsComponentManagerImpl@@IAEIPAI@Z ; 1
+?PlatformInit@nsComponentManagerImpl@@IAEIXZ ; 1
+??_EnsAppFileLocationProvider@@MAEPAXI@Z ; 1
+??_EnsVoidArray@@UAEPAXI@Z ; 1
+??RnsGetServiceFromCategory@@UBEIABUnsID@@PAPAX@Z ; 1
+??0nsIOFileStream@@QAE@ABVnsFileSpec@@HH@Z ; 1
+?NS_PurgeAtomTable@@YAXXZ ; 1
+??0nsProxyObjectManager@@QAE@XZ ; 1
+?NS_NewThreadPool@@YAIPAPAVnsIThreadPool@@IIIW4PRThreadPriority@@W4PRThreadScope@@@Z ; 1
+?GetNext@EmptyEnumeratorImpl@@UAGIPAPAVnsISupports@@@Z ; 1
+??_GxptiInterfaceInfoManager@@UAEPAXI@Z ; 1
+?ReallocLastSegment@nsSegmentedBuffer@@QAEHI@Z ; 1
+??0nsNativeComponentLoader@@QAE@XZ ; 1
+?Init@nsComponentManagerImpl@@QAEIXZ ; 1
+?CreateMonitoredThreadEventQueue@nsEventQueueServiceImpl@@UAGIXZ ; 1
+?UnloadLibraries@nsComponentManagerImpl@@IAEIPAVnsIServiceManager@@H@Z ; 1
+?Run@MemoryFlusher@@UAGIXZ ; 1
+??1nsDirectoryService@@UAE@XZ ; 1
+?SetRegistryDllInfo@nsNativeComponentLoader@@AAEIPBDPA_J1@Z ; 1
+??1nsDirectoryIteratorImpl@@UAE@XZ ; 1
+?DestroyThreadEventQueue@nsEventQueueServiceImpl@@UAGIXZ ; 1
+?GetInt@nsRegistry@@UAGIIPBDPAH@Z ; 1
+??0MemoryFlusher@@IAE@PAVnsMemoryImpl@@@Z ; 1
+?EnumerateBackwards@nsCStringArray@@QAEHP6AHAAVnsCString@@PAX@Z1@Z ; 1
+?GetParent@nsFileSpecImpl@@UAGIPAPAVnsIFileSpec@@@Z ; 1
+?BuildFileList@xptiInterfaceInfoManager@@AAEHPAPAVnsISupportsArray@@@Z ; 1
+??1nsServiceManagerImpl@@MAE@XZ ; 1
+??1nsObserverService@@UAE@XZ ; 1
+?GetRegistryDllInfo@nsNativeComponentLoader@@AAEIPBDPA_J1@Z ; 1
+?Shutdown@nsMemoryImpl@@SAIXZ ; 1
+NS_CategoryManagerGetFactory ; 1
+?Create@nsProxyObjectManager@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 1
+??_EnsDirectoryIteratorImpl@@UAEPAXI@Z ; 1
+??1nsAppFileLocationProvider@@MAE@XZ ; 1
+?GetProductDirectory@nsAppFileLocationProvider@@IAGIPAPAVnsILocalFile@@@Z ; 1
+??0?$nsCOMPtr@VnsIServiceManager@@@@QAE@ABVnsCOMPtr_helper@@@Z ; 1
+??_EnsNativeComponentLoader@@UAEPAXI@Z ; 1
+?Create@nsObserverService@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 1
+??0nsCategoryManager@@AAE@XZ ; 1
+??1nsIOFileStream@@UAE@XZ ; 1
+??1nsCategoryManager@@UAE@XZ ; 1
+?InvalidateInterfaceInfos@xptiWorkingSet@@QAEXXZ ; 1
+?PlatformPrePopulateRegistry@nsComponentManagerImpl@@QAEIXZ ; 1
+?NS_InitXPCOM2@@YAIPAPAVnsIServiceManager@@PAVnsIFile@@PAVnsIDirectoryServiceProvider@@@Z ; 1
+??_EnsDirectoryIterator@@UAEPAXI@Z ; 1
+?IsValid@xptiInterfaceInfoManager@@AAEHXZ ; 1
+?Shutdown@xptiZipLoader@@SAXXZ ; 1
+?Init@nsDirectoryService@@UAGIXZ ; 1
+?Create@nsErrorService@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 1
+?RegisterDeferredComponents@nsNativeComponentLoader@@UAGIHPAH@Z ; 1
+?Shutdown@nsComponentManagerImpl@@QAEIXZ ; 1
+?Shutdown@nsThread@@SAXXZ ; 1
+?Sync@nsDll@@QAEIXZ ; 1
+?Startup@nsMemoryImpl@@SAIXZ ; 1
+?Define@nsDirectoryService@@UAGIPBDPAVnsISupports@@@Z ; 1
+?SetMainThread@nsIThread@@SAIXZ ; 1
+?ShutdownSpecialSystemDirectory@@YAXXZ ; 1
+?Init@nsNativeComponentLoader@@UAGIPAVnsIComponentManager@@PAVnsISupports@@@Z ; 1
+??0nsCategoryManagerFactory@@QAE@XZ ; 1
+?RegisterErrorStringBundle@nsErrorService@@UAGIFPBD@Z ; 1
+??0nsDirectoryService@@QAE@XZ ; 1
+?RegisterFactory@nsComponentManager@@SAIABUnsID@@PBD1PAVnsIFactory@@H@Z ; 1
+?AutoRegisterImpl@nsComponentManagerImpl@@AAEIHPAVnsIFile@@@Z ; 1
+?DetermineAutoRegStrategy@xptiInterfaceInfoManager@@AAE?AW4AutoRegMode@1@PAVnsISupportsArray@@PAVxptiWorkingSet@@@Z ; 1
+??0nsAppFileLocationProvider@@QAE@XZ ; 1
+??1MemoryFlusher@@MAE@XZ ; 1
+?Create@nsLocalFile@@UAGIII@Z ; 1
+?Join@nsThread@@UAGIXZ ; 1
+??_GnsProxyObjectManager@@UAEPAXI@Z ; 1
+?LogStats@xptiInterfaceInfoManager@@AAEXXZ ; 1
+?Valid@nsFileSpec@@QBEHXZ ; 1
+?NS_InitXPCOM@@YAIPAPAVnsIServiceManager@@PAVnsIFile@@@Z ; 1
+?ShutdownGlobalServiceManager@nsServiceManager@@SAIPAPAVnsIServiceManager@@@Z ; 1
+??1xptiInterfaceInfoManager@@UAE@XZ ; 1
+??_GnsComponentManagerImpl@@UAEPAXI@Z ; 1
+?FreeInterfaceInfoManager@xptiInterfaceInfoManager@@SAXXZ ; 1
+?Create@MemoryFlusher@@SAIPAPAV1@PAVnsMemoryImpl@@@Z ; 1
+??_EnsErrorService@@UAEPAXI@Z ; 1
+??1nsProxyObjectManager@@UAE@XZ ; 1
+??0nsConsoleService@@QAE@XZ ; 1
+?AutoRegisterComponents@nsNativeComponentLoader@@UAGIHPAVnsIFile@@@Z ; 1
+?AutoRegister@nsComponentManager@@SAIHPAVnsIFile@@@Z ; 1
+?QueryInterface@nsDirectoryIteratorImpl@@UAGIABUnsID@@PAPAX@Z ; 1
+??_EMemoryFlusher@@MAEPAXI@Z ; 1
+?initialize@nsCategoryManager@@AAEIXZ ; 1
+?AutoRegisterInterfaces@xptiInterfaceInfoManager@@UAGIXZ ; 1
+PL_CreateMonitoredEventQueue ; 1
+??_GnsCategoryManager@@UAEPAXI@Z ; 1
+?Close@nsStorageStream@@UAGIXZ ; 1
+?Init@nsThreadPool@@UAGIIIIW4PRThreadPriority@@W4PRThreadScope@@@Z ; 1
+??0nsObserverService@@QAE@XZ ; 1
+?Create@nsEventQueueServiceImpl@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 1
+??0xptiInterfaceInfoManager@@AAE@XZ ; 1
+?GetDllSpec@nsDll@@QAEIPAPAVnsIFile@@@Z ; 1
+??_EnsServiceManagerImpl@@MAEPAXI@Z ; 1
+?SelfRegisterDll@nsNativeComponentLoader@@AAEIPAVnsDll@@PBDH@Z ; 1
+?UnloadAll@nsNativeComponentLoader@@UAGIH@Z ; 1
+??0?$nsCOMPtr@VnsIOutputStream@@@@QAE@ABVnsCOMPtr_helper@@@Z ; 1
+?Undefine@nsDirectoryService@@UAGIPBD@Z ; 1
+??0nsDirectoryIteratorImpl@@QAE@XZ ; 1
+??0CCaseConversionServiceInitializer@@QAE@XZ ; 1
+??1nsComponentManagerImpl@@UAE@XZ ; 1
+?RegisterComponentsInDir@nsNativeComponentLoader@@MAGIHPAVnsIFile@@@Z ; 1
+??0nsEventQueueServiceImpl@@QAE@XZ ; 1
+?CreateInstance@nsCategoryManagerFactory@@UAGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 1
+??_GnsObserverService@@UAEPAXI@Z ; 1
+XPTI_FreeInterfaceInfoManager ; 1
+?Stop@MemoryFlusher@@QAEIXZ ; 1
+?CreateThreadEventQueue@nsEventQueueServiceImpl@@UAGIXZ ; 1
+??0nsServiceManagerImpl@@QAE@XZ ; 1
+??1nsNativeComponentLoader@@UAE@XZ ; 1
+??0nsThreadPool@@QAE@XZ ; 1
+?NS_ShutdownLocalFile@@YAXXZ ; 1
+??_GHandleCaseConversionShutdown3@@UAEPAXI@Z ; 1
+?Init@nsDirectoryIteratorImpl@@UAGIPAVnsIFileSpec@@H@Z ; 1
+??0nsErrorService@@QAE@XZ ; 1
+??_EnsConsoleService@@UAEPAXI@Z ; 1
+??0nsSlidingSubstring@@QAE@ABVnsAString@@@Z ; 1
+?CleanUp@nsFSStringConversion@@SAXXZ ; 1
+?Create@nsDirectoryIteratorImpl@@SGIPAVnsISupports@@ABUnsID@@PAPAX@Z ; 1
diff --git a/src/libs/xpcom18a4/xpcom/build/xpcom-tests.pkg b/src/libs/xpcom18a4/xpcom/build/xpcom-tests.pkg
new file mode 100644
index 00000000..8a32b21f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/xpcom-tests.pkg
@@ -0,0 +1,47 @@
+[xpcom-tests]
+#if USE_SHORT_LIBNAME
+dist/bin/components/@DLLP@tdynamic@DLLS@
+dist/bin/components/@DLLP@MyServce@DLLS@
+dist/bin/components/@DLLP@xpcomsmp@DLLS@
+#else
+dist/bin/components/@DLLP@testdynamic@DLLS@
+dist/bin/components/@DLLP@MyService@DLLS@
+dist/bin/components/@DLLP@xpcomsample@DLLS@
+#endif
+dist/bin/components/nsSample.js
+!xpt dist/bin/components/xpcomsample.xpt
+dist/bin/nsTestSample@BINS@
+dist/bin/res/test.properties
+dist/bin/res/samples/xpconnect-sample.html
+!xpt dist/bin/components/proxytest.xpt
+dist/bin/proxytests@BINS@
+
+dist/bin/PrimitiveTest@BINS@
+dist/bin/SimpleTypeLib@BINS@
+dist/bin/TestInterfaceInfo@BINS@
+dist/bin/TestXPTCInvoke@BINS@
+
+dist/bin/nsIFileEnumerator@BINS@
+dist/bin/nsIFileTest@BINS@
+dist/bin/TestArray@BINS@
+dist/bin/TestAtoms@BINS@
+dist/bin/TestAutoLock@BINS@
+dist/bin/TestCallTemplates@BINS@
+dist/bin/TestCOMPtr@BINS@
+dist/bin/TestCOMPtrEq@BINS@
+dist/bin/TestCRT@BINS@
+dist/bin/TestFactory@BINS@
+dist/bin/TestHashtables@BINS@
+dist/bin/TestID@BINS@
+dist/bin/TestObserverService@BINS@
+dist/bin/TestPermanentAtoms@BINS@
+dist/bin/TestPipes@BINS@
+dist/bin/TestServMgr@BINS@
+dist/bin/TestThreads@BINS@
+dist/bin/TestXPIDLString@BINS@
+dist/bin/TestDeque@BINS@
+dist/bin/TestAutoPtr@BINS@
+
+#if OS_ARCH==WINNT
+dist/bin/TestCOM.exe
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/build/xpcom.pkg b/src/libs/xpcom18a4/xpcom/build/xpcom.pkg
new file mode 100644
index 00000000..eab0e19d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/xpcom.pkg
@@ -0,0 +1,106 @@
+[xpcom]
+dist/bin/@DLLP@xpcom@DLLS@
+!xpt dist/bin/components/xpcom_base.xpt
+!xpt dist/bin/components/xpcom_components.xpt
+!xpt dist/bin/components/xpcom_ds.xpt
+!xpt dist/bin/components/xpcom_io.xpt
+!xpt dist/bin/components/xpcom_xpti.xpt
+
+#if OS_ARCH==WINNT
+!xpt dist/bin/components/xpcom_thread.xpt
+!xpt dist/bin/components/proxyObject.xpt
+#else
+!xpt dist/bin/components/xpcom_threads.xpt
+!xpt dist/bin/components/proxyObjInst.xpt
+#endif
+
+[gecko-support]
+dist/bin/regxpcom@BINS@
+dist/bin/xpt_dump@BINS@
+dist/bin/xpt_link@BINS@
+#if MOZ_DEBUG
+#if OS_ARCH==WINNT
+dist/bin/windbgdlg.exe
+#endif
+#endif
+
+# xpidl.exe is not licensed MPL, so we don't include it with applications.
+# It is only included in the developer (SDK) packages.
+[gecko-devel]
+dist/bin/xpidl@BINS@
+
+# put NSPR here, because hacking the NSPR build system is too painful
+# xxxbsmedberg: this doesn't obey --with-system-nspr
+[nspr]
+dist/bin/@DLLP@nspr4@DLLS@
+dist/bin/@DLLP@plc4@DLLS@
+dist/bin/@DLLP@plds4@DLLS@
+
+[nspr-devel]
+dist/lib/@LIBP@nspr4@LIBS@
+dist/lib/@LIBP@plc4@LIBS@
+dist/lib/@LIBP@plds4@LIBS@
+dist/include/nspr/private/pprio.h
+dist/include/nspr/private/pprthred.h
+dist/include/nspr/private/prpriv.h
+dist/include/nspr/prcpucfg.h
+dist/include/nspr/obsolete/pralarm.h
+dist/include/nspr/obsolete/probslet.h
+dist/include/nspr/obsolete/protypes.h
+dist/include/nspr/obsolete/prsem.h
+dist/include/nspr/nspr.h
+dist/include/nspr/pratom.h
+dist/include/nspr/prbit.h
+dist/include/nspr/prclist.h
+dist/include/nspr/prcmon.h
+dist/include/nspr/prcountr.h
+dist/include/nspr/prcvar.h
+dist/include/nspr/prdtoa.h
+dist/include/nspr/prenv.h
+dist/include/nspr/prerr.h
+dist/include/nspr/prerror.h
+dist/include/nspr/prinet.h
+dist/include/nspr/prinit.h
+dist/include/nspr/prinrval.h
+dist/include/nspr/prio.h
+dist/include/nspr/pripcsem.h
+dist/include/nspr/prlink.h
+dist/include/nspr/prlock.h
+dist/include/nspr/prlog.h
+dist/include/nspr/prlong.h
+dist/include/nspr/prmem.h
+dist/include/nspr/prmon.h
+dist/include/nspr/prmwait.h
+dist/include/nspr/prnetdb.h
+dist/include/nspr/prolock.h
+dist/include/nspr/prpdce.h
+dist/include/nspr/prprf.h
+dist/include/nspr/prproces.h
+dist/include/nspr/prrng.h
+dist/include/nspr/prrwlock.h
+dist/include/nspr/prshma.h
+dist/include/nspr/prshm.h
+dist/include/nspr/prsystem.h
+dist/include/nspr/prthread.h
+dist/include/nspr/prtime.h
+dist/include/nspr/prtpool.h
+dist/include/nspr/prtrace.h
+dist/include/nspr/prtypes.h
+dist/include/nspr/prvrsion.h
+dist/include/nspr/prwin16.h
+dist/include/nspr/plarenas.h
+dist/include/nspr/plarena.h
+dist/include/nspr/plhash.h
+dist/include/nspr/plbase64.h
+dist/include/nspr/plerror.h
+dist/include/nspr/plgetopt.h
+dist/include/nspr/plresolv.h
+dist/include/nspr/plstr.h
+
+[unpackaged-files]
+!optional dist/bin/.autoreg
+!optional dist/bin/components/xpti.dat
+!optional dist/bin/components/compreg.dat
+#if OS_ARCH==WINNT
+dist/bin/rebasedlls.exe
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/build/xpcom_alpha.def b/src/libs/xpcom18a4/xpcom/build/xpcom_alpha.def
new file mode 100644
index 00000000..966f2ea4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/build/xpcom_alpha.def
@@ -0,0 +1,252 @@
+LIBRARY xpcom
+DESCRIPTION "xpcom library"
+
+EXPORTS
+ ?Stub3@nsXPTCStubBase@@UAAIXZ
+ ?Stub4@nsXPTCStubBase@@UAAIXZ
+ ?Stub5@nsXPTCStubBase@@UAAIXZ
+ ?Stub6@nsXPTCStubBase@@UAAIXZ
+ ?Stub7@nsXPTCStubBase@@UAAIXZ
+ ?Stub8@nsXPTCStubBase@@UAAIXZ
+ ?Stub9@nsXPTCStubBase@@UAAIXZ
+ ?Stub10@nsXPTCStubBase@@UAAIXZ
+ ?Stub11@nsXPTCStubBase@@UAAIXZ
+ ?Stub12@nsXPTCStubBase@@UAAIXZ
+ ?Stub13@nsXPTCStubBase@@UAAIXZ
+ ?Stub14@nsXPTCStubBase@@UAAIXZ
+ ?Stub15@nsXPTCStubBase@@UAAIXZ
+ ?Stub16@nsXPTCStubBase@@UAAIXZ
+ ?Stub17@nsXPTCStubBase@@UAAIXZ
+ ?Stub18@nsXPTCStubBase@@UAAIXZ
+ ?Stub19@nsXPTCStubBase@@UAAIXZ
+ ?Stub20@nsXPTCStubBase@@UAAIXZ
+ ?Stub21@nsXPTCStubBase@@UAAIXZ
+ ?Stub22@nsXPTCStubBase@@UAAIXZ
+ ?Stub23@nsXPTCStubBase@@UAAIXZ
+ ?Stub24@nsXPTCStubBase@@UAAIXZ
+ ?Stub25@nsXPTCStubBase@@UAAIXZ
+ ?Stub26@nsXPTCStubBase@@UAAIXZ
+ ?Stub27@nsXPTCStubBase@@UAAIXZ
+ ?Stub28@nsXPTCStubBase@@UAAIXZ
+ ?Stub29@nsXPTCStubBase@@UAAIXZ
+ ?Stub30@nsXPTCStubBase@@UAAIXZ
+ ?Stub31@nsXPTCStubBase@@UAAIXZ
+ ?Stub32@nsXPTCStubBase@@UAAIXZ
+ ?Stub33@nsXPTCStubBase@@UAAIXZ
+ ?Stub34@nsXPTCStubBase@@UAAIXZ
+ ?Stub35@nsXPTCStubBase@@UAAIXZ
+ ?Stub36@nsXPTCStubBase@@UAAIXZ
+ ?Stub37@nsXPTCStubBase@@UAAIXZ
+ ?Stub38@nsXPTCStubBase@@UAAIXZ
+ ?Stub39@nsXPTCStubBase@@UAAIXZ
+ ?Stub40@nsXPTCStubBase@@UAAIXZ
+ ?Stub41@nsXPTCStubBase@@UAAIXZ
+ ?Stub42@nsXPTCStubBase@@UAAIXZ
+ ?Stub43@nsXPTCStubBase@@UAAIXZ
+ ?Stub44@nsXPTCStubBase@@UAAIXZ
+ ?Stub45@nsXPTCStubBase@@UAAIXZ
+ ?Stub46@nsXPTCStubBase@@UAAIXZ
+ ?Stub47@nsXPTCStubBase@@UAAIXZ
+ ?Stub48@nsXPTCStubBase@@UAAIXZ
+ ?Stub49@nsXPTCStubBase@@UAAIXZ
+ ?Stub50@nsXPTCStubBase@@UAAIXZ
+ ?Stub51@nsXPTCStubBase@@UAAIXZ
+ ?Stub52@nsXPTCStubBase@@UAAIXZ
+ ?Stub53@nsXPTCStubBase@@UAAIXZ
+ ?Stub54@nsXPTCStubBase@@UAAIXZ
+ ?Stub55@nsXPTCStubBase@@UAAIXZ
+ ?Stub56@nsXPTCStubBase@@UAAIXZ
+ ?Stub57@nsXPTCStubBase@@UAAIXZ
+ ?Stub58@nsXPTCStubBase@@UAAIXZ
+ ?Stub59@nsXPTCStubBase@@UAAIXZ
+ ?Stub60@nsXPTCStubBase@@UAAIXZ
+ ?Stub61@nsXPTCStubBase@@UAAIXZ
+ ?Stub62@nsXPTCStubBase@@UAAIXZ
+ ?Stub63@nsXPTCStubBase@@UAAIXZ
+ ?Stub64@nsXPTCStubBase@@UAAIXZ
+ ?Stub65@nsXPTCStubBase@@UAAIXZ
+ ?Stub66@nsXPTCStubBase@@UAAIXZ
+ ?Stub67@nsXPTCStubBase@@UAAIXZ
+ ?Stub68@nsXPTCStubBase@@UAAIXZ
+ ?Stub69@nsXPTCStubBase@@UAAIXZ
+ ?Stub70@nsXPTCStubBase@@UAAIXZ
+ ?Stub71@nsXPTCStubBase@@UAAIXZ
+ ?Stub72@nsXPTCStubBase@@UAAIXZ
+ ?Stub73@nsXPTCStubBase@@UAAIXZ
+ ?Stub74@nsXPTCStubBase@@UAAIXZ
+ ?Stub75@nsXPTCStubBase@@UAAIXZ
+ ?Stub76@nsXPTCStubBase@@UAAIXZ
+ ?Stub77@nsXPTCStubBase@@UAAIXZ
+ ?Stub78@nsXPTCStubBase@@UAAIXZ
+ ?Stub79@nsXPTCStubBase@@UAAIXZ
+ ?Stub80@nsXPTCStubBase@@UAAIXZ
+ ?Stub81@nsXPTCStubBase@@UAAIXZ
+ ?Stub82@nsXPTCStubBase@@UAAIXZ
+ ?Stub83@nsXPTCStubBase@@UAAIXZ
+ ?Stub84@nsXPTCStubBase@@UAAIXZ
+ ?Stub85@nsXPTCStubBase@@UAAIXZ
+ ?Stub86@nsXPTCStubBase@@UAAIXZ
+ ?Stub87@nsXPTCStubBase@@UAAIXZ
+ ?Stub88@nsXPTCStubBase@@UAAIXZ
+ ?Stub89@nsXPTCStubBase@@UAAIXZ
+ ?Stub90@nsXPTCStubBase@@UAAIXZ
+ ?Stub91@nsXPTCStubBase@@UAAIXZ
+ ?Stub92@nsXPTCStubBase@@UAAIXZ
+ ?Stub93@nsXPTCStubBase@@UAAIXZ
+ ?Stub94@nsXPTCStubBase@@UAAIXZ
+ ?Stub95@nsXPTCStubBase@@UAAIXZ
+ ?Stub96@nsXPTCStubBase@@UAAIXZ
+ ?Stub97@nsXPTCStubBase@@UAAIXZ
+ ?Stub98@nsXPTCStubBase@@UAAIXZ
+ ?Stub99@nsXPTCStubBase@@UAAIXZ
+ ?Stub100@nsXPTCStubBase@@UAAIXZ
+ ?Stub101@nsXPTCStubBase@@UAAIXZ
+ ?Stub102@nsXPTCStubBase@@UAAIXZ
+ ?Stub103@nsXPTCStubBase@@UAAIXZ
+ ?Stub104@nsXPTCStubBase@@UAAIXZ
+ ?Stub105@nsXPTCStubBase@@UAAIXZ
+ ?Stub106@nsXPTCStubBase@@UAAIXZ
+ ?Stub107@nsXPTCStubBase@@UAAIXZ
+ ?Stub108@nsXPTCStubBase@@UAAIXZ
+ ?Stub109@nsXPTCStubBase@@UAAIXZ
+ ?Stub110@nsXPTCStubBase@@UAAIXZ
+ ?Stub111@nsXPTCStubBase@@UAAIXZ
+ ?Stub112@nsXPTCStubBase@@UAAIXZ
+ ?Stub113@nsXPTCStubBase@@UAAIXZ
+ ?Stub114@nsXPTCStubBase@@UAAIXZ
+ ?Stub115@nsXPTCStubBase@@UAAIXZ
+ ?Stub116@nsXPTCStubBase@@UAAIXZ
+ ?Stub117@nsXPTCStubBase@@UAAIXZ
+ ?Stub118@nsXPTCStubBase@@UAAIXZ
+ ?Stub119@nsXPTCStubBase@@UAAIXZ
+ ?Stub120@nsXPTCStubBase@@UAAIXZ
+ ?Stub121@nsXPTCStubBase@@UAAIXZ
+ ?Stub122@nsXPTCStubBase@@UAAIXZ
+ ?Stub123@nsXPTCStubBase@@UAAIXZ
+ ?Stub124@nsXPTCStubBase@@UAAIXZ
+ ?Stub125@nsXPTCStubBase@@UAAIXZ
+ ?Stub126@nsXPTCStubBase@@UAAIXZ
+ ?Stub127@nsXPTCStubBase@@UAAIXZ
+ ?Stub128@nsXPTCStubBase@@UAAIXZ
+ ?Stub129@nsXPTCStubBase@@UAAIXZ
+ ?Stub130@nsXPTCStubBase@@UAAIXZ
+ ?Stub131@nsXPTCStubBase@@UAAIXZ
+ ?Stub132@nsXPTCStubBase@@UAAIXZ
+ ?Stub133@nsXPTCStubBase@@UAAIXZ
+ ?Stub134@nsXPTCStubBase@@UAAIXZ
+ ?Stub135@nsXPTCStubBase@@UAAIXZ
+ ?Stub136@nsXPTCStubBase@@UAAIXZ
+ ?Stub137@nsXPTCStubBase@@UAAIXZ
+ ?Stub138@nsXPTCStubBase@@UAAIXZ
+ ?Stub139@nsXPTCStubBase@@UAAIXZ
+ ?Stub140@nsXPTCStubBase@@UAAIXZ
+ ?Stub141@nsXPTCStubBase@@UAAIXZ
+ ?Stub142@nsXPTCStubBase@@UAAIXZ
+ ?Stub143@nsXPTCStubBase@@UAAIXZ
+ ?Stub144@nsXPTCStubBase@@UAAIXZ
+ ?Stub145@nsXPTCStubBase@@UAAIXZ
+ ?Stub146@nsXPTCStubBase@@UAAIXZ
+ ?Stub147@nsXPTCStubBase@@UAAIXZ
+ ?Stub148@nsXPTCStubBase@@UAAIXZ
+ ?Stub149@nsXPTCStubBase@@UAAIXZ
+ ?Stub150@nsXPTCStubBase@@UAAIXZ
+ ?Stub151@nsXPTCStubBase@@UAAIXZ
+ ?Stub152@nsXPTCStubBase@@UAAIXZ
+ ?Stub153@nsXPTCStubBase@@UAAIXZ
+ ?Stub154@nsXPTCStubBase@@UAAIXZ
+ ?Stub155@nsXPTCStubBase@@UAAIXZ
+ ?Stub156@nsXPTCStubBase@@UAAIXZ
+ ?Stub157@nsXPTCStubBase@@UAAIXZ
+ ?Stub158@nsXPTCStubBase@@UAAIXZ
+ ?Stub159@nsXPTCStubBase@@UAAIXZ
+ ?Stub160@nsXPTCStubBase@@UAAIXZ
+ ?Stub161@nsXPTCStubBase@@UAAIXZ
+ ?Stub162@nsXPTCStubBase@@UAAIXZ
+ ?Stub163@nsXPTCStubBase@@UAAIXZ
+ ?Stub164@nsXPTCStubBase@@UAAIXZ
+ ?Stub165@nsXPTCStubBase@@UAAIXZ
+ ?Stub166@nsXPTCStubBase@@UAAIXZ
+ ?Stub167@nsXPTCStubBase@@UAAIXZ
+ ?Stub168@nsXPTCStubBase@@UAAIXZ
+ ?Stub169@nsXPTCStubBase@@UAAIXZ
+ ?Stub170@nsXPTCStubBase@@UAAIXZ
+ ?Stub171@nsXPTCStubBase@@UAAIXZ
+ ?Stub172@nsXPTCStubBase@@UAAIXZ
+ ?Stub173@nsXPTCStubBase@@UAAIXZ
+ ?Stub174@nsXPTCStubBase@@UAAIXZ
+ ?Stub175@nsXPTCStubBase@@UAAIXZ
+ ?Stub176@nsXPTCStubBase@@UAAIXZ
+ ?Stub177@nsXPTCStubBase@@UAAIXZ
+ ?Stub178@nsXPTCStubBase@@UAAIXZ
+ ?Stub179@nsXPTCStubBase@@UAAIXZ
+ ?Stub180@nsXPTCStubBase@@UAAIXZ
+ ?Stub181@nsXPTCStubBase@@UAAIXZ
+ ?Stub182@nsXPTCStubBase@@UAAIXZ
+ ?Stub183@nsXPTCStubBase@@UAAIXZ
+ ?Stub184@nsXPTCStubBase@@UAAIXZ
+ ?Stub185@nsXPTCStubBase@@UAAIXZ
+ ?Stub186@nsXPTCStubBase@@UAAIXZ
+ ?Stub187@nsXPTCStubBase@@UAAIXZ
+ ?Stub188@nsXPTCStubBase@@UAAIXZ
+ ?Stub189@nsXPTCStubBase@@UAAIXZ
+ ?Stub190@nsXPTCStubBase@@UAAIXZ
+ ?Stub191@nsXPTCStubBase@@UAAIXZ
+ ?Stub192@nsXPTCStubBase@@UAAIXZ
+ ?Stub193@nsXPTCStubBase@@UAAIXZ
+ ?Stub194@nsXPTCStubBase@@UAAIXZ
+ ?Stub195@nsXPTCStubBase@@UAAIXZ
+ ?Stub196@nsXPTCStubBase@@UAAIXZ
+ ?Stub197@nsXPTCStubBase@@UAAIXZ
+ ?Stub198@nsXPTCStubBase@@UAAIXZ
+ ?Stub199@nsXPTCStubBase@@UAAIXZ
+ ?Stub200@nsXPTCStubBase@@UAAIXZ
+ ?Stub201@nsXPTCStubBase@@UAAIXZ
+ ?Stub202@nsXPTCStubBase@@UAAIXZ
+ ?Stub203@nsXPTCStubBase@@UAAIXZ
+ ?Stub204@nsXPTCStubBase@@UAAIXZ
+ ?Stub205@nsXPTCStubBase@@UAAIXZ
+ ?Stub206@nsXPTCStubBase@@UAAIXZ
+ ?Stub207@nsXPTCStubBase@@UAAIXZ
+ ?Stub208@nsXPTCStubBase@@UAAIXZ
+ ?Stub209@nsXPTCStubBase@@UAAIXZ
+ ?Stub210@nsXPTCStubBase@@UAAIXZ
+ ?Stub211@nsXPTCStubBase@@UAAIXZ
+ ?Stub212@nsXPTCStubBase@@UAAIXZ
+ ?Stub213@nsXPTCStubBase@@UAAIXZ
+ ?Stub214@nsXPTCStubBase@@UAAIXZ
+ ?Stub215@nsXPTCStubBase@@UAAIXZ
+ ?Stub216@nsXPTCStubBase@@UAAIXZ
+ ?Stub217@nsXPTCStubBase@@UAAIXZ
+ ?Stub218@nsXPTCStubBase@@UAAIXZ
+ ?Stub219@nsXPTCStubBase@@UAAIXZ
+ ?Stub220@nsXPTCStubBase@@UAAIXZ
+ ?Stub221@nsXPTCStubBase@@UAAIXZ
+ ?Stub222@nsXPTCStubBase@@UAAIXZ
+ ?Stub223@nsXPTCStubBase@@UAAIXZ
+ ?Stub224@nsXPTCStubBase@@UAAIXZ
+ ?Stub225@nsXPTCStubBase@@UAAIXZ
+ ?Stub226@nsXPTCStubBase@@UAAIXZ
+ ?Stub227@nsXPTCStubBase@@UAAIXZ
+ ?Stub228@nsXPTCStubBase@@UAAIXZ
+ ?Stub229@nsXPTCStubBase@@UAAIXZ
+ ?Stub230@nsXPTCStubBase@@UAAIXZ
+ ?Stub231@nsXPTCStubBase@@UAAIXZ
+ ?Stub232@nsXPTCStubBase@@UAAIXZ
+ ?Stub233@nsXPTCStubBase@@UAAIXZ
+ ?Stub234@nsXPTCStubBase@@UAAIXZ
+ ?Stub235@nsXPTCStubBase@@UAAIXZ
+ ?Stub236@nsXPTCStubBase@@UAAIXZ
+ ?Stub237@nsXPTCStubBase@@UAAIXZ
+ ?Stub238@nsXPTCStubBase@@UAAIXZ
+ ?Stub239@nsXPTCStubBase@@UAAIXZ
+ ?Stub240@nsXPTCStubBase@@UAAIXZ
+ ?Stub241@nsXPTCStubBase@@UAAIXZ
+ ?Stub242@nsXPTCStubBase@@UAAIXZ
+ ?Stub243@nsXPTCStubBase@@UAAIXZ
+ ?Stub244@nsXPTCStubBase@@UAAIXZ
+ ?Stub245@nsXPTCStubBase@@UAAIXZ
+ ?Stub246@nsXPTCStubBase@@UAAIXZ
+ ?Stub247@nsXPTCStubBase@@UAAIXZ
+ ?Stub248@nsXPTCStubBase@@UAAIXZ
+ ?Stub249@nsXPTCStubBase@@UAAIXZ
+
diff --git a/src/libs/xpcom18a4/xpcom/components/.cvsignore b/src/libs/xpcom18a4/xpcom/components/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/components/Makefile.in b/src/libs/xpcom18a4/xpcom/components/Makefile.in
new file mode 100644
index 00000000..68614854
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/Makefile.in
@@ -0,0 +1,107 @@
+#
+# ***** 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_components
+LIBRARY_NAME = xpcomcomponents_s
+GRE_MODULE = 1
+
+REQUIRES = string \
+ $(NULL)
+
+CPPSRCS = \
+ nsCategoryManager.cpp \
+ nsComponentManager.cpp \
+ nsComponentManagerObsolete.cpp \
+ nsNativeComponentLoader.cpp \
+ nsServiceManagerObsolete.cpp \
+ xcDll.cpp \
+ $(NULL)
+
+ifdef MOZ_STATIC_COMPONENT_LOADER
+CPPSRCS += nsStaticComponentLoader.cpp
+endif
+
+EXPORTS = \
+ nsCategoryManagerUtils.h \
+ nsComponentManagerUtils.h \
+ nsComponentManagerObsolete.h \
+ nsIServiceManagerUtils.h \
+ nsIServiceManagerObsolete.h \
+ nsModule.h \
+ nsNativeComponentLoader.h \
+ nsStaticComponent.h \
+ nsObsoleteModuleLoading.h \
+ xcDll.h \
+ $(NULL)
+
+XPIDLSRCS = \
+ nsIComponentLoader.idl \
+ nsIComponentLoaderManager.idl \
+ nsIComponentManagerObsolete.idl \
+ nsINativeComponentLoader.idl \
+ $(NULL)
+
+SDK_XPIDLSRCS = \
+ nsIClassInfo.idl \
+ nsIComponentRegistrar.idl \
+ nsIFactory.idl \
+ nsIModule.idl \
+ nsIServiceManager.idl \
+ nsIComponentManager.idl \
+ nsICategoryManager.idl \
+ $(NULL)
+
+EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
+
+LOCAL_INCLUDES = -I$(srcdir)/../base -I$(srcdir)/../thread -I$(srcdir)/../ds -I..
+
+# 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 -DEXPORT_XPTI_API
diff --git a/src/libs/xpcom18a4/xpcom/components/nsCategoryManager.cpp b/src/libs/xpcom18a4/xpcom/components/nsCategoryManager.cpp
new file mode 100644
index 00000000..d7202bdb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsCategoryManager.cpp
@@ -0,0 +1,799 @@
+/* -*- 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 ***** */
+
+#define PL_ARENA_CONST_ALIGN_MASK 7
+
+#include "nsICategoryManager.h"
+#include "nsCategoryManager.h"
+
+#include "plarena.h"
+#include "prio.h"
+#include "prprf.h"
+#include "prlock.h"
+#include "nsCOMPtr.h"
+#include "nsTHashtable.h"
+#include "nsClassHashtable.h"
+#include "nsIFactory.h"
+#include "nsIStringEnumerator.h"
+#include "nsSupportsPrimitives.h"
+#include "nsIServiceManagerUtils.h"
+#include "nsIObserver.h"
+#include "nsReadableUtils.h"
+#include "nsCRT.h"
+#include "nsEnumeratorUtils.h"
+
+class nsIComponentLoaderManager;
+
+/*
+ CategoryDatabase
+ contains 0 or more 1-1 mappings of string to Category
+ each Category contains 0 or more 1-1 mappings of string keys to string values
+
+ In other words, the CategoryDatabase is a tree, whose root is a hashtable.
+ Internal nodes (or Categories) are hashtables. Leaf nodes are strings.
+
+ The leaf strings are allocated in an arena, because we assume they're not
+ going to change much ;)
+*/
+
+#define NS_CATEGORYMANAGER_ARENA_SIZE (1024 * 8)
+
+// pulled in from nsComponentManager.cpp
+char* ArenaStrdup(const char* s, PLArenaPool* aArena);
+
+//
+// BaseStringEnumerator is subclassed by EntryEnumerator and
+// CategoryEnumerator
+//
+class BaseStringEnumerator
+ : public nsISimpleEnumerator,
+ nsIUTF8StringEnumerator
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISIMPLEENUMERATOR
+ NS_DECL_NSIUTF8STRINGENUMERATOR
+
+protected:
+ BaseStringEnumerator()
+ : mArray(nsnull),
+ mCount(0),
+ mSimpleCurItem(0),
+ mStringCurItem(0) { }
+
+ // A virtual destructor is needed here because subclasses of
+ // BaseStringEnumerator do not implement their own Release() method.
+
+ virtual ~BaseStringEnumerator()
+ {
+ if (mArray)
+ delete[] mArray;
+ }
+
+ const char** mArray;
+ PRUint32 mCount;
+ PRUint32 mSimpleCurItem;
+ PRUint32 mStringCurItem;
+};
+
+NS_IMPL_ISUPPORTS2(BaseStringEnumerator, nsISimpleEnumerator, nsIUTF8StringEnumerator)
+
+NS_IMETHODIMP
+BaseStringEnumerator::HasMoreElements(PRBool *_retval)
+{
+ *_retval = (mSimpleCurItem < mCount);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+BaseStringEnumerator::GetNext(nsISupports **_retval)
+{
+ if (mSimpleCurItem >= mCount)
+ return NS_ERROR_FAILURE;
+
+ nsSupportsDependentCString* str =
+ new nsSupportsDependentCString(mArray[mSimpleCurItem++]);
+ if (!str)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ *_retval = str;
+ NS_ADDREF(*_retval);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+BaseStringEnumerator::HasMore(PRBool *_retval)
+{
+ *_retval = (mStringCurItem < mCount);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+BaseStringEnumerator::GetNext(nsACString& _retval)
+{
+ if (mStringCurItem >= mCount)
+ return NS_ERROR_FAILURE;
+
+ _retval = nsDependentCString(mArray[mStringCurItem++]);
+ return NS_OK;
+}
+
+
+//
+// EntryEnumerator is the wrapper that allows nsICategoryManager::EnumerateCategory
+//
+class EntryEnumerator
+ : public BaseStringEnumerator
+{
+public:
+ static EntryEnumerator* Create(nsTHashtable<CategoryLeaf>& aTable);
+
+private:
+ static PLDHashOperator PR_CALLBACK
+ enumfunc_createenumerator(CategoryLeaf* aLeaf, void* userArg);
+};
+
+
+PLDHashOperator PR_CALLBACK
+EntryEnumerator::enumfunc_createenumerator(CategoryLeaf* aLeaf, void* userArg)
+{
+ EntryEnumerator* mythis = NS_STATIC_CAST(EntryEnumerator*, userArg);
+ mythis->mArray[mythis->mCount++] = aLeaf->GetKey();
+
+ return PL_DHASH_NEXT;
+}
+
+EntryEnumerator*
+EntryEnumerator::Create(nsTHashtable<CategoryLeaf>& aTable)
+{
+ EntryEnumerator* enumObj = new EntryEnumerator();
+ if (!enumObj)
+ return nsnull;
+
+ enumObj->mArray = new char const* [aTable.Count()];
+ if (!enumObj->mArray) {
+ delete enumObj;
+ return nsnull;
+ }
+
+ aTable.EnumerateEntries(enumfunc_createenumerator, enumObj);
+
+ return enumObj;
+}
+
+
+//
+// CategoryNode implementations
+//
+
+CategoryNode*
+CategoryNode::Create(PLArenaPool* aArena)
+{
+ CategoryNode* node = new(aArena) CategoryNode();
+ if (!node)
+ return nsnull;
+
+ if (!node->mTable.Init()) {
+ delete node;
+ return nsnull;
+ }
+
+ node->mLock = PR_NewLock();
+ if (!node->mLock) {
+ delete node;
+ return nsnull;
+ }
+
+ return node;
+}
+
+CategoryNode::~CategoryNode()
+{
+ if (mLock)
+ PR_DestroyLock(mLock);
+}
+
+void*
+CategoryNode::operator new(size_t aSize, PLArenaPool* aArena)
+{
+ void* p;
+ PL_ARENA_ALLOCATE(p, aArena, aSize);
+ return p;
+}
+
+NS_METHOD
+CategoryNode::GetLeaf(const char* aEntryName,
+ char** _retval)
+{
+ PR_Lock(mLock);
+ nsresult rv = NS_ERROR_NOT_AVAILABLE;
+ CategoryLeaf* ent =
+ mTable.GetEntry(aEntryName);
+
+ // we only want the non-persistent value
+ if (ent && ent->nonpValue) {
+ *_retval = nsCRT::strdup(ent->nonpValue);
+ if (*_retval)
+ rv = NS_OK;
+ }
+ PR_Unlock(mLock);
+
+ return rv;
+}
+
+NS_METHOD
+CategoryNode::AddLeaf(const char* aEntryName,
+ const char* aValue,
+ PRBool aPersist,
+ PRBool aReplace,
+ char** _retval,
+ PLArenaPool* aArena)
+{
+ PR_Lock(mLock);
+ CategoryLeaf* leaf =
+ mTable.GetEntry(aEntryName);
+
+ nsresult rv = NS_OK;
+ if (leaf) {
+ //if the entry was found, aReplace must be specified
+ if (!aReplace && (leaf->nonpValue || (aPersist && leaf->pValue )))
+ rv = NS_ERROR_INVALID_ARG;
+ } else {
+ const char* arenaEntryName = ArenaStrdup(aEntryName, aArena);
+ if (!arenaEntryName) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ } else {
+ leaf = mTable.PutEntry(arenaEntryName);
+ if (!leaf)
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+
+ if (NS_SUCCEEDED(rv)) {
+ const char* arenaValue = ArenaStrdup(aValue, aArena);
+ if (!arenaValue) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ } else {
+ leaf->nonpValue = arenaValue;
+ if (aPersist)
+ leaf->pValue = arenaValue;
+ }
+ }
+
+ PR_Unlock(mLock);
+ return rv;
+}
+
+NS_METHOD
+CategoryNode::DeleteLeaf(const char* aEntryName,
+ PRBool aDontPersist)
+{
+ // we don't throw any errors, because it normally doesn't matter
+ // and it makes JS a lot cleaner
+ PR_Lock(mLock);
+
+ if (aDontPersist) {
+ // we can just remove the entire hash entry without introspection
+ mTable.RemoveEntry(aEntryName);
+ } else {
+ // if we are keeping the persistent value, we need to look at
+ // the contents of the current entry
+ CategoryLeaf* leaf = mTable.GetEntry(aEntryName);
+ if (leaf) {
+ if (leaf->pValue) {
+ leaf->nonpValue = nsnull;
+ } else {
+ // if there is no persistent value, just remove the entry
+ mTable.RawRemoveEntry(leaf);
+ }
+ }
+ }
+ PR_Unlock(mLock);
+
+ return NS_OK;
+}
+
+NS_METHOD
+CategoryNode::Enumerate(nsISimpleEnumerator **_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ PR_Lock(mLock);
+ EntryEnumerator* enumObj = EntryEnumerator::Create(mTable);
+ PR_Unlock(mLock);
+
+ if (!enumObj)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ *_retval = enumObj;
+ NS_ADDREF(*_retval);
+ return NS_OK;
+}
+
+struct persistent_userstruct {
+ PRFileDesc* fd;
+ const char* categoryName;
+ PRBool success;
+};
+
+PLDHashOperator PR_CALLBACK
+enumfunc_pentries(CategoryLeaf* aLeaf, void* userArg)
+{
+ persistent_userstruct* args =
+ NS_STATIC_CAST(persistent_userstruct*, userArg);
+
+ PLDHashOperator status = PL_DHASH_NEXT;
+
+ if (aLeaf->pValue) {
+ if (PR_fprintf(args->fd,
+ "%s,%s,%s\n",
+ args->categoryName,
+ aLeaf->GetKey(),
+ aLeaf->pValue) == (PRUint32) -1) {
+ args->success = PR_FALSE;
+ status = PL_DHASH_STOP;
+ }
+ }
+
+ return status;
+}
+
+PRBool
+CategoryNode::WritePersistentEntries(PRFileDesc* fd, const char* aCategoryName)
+{
+ persistent_userstruct args = {
+ fd,
+ aCategoryName,
+ PR_TRUE
+ };
+
+ PR_Lock(mLock);
+ mTable.EnumerateEntries(enumfunc_pentries, &args);
+ PR_Unlock(mLock);
+
+ return args.success;
+}
+
+
+//
+// CategoryEnumerator class
+//
+
+class CategoryEnumerator
+ : public BaseStringEnumerator
+{
+public:
+ static CategoryEnumerator* Create(nsClassHashtable<nsDepCharHashKey, CategoryNode>& aTable);
+
+private:
+ static PLDHashOperator PR_CALLBACK
+ enumfunc_createenumerator(const char* aStr,
+ CategoryNode* aNode,
+ void* userArg);
+};
+
+CategoryEnumerator*
+CategoryEnumerator::Create(nsClassHashtable<nsDepCharHashKey, CategoryNode>& aTable)
+{
+ CategoryEnumerator* enumObj = new CategoryEnumerator();
+ if (!enumObj)
+ return nsnull;
+
+ enumObj->mArray = new const char* [aTable.Count()];
+ if (!enumObj->mArray) {
+ delete enumObj;
+ return nsnull;
+ }
+
+ aTable.EnumerateRead(enumfunc_createenumerator, enumObj);
+
+ return enumObj;
+}
+
+PLDHashOperator PR_CALLBACK
+CategoryEnumerator::enumfunc_createenumerator(const char* aStr, CategoryNode* aNode, void* userArg)
+{
+ CategoryEnumerator* mythis = NS_STATIC_CAST(CategoryEnumerator*, userArg);
+
+ // if a category has no entries, we pretend it doesn't exist
+ if (aNode->Count())
+ mythis->mArray[mythis->mCount++] = aStr;
+
+ return PL_DHASH_NEXT;
+}
+
+
+//
+// nsCategoryManager implementations
+//
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsCategoryManager, nsICategoryManager)
+
+nsCategoryManager*
+nsCategoryManager::Create()
+{
+ nsCategoryManager* manager = new nsCategoryManager();
+
+ if (!manager)
+ return nsnull;
+
+ PL_INIT_ARENA_POOL(&(manager->mArena), "CategoryManagerArena",
+ NS_CATEGORYMANAGER_ARENA_SIZE); // this never fails
+
+ if (!manager->mTable.Init()) {
+ delete manager;
+ return nsnull;
+ }
+
+ manager->mLock = PR_NewLock();
+
+ if (!manager->mLock) {
+ delete manager;
+ return nsnull;
+ }
+
+ return manager;
+}
+
+nsCategoryManager::~nsCategoryManager()
+{
+ if (mLock)
+ PR_DestroyLock(mLock);
+
+ // the hashtable contains entries that must be deleted before the arena is
+ // destroyed, or else you will have PRLocks undestroyed and other Really
+ // Bad Stuff (TM)
+ mTable.Clear();
+
+ PL_FinishArenaPool(&mArena);
+}
+
+inline CategoryNode*
+nsCategoryManager::get_category(const char* aName) {
+ CategoryNode* node;
+ if (!mTable.Get(aName, &node)) {
+ return nsnull;
+ }
+ return node;
+}
+
+NS_IMETHODIMP
+nsCategoryManager::GetCategoryEntry( const char *aCategoryName,
+ const char *aEntryName,
+ char **_retval )
+{
+ NS_ENSURE_ARG_POINTER(aCategoryName);
+ NS_ENSURE_ARG_POINTER(aEntryName);
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ nsresult status = NS_ERROR_NOT_AVAILABLE;
+
+ PR_Lock(mLock);
+ CategoryNode* category = get_category(aCategoryName);
+ PR_Unlock(mLock);
+
+ if (category) {
+ status = category->GetLeaf(aEntryName, _retval);
+ }
+
+ return status;
+}
+
+NS_IMETHODIMP
+nsCategoryManager::AddCategoryEntry( const char *aCategoryName,
+ const char *aEntryName,
+ const char *aValue,
+ PRBool aPersist,
+ PRBool aReplace,
+ char **_retval )
+{
+ NS_ENSURE_ARG_POINTER(aCategoryName);
+ NS_ENSURE_ARG_POINTER(aEntryName);
+ NS_ENSURE_ARG_POINTER(aValue);
+
+ // Before we can insert a new entry, we'll need to
+ // find the |CategoryNode| to put it in...
+ PR_Lock(mLock);
+ CategoryNode* category = get_category(aCategoryName);
+
+ if (!category) {
+ // That category doesn't exist yet; let's make it.
+ category = CategoryNode::Create(&mArena);
+
+ char* categoryName = ArenaStrdup(aCategoryName, &mArena);
+ mTable.Put(categoryName, category);
+ }
+ PR_Unlock(mLock);
+
+ if (!category)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return category->AddLeaf(aEntryName,
+ aValue,
+ aPersist,
+ aReplace,
+ _retval,
+ &mArena);
+}
+
+NS_IMETHODIMP
+nsCategoryManager::DeleteCategoryEntry( const char *aCategoryName,
+ const char *aEntryName,
+ PRBool aDontPersist)
+{
+ NS_ENSURE_ARG_POINTER(aCategoryName);
+ NS_ENSURE_ARG_POINTER(aEntryName);
+
+ /*
+ Note: no errors are reported since failure to delete
+ probably won't hurt you, and returning errors seriously
+ inconveniences JS clients
+ */
+
+ PR_Lock(mLock);
+ CategoryNode* category = get_category(aCategoryName);
+ PR_Unlock(mLock);
+
+ if (!category)
+ return NS_OK;
+
+ return category->DeleteLeaf(aEntryName,
+ aDontPersist);
+}
+
+NS_IMETHODIMP
+nsCategoryManager::DeleteCategory( const char *aCategoryName )
+{
+ NS_ENSURE_ARG_POINTER(aCategoryName);
+
+ // the categories are arena-allocated, so we don't
+ // actually delete them. We just remove all of the
+ // leaf nodes.
+
+ PR_Lock(mLock);
+ CategoryNode* category = get_category(aCategoryName);
+ PR_Unlock(mLock);
+
+ if (category)
+ category->Clear();
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsCategoryManager::EnumerateCategory( const char *aCategoryName,
+ nsISimpleEnumerator **_retval )
+{
+ NS_ENSURE_ARG_POINTER(aCategoryName);
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ PR_Lock(mLock);
+ CategoryNode* category = get_category(aCategoryName);
+ PR_Unlock(mLock);
+
+ if (!category) {
+ return NS_NewEmptyEnumerator(_retval);
+ }
+
+ return category->Enumerate(_retval);
+}
+
+NS_IMETHODIMP
+nsCategoryManager::EnumerateCategories(nsISimpleEnumerator **_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ PR_Lock(mLock);
+ CategoryEnumerator* enumObj = CategoryEnumerator::Create(mTable);
+ PR_Unlock(mLock);
+
+ if (!enumObj)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ *_retval = enumObj;
+ NS_ADDREF(*_retval);
+ return NS_OK;
+}
+
+struct writecat_struct {
+ PRFileDesc* fd;
+ PRBool success;
+};
+
+PLDHashOperator PR_CALLBACK
+enumfunc_categories(const char* aKey, CategoryNode* aCategory, void* userArg)
+{
+ writecat_struct* args = NS_STATIC_CAST(writecat_struct*, userArg);
+
+ PLDHashOperator result = PL_DHASH_NEXT;
+
+ if (!aCategory->WritePersistentEntries(args->fd, aKey)) {
+ args->success = PR_FALSE;
+ result = PL_DHASH_STOP;
+ }
+
+ return result;
+}
+
+NS_METHOD
+nsCategoryManager::WriteCategoryManagerToRegistry(PRFileDesc* fd)
+{
+ writecat_struct args = {
+ fd,
+ PR_TRUE
+ };
+
+ PR_Lock(mLock);
+ mTable.EnumerateRead(enumfunc_categories, &args);
+ PR_Unlock(mLock);
+
+ if (!args.success) {
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ return NS_OK;
+}
+
+class nsCategoryManagerFactory : public nsIFactory
+ {
+ public:
+ nsCategoryManagerFactory() { }
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIFACTORY
+ };
+
+NS_IMPL_ISUPPORTS1(nsCategoryManagerFactory, nsIFactory)
+
+NS_IMETHODIMP
+nsCategoryManagerFactory::CreateInstance( nsISupports* aOuter, const nsIID& aIID, void** aResult )
+ {
+ NS_ENSURE_ARG_POINTER(aResult);
+
+ *aResult = 0;
+
+ nsresult status = NS_OK;
+ if ( aOuter )
+ status = NS_ERROR_NO_AGGREGATION;
+ else
+ {
+ nsCategoryManager* raw_category_manager = nsCategoryManager::Create();
+ nsCOMPtr<nsICategoryManager> new_category_manager = raw_category_manager;
+ if ( new_category_manager )
+ status = new_category_manager->QueryInterface(aIID, aResult);
+ else
+ status = NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ return status;
+ }
+
+NS_IMETHODIMP
+nsCategoryManagerFactory::LockFactory( PRBool )
+ {
+ // Not implemented...
+ return NS_OK;
+ }
+
+nsresult
+NS_CategoryManagerGetFactory( nsIFactory** aFactory )
+ {
+ // assert(aFactory);
+
+ nsresult status;
+
+ *aFactory = 0;
+ nsIFactory* new_factory = NS_STATIC_CAST(nsIFactory*, new nsCategoryManagerFactory);
+ if (new_factory)
+ {
+ *aFactory = new_factory;
+ NS_ADDREF(*aFactory);
+ status = NS_OK;
+ }
+ else
+ status = NS_ERROR_OUT_OF_MEMORY;
+
+ return status;
+ }
+
+
+
+/*
+ * CreateServicesFromCategory()
+ *
+ * Given a category, this convenience functions enumerates the category and
+ * creates a service of every CID or ContractID registered under the category.
+ * If observerTopic is non null and the service implements nsIObserver,
+ * this will attempt to notify the observer with the origin, observerTopic string
+ * as parameter.
+ */
+NS_COM nsresult
+NS_CreateServicesFromCategory(const char *category,
+ nsISupports *origin,
+ const char *observerTopic)
+{
+ nsresult rv = NS_OK;
+
+ int nFailed = 0;
+ nsCOMPtr<nsICategoryManager> categoryManager =
+ do_GetService("@mozilla.org/categorymanager;1", &rv);
+ if (!categoryManager) return rv;
+
+ nsCOMPtr<nsISimpleEnumerator> enumerator;
+ rv = categoryManager->EnumerateCategory(category,
+ getter_AddRefs(enumerator));
+ if (NS_FAILED(rv)) return rv;
+
+ nsCOMPtr<nsISupports> entry;
+ while (NS_SUCCEEDED(enumerator->GetNext(getter_AddRefs(entry)))) {
+ // From here on just skip any error we get.
+ nsCOMPtr<nsISupportsCString> catEntry = do_QueryInterface(entry, &rv);
+ if (NS_FAILED(rv)) {
+ nFailed++;
+ continue;
+ }
+ nsCAutoString entryString;
+ rv = catEntry->GetData(entryString);
+ if (NS_FAILED(rv)) {
+ nFailed++;
+ continue;
+ }
+ nsXPIDLCString contractID;
+ rv = categoryManager->GetCategoryEntry(category,entryString.get(), getter_Copies(contractID));
+ if (NS_FAILED(rv)) {
+ nFailed++;
+ continue;
+ }
+
+ nsCOMPtr<nsISupports> instance = do_GetService(contractID, &rv);
+ if (NS_FAILED(rv)) {
+ nFailed++;
+ continue;
+ }
+
+ if (observerTopic) {
+ // try an observer, if it implements it.
+ nsCOMPtr<nsIObserver> observer = do_QueryInterface(instance, &rv);
+ if (NS_SUCCEEDED(rv) && observer)
+ observer->Observe(origin, observerTopic, EmptyString().get());
+ }
+ }
+ return (nFailed ? NS_ERROR_FAILURE : NS_OK);
+}
diff --git a/src/libs/xpcom18a4/xpcom/components/nsCategoryManager.h b/src/libs/xpcom18a4/xpcom/components/nsCategoryManager.h
new file mode 100644
index 00000000..a5cdb59a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsCategoryManager.h
@@ -0,0 +1,159 @@
+/* -*- 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 NSCATEGORYMANAGER_H
+#define NSCATEGORYMANAGER_H
+
+#include "prio.h"
+#include "prlock.h"
+#include "plarena.h"
+#include "nsClassHashtable.h"
+#include "nsICategoryManager.h"
+
+#define NS_CATEGORYMANAGER_CLASSNAME "Category Manager"
+
+/* 16d222a6-1dd2-11b2-b693-f38b02c021b2 */
+#define NS_CATEGORYMANAGER_CID \
+{ 0x16d222a6, 0x1dd2, 0x11b2, \
+ {0xb6, 0x93, 0xf3, 0x8b, 0x02, 0xc0, 0x21, 0xb2} }
+
+/**
+ * a "leaf-node", managed by the nsCategoryNode hashtable.
+ *
+ * we need to keep a "persistent value" (which will be written to the registry)
+ * and a non-persistent value (for the current runtime): these are usually
+ * the same, except when aPersist==PR_FALSE. The strings are permanently arena-
+ * allocated, and will never go away.
+ */
+class CategoryLeaf : public nsDepCharHashKey
+{
+public:
+ CategoryLeaf(const char* aKey)
+ : nsDepCharHashKey(aKey),
+ pValue(nsnull),
+ nonpValue(nsnull) { }
+ const char* pValue;
+ const char* nonpValue;
+};
+
+
+/**
+ * CategoryNode keeps a hashtable of it's entries.
+ * the CategoryNode itself is permanently allocated in
+ * the arena.
+ */
+class CategoryNode
+{
+public:
+ NS_METHOD GetLeaf(const char* aEntryName,
+ char** _retval);
+
+ NS_METHOD AddLeaf(const char* aEntryName,
+ const char* aValue,
+ PRBool aPersist,
+ PRBool aReplace,
+ char** _retval,
+ PLArenaPool* aArena);
+
+ NS_METHOD DeleteLeaf(const char* aEntryName,
+ PRBool aDontPersist);
+
+ void Clear() {
+ PR_Lock(mLock);
+ mTable.Clear();
+ PR_Unlock(mLock);
+ }
+
+ PRUint32 Count() {
+ PR_Lock(mLock);
+ PRUint32 tCount = mTable.Count();
+ PR_Unlock(mLock);
+ return tCount;
+ }
+
+ NS_METHOD Enumerate(nsISimpleEnumerator** _retval);
+
+ PRBool WritePersistentEntries(PRFileDesc* fd, const char* aCategoryName);
+
+ // CategoryNode is arena-allocated, with the strings
+ static CategoryNode* Create(PLArenaPool* aArena);
+ ~CategoryNode();
+ void operator delete(void*) { }
+
+private:
+ CategoryNode() : mLock(nsnull) { }
+ void* operator new(size_t aSize, PLArenaPool* aArena);
+
+ nsTHashtable<CategoryLeaf> mTable;
+ PRLock* mLock;
+};
+
+
+/**
+ * The main implementation of nsICategoryManager.
+ *
+ * This implementation is thread-safe.
+ */
+class nsCategoryManager
+ : public nsICategoryManager
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSICATEGORYMANAGER
+
+ /**
+ * Write the categories to the XPCOM persistent registry.
+ * This is to be used by nsComponentManagerImpl (and NO ONE ELSE).
+ */
+ NS_METHOD WriteCategoryManagerToRegistry(PRFileDesc* fd);
+
+ nsCategoryManager() : mLock(nsnull) { }
+private:
+ friend class nsCategoryManagerFactory;
+ static nsCategoryManager* Create();
+
+ ~nsCategoryManager();
+
+ CategoryNode* get_category(const char* aName);
+
+ PLArenaPool mArena;
+ nsClassHashtable<nsDepCharHashKey, CategoryNode> mTable;
+ PRLock* mLock;
+};
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/components/nsCategoryManagerUtils.h b/src/libs/xpcom18a4/xpcom/components/nsCategoryManagerUtils.h
new file mode 100644
index 00000000..54a9fcec
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsCategoryManagerUtils.h
@@ -0,0 +1,88 @@
+/* -*- 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 ***** */
+
+#ifndef nsCategoryManagerUtils_h__
+#define nsCategoryManagerUtils_h__
+
+#include "nsICategoryManager.h"
+#include "nsCOMPtr.h"
+
+NS_COM nsresult
+NS_CreateServicesFromCategory(const char *category,
+ nsISupports *origin,
+ const char *observerTopic);
+
+class NS_COM nsCreateInstanceFromCategory : public nsCOMPtr_helper
+{
+public:
+ nsCreateInstanceFromCategory(const char *aCategory, const char *aEntry,
+ nsISupports *aOuter, nsresult *aErrorPtr)
+ : mCategory(aCategory),
+ mEntry(aEntry),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do;
+ }
+ virtual nsresult NS_FASTCALL operator()( const nsIID& aIID, void** aInstancePtr) const;
+
+private:
+ const char *mCategory; // Do not free. This char * is not owned.
+ const char *mEntry; // Do not free. This char * is not owned.
+
+ nsISupports *mOuter;
+ nsresult *mErrorPtr;
+
+};
+
+inline
+const nsCreateInstanceFromCategory
+do_CreateInstanceFromCategory( const char *aCategory, const char *aEntry,
+ nsresult *aErrorPtr = 0)
+{
+ return nsCreateInstanceFromCategory(aCategory, aEntry, 0, aErrorPtr);
+}
+
+inline
+const nsCreateInstanceFromCategory
+do_CreateInstanceFromCategory( const char *aCategory, const char *aEntry,
+ nsISupports *aOuter, nsresult *aErrorPtr = 0)
+{
+ return nsCreateInstanceFromCategory(aCategory, aEntry, aOuter, aErrorPtr);
+}
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/components/nsComponentManager.cpp b/src/libs/xpcom18a4/xpcom/components/nsComponentManager.cpp
new file mode 100644
index 00000000..980b0565
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsComponentManager.cpp
@@ -0,0 +1,3794 @@
+/* -*- 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 <stdlib.h>
+#include "nscore.h"
+#include "nsISupports.h"
+#include "nspr.h"
+#include "nsCRT.h" // for atoll
+// Arena used by component manager for storing contractid string, dll
+// location strings and small objects
+// CAUTION: Arena align mask needs to be defined before including plarena.h
+// currently from nsComponentManager.h
+#define PL_ARENA_CONST_ALIGN_MASK 7
+#define NS_CM_BLOCK_SIZE (1024 * 8)
+
+#include "nsAutoLock.h"
+#include "nsCOMPtr.h"
+#include "nsComponentManager.h"
+#include "nsComponentManagerObsolete.h"
+#include "nsDirectoryService.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsCategoryManager.h"
+#include "nsCategoryManagerUtils.h"
+#include "nsIComponentLoader.h"
+#include "nsIEnumerator.h"
+#include "nsIInterfaceInfoManager.h"
+#include "nsIModule.h"
+#include "nsIObserverService.h"
+#include "nsISimpleEnumerator.h"
+#include "nsXPCOM.h"
+#include "nsISupportsPrimitives.h"
+#include "nsLocalFile.h"
+#include "nsNativeComponentLoader.h"
+#include "nsReadableUtils.h"
+#include "nsString.h"
+#include "nsXPIDLString.h"
+#include "prcmon.h"
+#include "xptinfo.h" // this after nsISupports, to pick up IID so that xpt stuff doesn't try to define it itself...
+
+#include "nsInt64.h"
+#include "nsManifestLineReader.h"
+
+#include NEW_H // for placement new
+
+
+#ifdef XP_BEOS
+#include <FindDirectory.h>
+#include <Path.h>
+#endif
+
+#include "prlog.h"
+
+PRLogModuleInfo* nsComponentManagerLog = nsnull;
+
+#if 0 || defined (DEBUG_timeless)
+ #define SHOW_DENIED_ON_SHUTDOWN
+ #define SHOW_CI_ON_EXISTING_SERVICE
+ #define XPCOM_CHECK_PENDING_CIDS
+#endif
+
+// Loader Types
+#define NS_LOADER_DATA_ALLOC_STEP 6
+
+// Bloated registry buffer size to improve startup performance -- needs to
+// be big enough to fit the entire file into memory or it'll thrash.
+// 512K is big enough to allow for some future growth in the registry.
+#define BIG_REGISTRY_BUFLEN (512*1024)
+
+// Common Key Names
+const char classIDKeyName[]="classID";
+const char classesKeyName[]="contractID";
+const char componentLoadersKeyName[]="componentLoaders";
+const char componentsKeyName[]="components";
+const char xpcomComponentsKeyName[]="software/mozilla/XPCOM/components";
+const char xpcomKeyName[]="software/mozilla/XPCOM";
+
+// Common Value Names
+const char classIDValueName[]="ClassID";
+const char classNameValueName[]="ClassName";
+const char componentCountValueName[]="ComponentsCount";
+const char componentTypeValueName[]="ComponentType";
+const char contractIDValueName[]="ContractID";
+const char fileSizeValueName[]="FileSize";
+const char inprocServerValueName[]="InprocServer";
+const char lastModValueName[]="LastModTimeStamp";
+const char nativeComponentType[]="application/x-mozilla-native";
+const char staticComponentType[]="application/x-mozilla-static";
+const char versionValueName[]="VersionString";
+
+const static char XPCOM_ABSCOMPONENT_PREFIX[] = "abs:";
+const static char XPCOM_RELCOMPONENT_PREFIX[] = "rel:";
+const static char XPCOM_GRECOMPONENT_PREFIX[] = "gre:";
+
+static const char gIDFormat[] =
+ "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}";
+
+
+#define NS_EMPTY_IID \
+{ \
+ 0x00000000, \
+ 0x0000, \
+ 0x0000, \
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} \
+}
+
+NS_DEFINE_CID(kEmptyCID, NS_EMPTY_IID);
+NS_DEFINE_CID(kCategoryManagerCID, NS_CATEGORYMANAGER_CID);
+
+#define UID_STRING_LENGTH 39
+
+// Set to true from NS_ShutdownXPCOM.
+extern PRBool gXPCOMShuttingDown;
+
+static void GetIDString(const nsID& aCID, char buf[UID_STRING_LENGTH])
+{
+ PR_snprintf(buf, UID_STRING_LENGTH, gIDFormat,
+ aCID.m0, (PRUint32) aCID.m1, (PRUint32) aCID.m2,
+ (PRUint32) aCID.m3[0], (PRUint32) aCID.m3[1],
+ (PRUint32) aCID.m3[2], (PRUint32) aCID.m3[3],
+ (PRUint32) aCID.m3[4], (PRUint32) aCID.m3[5],
+ (PRUint32) aCID.m3[6], (PRUint32) aCID.m3[7]);
+}
+
+nsresult
+nsCreateInstanceFromCategory::operator()(const nsIID& aIID, void** aInstancePtr) const
+{
+ /*
+ * If I were a real man, I would consolidate this with
+ * nsGetServiceFromContractID::operator().
+ */
+ nsresult rv;
+ nsXPIDLCString value;
+ nsCOMPtr<nsIComponentManager> compMgr;
+ nsCOMPtr<nsICategoryManager> catman =
+ do_GetService(kCategoryManagerCID, &rv);
+
+ if (NS_FAILED(rv)) goto error;
+
+ if (!mCategory || !mEntry) {
+ // when categories have defaults, use that for null mEntry
+ rv = NS_ERROR_NULL_POINTER;
+ goto error;
+ }
+
+ /* find the contractID for category.entry */
+ rv = catman->GetCategoryEntry(mCategory, mEntry,
+ getter_Copies(value));
+ if (NS_FAILED(rv)) goto error;
+ if (!value) {
+ rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
+ goto error;
+ }
+ NS_GetComponentManager(getter_AddRefs(compMgr));
+ if (!compMgr)
+ return NS_ERROR_FAILURE;
+ compMgr->CreateInstanceByContractID(value,
+ mOuter,
+ aIID,
+ aInstancePtr);
+ if (NS_FAILED(rv)) {
+ error:
+ *aInstancePtr = 0;
+ }
+
+ *mErrorPtr = rv;
+ return rv;
+}
+
+
+nsresult
+nsGetServiceFromCategory::operator()(const nsIID& aIID, void** aInstancePtr) const
+{
+ nsresult rv;
+ nsXPIDLCString value;
+ nsCOMPtr<nsICategoryManager> catman =
+ do_GetService(kCategoryManagerCID, &rv);
+ if (NS_FAILED(rv)) goto error;
+ if (!mCategory || !mEntry) {
+ // when categories have defaults, use that for null mEntry
+ rv = NS_ERROR_NULL_POINTER;
+ goto error;
+ }
+ /* find the contractID for category.entry */
+ rv = catman->GetCategoryEntry(mCategory, mEntry,
+ getter_Copies(value));
+ if (NS_FAILED(rv)) goto error;
+ if (!value) {
+ rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
+ goto error;
+ }
+ if (mServiceManager) {
+ rv = mServiceManager->GetServiceByContractID(value, aIID, (void**)aInstancePtr);
+ } else {
+ nsCOMPtr<nsIServiceManager> mgr;
+ NS_GetServiceManager(getter_AddRefs(mgr));
+ if (mgr)
+ rv = mgr->GetServiceByContractID(value, aIID, (void**)aInstancePtr);
+ }
+ if (NS_FAILED(rv)) {
+ error:
+ *aInstancePtr = 0;
+ }
+ *mErrorPtr = rv;
+ return rv;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Arena helper functions
+////////////////////////////////////////////////////////////////////////////////
+char *
+ArenaStrndup(const char *s, PRUint32 len, PLArenaPool *arena)
+{
+ void *mem;
+ // Include trailing null in the len
+ PL_ARENA_ALLOCATE(mem, arena, len+1);
+ if (mem)
+ memcpy(mem, s, len+1);
+ return NS_STATIC_CAST(char *, mem);
+}
+
+char*
+ArenaStrdup(const char *s, PLArenaPool *arena)
+{
+ return ArenaStrndup(s, strlen(s), arena);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Hashtable Callbacks
+////////////////////////////////////////////////////////////////////////////////
+
+PRBool PR_CALLBACK
+nsFactoryEntry_Destroy(nsHashKey *aKey, void *aData, void* closure);
+
+PR_STATIC_CALLBACK(const void *)
+factory_GetKey(PLDHashTable *aTable, PLDHashEntryHdr *aHdr)
+{
+ nsFactoryTableEntry* entry = NS_STATIC_CAST(nsFactoryTableEntry*, aHdr);
+
+ return &entry->mFactoryEntry->mCid;
+}
+
+PR_STATIC_CALLBACK(PLDHashNumber)
+factory_HashKey(PLDHashTable *aTable, const void *aKey)
+{
+ const nsCID *cidp = NS_REINTERPRET_CAST(const nsCID*, aKey);
+
+ return cidp->m0;
+}
+
+PR_STATIC_CALLBACK(PRBool)
+factory_MatchEntry(PLDHashTable *aTable, const PLDHashEntryHdr *aHdr,
+ const void *aKey)
+{
+ const nsFactoryTableEntry* entry =
+ NS_STATIC_CAST(const nsFactoryTableEntry*, aHdr);
+ const nsCID *cidp = NS_REINTERPRET_CAST(const nsCID*, aKey);
+
+ return (entry->mFactoryEntry->mCid).Equals(*cidp);
+}
+
+PR_STATIC_CALLBACK(void)
+factory_ClearEntry(PLDHashTable *aTable, PLDHashEntryHdr *aHdr)
+{
+ nsFactoryTableEntry* entry = NS_STATIC_CAST(nsFactoryTableEntry*, aHdr);
+ // nsFactoryEntry is arena allocated. So we dont delete it.
+ // We call the destructor by hand.
+ entry->mFactoryEntry->~nsFactoryEntry();
+ PL_DHashClearEntryStub(aTable, aHdr);
+}
+
+static const PLDHashTableOps factory_DHashTableOps = {
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ factory_GetKey,
+ factory_HashKey,
+ factory_MatchEntry,
+ PL_DHashMoveEntryStub,
+ factory_ClearEntry,
+ PL_DHashFinalizeStub,
+};
+
+PR_STATIC_CALLBACK(void)
+contractID_ClearEntry(PLDHashTable *aTable, PLDHashEntryHdr *aHdr)
+{
+ nsContractIDTableEntry* entry = NS_STATIC_CAST(nsContractIDTableEntry*, aHdr);
+ if (entry->mFactoryEntry->mTypeIndex == NS_COMPONENT_TYPE_SERVICE_ONLY &&
+ entry->mFactoryEntry->mCid.Equals(kEmptyCID)) {
+ // this object is owned by the hash.
+ // nsFactoryEntry is arena allocated. So we dont delete it.
+ // We call the destructor by hand.
+ entry->mFactoryEntry->~nsFactoryEntry();
+ }
+
+ // contractIDs are arena allocated. No need to free them.
+
+ PL_DHashClearEntryStub(aTable, aHdr);
+}
+
+static const PLDHashTableOps contractID_DHashTableOps = {
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ PL_DHashGetKeyStub,
+ PL_DHashStringKey,
+ PL_DHashMatchStringKey,
+ PL_DHashMoveEntryStub,
+ contractID_ClearEntry,
+ PL_DHashFinalizeStub,
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// nsFactoryEntry
+////////////////////////////////////////////////////////////////////////////////
+
+MOZ_DECL_CTOR_COUNTER(nsFactoryEntry)
+nsFactoryEntry::nsFactoryEntry(const nsCID &aClass,
+ const char *aLocation,
+ PRUint32 locationlen,
+ int aType,
+ class nsFactoryEntry* parent)
+: mCid(aClass), mTypeIndex(aType), mParent(parent)
+{
+ // Arena allocate the location string
+ mLocation = ArenaStrndup(aLocation, locationlen, &nsComponentManagerImpl::gComponentManager->mArena);
+}
+
+nsFactoryEntry::nsFactoryEntry(const nsCID &aClass,
+ nsIFactory *aFactory,
+ class nsFactoryEntry* parent)
+: mCid(aClass), mTypeIndex(NS_COMPONENT_TYPE_FACTORY_ONLY), mParent(parent)
+{
+ mFactory = aFactory;
+ mLocation = nsnull;
+}
+
+// nsFactoryEntry is usually arena allocated including the strings it
+// holds. So we call destructor by hand.
+nsFactoryEntry::~nsFactoryEntry(void)
+{
+ // Release the reference to the factory
+ mFactory = nsnull;
+
+ // Release any service reference
+ mServiceObject = nsnull;
+
+ // nsFactoryEntry is arena allocated. So we dont delete it.
+ // We call the destructor by hand.
+ if (mParent)
+ mParent->~nsFactoryEntry();
+}
+
+nsresult
+nsFactoryEntry::ReInit(const nsCID &aClass, const char *aLocation, int aType)
+{
+ NS_ENSURE_TRUE(mTypeIndex != NS_COMPONENT_TYPE_FACTORY_ONLY, NS_ERROR_INVALID_ARG);
+ // cid has to match
+ // SERVICE_ONLY entries can be promoted to an entry of another type
+ NS_ENSURE_TRUE((mTypeIndex == NS_COMPONENT_TYPE_SERVICE_ONLY || mCid.Equals(aClass)),
+ NS_ERROR_INVALID_ARG);
+
+ // Arena allocate the location string
+ mLocation = ArenaStrdup(aLocation, &nsComponentManagerImpl::gComponentManager->mArena);
+
+ mTypeIndex = aType;
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Hashtable Enumeration
+////////////////////////////////////////////////////////////////////////////////
+typedef NS_CALLBACK(EnumeratorConverter)(PLDHashTable *table,
+ const PLDHashEntryHdr *hdr,
+ void *data,
+ nsISupports **retval);
+
+class PLDHashTableEnumeratorImpl : public nsIBidirectionalEnumerator,
+ public nsISimpleEnumerator
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIENUMERATOR
+ NS_DECL_NSIBIDIRECTIONALENUMERATOR
+ NS_DECL_NSISIMPLEENUMERATOR
+
+ PLDHashTableEnumeratorImpl(PLDHashTable *table,
+ EnumeratorConverter converter,
+ void *converterData);
+ PRInt32 Count() { return mCount; }
+private:
+ PLDHashTableEnumeratorImpl(); /* no implementation */
+
+ ~PLDHashTableEnumeratorImpl();
+ NS_IMETHODIMP ReleaseElements();
+
+ nsVoidArray mElements;
+ PRInt32 mCount, mCurrent;
+ PRMonitor* mMonitor;
+
+ struct Closure {
+ PRBool succeeded;
+ EnumeratorConverter converter;
+ void *data;
+ PLDHashTableEnumeratorImpl *impl;
+ };
+
+ static PLDHashOperator PR_CALLBACK Enumerator(PLDHashTable *table,
+ PLDHashEntryHdr *hdr,
+ PRUint32 number,
+ void *data);
+};
+
+// static
+PLDHashOperator PR_CALLBACK
+PLDHashTableEnumeratorImpl::Enumerator(PLDHashTable *table,
+ PLDHashEntryHdr *hdr,
+ PRUint32 number,
+ void *data)
+{
+ Closure *c = NS_REINTERPRET_CAST(Closure *, data);
+ nsISupports *converted;
+ if (NS_FAILED(c->converter(table, hdr, c->data, &converted)) ||
+ !c->impl->mElements.AppendElement(converted)) {
+ c->succeeded = PR_FALSE;
+ return PL_DHASH_STOP;
+ }
+
+ c->succeeded = PR_TRUE;
+ return PL_DHASH_NEXT;
+}
+
+PLDHashTableEnumeratorImpl::PLDHashTableEnumeratorImpl(PLDHashTable *table,
+ EnumeratorConverter converter,
+ void *converterData)
+: mCurrent(0)
+{
+ mMonitor = nsAutoMonitor::NewMonitor("PLDHashTableEnumeratorImpl");
+ NS_ASSERTION(mMonitor, "NULL Monitor");
+
+ nsAutoMonitor mon(mMonitor);
+
+ Closure c = { PR_FALSE, converter, converterData, this };
+ mCount = PL_DHashTableEnumerate(table, Enumerator, &c);
+ if (!c.succeeded) {
+ ReleaseElements();
+ mCount = 0;
+ }
+}
+
+NS_IMPL_ISUPPORTS3(PLDHashTableEnumeratorImpl,
+ nsIBidirectionalEnumerator,
+ nsIEnumerator,
+ nsISimpleEnumerator)
+
+PLDHashTableEnumeratorImpl::~PLDHashTableEnumeratorImpl()
+{
+ (void) ReleaseElements();
+
+ // Destroy the Lock
+ if (mMonitor)
+ nsAutoMonitor::DestroyMonitor(mMonitor);
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::ReleaseElements()
+{
+ for (PRInt32 i = 0; i < mCount; i++) {
+ nsISupports *supports = NS_REINTERPRET_CAST(nsISupports *,
+ mElements[i]);
+ NS_IF_RELEASE(supports);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PL_NewDHashTableEnumerator(PLDHashTable *table,
+ EnumeratorConverter converter,
+ void *converterData,
+ PLDHashTableEnumeratorImpl **retval)
+{
+ PLDHashTableEnumeratorImpl *impl =
+ new PLDHashTableEnumeratorImpl(table, converter, converterData);
+
+ if (!impl)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(impl);
+
+ if (impl->Count() == -1) {
+ // conversion failed
+ NS_RELEASE(impl);
+ return NS_ERROR_FAILURE;
+ }
+
+ *retval = impl;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::First()
+{
+ if (!mCount)
+ return NS_ERROR_FAILURE;
+
+ mCurrent = 0;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::Last()
+{
+ if (!mCount)
+ return NS_ERROR_FAILURE;
+ mCurrent = mCount - 1;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::Prev()
+{
+ if (!mCurrent)
+ return NS_ERROR_FAILURE;
+
+ mCurrent--;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::Next()
+{
+ // If empty or we're past the end, or we are at the end return error
+ if (!mCount || (mCurrent == mCount) || (++mCurrent == mCount))
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::CurrentItem(nsISupports **retval)
+{
+ if (!mCount || mCurrent == mCount)
+ return NS_ERROR_FAILURE;
+
+ *retval = NS_REINTERPRET_CAST(nsISupports *, mElements[mCurrent]);
+ if (*retval)
+ NS_ADDREF(*retval);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::IsDone()
+{
+ if (!mCount || (mCurrent == mCount))
+ return NS_OK;
+
+ return NS_ENUMERATOR_FALSE;
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::HasMoreElements(PRBool *_retval)
+{
+ if (!mCount || (mCurrent == mCount))
+ *_retval = PR_FALSE;
+ else
+ *_retval = PR_TRUE;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PLDHashTableEnumeratorImpl::GetNext(nsISupports **_retval)
+{
+ nsresult rv = Next();
+ if (NS_FAILED(rv)) return rv;
+
+ return CurrentItem(_retval);
+}
+
+static NS_IMETHODIMP
+ConvertFactoryEntryToCID(PLDHashTable *table,
+ const PLDHashEntryHdr *hdr,
+ void *data, nsISupports **retval)
+{
+ nsresult rv;
+ nsCOMPtr<nsISupportsID> wrapper;
+
+ nsComponentManagerImpl *cm = NS_STATIC_CAST(nsComponentManagerImpl *, data);
+
+ rv = cm->CreateInstanceByContractID(NS_SUPPORTS_ID_CONTRACTID, nsnull,
+ NS_GET_IID(nsISupportsID), getter_AddRefs(wrapper));
+
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ const nsFactoryTableEntry *entry =
+ NS_REINTERPRET_CAST(const nsFactoryTableEntry *, hdr);
+ if (entry) {
+ nsFactoryEntry *fe = entry->mFactoryEntry;
+
+ wrapper->SetData(&fe->mCid);
+ *retval = wrapper;
+ NS_ADDREF(*retval);
+ return NS_OK;
+ }
+ *retval = nsnull;
+
+ return rv;
+}
+
+static NS_IMETHODIMP
+ConvertContractIDKeyToString(PLDHashTable *table,
+ const PLDHashEntryHdr *hdr,
+ void *data, nsISupports **retval)
+{
+ nsresult rv;
+ nsCOMPtr<nsISupportsCString> wrapper;
+
+ nsComponentManagerImpl *cm = NS_STATIC_CAST(nsComponentManagerImpl *, data);
+
+ rv = cm->CreateInstanceByContractID(NS_SUPPORTS_CSTRING_CONTRACTID, nsnull,
+ NS_GET_IID(nsISupportsCString), getter_AddRefs(wrapper));
+
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ const nsContractIDTableEntry *entry =
+ NS_REINTERPRET_CAST(const nsContractIDTableEntry *, hdr);
+
+ wrapper->SetData(nsDependentCString(entry->mContractID,
+ entry->mContractIDLen));
+ *retval = wrapper;
+ NS_ADDREF(*retval);
+ return NS_OK;
+}
+
+// this is safe to call during InitXPCOM
+static nsresult GetLocationFromDirectoryService(const char* prop,
+ nsIFile** aDirectory)
+{
+ nsCOMPtr<nsIProperties> directoryService;
+ nsDirectoryService::Create(nsnull,
+ NS_GET_IID(nsIProperties),
+ getter_AddRefs(directoryService));
+
+ if (!directoryService)
+ return NS_ERROR_FAILURE;
+
+ return directoryService->Get(prop,
+ NS_GET_IID(nsIFile),
+ (void**)aDirectory);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// nsComponentManagerImpl
+////////////////////////////////////////////////////////////////////////////////
+
+
+nsComponentManagerImpl::nsComponentManagerImpl()
+ :
+ mMon(NULL),
+ mNativeComponentLoader(0),
+#ifdef ENABLE_STATIC_COMPONENT_LOADER
+ mStaticComponentLoader(0),
+#endif
+ mShuttingDown(NS_SHUTDOWN_NEVERHAPPENED),
+ mLoaderData(nsnull),
+ mRegistryDirty(PR_FALSE)
+{
+ mFactories.ops = nsnull;
+ mContractIDs.ops = nsnull;
+}
+
+nsresult nsComponentManagerImpl::Init(void)
+{
+ PR_ASSERT(mShuttingDown != NS_SHUTDOWN_INPROGRESS);
+ if (mShuttingDown == NS_SHUTDOWN_INPROGRESS)
+ return NS_ERROR_FAILURE;
+
+ mShuttingDown = NS_SHUTDOWN_NEVERHAPPENED;
+
+ if (nsComponentManagerLog == nsnull)
+ {
+ nsComponentManagerLog = PR_NewLogModule("nsComponentManager");
+ }
+
+ // Initialize our arena
+ PL_INIT_ARENA_POOL(&mArena, "ComponentManagerArena", NS_CM_BLOCK_SIZE);
+
+ if (!mFactories.ops) {
+ if (!PL_DHashTableInit(&mFactories, &factory_DHashTableOps,
+ 0, sizeof(nsFactoryTableEntry),
+ 1024)) {
+ mFactories.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ // Minimum alpha uses k=2 because nsFactoryTableEntry saves two
+ // words compared to what a chained hash table requires.
+ PL_DHashTableSetAlphaBounds(&mFactories,
+ 0.875,
+ PL_DHASH_MIN_ALPHA(&mFactories, 2));
+ }
+
+ if (!mContractIDs.ops) {
+ if (!PL_DHashTableInit(&mContractIDs, &contractID_DHashTableOps,
+ 0, sizeof(nsContractIDTableEntry),
+ 1024)) {
+ mContractIDs.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ // Minimum alpha uses k=1 because nsContractIDTableEntry saves one
+ // word compared to what a chained hash table requires.
+#if 0
+ PL_DHashTableSetAlphaBounds(&mContractIDs,
+ 0.875,
+ PL_DHASH_MIN_ALPHA(&mContractIDs, 1));
+#endif
+ }
+ if (mMon == nsnull) {
+ mMon = nsAutoMonitor::NewMonitor("nsComponentManagerImpl");
+ if (mMon == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (mNativeComponentLoader == nsnull) {
+ /* Create the NativeComponentLoader */
+ mNativeComponentLoader = new nsNativeComponentLoader();
+ if (!mNativeComponentLoader)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(mNativeComponentLoader);
+
+ nsresult rv = mNativeComponentLoader->Init(this, nsnull);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ // Add predefined loaders
+ mLoaderData = (nsLoaderdata *) PR_Malloc(sizeof(nsLoaderdata) * NS_LOADER_DATA_ALLOC_STEP);
+ if (!mLoaderData)
+ return NS_ERROR_OUT_OF_MEMORY;
+ mMaxNLoaderData = NS_LOADER_DATA_ALLOC_STEP;
+
+ mNLoaderData = NS_COMPONENT_TYPE_NATIVE;
+ mLoaderData[mNLoaderData].type = PL_strdup(nativeComponentType);
+ mLoaderData[mNLoaderData].loader = mNativeComponentLoader;
+ NS_ADDREF(mLoaderData[mNLoaderData].loader);
+ mNLoaderData++;
+
+#ifdef ENABLE_STATIC_COMPONENT_LOADER
+ if (mStaticComponentLoader == nsnull) {
+ extern nsresult NS_NewStaticComponentLoader(nsIComponentLoader **);
+ NS_NewStaticComponentLoader(&mStaticComponentLoader);
+ if (!mStaticComponentLoader)
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ mLoaderData[mNLoaderData].type = PL_strdup(staticComponentType);
+ mLoaderData[mNLoaderData].loader = mStaticComponentLoader;
+ NS_ADDREF(mLoaderData[mNLoaderData].loader);
+ mNLoaderData++;
+
+ if (mStaticComponentLoader) {
+ /* Init the static loader */
+ mStaticComponentLoader->Init(this, nsnull);
+ }
+#endif
+ GetLocationFromDirectoryService(NS_XPCOM_COMPONENT_DIR, getter_AddRefs(mComponentsDir));
+ if (!mComponentsDir)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsCAutoString componentDescriptor;
+ nsresult rv = mComponentsDir->GetNativePath(componentDescriptor);
+ if (NS_FAILED(rv))
+ return rv;
+
+ mComponentsOffset = componentDescriptor.Length();
+
+ GetLocationFromDirectoryService(NS_GRE_COMPONENT_DIR, getter_AddRefs(mGREComponentsDir));
+ if (mGREComponentsDir) {
+ nsresult rv = mGREComponentsDir->GetNativePath(componentDescriptor);
+ if (NS_FAILED(rv)) {
+ NS_WARNING("No GRE component manager");
+ return rv;
+ }
+ mGREComponentsOffset = componentDescriptor.Length();
+ }
+
+ GetLocationFromDirectoryService(NS_XPCOM_COMPONENT_REGISTRY_FILE,
+ getter_AddRefs(mRegistryFile));
+
+ if(!mRegistryFile) {
+ NS_WARNING("No Component Registry file was found in the directory service");
+ return NS_ERROR_FAILURE;
+ }
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
+ ("nsComponentManager: Initialized."));
+
+ return NS_OK;
+}
+
+PRIntn PR_CALLBACK AutoRegEntryDestroy(nsHashKey *aKey, void *aData, void* aClosure)
+{
+ delete (AutoRegEntry*)aData;
+ return kHashEnumerateNext;
+}
+
+nsresult nsComponentManagerImpl::Shutdown(void)
+{
+ PR_ASSERT(mShuttingDown == NS_SHUTDOWN_NEVERHAPPENED);
+ if (mShuttingDown != NS_SHUTDOWN_NEVERHAPPENED)
+ return NS_ERROR_FAILURE;
+
+ mShuttingDown = NS_SHUTDOWN_INPROGRESS;
+
+ // Shutdown the component manager
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Beginning Shutdown."));
+
+ PRInt32 i;
+
+ // Write out our component data file.
+ if (mRegistryDirty) {
+ nsresult rv = WritePersistentRegistry();
+ if (NS_FAILED(rv)) {
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR, ("nsComponentManager: Could not write out perisistant registry."));
+#ifdef DEBUG
+ printf("Could not write out perisistant registry!\n");
+#endif
+ }
+ }
+
+ mAutoRegEntries.Reset(AutoRegEntryDestroy);
+
+ // Release all cached factories
+ if (mContractIDs.ops) {
+ PL_DHashTableFinish(&mContractIDs);
+ mContractIDs.ops = nsnull;
+ }
+ if (mFactories.ops) {
+ PL_DHashTableFinish(&mFactories);
+ mFactories.ops = nsnull;
+ }
+ // Unload libraries
+ UnloadLibraries(nsnull, NS_Shutdown);
+
+ // delete arena for strings and small objects
+ PL_FinishArenaPool(&mArena);
+
+ mComponentsDir = 0;
+
+ mCategoryManager = 0;
+
+ // Release all the component data - loaders and type strings
+ for (i=0; i < mNLoaderData; i++) {
+ NS_IF_RELEASE(mLoaderData[i].loader);
+ PL_strfree((char *)mLoaderData[i].type);
+ }
+ PR_Free(mLoaderData);
+ mLoaderData = nsnull;
+
+ // we have an extra reference on this one, which is probably a good thing
+ NS_IF_RELEASE(mNativeComponentLoader);
+#ifdef ENABLE_STATIC_COMPONENT_LOADER
+ NS_IF_RELEASE(mStaticComponentLoader);
+#endif
+
+ mShuttingDown = NS_SHUTDOWN_COMPLETE;
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Shutdown complete."));
+
+ return NS_OK;
+}
+
+nsComponentManagerImpl::~nsComponentManagerImpl()
+{
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Beginning destruction."));
+
+ if (mShuttingDown != NS_SHUTDOWN_COMPLETE)
+ Shutdown();
+
+ if (mMon) {
+ nsAutoMonitor::DestroyMonitor(mMon);
+ }
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Destroyed."));
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS8(nsComponentManagerImpl,
+ nsIComponentManager,
+ nsIServiceManager,
+ nsISupportsWeakReference,
+ nsIInterfaceRequestor,
+ nsIComponentRegistrar,
+ nsIServiceManagerObsolete,
+ nsIComponentManagerObsolete,
+ nsIComponentLoaderManager)
+
+
+nsresult
+nsComponentManagerImpl::GetInterface(const nsIID & uuid, void **result)
+{
+ if (uuid.Equals(NS_GET_IID(nsINativeComponentLoader)))
+ {
+ if (!mNativeComponentLoader)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ return mNativeComponentLoader->QueryInterface(uuid, result);
+ }
+
+ NS_WARNING("This isn't supported");
+ // fall through to QI as anything QIable is a superset of what can be
+ // got via the GetInterface()
+ return QueryInterface(uuid, result);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsComponentManagerImpl: Platform methods
+////////////////////////////////////////////////////////////////////////////////
+
+#define PERSISTENT_REGISTRY_VERSION_MINOR 5
+#define PERSISTENT_REGISTRY_VERSION_MAJOR 0
+
+
+AutoRegEntry::AutoRegEntry(const nsACString& name, PRInt64* modDate) :
+ mName(ToNewCString(name)),
+ mNameLen(name.Length()),
+ mData(nsnull),
+ mModDate(*modDate)
+{
+}
+
+AutoRegEntry::~AutoRegEntry()
+{
+ if (mName) PL_strfree(mName);
+ if (mData) PL_strfree(mData);
+}
+
+PRBool
+AutoRegEntry::Modified(PRInt64 *date)
+{
+ return !LL_EQ(*date, mModDate);
+}
+
+void
+AutoRegEntry::SetOptionalData(const char* data)
+{
+ if (mData)
+ PL_strfree(mData);
+
+ if (!data) {
+ mData = nsnull;
+ return;
+ }
+
+ mData = PL_strdup(data);
+}
+
+static
+PRBool ReadSectionHeader(nsManifestLineReader& reader, const char *token)
+{
+ while (1)
+ {
+ if (*reader.LinePtr() == '[')
+ {
+ char* p = reader.LinePtr() + (reader.LineLength() - 1);
+ if (*p != ']')
+ break;
+ *p = 0;
+
+ char* values[1];
+ int lengths[1];
+ if (2 != reader.ParseLine(values, lengths, 1))
+ break;
+
+ // ignore the leading '['
+ if (0 != PL_strcmp(values[0]+1, token))
+ break;
+
+ return PR_TRUE;
+ }
+
+ if (!reader.NextLine())
+ break;
+ }
+ return PR_FALSE;
+}
+
+nsresult
+nsComponentManagerImpl::ReadPersistentRegistry()
+{
+
+ // populate Category Manager. need to get this early so that we don't get
+ // skipped by 'goto out'
+ nsresult rv = GetService(kCategoryManagerCID,
+ NS_GET_IID(nsICategoryManager),
+ getter_AddRefs(mCategoryManager));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsAutoMonitor mon(mMon);
+ nsManifestLineReader reader;
+
+ if (!mComponentsDir)
+ return NS_ERROR_NOT_INITIALIZED; // this should have been set by Init().
+
+ PRFileDesc* fd = nsnull;
+
+ // Set From Init
+ if (!mRegistryFile) {
+ return NS_ERROR_FILE_NOT_FOUND;
+ }
+
+ nsCOMPtr<nsIFile> file;
+ mRegistryFile->Clone(getter_AddRefs(file));
+ if (!file)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(file));
+
+ rv = localFile->OpenNSPRFileDesc(PR_RDONLY, 0444, &fd);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRInt64 fileSize;
+ rv = localFile->GetFileSize(&fileSize);
+ if (NS_FAILED(rv))
+ {
+ PR_Close(fd);
+ return rv;
+ }
+
+ PRInt32 flen = nsInt64(fileSize);
+ if (flen == 0)
+ {
+ PR_Close(fd);
+ NS_WARNING("Persistent Registry Empty!");
+ return NS_OK; // ERROR CONDITION
+ }
+
+ char* registry = new char[flen+1];
+ if (!registry)
+ goto out;
+
+ if (flen > PR_Read(fd, registry, flen))
+ {
+ rv = NS_ERROR_FAILURE;
+ goto out;
+ }
+ registry[flen] = '\0';
+
+ reader.Init(registry, flen);
+
+ if (ReadSectionHeader(reader, "HEADER"))
+ goto out;
+
+ if (!reader.NextLine())
+ goto out;
+
+ char* values[6];
+ int lengths[6];
+
+ // VersionLiteral,major,minor
+ if (3 != reader.ParseLine(values, lengths, 3))
+ goto out;
+
+ // VersionLiteral
+ if (!nsDependentCString(values[0], lengths[0]).EqualsLiteral("Version"))
+ goto out;
+
+ // major
+ if (PERSISTENT_REGISTRY_VERSION_MAJOR != atoi(values[1]))
+ goto out;
+
+ // minor
+ if (PERSISTENT_REGISTRY_VERSION_MINOR != atoi(values[2]))
+ goto out;
+
+ if (ReadSectionHeader(reader, "COMPONENTS"))
+ goto out;
+
+ while (1)
+ {
+ if (!reader.NextLine())
+ break;
+
+ //name,last_modification_date[,optionaldata]
+ int parts = reader.ParseLine(values, lengths, 3);
+ if (2 > parts)
+ break;
+
+ PRInt64 a = nsCRT::atoll(values[1]);
+ AutoRegEntry *entry =
+ new AutoRegEntry(nsDependentCString(values[0], lengths[0]), &a);
+
+ if (!entry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (parts == 3)
+ entry->SetOptionalData(values[2]);
+
+ nsCStringKey key((const char*)values[0]);
+ mAutoRegEntries.Put(&key, entry);
+ }
+
+ if (ReadSectionHeader(reader, "CLASSIDS"))
+ goto out;
+
+ while (1)
+ {
+ if (!reader.NextLine())
+ break;
+
+ // cid,contract_id,type,class_name,inproc_server
+ if (5 != reader.ParseLine(values, lengths, 5))
+ break;
+
+ nsCID aClass;
+ if (!aClass.Parse(values[0]))
+ continue;
+
+ int loadertype = GetLoaderType(values[2]);
+ if (loadertype < 0) {
+ rv = AddLoaderType(values[2], &loadertype);
+ if (NS_FAILED(rv))
+ continue;
+ }
+
+ void *mem;
+ PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
+ if (!mem)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsFactoryEntry *entry = new (mem) nsFactoryEntry(aClass, values[4], lengths[4], loadertype);
+
+ nsFactoryTableEntry* factoryTableEntry =
+ NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories,
+ &aClass,
+ PL_DHASH_ADD));
+
+ if (!factoryTableEntry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ factoryTableEntry->mFactoryEntry = entry;
+
+ }
+
+ if (ReadSectionHeader(reader, "CONTRACTIDS"))
+ goto out;
+
+ while (1)
+ {
+ if (!reader.NextLine())
+ break;
+
+ //contractID,cid
+ if (2 != reader.ParseLine(values, lengths, 2))
+ break;
+
+ nsCID aClass;
+ if (!aClass.Parse(values[1]))
+ continue;
+
+
+ //need to find the location for this cid.
+ nsFactoryEntry *cidEntry = GetFactoryEntry(aClass);
+ if (!cidEntry || cidEntry->mTypeIndex < 0)
+ continue; //what should we really do?
+
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs,
+ values[0],
+ PL_DHASH_ADD));
+ if (!contractIDTableEntry) {
+ continue;
+ }
+
+ if (!contractIDTableEntry->mContractID) {
+ contractIDTableEntry->mContractID = ArenaStrndup(values[0], lengths[0], &mArena);
+ contractIDTableEntry->mContractIDLen = lengths[0];
+ }
+
+ contractIDTableEntry->mFactoryEntry = cidEntry;
+ }
+
+#ifdef XPCOM_CHECK_PENDING_CIDS
+ {
+/*
+ * If you get Asserts when you define SHOW_CI_ON_EXISTING_SERVICE and want to
+ * track down their cause, then you should add the contracts listed by the
+ * assertion to abusedContracts. The next time you run your xpcom app, xpcom
+ * will assert the first time the object associated with the contract is
+ * instantiated (which in many cases is the source of the problem).
+ *
+ * If you're doing this then you might want to NOP and soft breakpoint the
+ * lines labeled: NOP_AND_BREAK.
+ *
+ * Otherwise XPCOM will refuse to create the object for the caller, which
+ * while reasonable at some level, will almost certainly cause the app to
+ * stop functioning normally.
+ */
+ static char abusedContracts[][128] = {
+ /*// Example contracts:
+ "@mozilla.org/rdf/container;1",
+ "@mozilla.org/intl/charsetalias;1",
+ "@mozilla.org/locale/win32-locale;1",
+ "@mozilla.org/widget/lookandfeel/win;1",
+ // */
+ { 0 }
+ };
+ for (int i=0; abusedContracts[i] && *abusedContracts[i]; i++) {
+ nsFactoryEntry *entry = nsnull;
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs, abusedContracts[i],
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(contractIDTableEntry)) {
+ entry = contractIDTableEntry->mFactoryEntry;
+ AddPendingCID(entry->mCid);
+ }
+ }
+ }
+#endif
+
+ if (ReadSectionHeader(reader, "CATEGORIES"))
+ goto out;
+
+ while (1)
+ {
+ if (!reader.NextLine())
+ break;
+
+ //type,name,value
+ if (3 != reader.ParseLine(values, lengths, 3))
+ break;
+
+ mCategoryManager->AddCategoryEntry(values[0],
+ values[1],
+ values[2],
+ PR_TRUE,
+ PR_TRUE,
+ 0);
+ }
+
+ mRegistryDirty = PR_FALSE;
+out:
+ if (fd)
+ PR_Close(fd);
+
+ if (registry)
+ delete [] registry;
+
+ return rv;
+}
+
+struct PersistentWriterArgs
+{
+ PRFileDesc *mFD;
+ nsLoaderdata *mLoaderData;
+};
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+ContractIDWriter(PLDHashTable *table,
+ PLDHashEntryHdr *hdr,
+ PRUint32 number,
+ void *arg)
+{
+ char *contractID = ((nsContractIDTableEntry*)hdr)->mContractID;
+ nsFactoryEntry *factoryEntry = ((nsContractIDTableEntry*)hdr)->mFactoryEntry;
+
+ // for now, we only save out the top most parent.
+ while (factoryEntry->mParent)
+ factoryEntry = factoryEntry->mParent;
+
+ if (factoryEntry->mTypeIndex < 0)
+ return PL_DHASH_NEXT;
+
+ PRFileDesc* fd = ((PersistentWriterArgs*)arg)->mFD;
+
+ char cidString[UID_STRING_LENGTH];
+ GetIDString(factoryEntry->mCid, cidString);
+ PR_fprintf(fd, "%s,%s\n", contractID, cidString); // what if this fails?
+ return PL_DHASH_NEXT;
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+ClassIDWriter(PLDHashTable *table,
+ PLDHashEntryHdr *hdr,
+ PRUint32 number,
+ void *arg)
+{
+ nsFactoryEntry *factoryEntry = ((nsFactoryTableEntry*)hdr)->mFactoryEntry;
+ PRFileDesc* fd = ((PersistentWriterArgs*)arg)->mFD;
+ nsLoaderdata *loaderData = ((PersistentWriterArgs*)arg)->mLoaderData;
+
+ // for now, we only save out the top most parent.
+ while (factoryEntry->mParent)
+ factoryEntry = factoryEntry->mParent;
+
+ if (factoryEntry->mTypeIndex < 0) {
+ return PL_DHASH_NEXT;
+ }
+
+ char cidString[UID_STRING_LENGTH];
+ GetIDString(factoryEntry->mCid, cidString);
+
+ char *contractID = nsnull, *className = nsnull;
+
+ nsCOMPtr<nsIClassInfo> classInfo = do_QueryInterface(factoryEntry->mFactory);
+ if (classInfo)
+ {
+ classInfo->GetContractID(&contractID);
+ classInfo->GetClassDescription(&className);
+ }
+
+ const char * loaderName = nsnull;
+ if (factoryEntry->mTypeIndex)
+ loaderName = loaderData[factoryEntry->mTypeIndex].type;
+
+ char* location = factoryEntry->mLocation;
+
+ // cid,contract_id,type,class_name,inproc_server
+ PR_fprintf(fd,
+ "%s,%s,%s,%s,%s\n",
+ cidString,
+ (contractID ? contractID : ""),
+ (loaderName ? loaderName : ""),
+ (className ? className : ""),
+ (location ? location : ""));
+
+ if (contractID)
+ PR_Free(contractID);
+ if (className)
+ PR_Free(className);
+
+ return PL_DHASH_NEXT;
+}
+
+PRIntn PR_CALLBACK
+AutoRegEntryWriter(nsHashKey *aKey, void *aData, void* aClosure)
+{
+ PRFileDesc* fd = (PRFileDesc*) aClosure;
+ AutoRegEntry* entry = (AutoRegEntry*) aData;
+
+ const char* extraData = entry->GetOptionalData();
+ const char *fmt;
+ if (extraData)
+ fmt = "%s,%lld,%s\n";
+ else
+ fmt = "%s,%lld\n";
+ PR_fprintf(fd, fmt, entry->GetName().get(), entry->GetDate(), extraData);
+
+ return PR_TRUE;
+}
+
+nsresult
+nsComponentManagerImpl::WritePersistentRegistry()
+{
+ if (!mRegistryFile)
+ return NS_ERROR_FAILURE; // this should have been set by Init().
+
+ nsCOMPtr<nsIFile> file;
+ mRegistryFile->Clone(getter_AddRefs(file));
+ if (!file)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(file));
+
+ nsCAutoString originalLeafName;
+ localFile->GetNativeLeafName(originalLeafName);
+
+ nsCAutoString leafName;
+ leafName.Assign(originalLeafName + NS_LITERAL_CSTRING(".tmp"));
+
+ localFile->SetNativeLeafName(leafName);
+
+ PRFileDesc* fd = nsnull;
+ nsresult rv = localFile->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0600, &fd);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (PR_fprintf(fd, "Generated File. Do not edit.\n") == (PRUint32) -1) {
+ rv = NS_ERROR_UNEXPECTED;
+ goto out;
+ }
+
+ if (PR_fprintf(fd, "\n[HEADER]\nVersion,%d,%d\n",
+ PERSISTENT_REGISTRY_VERSION_MAJOR,
+ PERSISTENT_REGISTRY_VERSION_MINOR) == (PRUint32) -1) {
+ rv = NS_ERROR_UNEXPECTED;
+ goto out;
+ }
+
+ if (PR_fprintf(fd, "\n[COMPONENTS]\n") == (PRUint32) -1) {
+ rv = NS_ERROR_UNEXPECTED;
+ goto out;
+ }
+
+ mAutoRegEntries.Enumerate(AutoRegEntryWriter, (void*)fd);
+
+ PersistentWriterArgs args;
+ args.mFD = fd;
+ args.mLoaderData = mLoaderData;
+
+ if (PR_fprintf(fd, "\n[CLASSIDS]\n") == (PRUint32) -1) {
+ rv = NS_ERROR_UNEXPECTED;
+ goto out;
+ }
+
+
+ PL_DHashTableEnumerate(&mFactories, ClassIDWriter, (void*)&args);
+
+ if (PR_fprintf(fd, "\n[CONTRACTIDS]\n") == (PRUint32) -1) {
+ rv = NS_ERROR_UNEXPECTED;
+ goto out;
+ }
+
+
+ PL_DHashTableEnumerate(&mContractIDs, ContractIDWriter, (void*)&args);
+
+ if (PR_fprintf(fd, "\n[CATEGORIES]\n") == (PRUint32) -1) {
+ rv = NS_ERROR_UNEXPECTED;
+ goto out;
+ }
+
+
+ if (!mCategoryManager) {
+ NS_WARNING("Could not access category manager. Will not be able to save categories!");
+ rv = NS_ERROR_UNEXPECTED;
+ } else {
+ rv = mCategoryManager->WriteCategoryManagerToRegistry(fd);
+ }
+
+out:
+ if (fd)
+ PR_Close(fd);
+
+ // don't create the file is there was a problem????
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!mRegistryFile)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ PRBool exists;
+ if(NS_FAILED(mRegistryFile->Exists(&exists)))
+ return PR_FALSE;
+
+ if(exists && NS_FAILED(mRegistryFile->Remove(PR_FALSE)))
+ return PR_FALSE;
+
+ nsCOMPtr<nsIFile> parent;
+ mRegistryFile->GetParent(getter_AddRefs(parent));
+
+ rv = localFile->MoveToNative(parent, originalLeafName);
+ mRegistryDirty = PR_FALSE;
+
+ return rv;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Hash Functions
+////////////////////////////////////////////////////////////////////////////////
+nsresult
+nsComponentManagerImpl::HashContractID(const char *aContractID,
+ PRUint32 aContractIDLen,
+ nsFactoryEntry *fe)
+{
+ if(!aContractID || !aContractIDLen)
+ return NS_ERROR_NULL_POINTER;
+
+ nsAutoMonitor mon(mMon);
+
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs, aContractID,
+ PL_DHASH_ADD));
+ if (!contractIDTableEntry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ASSERTION(!contractIDTableEntry->mContractID || !strcmp(contractIDTableEntry->mContractID, aContractID), "contractid conflict");
+
+ if (!contractIDTableEntry->mContractID) {
+ contractIDTableEntry->mContractID = ArenaStrndup(aContractID, aContractIDLen, &mArena);
+ contractIDTableEntry->mContractIDLen = aContractIDLen;
+ }
+
+ contractIDTableEntry->mFactoryEntry = fe;
+
+ return NS_OK;
+}
+
+/**
+ * LoadFactory()
+ *
+ * Given a FactoryEntry, this loads the dll if it has to, find the NSGetFactory
+ * symbol, calls the routine to create a new factory and returns it to the
+ * caller.
+ *
+ * No attempt is made to store the factory in any form anywhere.
+ */
+nsresult
+nsComponentManagerImpl::LoadFactory(nsFactoryEntry *aEntry,
+ nsIFactory **aFactory)
+{
+
+ if (!aFactory)
+ return NS_ERROR_NULL_POINTER;
+ *aFactory = nsnull;
+
+ nsresult rv;
+ rv = aEntry->GetFactory(aFactory, this);
+ if (NS_FAILED(rv)) {
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("nsComponentManager: FAILED to load factory from %s (%s)\n",
+ (const char *)aEntry->mLocation, mLoaderData[aEntry->mTypeIndex].type));
+ return rv;
+ }
+
+ return NS_OK;
+}
+
+nsFactoryEntry *
+nsComponentManagerImpl::GetFactoryEntry(const char *aContractID,
+ PRUint32 aContractIDLen)
+{
+ nsFactoryEntry *fe = nsnull;
+ {
+ nsAutoMonitor mon(mMon);
+
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs, aContractID,
+ PL_DHASH_LOOKUP));
+
+
+ if (PL_DHASH_ENTRY_IS_BUSY(contractIDTableEntry)) {
+ fe = contractIDTableEntry->mFactoryEntry;
+ }
+ } //exit monitor
+
+ return fe;
+}
+
+
+nsFactoryEntry *
+nsComponentManagerImpl::GetFactoryEntry(const nsCID &aClass)
+{
+ nsFactoryEntry *entry = nsnull;
+ {
+ nsAutoMonitor mon(mMon);
+
+ nsFactoryTableEntry* factoryTableEntry =
+ NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories, &aClass,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(factoryTableEntry)) {
+ entry = factoryTableEntry->mFactoryEntry;
+ }
+ } // exit monitor
+
+ return entry;
+}
+
+
+/**
+ * FindFactory()
+ *
+ * Given a classID, this finds the factory for this CID by first searching the
+ * local CID<->factory mapping. Next it searches for a Dll that implements
+ * this classID and calls LoadFactory() to create the factory.
+ *
+ * Again, no attempt is made at storing the factory.
+ */
+nsresult
+nsComponentManagerImpl::FindFactory(const nsCID &aClass,
+ nsIFactory **aFactory)
+{
+ PR_ASSERT(aFactory != nsnull);
+
+ nsFactoryEntry *entry = GetFactoryEntry(aClass);
+
+ if (!entry)
+ return NS_ERROR_FACTORY_NOT_REGISTERED;
+
+ return entry->GetFactory(aFactory, this);
+}
+
+
+nsresult
+nsComponentManagerImpl::FindFactory(const char *contractID,
+ PRUint32 aContractIDLen,
+ nsIFactory **aFactory)
+{
+ PR_ASSERT(aFactory != nsnull);
+
+ nsFactoryEntry *entry = GetFactoryEntry(contractID, aContractIDLen);
+
+ if (!entry)
+ return NS_ERROR_FACTORY_NOT_REGISTERED;
+
+ return entry->GetFactory(aFactory, this);
+}
+
+/**
+ * GetClassObject()
+ *
+ * Given a classID, this finds the singleton ClassObject that implements the CID.
+ * Returns an interface of type aIID off the singleton classobject.
+ */
+nsresult
+nsComponentManagerImpl::GetClassObject(const nsCID &aClass, const nsIID &aIID,
+ void **aResult)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIFactory> factory;
+
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_DEBUG))
+ {
+ char *buf = aClass.ToString();
+ PR_LogPrint("nsComponentManager: GetClassObject(%s)", buf);
+ if (buf)
+ PR_Free(buf);
+ }
+#endif
+
+ PR_ASSERT(aResult != nsnull);
+
+ rv = FindFactory(aClass, getter_AddRefs(factory));
+ if (NS_FAILED(rv)) return rv;
+
+ rv = factory->QueryInterface(aIID, aResult);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("\t\tGetClassObject() %s", NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
+
+ return rv;
+}
+
+
+nsresult
+nsComponentManagerImpl::GetClassObjectByContractID(const char *contractID,
+ const nsIID &aIID,
+ void **aResult)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIFactory> factory;
+
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_DEBUG))
+ {
+ PR_LogPrint("nsComponentManager: GetClassObject(%s)", contractID);
+ }
+#endif
+
+ PR_ASSERT(aResult != nsnull);
+
+ rv = FindFactory(contractID, strlen(contractID), getter_AddRefs(factory));
+ if (NS_FAILED(rv)) return rv;
+
+ rv = factory->QueryInterface(aIID, aResult);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("\t\tGetClassObject() %s", NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
+
+ return rv;
+}
+
+/**
+ * ContractIDToClassID()
+ *
+ * Mapping function from a ContractID to a classID. Directly talks to the registry.
+ *
+ */
+nsresult
+nsComponentManagerImpl::ContractIDToClassID(const char *aContractID, nsCID *aClass)
+{
+ NS_PRECONDITION(aContractID != nsnull, "null ptr");
+ if (!aContractID)
+ return NS_ERROR_NULL_POINTER;
+
+ NS_PRECONDITION(aClass != nsnull, "null ptr");
+ if (!aClass)
+ return NS_ERROR_NULL_POINTER;
+
+ nsresult rv = NS_ERROR_FACTORY_NOT_REGISTERED;
+
+ nsFactoryEntry *fe = GetFactoryEntry(aContractID, strlen(aContractID));
+ if (fe) {
+ *aClass = fe->mCid;
+ rv = NS_OK;
+ }
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING)) {
+ char *buf = 0;
+ if (NS_SUCCEEDED(rv))
+ buf = aClass->ToString();
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: ContractIDToClassID(%s)->%s", aContractID,
+ NS_SUCCEEDED(rv) ? buf : "[FAILED]"));
+ if (buf)
+ PR_Free(buf);
+ }
+#endif
+ return rv;
+}
+
+/**
+ * CLSIDToContractID()
+ *
+ * Translates a classID to a {ContractID, Class Name}. Does direct registry
+ * access to do the translation.
+ *
+ * NOTE: Since this isn't heavily used, we arent caching this.
+ */
+nsresult
+nsComponentManagerImpl::CLSIDToContractID(const nsCID &aClass,
+ char* *aClassName,
+ char* *aContractID)
+{
+ NS_WARNING("Need to implement CLSIDToContractID");
+
+ nsresult rv = NS_ERROR_FACTORY_NOT_REGISTERED;
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING))
+ {
+ char *buf = aClass.ToString();
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: CLSIDToContractID(%s)->%s", buf,
+ NS_SUCCEEDED(rv) ? *aContractID : "[FAILED]"));
+ if (buf)
+ PR_Free(buf);
+ }
+#endif
+ return rv;
+}
+
+#ifdef XPCOM_CHECK_PENDING_CIDS
+
+// This method must be called from within the mMon monitor
+nsresult
+nsComponentManagerImpl::AddPendingCID(const nsCID &aClass)
+{
+ int max = mPendingCIDs.Count();
+ for (int index = 0; index < max; index++)
+ {
+ nsCID *cidp = (nsCID*) mPendingCIDs.ElementAt(index);
+ NS_ASSERTION(cidp, "Bad CID in pending list");
+ if (cidp->Equals(aClass)) {
+ nsXPIDLCString cid;
+ cid.Adopt(aClass.ToString());
+ nsCAutoString message;
+ message = NS_LITERAL_CSTRING("Creation of \"") +
+ cid + NS_LITERAL_CSTRING("\" in progress (Reentrant GS - see bug 194568)");
+ // Note that you may see this assertion by near-simultaneous
+ // calls to GetService on multiple threads.
+ NS_WARNING(message.get());
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+ }
+ mPendingCIDs.AppendElement((void*)&aClass);
+ return NS_OK;
+}
+
+// This method must be called from within the mMon monitor
+void
+nsComponentManagerImpl::RemovePendingCID(const nsCID &aClass)
+{
+ mPendingCIDs.RemoveElement((void*)&aClass);
+}
+#endif
+/**
+ * CreateInstance()
+ *
+ * Create an instance of an object that implements an interface and belongs
+ * to the implementation aClass using the factory. The factory is immediately
+ * released and not held onto for any longer.
+ */
+nsresult
+nsComponentManagerImpl::CreateInstance(const nsCID &aClass,
+ nsISupports *aDelegate,
+ const nsIID &aIID,
+ void **aResult)
+{
+ // test this first, since there's no point in creating a component during
+ // shutdown -- whether it's available or not would depend on the order it
+ // occurs in the list
+ if (gXPCOMShuttingDown) {
+ // When processing shutdown, dont process new GetService() requests
+#ifdef SHOW_DENIED_ON_SHUTDOWN
+ nsXPIDLCString cid, iid;
+ cid.Adopt(aClass.ToString());
+ iid.Adopt(aIID.ToString());
+ fprintf(stderr, "Creating new instance on shutdown. Denied.\n"
+ " CID: %s\n IID: %s\n", cid.get(), iid.get());
+#endif /* SHOW_DENIED_ON_SHUTDOWN */
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ if (aResult == nsnull)
+ {
+ return NS_ERROR_NULL_POINTER;
+ }
+ *aResult = nsnull;
+
+ nsFactoryEntry *entry = GetFactoryEntry(aClass);
+
+ if (!entry)
+ return NS_ERROR_FACTORY_NOT_REGISTERED;
+
+#ifdef SHOW_CI_ON_EXISTING_SERVICE
+ if (entry->mServiceObject) {
+ nsXPIDLCString cid;
+ cid.Adopt(aClass.ToString());
+ nsCAutoString message;
+ message = NS_LITERAL_CSTRING("You are calling CreateInstance \"") +
+ cid + NS_LITERAL_CSTRING("\" when a service for this CID already exists!");
+ NS_ERROR(message.get());
+ }
+#endif
+
+ nsIFactory *factory = nsnull;
+ nsresult rv = entry->GetFactory(&factory, this);
+
+ if (NS_SUCCEEDED(rv))
+ {
+ rv = factory->CreateInstance(aDelegate, aIID, aResult);
+ NS_RELEASE(factory);
+ }
+ else
+ {
+ // Translate error values
+ rv = NS_ERROR_FACTORY_NOT_REGISTERED;
+ }
+
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING))
+ {
+ char *buf = aClass.ToString();
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: CreateInstance(%s) %s", buf,
+ NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
+ if (buf)
+ PR_Free(buf);
+ }
+#endif
+
+ return rv;
+}
+
+/**
+ * CreateInstanceByContractID()
+ *
+ * A variant of CreateInstance() that creates an instance of the object that
+ * implements the interface aIID and whose implementation has a contractID aContractID.
+ *
+ * This is only a convenience routine that turns around can calls the
+ * CreateInstance() with classid and iid.
+ */
+nsresult
+nsComponentManagerImpl::CreateInstanceByContractID(const char *aContractID,
+ nsISupports *aDelegate,
+ const nsIID &aIID,
+ void **aResult)
+{
+ // test this first, since there's no point in creating a component during
+ // shutdown -- whether it's available or not would depend on the order it
+ // occurs in the list
+ if (gXPCOMShuttingDown) {
+ // When processing shutdown, dont process new GetService() requests
+#ifdef SHOW_DENIED_ON_SHUTDOWN
+ nsXPIDLCString iid;
+ iid.Adopt(aIID.ToString());
+ fprintf(stderr, "Creating new instance on shutdown. Denied.\n"
+ " ContractID: %s\n IID: %s\n", aContractID, iid.get());
+#endif /* SHOW_DENIED_ON_SHUTDOWN */
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ if (aResult == nsnull)
+ {
+ return NS_ERROR_NULL_POINTER;
+ }
+ *aResult = nsnull;
+
+ nsFactoryEntry *entry = GetFactoryEntry(aContractID, strlen(aContractID));
+
+ if (!entry)
+ return NS_ERROR_FACTORY_NOT_REGISTERED;
+
+#ifdef SHOW_CI_ON_EXISTING_SERVICE
+ if (entry->mServiceObject) {
+ nsCAutoString message;
+ message =
+ NS_LITERAL_CSTRING("You are calling CreateInstance \"") +
+ nsDependentCString(aContractID) +
+ NS_LITERAL_CSTRING("\" when a service for this CID already exists! "
+ "Add it to abusedContracts to track down the service consumer.");
+ NS_ERROR(message.get());
+ }
+#endif
+
+ nsIFactory *factory = nsnull;
+ nsresult rv = entry->GetFactory(&factory, this);
+
+ if (NS_SUCCEEDED(rv))
+ {
+
+ rv = factory->CreateInstance(aDelegate, aIID, aResult);
+ NS_RELEASE(factory);
+ }
+ else
+ {
+ // Translate error values
+ if (rv != NS_ERROR_SOCKET_FAIL)
+ rv = NS_ERROR_FACTORY_NOT_REGISTERED;
+ }
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: CreateInstanceByContractID(%s) %s", aContractID,
+ NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
+
+ return rv;
+}
+
+// Service Manager Impl
+static
+PLDHashOperator PR_CALLBACK
+FreeServiceFactoryEntryEnumerate(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData)
+{
+ nsFactoryTableEntry* entry = NS_STATIC_CAST(nsFactoryTableEntry*, aHdr);
+
+ if (!entry->mFactoryEntry)
+ return PL_DHASH_NEXT;
+
+ nsFactoryEntry* factoryEntry = entry->mFactoryEntry;
+ factoryEntry->mServiceObject = nsnull;
+ return PL_DHASH_NEXT;
+}
+
+static
+PLDHashOperator PR_CALLBACK
+FreeServiceContractIDEntryEnumerate(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData)
+{
+ nsContractIDTableEntry* entry = NS_STATIC_CAST(nsContractIDTableEntry*, aHdr);
+
+ if (!entry->mFactoryEntry)
+ return PL_DHASH_NEXT;
+
+ nsFactoryEntry* factoryEntry = entry->mFactoryEntry;
+ factoryEntry->mServiceObject = nsnull;
+ return PL_DHASH_NEXT;
+}
+
+nsresult
+nsComponentManagerImpl::FreeServices()
+{
+ NS_ASSERTION(gXPCOMShuttingDown, "Must be shutting down in order to free all services");
+
+ if (!gXPCOMShuttingDown)
+ return NS_ERROR_FAILURE;
+
+ if (mContractIDs.ops) {
+ PL_DHashTableEnumerate(&mContractIDs, FreeServiceContractIDEntryEnumerate, nsnull);
+ }
+
+
+ if (mFactories.ops) {
+ PL_DHashTableEnumerate(&mFactories, FreeServiceFactoryEntryEnumerate, nsnull);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::GetService(const nsCID& aClass,
+ const nsIID& aIID,
+ void* *result)
+{
+ // test this first, since there's no point in returning a service during
+ // shutdown -- whether it's available or not would depend on the order it
+ // occurs in the list
+ if (gXPCOMShuttingDown) {
+ // When processing shutdown, dont process new GetService() requests
+#ifdef SHOW_DENIED_ON_SHUTDOWN
+ nsXPIDLCString cid, iid;
+ cid.Adopt(aClass.ToString());
+ iid.Adopt(aIID.ToString());
+ fprintf(stderr, "Getting service on shutdown. Denied.\n"
+ " CID: %s\n IID: %s\n", cid.get(), iid.get());
+#endif /* SHOW_DENIED_ON_SHUTDOWN */
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ nsAutoMonitor mon(mMon);
+
+ nsresult rv = NS_OK;
+ nsIDKey key(aClass);
+ nsFactoryEntry* entry = nsnull;
+ nsFactoryTableEntry* factoryTableEntry =
+ NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories, &aClass,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(factoryTableEntry)) {
+ entry = factoryTableEntry->mFactoryEntry;
+ }
+
+ if (entry && entry->mServiceObject) {
+ return entry->mServiceObject->QueryInterface(aIID, result);
+ }
+
+#ifdef XPCOM_CHECK_PENDING_CIDS
+ rv = AddPendingCID(aClass);
+ if (NS_FAILED(rv))
+ return rv; // NOP_AND_BREAK
+#endif
+ nsCOMPtr<nsISupports> service;
+ // We need to not be holding the service manager's monitor while calling
+ // CreateInstance, because it invokes user code which could try to re-enter
+ // the service manager:
+ mon.Exit();
+
+ rv = CreateInstance(aClass, nsnull, aIID, getter_AddRefs(service));
+
+ mon.Enter();
+
+#ifdef XPCOM_CHECK_PENDING_CIDS
+ RemovePendingCID(aClass);
+#endif
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (!entry) { // second hash lookup for GetService
+ nsFactoryTableEntry* factoryTableEntry =
+ NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories, &aClass,
+ PL_DHASH_LOOKUP));
+ if (PL_DHASH_ENTRY_IS_BUSY(factoryTableEntry)) {
+ entry = factoryTableEntry->mFactoryEntry;
+ }
+ NS_ASSERTION(entry, "we should have a factory entry since CI succeeded - we should not get here");
+ if (!entry) return NS_ERROR_FAILURE;
+ }
+
+ entry->mServiceObject = service;
+ *result = service.get();
+ NS_ADDREF(NS_STATIC_CAST(nsISupports*, (*result)));
+ return rv;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::RegisterService(const nsCID& aClass, nsISupports* aService)
+{
+ nsAutoMonitor mon(mMon);
+
+ // check to see if we have a factory entry for the service
+ nsFactoryEntry *entry = GetFactoryEntry(aClass);
+
+ if (!entry) { // XXXdougt - should we require that all services register factories?? probably not.
+ void *mem;
+ PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
+ if (!mem)
+ return NS_ERROR_OUT_OF_MEMORY;
+ entry = new (mem) nsFactoryEntry(aClass, nsnull);
+
+ entry->mTypeIndex = NS_COMPONENT_TYPE_SERVICE_ONLY;
+ nsFactoryTableEntry* factoryTableEntry =
+ NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories, &aClass,
+ PL_DHASH_ADD));
+ if (!factoryTableEntry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ factoryTableEntry->mFactoryEntry = entry;
+ }
+ else {
+ if (entry->mServiceObject)
+ return NS_ERROR_FAILURE;
+ }
+
+ entry->mServiceObject = aService;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::UnregisterService(const nsCID& aClass)
+{
+ nsresult rv = NS_OK;
+
+ nsFactoryEntry* entry = nsnull;
+
+ nsAutoMonitor mon(mMon);
+
+ nsFactoryTableEntry* factoryTableEntry =
+ NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories, &aClass,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(factoryTableEntry)) {
+ entry = factoryTableEntry->mFactoryEntry;
+ }
+
+ if (!entry || !entry->mServiceObject)
+ return NS_ERROR_SERVICE_NOT_AVAILABLE;
+
+ entry->mServiceObject = nsnull;
+ return rv;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::RegisterService(const char* aContractID, nsISupports* aService)
+{
+
+ nsAutoMonitor mon(mMon);
+
+ // check to see if we have a factory entry for the service
+ PRUint32 contractIDLen = strlen(aContractID);
+ nsFactoryEntry *entry = GetFactoryEntry(aContractID, contractIDLen);
+
+ if (!entry) { // XXXdougt - should we require that all services register factories?? probably not.
+ void *mem;
+ PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
+ if (!mem)
+ return NS_ERROR_OUT_OF_MEMORY;
+ entry = new (mem) nsFactoryEntry(kEmptyCID, nsnull);
+
+ entry->mTypeIndex = NS_COMPONENT_TYPE_SERVICE_ONLY;
+
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs, aContractID,
+ PL_DHASH_ADD));
+ if (!contractIDTableEntry) {
+ delete entry;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (!contractIDTableEntry->mContractID) {
+ contractIDTableEntry->mContractID =
+ ArenaStrndup(aContractID, contractIDLen, &mArena);
+
+ contractIDTableEntry->mContractIDLen = contractIDLen;
+ }
+
+ contractIDTableEntry->mFactoryEntry = entry;
+ }
+ else {
+ if (entry->mServiceObject)
+ return NS_ERROR_FAILURE;
+ }
+
+ entry->mServiceObject = aService;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsComponentManagerImpl::IsServiceInstantiated(const nsCID & aClass,
+ const nsIID& aIID,
+ PRBool *result)
+{
+ // Now we want to get the service if we already got it. If not, we dont want
+ // to create an instance of it. mmh!
+
+ // test this first, since there's no point in returning a service during
+ // shutdown -- whether it's available or not would depend on the order it
+ // occurs in the list
+ if (gXPCOMShuttingDown) {
+ // When processing shutdown, dont process new GetService() requests
+#ifdef SHOW_DENIED_ON_SHUTDOWN
+ nsXPIDLCString cid, iid;
+ cid.Adopt(aClass.ToString());
+ iid.Adopt(aIID.ToString());
+ fprintf(stderr, "Checking for service on shutdown. Denied.\n"
+ " CID: %s\n IID: %s\n", cid.get(), iid.get());
+#endif /* SHOW_DENIED_ON_SHUTDOWN */
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ nsresult rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
+ nsFactoryEntry* entry = nsnull;
+ nsFactoryTableEntry* factoryTableEntry =
+ NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories, &aClass,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(factoryTableEntry)) {
+ entry = factoryTableEntry->mFactoryEntry;
+ }
+
+ if (entry && entry->mServiceObject) {
+ nsCOMPtr<nsISupports> service;
+ rv = entry->mServiceObject->QueryInterface(aIID, getter_AddRefs(service));
+ *result = (service!=nsnull);
+ }
+ return rv;
+
+}
+
+NS_IMETHODIMP nsComponentManagerImpl::IsServiceInstantiatedByContractID(const char *aContractID,
+ const nsIID& aIID,
+ PRBool *result)
+{
+ // Now we want to get the service if we already got it. If not, we dont want
+ // to create an instance of it. mmh!
+
+ // test this first, since there's no point in returning a service during
+ // shutdown -- whether it's available or not would depend on the order it
+ // occurs in the list
+ if (gXPCOMShuttingDown) {
+ // When processing shutdown, dont process new GetService() requests
+#ifdef SHOW_DENIED_ON_SHUTDOWN
+ nsXPIDLCString iid;
+ iid.Adopt(aIID.ToString());
+ fprintf(stderr, "Checking for service on shutdown. Denied.\n"
+ " ContractID: %s\n IID: %s\n", aContractID, iid.get());
+#endif /* SHOW_DENIED_ON_SHUTDOWN */
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ nsresult rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
+ nsFactoryEntry *entry = nsnull;
+ {
+ nsAutoMonitor mon(mMon);
+
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs, aContractID,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(contractIDTableEntry)) {
+ entry = contractIDTableEntry->mFactoryEntry;
+ }
+ } // exit monitor
+
+ if (entry && entry->mServiceObject) {
+ nsCOMPtr<nsISupports> service;
+ rv = entry->mServiceObject->QueryInterface(aIID, getter_AddRefs(service));
+ *result = (service!=nsnull);
+ }
+ return rv;
+}
+
+
+NS_IMETHODIMP
+nsComponentManagerImpl::UnregisterService(const char* aContractID)
+{
+ nsresult rv = NS_OK;
+
+ nsAutoMonitor mon(mMon);
+
+ nsFactoryEntry *entry = nsnull;
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs, aContractID,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(contractIDTableEntry)) {
+ entry = contractIDTableEntry->mFactoryEntry;
+ }
+
+ if (!entry || !entry->mServiceObject)
+ return NS_ERROR_SERVICE_NOT_AVAILABLE;
+
+ entry->mServiceObject = nsnull;
+ return rv;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::GetServiceByContractID(const char* aContractID,
+ const nsIID& aIID,
+ void* *result)
+{
+ // test this first, since there's no point in returning a service during
+ // shutdown -- whether it's available or not would depend on the order it
+ // occurs in the list
+ if (gXPCOMShuttingDown) {
+ // When processing shutdown, dont process new GetService() requests
+#ifdef SHOW_DENIED_ON_SHUTDOWN
+ nsXPIDLCString iid;
+ iid.Adopt(aIID.ToString());
+ fprintf(stderr, "Getting service on shutdown. Denied.\n"
+ " ContractID: %s\n IID: %s\n", aContractID, iid.get());
+#endif /* SHOW_DENIED_ON_SHUTDOWN */
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ nsAutoMonitor mon(mMon);
+
+ nsresult rv = NS_OK;
+ nsFactoryEntry *entry = nsnull;
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs, aContractID,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(contractIDTableEntry)) {
+ entry = contractIDTableEntry->mFactoryEntry;
+ }
+
+ if (entry) {
+ if (entry->mServiceObject) {
+ return entry->mServiceObject->QueryInterface(aIID, result);
+ }
+#ifdef XPCOM_CHECK_PENDING_CIDS
+ rv = AddPendingCID(entry->mCid);
+ if (NS_FAILED(rv))
+ return rv; // NOP_AND_BREAK
+#endif
+ }
+
+ nsCOMPtr<nsISupports> service;
+ // We need to not be holding the service manager's monitor while calling
+ // CreateInstance, because it invokes user code which could try to re-enter
+ // the service manager:
+ mon.Exit();
+
+ rv = CreateInstanceByContractID(aContractID, nsnull, aIID, getter_AddRefs(service));
+
+ mon.Enter();
+
+#ifdef XPCOM_CHECK_PENDING_CIDS
+ if (entry)
+ RemovePendingCID(entry->mCid);
+#endif
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (!entry) { // second hash lookup for GetService
+ nsContractIDTableEntry* contractIDTableEntry =
+ NS_STATIC_CAST(nsContractIDTableEntry*,
+ PL_DHashTableOperate(&mContractIDs, aContractID,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_BUSY(contractIDTableEntry)) {
+ entry = contractIDTableEntry->mFactoryEntry;
+ }
+ NS_ASSERTION(entry, "we should have a factory entry since CI succeeded - we should not get here");
+ if (!entry) return NS_ERROR_FAILURE;
+ }
+
+ entry->mServiceObject = service;
+ *result = service.get();
+ NS_ADDREF(NS_STATIC_CAST(nsISupports*, *result));
+ return rv;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::GetService(const nsCID& aClass, const nsIID& aIID,
+ nsISupports* *result,
+ nsIShutdownListener* shutdownListener)
+{
+ return GetService(aClass, aIID, (void**)result);
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::GetService(const char* aContractID, const nsIID& aIID,
+ nsISupports* *result,
+ nsIShutdownListener* shutdownListener)
+{
+ return GetServiceByContractID(aContractID, aIID, (void**)result);
+}
+
+
+NS_IMETHODIMP
+nsComponentManagerImpl::ReleaseService(const nsCID& aClass, nsISupports* service,
+ nsIShutdownListener* shutdownListener)
+{
+ NS_IF_RELEASE(service);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::ReleaseService(const char* aContractID, nsISupports* service,
+ nsIShutdownListener* shutdownListener)
+{
+ NS_IF_RELEASE(service);
+ return NS_OK;
+}
+
+/*
+ * I want an efficient way to allocate a buffer to the right size
+ * and stick the prefix and dllName in, then be able to hand that buffer
+ * off to the FactoryEntry. Is that so wrong?
+ *
+ * *regName is allocated on success.
+ *
+ * This should live in nsNativeComponentLoader.cpp, I think.
+ */
+static nsresult
+MakeRegistryName(const char *aDllName, const char *prefix, char **regName)
+{
+ char *registryName;
+
+ PRUint32 len = strlen(prefix);
+
+ PRUint32 registryNameLen = strlen(aDllName) + len;
+ registryName = (char *)nsMemory::Alloc(registryNameLen + 1);
+
+ // from here on it, we want len sans terminating NUL
+
+ if (!registryName)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ memcpy(registryName, prefix, len);
+ strcpy(registryName + len, aDllName);
+ registryName[registryNameLen] = '\0';
+ *regName = registryName;
+
+#ifdef DEBUG_shaver_off
+ fprintf(stderr, "MakeRegistryName(%s, %s, &[%s])\n",
+ aDllName, prefix, *regName);
+#endif
+
+ return NS_OK;
+}
+
+nsresult
+nsComponentManagerImpl::RegistryLocationForSpec(nsIFile *aSpec,
+ char **aRegistryName)
+{
+ nsresult rv;
+
+ if (!mComponentsDir)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ if (!aSpec) {
+ *aRegistryName = PL_strdup("");
+ return NS_OK;
+ }
+
+
+ // First check to see if this component is in the application
+ // components directory
+ PRBool containedIn;
+ mComponentsDir->Contains(aSpec, PR_TRUE, &containedIn);
+
+ nsCAutoString nativePathString;
+
+ if (containedIn){
+ rv = aSpec->GetNativePath(nativePathString);
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char* relativeLocation = nativePathString.get() + mComponentsOffset + 1;
+ return MakeRegistryName(relativeLocation, XPCOM_RELCOMPONENT_PREFIX, aRegistryName);
+ }
+
+ // Next check to see if this component is in the GRE
+ // components directory
+
+ mGREComponentsDir->Contains(aSpec, PR_TRUE, &containedIn);
+
+ if (containedIn){
+ rv = aSpec->GetNativePath(nativePathString);
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char* relativeLocation = nativePathString.get() + mGREComponentsOffset + 1;
+ return MakeRegistryName(relativeLocation, XPCOM_GRECOMPONENT_PREFIX, aRegistryName);
+ }
+
+ /* absolute names include volume info on Mac, so persistent descriptor */
+ rv = aSpec->GetNativePath(nativePathString);
+ if (NS_FAILED(rv))
+ return rv;
+ return MakeRegistryName(nativePathString.get(), XPCOM_ABSCOMPONENT_PREFIX, aRegistryName);
+}
+
+nsresult
+nsComponentManagerImpl::SpecForRegistryLocation(const char *aLocation,
+ nsIFile **aSpec)
+{
+ // i18n: assuming aLocation is encoded for the current locale
+
+ nsresult rv;
+ if (!aLocation || !aSpec)
+ return NS_ERROR_NULL_POINTER;
+
+ /* abs:/full/path/to/libcomponent.so */
+ if (!strncmp(aLocation, XPCOM_ABSCOMPONENT_PREFIX, 4)) {
+
+ nsLocalFile* file = new nsLocalFile;
+ if (!file) return NS_ERROR_FAILURE;
+
+ rv = file->InitWithNativePath(nsDependentCString((char *)aLocation + 4));
+ file->QueryInterface(NS_GET_IID(nsILocalFile), (void**)aSpec);
+ return rv;
+ }
+
+ if (!strncmp(aLocation, XPCOM_RELCOMPONENT_PREFIX, 4)) {
+
+ if (!mComponentsDir)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ nsILocalFile* file = nsnull;
+ rv = mComponentsDir->Clone((nsIFile**)&file);
+
+ if (NS_FAILED(rv)) return rv;
+
+ rv = file->AppendRelativeNativePath(nsDependentCString(aLocation + 4));
+ *aSpec = file;
+ return rv;
+ }
+
+ if (!strncmp(aLocation, XPCOM_GRECOMPONENT_PREFIX, 4)) {
+
+ if (!mGREComponentsDir)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ nsILocalFile* file = nsnull;
+ rv = mGREComponentsDir->Clone((nsIFile**)&file);
+
+ if (NS_FAILED(rv)) return rv;
+
+ rv = file->AppendRelativeNativePath(nsDependentCString(aLocation + 4));
+ *aSpec = file;
+ return rv;
+ }
+
+ *aSpec = nsnull;
+ return NS_ERROR_INVALID_ARG;
+}
+
+/**
+ * RegisterFactory()
+ *
+ * Register a factory to be responsible for creation of implementation of
+ * classID aClass. Plus creates as association of aClassName and aContractID
+ * to the classID. If replace is PR_TRUE, we replace any existing registrations
+ * with this one.
+ *
+ * Once registration is complete, we add the class to the factories cache
+ * that we maintain. The factories cache is the ONLY place where these
+ * registrations are ever kept.
+ *
+ * The other RegisterFunctions create a loader mapping and persistent
+ * location, but we just slam it into the cache here. And we don't call the
+ * loader's OnRegister function, either.
+ */
+nsresult
+nsComponentManagerImpl::RegisterFactory(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFactory *aFactory,
+ PRBool aReplace)
+{
+ nsAutoMonitor mon(mMon);
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING))
+ {
+ char *buf = aClass.ToString();
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: RegisterFactory(%s, %s)", buf,
+ (aContractID ? aContractID : "(null)")));
+ if (buf)
+ PR_Free(buf);
+ }
+#endif
+ nsFactoryEntry *entry = nsnull;
+ nsFactoryTableEntry* factoryTableEntry = NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories,
+ &aClass,
+ PL_DHASH_ADD));
+
+ if (!factoryTableEntry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+
+ if (PL_DHASH_ENTRY_IS_BUSY(factoryTableEntry)) {
+ entry = factoryTableEntry->mFactoryEntry;
+ }
+
+ if (entry && !aReplace)
+ {
+ // Already registered
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("\t\tFactory already registered."));
+ return NS_ERROR_FACTORY_EXISTS;
+ }
+
+ void *mem;
+ PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
+ if (!mem)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ entry = new (mem) nsFactoryEntry(aClass, aFactory, entry);
+
+ if (!entry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ factoryTableEntry->mFactoryEntry = entry;
+
+ // Update the ContractID->CLSID Map
+ if (aContractID) {
+ nsresult rv = HashContractID(aContractID, strlen(aContractID), entry);
+ if (NS_FAILED(rv)) {
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("\t\tFactory register succeeded. "
+ "Hashing contractid (%s) FAILED.", aContractID));
+ return rv;
+ }
+ }
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("\t\tFactory register succeeded contractid=%s.",
+ aContractID ? aContractID : "<none>"));
+
+ return NS_OK;
+}
+
+nsresult
+nsComponentManagerImpl::RegisterComponent(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ const char *aPersistentDescriptor,
+ PRBool aReplace,
+ PRBool aPersist)
+{
+ return RegisterComponentCommon(aClass, aClassName,
+ aContractID,
+ aContractID ? strlen(aContractID) : 0,
+ aPersistentDescriptor,
+ aPersistentDescriptor ?
+ strlen(aPersistentDescriptor) : 0,
+ aReplace, aPersist,
+ nativeComponentType);
+}
+
+nsresult
+nsComponentManagerImpl::RegisterComponentWithType(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFile *aSpec,
+ const char *aLocation,
+ PRBool aReplace,
+ PRBool aPersist,
+ const char *aType)
+{
+ return RegisterComponentCommon(aClass, aClassName,
+ aContractID,
+ aContractID ? strlen(aContractID) : 0,
+ aLocation,
+ aLocation ? strlen(aLocation) : 0,
+ aReplace, aPersist,
+ aType);
+}
+
+/*
+ * Register a component, using whatever they stuck in the nsIFile.
+ */
+nsresult
+nsComponentManagerImpl::RegisterComponentSpec(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFile *aLibrarySpec,
+ PRBool aReplace,
+ PRBool aPersist)
+{
+ nsXPIDLCString registryName;
+ nsresult rv = RegistryLocationForSpec(aLibrarySpec, getter_Copies(registryName));
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = RegisterComponentWithType(aClass, aClassName,
+ aContractID,
+ aLibrarySpec,
+ registryName,
+ aReplace, aPersist,
+ nativeComponentType);
+ return rv;
+}
+
+nsresult
+nsComponentManagerImpl::RegisterComponentLib(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ const char *aDllName,
+ PRBool aReplace,
+ PRBool aPersist)
+{
+ // deprecated and obsolete.
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/*
+ * Add a component to the known universe of components.
+
+ * Once we enter this function, we own aRegistryName, and must free it
+ * or hand it to nsFactoryEntry. Common exit point ``out'' helps keep us
+ * sane.
+ */
+
+nsresult
+nsComponentManagerImpl::RegisterComponentCommon(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ PRUint32 aContractIDLen,
+ const char *aRegistryName,
+ PRUint32 aRegistryNameLen,
+ PRBool aReplace,
+ PRBool aPersist,
+ const char *aType)
+{
+ nsIDKey key(aClass);
+ nsAutoMonitor mon(mMon);
+
+ nsFactoryEntry *entry = GetFactoryEntry(aClass);
+
+ // Normalize proid and classname
+ const char *contractID = (aContractID && *aContractID) ? aContractID : nsnull;
+ const char *className = (aClassName && *aClassName) ? aClassName : nsnull;
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING))
+ {
+ char *buf = aClass.ToString();
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: RegisterComponentCommon(%s, %s, %s, %s)",
+ buf,
+ contractID ? contractID : "(null)",
+ aRegistryName, aType));
+ if (buf)
+ PR_Free(buf);
+ }
+#endif
+ if (entry && !aReplace) {
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("\t\tFactory already registered."));
+ return NS_ERROR_FACTORY_EXISTS;
+ }
+
+ int typeIndex = GetLoaderType(aType);
+
+ nsCOMPtr<nsIComponentLoader> loader;
+ nsresult rv = GetLoaderForType(typeIndex, getter_AddRefs(loader));
+ if (NS_FAILED(rv)) {
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("\t\tgetting loader for %s FAILED\n", aType));
+ return rv;
+ }
+
+ if (entry) {
+ entry->ReInit(aClass, aRegistryName, typeIndex);
+ }
+ else {
+
+ // Arena allocate the nsFactoryEntry
+ void *mem;
+ PL_ARENA_ALLOCATE(mem, &mArena, sizeof(nsFactoryEntry));
+ if (!mem)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ mRegistryDirty = PR_TRUE;
+ entry = new (mem) nsFactoryEntry(aClass,
+ aRegistryName, aRegistryNameLen,
+ typeIndex);
+ if (!entry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsFactoryTableEntry* factoryTableEntry =
+ NS_STATIC_CAST(nsFactoryTableEntry*,
+ PL_DHashTableOperate(&mFactories, &aClass,
+ PL_DHASH_ADD));
+
+ if (!factoryTableEntry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ factoryTableEntry->mFactoryEntry = entry;
+ }
+
+ // Update the ContractID->CLSID Map
+ if (contractID) {
+ rv = HashContractID(contractID, aContractIDLen, entry);
+ if (NS_FAILED(rv)) {
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("\t\tHashContractID(%s) FAILED\n", contractID));
+ return rv;
+ }
+ }
+ return rv;
+}
+
+
+nsresult
+nsComponentManagerImpl::GetLoaderForType(int aType,
+ nsIComponentLoader **aLoader)
+{
+ nsresult rv;
+
+ // Make sure we have a valid type
+ if (aType < 0 || aType >= mNLoaderData)
+ return NS_ERROR_INVALID_ARG;
+
+ *aLoader = mLoaderData[aType].loader;
+ if (*aLoader) {
+ NS_ADDREF(*aLoader);
+ return NS_OK;
+ }
+
+ nsCOMPtr<nsIComponentLoader> loader;
+ loader = do_GetServiceFromCategory("component-loader", mLoaderData[aType].type, &rv);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = loader->Init(this, nsnull);
+
+ if (NS_SUCCEEDED(rv)) {
+ mLoaderData[aType].loader = loader;
+ NS_ADDREF(mLoaderData[aType].loader);
+ *aLoader = loader;
+ NS_ADDREF(*aLoader);
+ }
+ return rv;
+}
+
+
+
+// Convert a loader type string into an index into the component data
+// array. Empty loader types are converted to NATIVE. Returns -1 if
+// loader type cannot be determined.
+int
+nsComponentManagerImpl::GetLoaderType(const char *typeStr)
+{
+ if (!typeStr || !*typeStr) {
+ // Empty type strings are NATIVE
+ return NS_COMPONENT_TYPE_NATIVE;
+ }
+
+ for (int i=NS_COMPONENT_TYPE_NATIVE; i<mNLoaderData; i++) {
+ if (!strcmp(typeStr, mLoaderData[i].type))
+ return i;
+ }
+ // Not found
+ return NS_COMPONENT_TYPE_FACTORY_ONLY;
+}
+
+// Add a loader type if not already known. Out the typeIndex
+// if the loader type is either added or already there.
+nsresult
+nsComponentManagerImpl::AddLoaderType(const char *typeStr, int *aTypeIndex)
+{
+ int typeIndex = GetLoaderType(typeStr);
+ if (typeIndex >= 0) {
+ *aTypeIndex = typeIndex;
+ return NS_OK;
+ }
+
+ // Add the loader type
+ if (mNLoaderData >= mMaxNLoaderData) {
+ NS_ASSERTION(mNLoaderData == mMaxNLoaderData,
+ "Memory corruption. nsComponentManagerImpl::mLoaderData array overrun.");
+ // Need to increase our loader array
+ nsLoaderdata *new_mLoaderData = (nsLoaderdata *) PR_Realloc(mLoaderData, (mMaxNLoaderData + NS_LOADER_DATA_ALLOC_STEP) * sizeof(nsLoaderdata));
+ if (!new_mLoaderData)
+ return NS_ERROR_OUT_OF_MEMORY;
+ mLoaderData = new_mLoaderData;
+ mMaxNLoaderData += NS_LOADER_DATA_ALLOC_STEP;
+ }
+
+ typeIndex = mNLoaderData;
+ mLoaderData[typeIndex].type = PL_strdup(typeStr);
+ if (!mLoaderData[typeIndex].type) {
+ // mmh! no memory. return failure.
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ mLoaderData[typeIndex].loader = nsnull;
+ mNLoaderData++;
+
+ *aTypeIndex = typeIndex;
+ return NS_OK;
+}
+
+typedef struct
+{
+ const nsCID* cid;
+ const char* regName;
+ nsIFactory* factory;
+} UnregisterConditions;
+
+static PLDHashOperator PR_CALLBACK
+DeleteFoundCIDs(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData)
+{
+ nsContractIDTableEntry* entry = NS_STATIC_CAST(nsContractIDTableEntry*, aHdr);
+
+ if (!entry->mFactoryEntry)
+ return PL_DHASH_NEXT;
+
+ UnregisterConditions* data = (UnregisterConditions*)aData;
+
+ nsFactoryEntry* factoryEntry = entry->mFactoryEntry;
+ if (data->cid->Equals(factoryEntry->mCid) &&
+ ((data->regName && !PL_strcasecmp(factoryEntry->mLocation, data->regName)) ||
+ (data->factory && data->factory == factoryEntry->mFactory.get())))
+ return PL_DHASH_REMOVE;
+
+ return PL_DHASH_NEXT;
+}
+
+void
+nsComponentManagerImpl::DeleteContractIDEntriesByCID(const nsCID* aClass, const char*registryName)
+{
+ UnregisterConditions aData;
+ aData.cid = aClass;
+ aData.regName = registryName;
+ aData.factory = nsnull;
+ PL_DHashTableEnumerate(&mContractIDs, DeleteFoundCIDs, (void*)&aData);
+
+}
+
+void
+nsComponentManagerImpl::DeleteContractIDEntriesByCID(const nsCID* aClass, nsIFactory* factory)
+{
+ UnregisterConditions aData;
+ aData.cid = aClass;
+ aData.regName = nsnull;
+ aData.factory = factory;
+ PL_DHashTableEnumerate(&mContractIDs, DeleteFoundCIDs, (void*)&aData);
+}
+
+nsresult
+nsComponentManagerImpl::UnregisterFactory(const nsCID &aClass,
+ nsIFactory *aFactory)
+{
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING))
+ {
+ char *buf = aClass.ToString();
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: UnregisterFactory(%s)", buf));
+ if (buf)
+ PR_Free(buf);
+ }
+#endif
+ nsFactoryEntry *old;
+
+ // first delete all contract id entries that are registered with this cid.
+ DeleteContractIDEntriesByCID(&aClass, aFactory);
+
+ // next check to see if there is a CID registered
+ nsresult rv = NS_ERROR_FACTORY_NOT_REGISTERED;
+ old = GetFactoryEntry(aClass);
+
+ if (old && (old->mFactory.get() == aFactory))
+ {
+ nsAutoMonitor mon(mMon);
+ PL_DHashTableOperate(&mFactories, &aClass, PL_DHASH_REMOVE);
+ rv = NS_OK;
+ }
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("\t\tUnregisterFactory() %s",
+ NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
+ return rv;
+}
+
+nsresult
+nsComponentManagerImpl::UnregisterComponent(const nsCID &aClass,
+ const char *registryName)
+{
+#ifdef PR_LOGGING
+ if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING))
+ {
+ char *buf = aClass.ToString();
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: UnregisterComponent(%s)", buf));
+ if (buf)
+ PR_Free(buf);
+ }
+#endif
+
+ NS_ENSURE_ARG_POINTER(registryName);
+ nsFactoryEntry *old;
+
+ // first delete all contract id entries that are registered with this cid.
+ DeleteContractIDEntriesByCID(&aClass, registryName);
+
+ // next check to see if there is a CID registered
+ old = GetFactoryEntry(aClass);
+ if (old && old->mLocation && !PL_strcasecmp(old->mLocation, registryName))
+ {
+ nsAutoMonitor mon(mMon);
+ PL_DHashTableOperate(&mFactories, &aClass, PL_DHASH_REMOVE);
+ }
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: Factory unregister(%s) succeeded.", registryName));
+
+ return NS_OK;
+}
+
+nsresult
+nsComponentManagerImpl::UnregisterComponentSpec(const nsCID &aClass,
+ nsIFile *aLibrarySpec)
+{
+ nsXPIDLCString registryName;
+ nsresult rv = RegistryLocationForSpec(aLibrarySpec, getter_Copies(registryName));
+ if (NS_FAILED(rv)) return rv;
+ return UnregisterComponent(aClass, registryName);
+}
+
+// XXX Need to pass in aWhen and servicemanager
+nsresult
+nsComponentManagerImpl::FreeLibraries(void)
+{
+ return UnloadLibraries(NS_STATIC_CAST(nsIServiceManager*, this), NS_Timer); // XXX when
+}
+
+// Private implementation of unloading libraries
+nsresult
+nsComponentManagerImpl::UnloadLibraries(nsIServiceManager *serviceMgr, PRInt32 aWhen)
+{
+ nsresult rv = NS_OK;
+
+ nsAutoMonitor mon(mMon);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsComponentManager: Unloading Libraries."));
+
+ // UnloadAll the loaders
+ /* iterate over all known loaders and ask them to autoregister. */
+ // Skip mNativeComponentLoader
+ for (int i=NS_COMPONENT_TYPE_NATIVE + 1; i<mNLoaderData; i++) {
+ if (mLoaderData[i].loader) {
+ rv = mLoaderData[i].loader->UnloadAll(aWhen);
+ if (NS_FAILED(rv))
+ break;
+ }
+ }
+
+ // UnloadAll the native loader
+ rv = mNativeComponentLoader->UnloadAll(aWhen);
+ return rv;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * AutoRegister(RegistrationInstant, const char *directory)
+ *
+ * Given a directory in the following format, this will ensure proper registration
+ * of all components. No default directory is looked at.
+ *
+ * Directory and fullname are what NSPR will accept. For eg.
+ * WIN y:/home/dp/mozilla/dist/bin
+ * UNIX /home/dp/mozilla/dist/bin
+ * MAC /Hard drive/mozilla/dist/apprunner
+ *
+ * This will take care not loading already registered dlls, finding and
+ * registering new dlls, re-registration of modified dlls
+ *
+ */
+
+nsresult
+nsComponentManagerImpl::AutoRegister(PRInt32 when, nsIFile *inDirSpec)
+{
+ return AutoRegisterImpl(when, inDirSpec);
+}
+
+nsresult
+nsComponentManagerImpl::AutoRegisterImpl(PRInt32 when,
+ nsIFile *inDirSpec,
+ PRBool fileIsCompDir)
+{
+ nsCOMPtr<nsIFile> dir;
+ nsresult rv;
+
+#ifdef DEBUG
+ // testing release behaviour
+ if (getenv("XPCOM_NO_AUTOREG"))
+ return NS_OK;
+#endif
+ if (inDirSpec)
+ {
+ // Use supplied components' directory
+ dir = inDirSpec;
+ }
+ else
+ {
+ mComponentsDir->Clone(getter_AddRefs(dir));
+ if (!dir)
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ nsCOMPtr<nsIInterfaceInfoManager> iim =
+ dont_AddRef(XPTI_GetInterfaceInfoManager());
+
+ if (!iim)
+ return NS_ERROR_UNEXPECTED;
+
+ // Notify observers of xpcom autoregistration start
+ NS_CreateServicesFromCategory(NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID,
+ nsnull,
+ "start");
+
+ /* do the native loader first, so we can find other loaders */
+ rv = mNativeComponentLoader->AutoRegisterComponents((PRInt32)when, dir);
+ if (NS_FAILED(rv)) return rv;
+
+#ifdef ENABLE_STATIC_COMPONENT_LOADER
+ rv = mStaticComponentLoader->AutoRegisterComponents((PRInt32)when, inDirSpec);
+ if (NS_FAILED(rv)) return rv;
+#endif
+
+ /* do InterfaceInfoManager after native loader so it can use components. */
+ rv = iim->AutoRegisterInterfaces();
+ if (NS_FAILED(rv)) return rv;
+
+ if (!mCategoryManager) {
+ NS_WARNING("mCategoryManager is null");
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ nsCOMPtr<nsISimpleEnumerator> loaderEnum;
+ rv = mCategoryManager->EnumerateCategory("component-loader",
+ getter_AddRefs(loaderEnum));
+ if (NS_FAILED(rv)) return rv;
+
+ PRBool hasMore;
+ while (NS_SUCCEEDED(loaderEnum->HasMoreElements(&hasMore)) && hasMore) {
+ nsCOMPtr<nsISupports> supports;
+ if (NS_FAILED(loaderEnum->GetNext(getter_AddRefs(supports))))
+ continue;
+
+ nsCOMPtr<nsISupportsCString> supStr = do_QueryInterface(supports);
+ if (!supStr)
+ continue;
+
+ nsCAutoString loaderType;
+ if (NS_FAILED(supStr->GetData(loaderType)))
+ continue;
+
+ // We depend on the loader being created. Add the loader type and
+ // create the loader object too.
+ nsCOMPtr<nsIComponentLoader> loader;
+ int typeIndex;
+ rv = AddLoaderType(loaderType.get(), &typeIndex);
+ if (NS_FAILED(rv))
+ return rv;
+ GetLoaderForType(typeIndex, getter_AddRefs(loader));
+ }
+
+ rv = AutoRegisterNonNativeComponents(dir.get());
+
+ // Notify observers of xpcom autoregistration completion
+ NS_CreateServicesFromCategory(NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID,
+ nsnull,
+ "end");
+
+ if (mRegistryDirty)
+ FlushPersistentStore(PR_TRUE);
+ return rv;
+}
+
+nsresult
+nsComponentManagerImpl::AutoRegisterNonNativeComponents(nsIFile* spec)
+{
+ nsresult rv = NS_OK;
+ nsCOMPtr<nsIFile> directory = spec;
+
+ if (!directory) {
+ mComponentsDir->Clone(getter_AddRefs(directory));
+ if (!directory)
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ for (int i = 1; i < mNLoaderData; i++) {
+ if (!mLoaderData[i].loader) {
+ rv = GetLoaderForType(i, &mLoaderData[i].loader);
+ if (NS_FAILED(rv))
+ continue;
+ }
+ rv = mLoaderData[i].loader->AutoRegisterComponents(0, directory);
+ if (NS_FAILED(rv))
+ break;
+ }
+
+ if (NS_SUCCEEDED(rv))
+ {
+ PRBool registered;
+ do {
+ registered = PR_FALSE;
+ for (int i = 0; i < mNLoaderData; i++) {
+ PRBool b = PR_FALSE;
+ if (mLoaderData[i].loader) {
+ rv = mLoaderData[i].loader->RegisterDeferredComponents(0, &b);
+ if (NS_FAILED(rv))
+ continue;
+ registered |= b;
+ }
+ }
+ } while (NS_SUCCEEDED(rv) && registered);
+ }
+ return rv;
+}
+nsresult
+nsComponentManagerImpl::AutoRegisterComponent(PRInt32 when,
+ nsIFile *component)
+{
+ nsresult rv = NS_OK, res = NS_ERROR_FACTORY_NOT_REGISTERED;
+ /*
+ * Do we have to give the native loader first crack at it?
+ * I vote ``no''.
+ */
+ for (int i = 0; i < mNLoaderData; i++) {
+ PRBool didRegister;
+ if (!mLoaderData[i].loader) {
+ nsCOMPtr<nsIComponentLoader> loader;
+ rv = GetLoaderForType(i, getter_AddRefs(loader));
+ if (NS_FAILED(rv))
+ continue;
+ // |GetLoaderForType| has filled in |mLoaderData[i].loader|:
+ NS_ASSERTION(loader == mLoaderData[i].loader, "oops");
+ }
+ rv = mLoaderData[i].loader->AutoRegisterComponent((int)when, component, &didRegister);
+ if (NS_FAILED(rv)) {
+ res = rv;
+ } else if (didRegister) {
+ return rv;
+ }
+ }
+ return res;
+}
+
+nsresult
+nsComponentManagerImpl::AutoUnregisterComponent(PRInt32 when,
+ nsIFile *component)
+{
+ nsresult rv = NS_OK;
+ for (int i = 0; i < mNLoaderData; i++) {
+ PRBool didUnRegister;
+ if (!mLoaderData[i].loader) {
+ rv = GetLoaderForType(i, &mLoaderData[i].loader);
+ if (NS_FAILED(rv))
+ continue;
+ }
+ rv = mLoaderData[i].loader->AutoUnregisterComponent(when, component, &didUnRegister);
+ if (NS_SUCCEEDED(rv) && didUnRegister) {
+ // we need to remove this file from our list of known libraries.
+ RemoveFileInfo(component, nsnull);
+ mRegistryDirty = PR_TRUE;
+ break;
+ }
+ }
+ return NS_FAILED(rv) ? NS_ERROR_FACTORY_NOT_REGISTERED : NS_OK;
+}
+
+nsresult
+nsComponentManagerImpl::IsRegistered(const nsCID &aClass,
+ PRBool *aRegistered)
+{
+ if (!aRegistered)
+ {
+ NS_ASSERTION(0, "null ptr");
+ return NS_ERROR_NULL_POINTER;
+ }
+ *aRegistered = (nsnull != GetFactoryEntry(aClass));
+ return NS_OK;
+}
+
+nsresult
+nsComponentManagerImpl::EnumerateCLSIDs(nsIEnumerator** aEnumerator)
+{
+ NS_ASSERTION(aEnumerator != nsnull, "null ptr");
+ if (!aEnumerator)
+ {
+ return NS_ERROR_NULL_POINTER;
+ }
+ *aEnumerator = nsnull;
+
+ nsresult rv;
+
+ PLDHashTableEnumeratorImpl *aEnum;
+ rv = PL_NewDHashTableEnumerator(&mFactories,
+ ConvertFactoryEntryToCID,
+ (void*)this,
+ &aEnum);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aEnumerator = NS_STATIC_CAST(nsIEnumerator*, aEnum);
+ return NS_OK;
+}
+
+nsresult
+nsComponentManagerImpl::EnumerateContractIDs(nsIEnumerator** aEnumerator)
+{
+ NS_ASSERTION(aEnumerator != nsnull, "null ptr");
+ if (!aEnumerator)
+ {
+ return NS_ERROR_NULL_POINTER;
+ }
+
+ *aEnumerator = nsnull;
+
+ nsresult rv;
+ PLDHashTableEnumeratorImpl *aEnum;
+ rv = PL_NewDHashTableEnumerator(&mContractIDs,
+ ConvertContractIDKeyToString,
+ (void*)this,
+ &aEnum);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aEnumerator = NS_STATIC_CAST(nsIEnumerator*, aEnum);
+ return NS_OK;
+}
+
+// nsIComponentRegistrar
+
+NS_IMETHODIMP
+nsComponentManagerImpl::AutoRegister(nsIFile *aSpec)
+{
+ if (aSpec == nsnull)
+ return AutoRegisterImpl(0, aSpec);
+
+ PRBool directory;
+ aSpec->IsDirectory(&directory);
+
+ if (directory)
+ return AutoRegisterImpl(0, aSpec, PR_FALSE);
+
+ return AutoRegisterComponent(0, aSpec);
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::AutoUnregister(nsIFile *aSpec)
+{
+ // unregistering a complete directory is not implmeneted yet...FIX
+ if (aSpec == nsnull)
+ return NS_ERROR_NOT_IMPLEMENTED;
+
+ PRBool directory;
+ aSpec->IsDirectory(&directory);
+
+ if (directory)
+ return NS_ERROR_NOT_IMPLEMENTED;
+
+ return AutoUnregisterComponent(0, aSpec);
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::RegisterFactory(const nsCID & aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFactory *aFactory)
+{
+ return RegisterFactory(aClass,
+ aClassName,
+ aContractID,
+ aFactory,
+ PR_TRUE);
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::RegisterFactoryLocation(const nsCID & aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFile *aFile,
+ const char *loaderStr,
+ const char *aType)
+{
+ nsXPIDLCString registryName;
+
+ if (!loaderStr)
+ {
+ nsresult rv = RegistryLocationForSpec(aFile, getter_Copies(registryName));
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ nsresult rv;
+ rv = RegisterComponentWithType(aClass,
+ aClassName,
+ aContractID,
+ aFile,
+ (loaderStr ? loaderStr : registryName.get()),
+ PR_TRUE,
+ PR_TRUE,
+ (aType ? aType : nativeComponentType));
+ return rv;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::UnregisterFactoryLocation(const nsCID & aClass,
+ nsIFile *aFile)
+{
+ return UnregisterComponentSpec(aClass, aFile);
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::IsCIDRegistered(const nsCID & aClass,
+ PRBool *_retval)
+{
+ return IsRegistered(aClass, _retval);
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::IsContractIDRegistered(const char *aClass,
+ PRBool *_retval)
+{
+ nsFactoryEntry *entry = GetFactoryEntry(aClass, strlen(aClass));
+
+ if (entry)
+ *_retval = PR_TRUE;
+ else
+ *_retval = PR_FALSE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::EnumerateCIDs(nsISimpleEnumerator **aEnumerator)
+{
+ NS_ASSERTION(aEnumerator != nsnull, "null ptr");
+
+ if (!aEnumerator)
+ return NS_ERROR_NULL_POINTER;
+
+ *aEnumerator = nsnull;
+
+ nsresult rv;
+ PLDHashTableEnumeratorImpl *aEnum;
+ rv = PL_NewDHashTableEnumerator(&mFactories,
+ ConvertFactoryEntryToCID,
+ (void*)this,
+ &aEnum);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aEnumerator = NS_STATIC_CAST(nsISimpleEnumerator*, aEnum);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::EnumerateContractIDs(nsISimpleEnumerator **aEnumerator)
+{
+ NS_ASSERTION(aEnumerator != nsnull, "null ptr");
+ if (!aEnumerator)
+ return NS_ERROR_NULL_POINTER;
+
+ *aEnumerator = nsnull;
+
+ nsresult rv;
+ PLDHashTableEnumeratorImpl *aEnum;
+ rv = PL_NewDHashTableEnumerator(&mContractIDs,
+ ConvertContractIDKeyToString,
+ (void*)this,
+ &aEnum);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aEnumerator = NS_STATIC_CAST(nsISimpleEnumerator*, aEnum);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::CIDToContractID(const nsCID & aClass,
+ char **_retval)
+{
+ return CLSIDToContractID(aClass,
+ nsnull,
+ _retval);
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::ContractIDToCID(const char *aContractID,
+ nsCID * *_retval)
+{
+ *_retval = (nsCID*) nsMemory::Alloc(sizeof(nsCID));
+ if (!*_retval)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = ContractIDToClassID(aContractID, *_retval);
+ if (NS_FAILED(rv)) {
+ nsMemory::Free(*_retval);
+ *_retval = nsnull;
+ }
+ return rv;
+}
+
+// end nsIComponentRegistrar
+
+
+
+
+NS_IMETHODIMP
+nsComponentManagerImpl::HasFileChanged(nsIFile *file, const char *loaderString, PRInt64 modDate, PRBool *_retval)
+{
+ *_retval = PR_TRUE;
+
+ nsXPIDLCString registryName;
+ nsresult rv = RegistryLocationForSpec(file, getter_Copies(registryName));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCStringKey key(registryName);
+ AutoRegEntry* entry = (AutoRegEntry*)mAutoRegEntries.Get(&key);
+ if (entry)
+ *_retval = entry->Modified(&modDate);
+ else
+ *_retval = PR_TRUE;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::SaveFileInfo(nsIFile *file, const char *loaderString, PRInt64 modDate)
+{
+ mRegistryDirty = PR_TRUE;
+ nsXPIDLCString registryName;
+ nsresult rv = RegistryLocationForSpec(file, getter_Copies(registryName));
+ if (NS_FAILED(rv))
+ return rv;
+
+ // check to see if exists in the array before adding it so that we don't have dups.
+ nsCStringKey key(registryName);
+ AutoRegEntry* entry = (AutoRegEntry*)mAutoRegEntries.Get(&key);
+
+ if (entry)
+ {
+ entry->SetDate(&modDate);
+ return NS_OK;
+ }
+
+ entry = new AutoRegEntry(registryName, &modDate);
+ if (!entry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ mAutoRegEntries.Put(&key, entry);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::RemoveFileInfo(nsIFile *file, const char *loaderString)
+{
+ mRegistryDirty = PR_TRUE;
+ nsXPIDLCString registryName;
+ nsresult rv = RegistryLocationForSpec(file, getter_Copies(registryName));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCStringKey key(registryName);
+ AutoRegEntry* entry = (AutoRegEntry*)mAutoRegEntries.Remove(&key);
+ if (entry)
+ delete entry;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsComponentManagerImpl::GetOptionalData(nsIFile *file,
+ const char *loaderString,
+ char **_retval)
+{
+ nsXPIDLCString registryName;
+ nsresult rv = RegistryLocationForSpec(file, getter_Copies(registryName));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCStringKey key(registryName);
+ AutoRegEntry* entry = (AutoRegEntry*)mAutoRegEntries.Get(&key);
+ if (!entry) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+ const char* opData = entry->GetOptionalData();
+
+ if (opData)
+ *_retval = ToNewCString(nsDependentCString(opData));
+ else
+ *_retval = nsnull;
+ return NS_OK;
+ }
+
+NS_IMETHODIMP
+nsComponentManagerImpl::SetOptionalData(nsIFile *file,
+ const char *loaderString,
+ const char *data)
+{
+ nsXPIDLCString registryName;
+ nsresult rv = RegistryLocationForSpec(file, getter_Copies(registryName));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCStringKey key(registryName);
+ AutoRegEntry* entry = (AutoRegEntry*)mAutoRegEntries.Get(&key);
+
+ if (!entry) {
+ PRInt64 zero = LL_Zero();
+ entry = new AutoRegEntry(registryName, &zero);
+ if (!entry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ mAutoRegEntries.Put(&key, entry);
+ }
+
+ entry->SetOptionalData(data);
+
+ return NS_OK;
+ }
+
+
+NS_IMETHODIMP
+nsComponentManagerImpl::FlushPersistentStore(PRBool now)
+{
+ mRegistryDirty = PR_TRUE;
+ if (now)
+ return WritePersistentRegistry();
+
+ return NS_OK;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Static Access Functions
+////////////////////////////////////////////////////////////////////////////////
+
+NS_COM nsresult
+NS_GetGlobalComponentManager(nsIComponentManager* *result)
+{
+#ifdef DEBUG_dougt
+ // NS_WARNING("DEPRECATED FUNCTION: Use NS_GetComponentManager");
+#endif
+ nsresult rv = NS_OK;
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ {
+ // XPCOM needs initialization.
+ rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
+ }
+
+ if (NS_SUCCEEDED(rv))
+ {
+ // NO ADDREF since this is never intended to be released.
+ // See nsComponentManagerObsolete.h for the reason for such
+ // casting uglyness
+ *result = (nsIComponentManager*)(void*)(nsIComponentManagerObsolete*) nsComponentManagerImpl::gComponentManager;
+ }
+
+ return rv;
+}
+
+NS_COM nsresult
+NS_GetComponentManager(nsIComponentManager* *result)
+{
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ {
+ // XPCOM needs initialization.
+ nsresult rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ *result = NS_STATIC_CAST(nsIComponentManager*,
+ nsComponentManagerImpl::gComponentManager);
+ NS_IF_ADDREF(*result);
+ return NS_OK;
+}
+
+NS_COM nsresult
+NS_GetServiceManager(nsIServiceManager* *result)
+{
+ nsresult rv = NS_OK;
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ {
+#ifdef VBOX
+ // While XPCOM might need initialization, we're not in a position
+ // to pass the right values to this call. This is actually triggered
+ // on object destruction, so there is no point in re-initializing,
+ // and actually the attempt would lead to nested calls to
+ // xptiInterfaceInfoManager::BuildFileSearchPath, which it detects
+ // as unsafe in debug builds. Just fail, no real problem.
+#ifdef DEBUG
+ printf("NS_GetServiceManager: no current instance, suppressed XPCOM initialization!\n");
+#endif
+ rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
+#else /* !VBOX */
+ // XPCOM needs initialization.
+ rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
+#endif /* !VBOX */
+ }
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ *result = NS_STATIC_CAST(nsIServiceManager*,
+ nsComponentManagerImpl::gComponentManager);
+ NS_IF_ADDREF(*result);
+ return NS_OK;
+}
+
+
+NS_COM nsresult
+NS_GetComponentRegistrar(nsIComponentRegistrar* *result)
+{
+ nsresult rv = NS_OK;
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ {
+ // XPCOM needs initialization.
+ rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
+ }
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ *result = NS_STATIC_CAST(nsIComponentRegistrar*,
+ nsComponentManagerImpl::gComponentManager);
+ NS_IF_ADDREF(*result);
+ return NS_OK;
+}
+
+
+// nsIComponentLoaderManager is not frozen, but is defined here
+// so that I can use it internally in xpcom.
+nsresult
+NS_GetComponentLoaderManager(nsIComponentLoaderManager* *result)
+{
+ nsresult rv = NS_OK;
+
+ if (nsComponentManagerImpl::gComponentManager == NULL)
+ {
+ // XPCOM needs initialization.
+ rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
+ }
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ *result = NS_STATIC_CAST(nsIComponentLoaderManager*,
+ nsComponentManagerImpl::gComponentManager);
+ NS_IF_ADDREF(*result);
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/components/nsComponentManager.h b/src/libs/xpcom18a4/xpcom/components/nsComponentManager.h
new file mode 100644
index 00000000..df128125
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsComponentManager.h
@@ -0,0 +1,339 @@
+/* -*- 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 ***** */
+
+#ifndef nsComponentManager_h__
+#define nsComponentManager_h__
+
+#include "nsXPCOM.h"
+
+#include "nsIComponentLoader.h"
+#include "xpcom-private.h"
+#include "nsNativeComponentLoader.h"
+#include "nsIComponentManager.h"
+#include "nsIComponentRegistrar.h"
+#include "nsIComponentManagerObsolete.h"
+#include "nsIComponentLoaderManager.h"
+#include "nsCategoryManager.h"
+#include "nsIServiceManager.h"
+#include "nsIFactory.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include "pldhash.h"
+#include "prtime.h"
+#include "prmon.h"
+#include "nsCOMPtr.h"
+#include "nsWeakReference.h"
+#include "nsXPIDLString.h"
+#include "nsIFile.h"
+#include "plarena.h"
+
+class nsFactoryEntry;
+class nsDll;
+class nsIServiceManager;
+
+
+// Predefined loader types. Do not change the numbers.
+// NATIVE should be 0 as it is being used as the first array index.
+#define NS_COMPONENT_TYPE_NATIVE 0
+#define NS_COMPONENT_TYPE_FACTORY_ONLY -1
+// this define means that the factory entry only has a ContractID
+// to service mapping and has no cid mapping.
+#define NS_COMPONENT_TYPE_SERVICE_ONLY -2
+
+
+#ifdef DEBUG
+#define XPCOM_CHECK_PENDING_CIDS
+#endif
+////////////////////////////////////////////////////////////////////////////////
+
+// Array of Loaders and their type strings
+struct nsLoaderdata {
+ nsIComponentLoader *loader;
+ const char *type;
+};
+
+class nsComponentManagerImpl
+ : public nsIComponentManager,
+ public nsIServiceManager,
+ public nsIComponentRegistrar,
+ public nsSupportsWeakReference,
+ public nsIInterfaceRequestor,
+ public nsIComponentLoaderManager,
+ public nsIServiceManagerObsolete,
+ public nsIComponentManagerObsolete
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIINTERFACEREQUESTOR
+ // Since the nsIComponentManagerObsolete and nsIComponentManager share some of the
+ // same interface function names, we have to manually define the functions here.
+ // The only function that is in nsIComponentManagerObsolete and is in nsIComponentManager
+ // is GetClassObjectContractID.
+ //
+ // nsIComponentManager function not in nsIComponentManagerObsolete:
+ NS_IMETHOD GetClassObjectByContractID(const char *aContractID,
+ const nsIID &aIID,
+ void **_retval);
+
+
+ NS_DECL_NSICOMPONENTMANAGEROBSOLETE
+
+ // Since the nsIComponentManagerObsolete and nsIComponentRegistrar share some of the
+ // same interface function names, we have to manually define the functions here.
+ // the only function that is shared is UnregisterFactory
+ NS_IMETHOD AutoRegister(nsIFile *aSpec);
+ NS_IMETHOD AutoUnregister(nsIFile *aSpec);
+ NS_IMETHOD RegisterFactory(const nsCID & aClass, const char *aClassName, const char *aContractID, nsIFactory *aFactory);
+ // NS_IMETHOD UnregisterFactory(const nsCID & aClass, nsIFactory *aFactory);
+ NS_IMETHOD RegisterFactoryLocation(const nsCID & aClass, const char *aClassName, const char *aContractID, nsIFile *aFile, const char *loaderStr, const char *aType);
+ NS_IMETHOD UnregisterFactoryLocation(const nsCID & aClass, nsIFile *aFile);
+ NS_IMETHOD IsCIDRegistered(const nsCID & aClass, PRBool *_retval);
+ NS_IMETHOD IsContractIDRegistered(const char *aClass, PRBool *_retval);
+ NS_IMETHOD EnumerateCIDs(nsISimpleEnumerator **_retval);
+ NS_IMETHOD EnumerateContractIDs(nsISimpleEnumerator **_retval);
+ NS_IMETHOD CIDToContractID(const nsCID & aClass, char **_retval);
+ NS_IMETHOD ContractIDToCID(const char *aContractID, nsCID * *_retval);
+
+ NS_DECL_NSISERVICEMANAGER
+ NS_DECL_NSISERVICEMANAGEROBSOLETE
+ NS_DECL_NSICOMPONENTLOADERMANAGER
+
+ // nsComponentManagerImpl methods:
+ nsComponentManagerImpl();
+
+ static nsComponentManagerImpl* gComponentManager;
+ nsresult Init(void);
+
+ nsresult WritePersistentRegistry();
+ nsresult ReadPersistentRegistry();
+
+ nsresult Shutdown(void);
+
+ nsresult FreeServices();
+
+ nsresult
+ NS_GetService(const char *aContractID, const nsIID& aIID, PRBool aDontCreate, nsISupports** result);
+
+ nsresult RegisterComponentCommon(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ PRUint32 aContractIDLen,
+ const char *aRegistryName,
+ PRUint32 aRegistryNameLen,
+ PRBool aReplace, PRBool aPersist,
+ const char *aType);
+ nsresult GetLoaderForType(int aType,
+ nsIComponentLoader **aLoader);
+ nsresult FindFactory(const char *contractID, PRUint32 aContractIDLen, nsIFactory **aFactory) ;
+ nsresult LoadFactory(nsFactoryEntry *aEntry, nsIFactory **aFactory);
+
+ nsFactoryEntry *GetFactoryEntry(const char *aContractID,
+ PRUint32 aContractIDLen);
+ nsFactoryEntry *GetFactoryEntry(const nsCID &aClass);
+
+ nsresult SyncComponentsInDir(PRInt32 when, nsIFile *dirSpec);
+ nsresult SelfRegisterDll(nsDll *dll);
+ nsresult SelfUnregisterDll(nsDll *dll);
+ nsresult HashContractID(const char *acontractID, PRUint32 aContractIDLen,
+ nsFactoryEntry *fe_ptr);
+
+ void DeleteContractIDEntriesByCID(const nsCID* aClass, const char*registryName);
+ void DeleteContractIDEntriesByCID(const nsCID* aClass, nsIFactory* factory);
+
+ nsresult UnloadLibraries(nsIServiceManager *servmgr, PRInt32 when);
+
+ // Convert a loader type string into an index into the loader data
+ // array. Empty loader types are converted to NATIVE. Returns -1 if
+ // loader type cannot be determined.
+ int GetLoaderType(const char *typeStr);
+
+ // Add a loader type if not already known. Out the typeIndex
+ // if the loader type is either added or already there;
+ // returns NS_OK or an error on failure.
+ nsresult AddLoaderType(const char *typeStr, int *typeIndex);
+
+ int GetLoaderCount() { return mNLoaderData + 1; }
+
+ // registers only the files in spec's location by loaders other than the
+ // native loader. This is an optimization method only.
+ nsresult AutoRegisterNonNativeComponents(nsIFile* spec);
+
+ nsresult AutoRegisterImpl(PRInt32 when, nsIFile *inDirSpec, PRBool fileIsCompDir=PR_TRUE);
+ nsresult RemoveEntries(nsIFile* file);
+
+ PLDHashTable mFactories;
+ PLDHashTable mContractIDs;
+ PRMonitor* mMon;
+
+ nsNativeComponentLoader *mNativeComponentLoader;
+#ifdef ENABLE_STATIC_COMPONENT_LOADER
+ nsIComponentLoader *mStaticComponentLoader;
+#endif
+ nsCOMPtr<nsIFile> mComponentsDir;
+ PRInt32 mComponentsOffset;
+
+ nsCOMPtr<nsIFile> mGREComponentsDir;
+ PRInt32 mGREComponentsOffset;
+
+ nsCOMPtr<nsIFile> mRegistryFile;
+
+ // Shutdown
+ #define NS_SHUTDOWN_NEVERHAPPENED 0
+ #define NS_SHUTDOWN_INPROGRESS 1
+ #define NS_SHUTDOWN_COMPLETE 2
+ PRUint32 mShuttingDown;
+
+ nsLoaderdata *mLoaderData;
+ int mNLoaderData;
+ int mMaxNLoaderData;
+
+ PRBool mRegistryDirty;
+ nsHashtable mAutoRegEntries;
+ nsCOMPtr<nsCategoryManager> mCategoryManager;
+
+ PLArenaPool mArena;
+
+#ifdef XPCOM_CHECK_PENDING_CIDS
+ nsresult AddPendingCID(const nsCID &aClass);
+ void RemovePendingCID(const nsCID &aClass);
+
+ nsVoidArray mPendingCIDs;
+#endif
+
+private:
+ ~nsComponentManagerImpl();
+};
+
+
+#define NS_MAX_FILENAME_LEN 1024
+
+#define NS_ERROR_IS_DIR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 24)
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Class: nsFactoryEntry()
+ *
+ * There are two types of FactoryEntries.
+ *
+ * 1. {CID, dll} mapping.
+ * Factory is a consequence of the dll. These can be either session
+ * specific or persistent based on whether we write this
+ * to the registry or not.
+ *
+ * 2. {CID, factory} mapping
+ * These are strictly session specific and in memory only.
+ */
+
+class nsFactoryEntry {
+public:
+ nsFactoryEntry(const nsCID &aClass,
+ const char *location, PRUint32 locationlen, int aType, class nsFactoryEntry* parent = nsnull);
+ nsFactoryEntry(const nsCID &aClass, nsIFactory *aFactory, class nsFactoryEntry* parent = nsnull);
+ ~nsFactoryEntry();
+
+ nsresult ReInit(const nsCID &aClass, const char *location, int aType);
+
+ nsresult GetFactory(nsIFactory **aFactory,
+ nsComponentManagerImpl * mgr) {
+ if (mFactory) {
+ *aFactory = mFactory.get();
+ NS_ADDREF(*aFactory);
+ return NS_OK;
+ }
+
+ if (mTypeIndex < 0)
+ return NS_ERROR_FAILURE;
+
+ nsresult rv;
+ nsCOMPtr<nsIComponentLoader> loader;
+ rv = mgr->GetLoaderForType(mTypeIndex, getter_AddRefs(loader));
+ if(NS_FAILED(rv))
+ return rv;
+
+ rv = loader->GetFactory(mCid, mLocation, mgr->mLoaderData[mTypeIndex].type, aFactory);
+ if (NS_SUCCEEDED(rv))
+ mFactory = do_QueryInterface(*aFactory);
+ return rv;
+ }
+
+ nsCID mCid;
+ nsCOMPtr<nsIFactory> mFactory;
+ // This is an index into the mLoaderData array that holds the type string and the loader
+ int mTypeIndex;
+ nsCOMPtr<nsISupports> mServiceObject;
+ char* mLocation;
+ class nsFactoryEntry* mParent;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct nsFactoryTableEntry : public PLDHashEntryHdr {
+ nsFactoryEntry *mFactoryEntry;
+};
+
+struct nsContractIDTableEntry : public PLDHashEntryHdr {
+ char *mContractID;
+ PRUint32 mContractIDLen;
+ nsFactoryEntry *mFactoryEntry;
+};
+
+
+class AutoRegEntry
+{
+public:
+ AutoRegEntry(const nsACString& name, PRInt64* modDate);
+ ~AutoRegEntry();
+
+ const nsDependentCString GetName()
+ { return nsDependentCString(mName, mNameLen); }
+ PRInt64 GetDate() {return mModDate;}
+ void SetDate(PRInt64 *date) { mModDate = *date;}
+ PRBool Modified(PRInt64 *date);
+
+ // this is the optional field line in the compreg.dat.
+ // it must not contain any comma's and it must be null terminated.
+ char* GetOptionalData() {return mData;};
+ void SetOptionalData(const char* data);
+
+private:
+ char* mName;
+ PRUint32 mNameLen;
+ char* mData;
+ PRInt64 mModDate;
+};
+#endif // nsComponentManager_h__
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsComponentManagerObsolete.cpp b/src/libs/xpcom18a4/xpcom/components/nsComponentManagerObsolete.cpp
new file mode 100644
index 00000000..fca77cf7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsComponentManagerObsolete.cpp
@@ -0,0 +1,271 @@
+
+/* ***** 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.
+ *
+ * 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 ***** */
+
+////////////////////////////////////////////////////////////////////////////////
+// Global Static Component Manager Methods
+// (for when you need to link with xpcom)
+
+#include "nsIComponentManagerObsolete.h"
+#include "nsComponentManagerObsolete.h"
+
+
+nsresult
+nsComponentManager::Initialize(void)
+{
+ return NS_OK;
+}
+
+nsresult
+nsComponentManager::FindFactory(const nsCID &aClass,
+ nsIFactory **aFactory)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->FindFactory(aClass, aFactory);
+}
+
+nsresult
+nsComponentManager::GetClassObject(const nsCID &aClass, const nsIID &aIID,
+ void **aResult)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->GetClassObject(aClass, aIID, aResult);
+}
+
+nsresult
+nsComponentManager::ContractIDToClassID(const char *aContractID,
+ nsCID *aClass)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->ContractIDToClassID(aContractID, aClass);
+}
+
+nsresult
+nsComponentManager::CLSIDToContractID(nsCID *aClass,
+ char* *aClassName,
+ char* *aContractID)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->CLSIDToContractID(*aClass, aClassName, aContractID);
+}
+
+nsresult
+nsComponentManager::CreateInstance(const nsCID &aClass,
+ nsISupports *aDelegate,
+ const nsIID &aIID,
+ void **aResult)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->CreateInstance(aClass, aDelegate, aIID, aResult);
+}
+
+nsresult
+nsComponentManager::CreateInstance(const char *aContractID,
+ nsISupports *aDelegate,
+ const nsIID &aIID,
+ void **aResult)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->CreateInstanceByContractID(aContractID, aDelegate, aIID, aResult);
+}
+
+nsresult
+nsComponentManager::RegisterFactory(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFactory *aFactory,
+ PRBool aReplace)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->RegisterFactory(aClass, aClassName, aContractID,
+ aFactory, aReplace);
+}
+
+nsresult
+nsComponentManager::RegisterComponent(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ const char *aLibraryPersistentDescriptor,
+ PRBool aReplace,
+ PRBool aPersist)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->RegisterComponent(aClass, aClassName, aContractID,
+ aLibraryPersistentDescriptor, aReplace, aPersist);
+}
+
+nsresult
+nsComponentManager::RegisterComponentSpec(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFile *aLibrary,
+ PRBool aReplace,
+ PRBool aPersist)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->RegisterComponentSpec(aClass, aClassName, aContractID,
+ aLibrary, aReplace, aPersist);
+}
+
+nsresult
+nsComponentManager::RegisterComponentLib(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ const char *adllName,
+ PRBool aReplace,
+ PRBool aPersist)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->RegisterComponentLib(aClass, aClassName, aContractID,
+ adllName, aReplace, aPersist);
+}
+
+nsresult
+nsComponentManager::UnregisterFactory(const nsCID &aClass,
+ nsIFactory *aFactory)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->UnregisterFactory(aClass, aFactory);
+}
+
+nsresult
+nsComponentManager::UnregisterComponent(const nsCID &aClass,
+ const char *aLibrary)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->UnregisterComponent(aClass, aLibrary);
+}
+
+nsresult
+nsComponentManager::UnregisterComponentSpec(const nsCID &aClass,
+ nsIFile *aLibrarySpec)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->UnregisterComponentSpec(aClass, aLibrarySpec);
+}
+
+nsresult
+nsComponentManager::FreeLibraries(void)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->FreeLibraries();
+}
+
+nsresult
+nsComponentManager::AutoRegister(PRInt32 when, nsIFile *directory)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->AutoRegister(when, directory);
+}
+
+nsresult
+nsComponentManager::AutoRegisterComponent(PRInt32 when,
+ nsIFile *fullname)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->AutoRegisterComponent(when, fullname);
+}
+
+nsresult
+nsComponentManager::AutoUnregisterComponent(PRInt32 when,
+ nsIFile *fullname)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->AutoUnregisterComponent(when, fullname);
+}
+
+nsresult
+nsComponentManager::IsRegistered(const nsCID &aClass,
+ PRBool *aRegistered)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->IsRegistered(aClass, aRegistered);
+}
+
+nsresult
+nsComponentManager::EnumerateCLSIDs(nsIEnumerator** aEnumerator)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->EnumerateCLSIDs(aEnumerator);
+}
+
+nsresult
+nsComponentManager::EnumerateContractIDs(nsIEnumerator** aEnumerator)
+{
+ nsIComponentManagerObsolete* cm;
+ nsresult rv = NS_GetGlobalComponentManager((nsIComponentManager**)&cm);
+ if (NS_FAILED(rv)) return rv;
+ return cm->EnumerateContractIDs(aEnumerator);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsComponentManagerObsolete.h b/src/libs/xpcom18a4/xpcom/components/nsComponentManagerObsolete.h
new file mode 100644
index 00000000..dfcde87a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsComponentManagerObsolete.h
@@ -0,0 +1,185 @@
+/* -*- 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 XPCOM.
+ *
+ * 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 nsComponentManagerObsolete_h___
+#define nsComponentManagerObsolete_h___
+
+#include "nsIComponentManager.h"
+#include "nsIComponentManagerObsolete.h"
+
+class nsIEnumerator;
+class nsIFactory;
+class nsIFile;
+////////////////////////////////////////////////////////////////////
+//
+// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+//
+// Functions, classes, interfaces and types in this file are
+// obsolete. Use at your own risk.
+// Please see nsIComponentManager.idl for the supported interface
+// to the component manager.
+//
+////////////////////////////////////////////////////////////////////
+
+
+
+////////////////////////////////////////////////////////////////////
+// God save me from this evilness. Below is a very bad
+// function. Its out var is really a nsIComponentManagerObsolete
+// but it has been cast to a nsIComponentManager.
+// The reason for such uglyness is that this function is require for
+// backward compatiblity of some plugins. This funciton will
+// be removed at some point.
+////////////////////////////////////////////////////////////////////
+
+extern NS_COM nsresult
+NS_GetGlobalComponentManager(nsIComponentManager* *result);
+
+
+
+
+class NS_COM nsComponentManager {
+public:
+ static nsresult Initialize(void);
+
+ // Finds a factory for a specific class ID
+ static nsresult FindFactory(const nsCID &aClass,
+ nsIFactory **aFactory);
+
+ // Get the singleton class object that implements the CID aClass
+ static nsresult GetClassObject(const nsCID &aClass, const nsIID &aIID,
+ void **aResult);
+
+ // Finds a class ID for a specific Program ID
+ static nsresult ContractIDToClassID(const char *aContractID,
+ nsCID *aClass);
+
+ // Finds a Program ID for a specific class ID
+ // caller frees the result with delete[]
+ static nsresult CLSIDToContractID(nsCID *aClass,
+ char* *aClassName,
+ char* *aContractID);
+
+ // Creates a class instance for a specific class ID
+ static nsresult CreateInstance(const nsCID &aClass,
+ nsISupports *aDelegate,
+ const nsIID &aIID,
+ void **aResult);
+
+ // Convenience routine, creates a class instance for a specific ContractID
+ static nsresult CreateInstance(const char *aContractID,
+ nsISupports *aDelegate,
+ const nsIID &aIID,
+ void **aResult);
+
+ // Manually registry a factory for a class
+ static nsresult RegisterFactory(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFactory *aFactory,
+ PRBool aReplace);
+
+ // Manually register a dynamically loaded component.
+ // The libraryPersistentDescriptor is what gets passed to the library
+ // self register function from ComponentManager. The format of this string
+ // is the same as nsIFile::GetPath()
+ //
+ // This function will go away in favour of RegisterComponentSpec. In fact,
+ // it internally turns around and calls RegisterComponentSpec.
+ static nsresult RegisterComponent(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ const char *aLibraryPersistentDescriptor,
+ PRBool aReplace,
+ PRBool aPersist);
+
+ // Register a component using its FileSpec as its identification
+ // This is the more prevalent use.
+ static nsresult RegisterComponentSpec(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFile *aLibrary,
+ PRBool aReplace,
+ PRBool aPersist);
+
+ // Register a component using its dllName. This could be a dll name with
+ // no path so that LD_LIBRARY_PATH on unix or PATH on win can load it. Or
+ // this could be a code fragment name on the Mac.
+ static nsresult RegisterComponentLib(const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ const char *adllName,
+ PRBool aReplace,
+ PRBool aPersist);
+
+
+ // Manually unregister a factory for a class
+ static nsresult UnregisterFactory(const nsCID &aClass,
+ nsIFactory *aFactory);
+
+ // Manually unregister a dynamically loaded component
+ static nsresult UnregisterComponent(const nsCID &aClass,
+ const char *aLibrary);
+
+ // Manually unregister a dynamically loaded component
+ static nsresult UnregisterComponentSpec(const nsCID &aClass,
+ nsIFile *aLibrarySpec);
+
+ // Unload dynamically loaded factories that are not in use
+ static nsresult FreeLibraries(void);
+ //////////////////////////////////////////////////////////////////////////////
+ // DLL registration support
+
+ // If directory is NULL, then AutoRegister will try registering components
+ // in the default components directory.
+ static nsresult AutoRegister(PRInt32 when, nsIFile* directory);
+ static nsresult AutoRegisterComponent(PRInt32 when, nsIFile *component);
+ static nsresult AutoUnregisterComponent(PRInt32 when, nsIFile *component);
+
+ // Is the given CID currently registered?
+ static nsresult IsRegistered(const nsCID &aClass,
+ PRBool *aRegistered);
+
+ // Get an enumeration of all the CIDs
+ static nsresult EnumerateCLSIDs(nsIEnumerator** aEmumerator);
+
+ // Get an enumeration of all the ContractIDs
+ static nsresult EnumerateContractIDs(nsIEnumerator** aEmumerator);
+
+};
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/components/nsComponentManagerUtils.h b/src/libs/xpcom18a4/xpcom/components/nsComponentManagerUtils.h
new file mode 100644
index 00000000..cda56416
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsComponentManagerUtils.h
@@ -0,0 +1,196 @@
+/* -*- 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 nsComponentManagerUtils_h__
+#define nsComponentManagerUtils_h__
+
+/*
+ * Do not include this file directly. Instead,
+ * |#include "nsIComponentManager.h"|.
+ */
+
+#ifndef nsCOMPtr_h__
+#include "nsCOMPtr.h"
+#endif
+
+#ifndef nsComponentManagerObsolete_h___
+#include "nsComponentManagerObsolete.h"
+#endif
+
+#define NS_COMPONENTMANAGER_CID \
+{ /* 91775d60-d5dc-11d2-92fb-00e09805570f */ \
+ 0x91775d60, \
+ 0xd5dc, \
+ 0x11d2, \
+ {0x92, 0xfb, 0x00, 0xe0, 0x98, 0x05, 0x57, 0x0f} \
+}
+
+class NS_COM nsCreateInstanceByCID : public nsCOMPtr_helper
+{
+public:
+ nsCreateInstanceByCID( const nsCID& aCID, nsISupports* aOuter, nsresult* aErrorPtr )
+ : mCID(aCID),
+ mOuter(aOuter),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do here
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+
+private:
+ const nsCID& mCID;
+ nsISupports* mOuter;
+ nsresult* mErrorPtr;
+};
+
+class NS_COM nsCreateInstanceByContractID : public nsCOMPtr_helper
+{
+public:
+ nsCreateInstanceByContractID( const char* aContractID, nsISupports* aOuter, nsresult* aErrorPtr )
+ : mContractID(aContractID),
+ mOuter(aOuter),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do here
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+
+private:
+ const char* mContractID;
+ nsISupports* mOuter;
+ nsresult* mErrorPtr;
+};
+
+inline
+const nsCreateInstanceByCID
+do_CreateInstance( const nsCID& aCID, nsresult* error = 0 )
+{
+ return nsCreateInstanceByCID(aCID, 0, error);
+}
+
+inline
+const nsCreateInstanceByCID
+do_CreateInstance( const nsCID& aCID, nsISupports* aOuter, nsresult* error = 0 )
+{
+ return nsCreateInstanceByCID(aCID, aOuter, error);
+}
+
+inline
+const nsCreateInstanceByContractID
+do_CreateInstance( const char* aContractID, nsresult* error = 0 )
+{
+ return nsCreateInstanceByContractID(aContractID, 0, error);
+}
+
+inline
+const nsCreateInstanceByContractID
+do_CreateInstance( const char* aContractID, nsISupports* aOuter, nsresult* error = 0 )
+{
+ return nsCreateInstanceByContractID(aContractID, aOuter, error);
+}
+
+// type-safe shortcuts for calling |CreateInstance|
+template <class DestinationType>
+inline
+nsresult
+CallCreateInstance( const nsCID &aClass,
+ nsISupports *aDelegate,
+ DestinationType** aDestination )
+{
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ return nsComponentManager::CreateInstance(aClass, aDelegate,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+}
+
+template <class DestinationType>
+inline
+nsresult
+CallCreateInstance( const nsCID &aClass,
+ DestinationType** aDestination )
+{
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ return nsComponentManager::CreateInstance(aClass, nsnull,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+}
+
+template <class DestinationType>
+inline
+nsresult
+CallCreateInstance( const char *aContractID,
+ nsISupports *aDelegate,
+ DestinationType** aDestination )
+{
+ NS_PRECONDITION(aContractID, "null parameter");
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ return nsComponentManager::CreateInstance(aContractID,
+ aDelegate,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+}
+
+template <class DestinationType>
+inline
+nsresult
+CallCreateInstance( const char *aContractID,
+ DestinationType** aDestination )
+{
+ NS_PRECONDITION(aContractID, "null parameter");
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ return nsComponentManager::CreateInstance(aContractID, nsnull,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+}
+
+/* keys for registry use */
+extern const char xpcomKeyName[];
+extern const char xpcomComponentsKeyName[];
+extern const char lastModValueName[];
+extern const char fileSizeValueName[];
+extern const char nativeComponentType[];
+extern const char staticComponentType[];
+
+#endif /* nsComponentManagerUtils_h__ */
+
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsICategoryManager.idl b/src/libs/xpcom18a4/xpcom/components/nsICategoryManager.idl
new file mode 100644
index 00000000..509f7870
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsICategoryManager.idl
@@ -0,0 +1,101 @@
+/* -*- 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 "nsISimpleEnumerator.idl"
+
+/*
+ * nsICategoryManager
+ * @status FROZEN
+ */
+
+[scriptable, uuid(3275b2cd-af6d-429a-80d7-f0c5120342ac)]
+interface nsICategoryManager : nsISupports
+{
+ /**
+ * Get the value for the given category's entry.
+ * @param aCategory The name of the category ("protocol")
+ * @param aEntry The entry you're looking for ("http")
+ * @return The value.
+ */
+ string getCategoryEntry(in string aCategory, in string aEntry);
+
+ /**
+ * Add an entry to a category.
+ * @param aCategory The name of the category ("protocol")
+ * @param aEntry The entry to be added ("http")
+ * @param aValue The value for the entry ("moz.httprulez.1")
+ * @param aPersist Should this data persist between invocations?
+ * @param aReplace Should we replace an existing entry?
+ * @return Previous entry, if any
+ */
+ string addCategoryEntry(in string aCategory, in string aEntry,
+ in string aValue, in boolean aPersist,
+ in boolean aReplace);
+
+ /**
+ * Delete an entry from the category.
+ * @param aCategory The name of the category ("protocol")
+ * @param aEntry The entry to be added ("http")
+ * @param aPersist Delete persistent data from registry, if present?
+ */
+ void deleteCategoryEntry(in string aCategory, in string aEntry,
+ in boolean aPersist);
+
+ /**
+ * Delete a category and all entries.
+ * @param aCategory The category to be deleted.
+ */
+ void deleteCategory(in string aCategory);
+
+ /**
+ * Enumerate the entries in a category.
+ * @param aCategory The category to be enumerated.
+ * @return a simple enumerator, each result QIs to
+ * nsISupportsCString.
+ */
+ nsISimpleEnumerator enumerateCategory(in string aCategory);
+
+ /**
+ * Enumerate all existing categories
+ * @param aCategory The category to be enumerated.
+ * @return a simple enumerator, each result QIs to
+ * nsISupportsCString.
+ */
+ nsISimpleEnumerator enumerateCategories();
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIClassInfo.idl b/src/libs/xpcom18a4/xpcom/components/nsIClassInfo.idl
new file mode 100644
index 00000000..e934057c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIClassInfo.idl
@@ -0,0 +1,132 @@
+/* -*- 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 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):
+ * 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 ***** */
+
+#include "nsISupports.idl"
+#include "nsIProgrammingLanguage.idl"
+
+/**
+ * Provides information about a specific implementation class
+ * @status FROZEN
+ */
+
+[scriptable, uuid(986c11d0-f340-11d4-9075-0010a4e73d9a)]
+interface nsIClassInfo : nsISupports
+{
+ /**
+ * Get an ordered list of the interface ids that instances of the class
+ * promise to implement. Note that nsISupports is an implicit member
+ * of any such list and need not be included.
+ *
+ * Should set *count = 0 and *array = null and return NS_OK if getting the
+ * list is not supported.
+ */
+ void getInterfaces(out PRUint32 count,
+ [array, size_is(count), retval] out nsIIDPtr array);
+
+ /**
+ * Get a language mapping specific helper object that may assist in using
+ * objects of this class in a specific lanaguage. For instance, if asked
+ * for the helper for nsIProgrammingLanguage::JAVASCRIPT this might return
+ * an object that can be QI'd into the nsIXPCScriptable interface to assist
+ * XPConnect in supplying JavaScript specific behavior to callers of the
+ * instance object.
+ *
+ * see: nsIProgrammingLanguage.idl
+ *
+ * Should return null if no helper available for given language.
+ */
+ nsISupports getHelperForLanguage(in PRUint32 language);
+
+ /**
+ * A contract ID through which an instance of this class can be created
+ * (or accessed as a service, if |flags & SINGLETON|), or null.
+ */
+ readonly attribute string contractID;
+
+ /**
+ * A human readable string naming the class, or null.
+ */
+ readonly attribute string classDescription;
+
+ /**
+ * A class ID through which an instance of this class can be created
+ * (or accessed as a service, if |flags & SINGLETON|), or null.
+ */
+ readonly attribute nsCIDPtr classID;
+
+ /**
+ * Return language type from list in nsIProgrammingLanguage
+ */
+
+ readonly attribute PRUint32 implementationLanguage;
+
+ /**
+ * Bitflags for 'flags' attribute.
+ */
+ const PRUint32 SINGLETON = 1 << 0;
+ const PRUint32 THREADSAFE = 1 << 1;
+ const PRUint32 MAIN_THREAD_ONLY = 1 << 2;
+ const PRUint32 DOM_OBJECT = 1 << 3;
+ const PRUint32 PLUGIN_OBJECT = 1 << 4;
+ const PRUint32 EAGER_CLASSINFO = 1 << 5;
+ /**
+ * 'flags' attribute bitflag: whether objects of this type implement
+ * nsIContent.
+ */
+ const PRUint32 CONTENT_NODE = 1 << 6;
+
+ // The high order bit is RESERVED for consumers of these flags.
+ // No implementor of this interface should ever return flags
+ // with this bit set.
+ const PRUint32 RESERVED = 1 << 31;
+
+
+ readonly attribute PRUint32 flags;
+
+ /**
+ * Also a class ID through which an instance of this class can be created
+ * (or accessed as a service, if |flags & SINGLETON|). If the class does
+ * not have a CID, it should return NS_ERROR_NOT_AVAILABLE. This attribute
+ * exists so C++ callers can avoid allocating and freeing a CID, as would
+ * happen if they used classID.
+ */
+ [notxpcom] readonly attribute nsCID classIDNoAlloc;
+
+};
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIComponentLoader.idl b/src/libs/xpcom18a4/xpcom/components/nsIComponentLoader.idl
new file mode 100644
index 00000000..d1b4be6e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIComponentLoader.idl
@@ -0,0 +1,109 @@
+/* -*- 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 "nsIFactory.idl"
+#include "nsIFile.idl"
+#include "nsIComponentManager.idl"
+
+[object, uuid(c073cfc0-567c-11d3-aec1-0000f8e25c06)]
+interface nsIComponentLoader : nsISupports {
+
+ /**
+ * Get the factory for a given component.
+ */
+ nsIFactory getFactory(in nsIIDRef aCID, in string aLocation,
+ in string aType);
+
+ /**
+ * Initialize the loader.
+ *
+ * We use nsISupports here because nsIRegistry isn't IDLized yet.
+ */
+ void init(in nsIComponentManager aCompMgr, in nsISupports aRegistry);
+
+ /**
+ * Called when a component of the appropriate type is registered,
+ * to give the component loader an opportunity to do things like
+ * annotate the registry and such.
+ */
+ void onRegister(in nsIIDRef aCID, in string aType,
+ in string aClassName, in string aContractID,
+ in string aLocation, in boolean aReplace,
+ in boolean aPersist);
+
+ /**
+ * When is AutoRegistration occuring?
+ */
+ const long Startup = 0;
+ const long Component = 1;
+ const long Timer = 2;
+
+ /**
+ * AutoRegister components in the given directory.
+ */
+ void autoRegisterComponents(in long aWhen, in nsIFile aDirectory);
+
+ /**
+ * AutoRegister the given component.
+ *
+ * Returns true if the component was registered, false if it couldn't
+ * attempt to register the component (wrong type) and ``throws'' an
+ * NS_FAILED code if there was an error during registration.
+ */
+ boolean autoRegisterComponent(in long aWhen, in nsIFile aComponent);
+
+ /**
+ * AutoUnregister the given component.
+ * Returns true if the component was unregistered, false if it coudln't
+ * attempt to unregister the component (not found, wrong type).
+ */
+ boolean autoUnregisterComponent(in long aWhen, in nsIFile aComponent);
+
+ /**
+ * Register any deferred (NS_ERROR_FACTORY_REGISTER_AGAIN) components.
+ * Return registered-any-components?
+ */
+ boolean registerDeferredComponents(in long aWhen);
+
+ /**
+ * Unload all components that are willing.
+ */
+ void unloadAll(in long aWhen);
+
+};
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIComponentLoaderManager.idl b/src/libs/xpcom18a4/xpcom/components/nsIComponentLoaderManager.idl
new file mode 100644
index 00000000..9f1784d6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIComponentLoaderManager.idl
@@ -0,0 +1,72 @@
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is Netscape Communications.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * 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 ***** */
+
+/**
+ * The nsIComponentRegistrar interface.
+ * @status EXPERIMENTAL
+ *
+ * USE AT YOUR OWN RISK
+ * USE AT YOUR OWN RISK
+ * USE AT YOUR OWN RISK
+ * USE AT YOUR OWN RISK
+ * USE AT YOUR OWN RISK
+ * USE AT YOUR OWN RISK
+ */
+
+#include "nsISupports.idl"
+
+interface nsIFile;
+
+[uuid(fce83d37-a3c0-4e09-ad9f-6842a984dbdf)]
+interface nsIComponentLoaderManager : nsISupports
+{
+ boolean hasFileChanged(in nsIFile file, in string loaderString, in PRInt64 modDate);
+ void saveFileInfo(in nsIFile file, in string loaderString, in PRInt64 modDate);
+ void removeFileInfo(in nsIFile file, in string loaderString);
+ void flushPersistentStore(in boolean now);
+
+ string getOptionalData(in nsIFile file, in string loaderString);
+ void setOptionalData(in nsIFile file, in string loaderString, in string value);
+};
+
+
+
+
+
+
+
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIComponentManager.idl b/src/libs/xpcom18a4/xpcom/components/nsIComponentManager.idl
new file mode 100644
index 00000000..20661803
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIComponentManager.idl
@@ -0,0 +1,111 @@
+/* -*- 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 ***** */
+
+/**
+ * The nsIComponentManager interface.
+ * @status FROZEN
+ */
+
+#include "nsISupports.idl"
+
+interface nsIFactory;
+
+[scriptable, uuid(a88e5a60-205a-4bb1-94e1-2628daf51eae)]
+interface nsIComponentManager : nsISupports
+{
+ /**
+ * getClassObject
+ *
+ * Returns the factory object that can be used to create instances of
+ * CID aClass
+ *
+ * @param aClass The classid of the factory that is being requested
+ */
+ void getClassObject(in nsCIDRef aClass,
+ in nsIIDRef aIID,
+ [iid_is(aIID),retval] out nsQIResult result);
+
+ /**
+ * getClassObjectByContractID
+ *
+ * Returns the factory object that can be used to create instances of
+ * CID aClass
+ *
+ * @param aClass The classid of the factory that is being requested
+ */
+ void getClassObjectByContractID(in string aContractID,
+ in nsIIDRef aIID,
+ [iid_is(aIID),retval] out nsQIResult result);
+
+
+ /**
+ * createInstance
+ *
+ * Create an instance of the CID aClass and return the interface aIID.
+ *
+ * @param aClass : ClassID of object instance requested
+ * @param aDelegate : Used for aggregation
+ * @param aIID : IID of interface requested
+ */
+ void createInstance(in nsCIDRef aClass,
+ in nsISupports aDelegate,
+ in nsIIDRef aIID,
+ [iid_is(aIID),retval] out nsQIResult result);
+
+ /**
+ * createInstanceByContractID
+ *
+ * Create an instance of the CID that implements aContractID and return the
+ * interface aIID.
+ *
+ * @param aContractID : aContractID of object instance requested
+ * @param aDelegate : Used for aggregation
+ * @param aIID : IID of interface requested
+ */
+ void createInstanceByContractID(in string aContractID,
+ in nsISupports aDelegate,
+ in nsIIDRef aIID,
+ [iid_is(aIID),retval] out nsQIResult result);
+};
+
+
+%{ C++
+#ifndef MOZILLA_STRICT_API
+#include "nsComponentManagerUtils.h"
+#include "nsComponentManagerObsolete.h"
+#endif
+%} C++
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIComponentManagerObsolete.idl b/src/libs/xpcom18a4/xpcom/components/nsIComponentManagerObsolete.idl
new file mode 100644
index 00000000..ac5f7975
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIComponentManagerObsolete.idl
@@ -0,0 +1,351 @@
+/* -*- 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 "nsIFactory.idl"
+
+interface nsIFile;
+interface nsIEnumerator;
+
+[scriptable, uuid(8458a740-d5dc-11d2-92fb-00e09805570f)]
+interface nsIComponentManagerObsolete : nsISupports
+{
+ /**
+ * findFactory
+ *
+ * Returns the factory object that can be used to create instances of
+ * CID aClass
+ *
+ * @param aClass The classid of the factory that is being requested
+ */
+ nsIFactory findFactory(in nsCIDRef aClass);
+
+ /**
+ * getClassObject
+ *
+ * @param aClass : CID of the class whose class object is requested
+ * @param aIID : IID of an interface that the class object is known to
+ * to implement. nsISupports and nsIFactory are known to
+ * be implemented by the class object.
+ */
+ [noscript] voidPtr getClassObject(in nsCIDRef aClass, in nsIIDRef aIID);
+
+ /**
+ * contractIDToClassID
+ *
+ * Get the ClassID for a given ContractID. Many ClassIDs may implement a
+ * ContractID. In such a situation, this returns the preferred ClassID, which
+ * happens to be the last registered ClassID.
+ *
+ * @param aContractID : Contractid for which ClassID is requested
+ * @return aClass : ClassID return
+ */
+ [notxpcom] nsresult contractIDToClassID(in string aContractID, out nsCID aClass);
+
+ /**
+ * classIDToContractid
+ *
+ * Get the ContractID for a given ClassID. A ClassIDs may implement multiple
+ * ContractIDs. This function return the last registered ContractID.
+ *
+ * @param aClass : ClassID for which ContractID is requested.
+ * @return aClassName : returns class name asssociated with aClass
+ * @return : ContractID last registered for aClass
+ */
+ string CLSIDToContractID(in nsCIDRef aClass, out string aClassName);
+
+ /**
+ * createInstance
+ *
+ * Create an instance of the CID aClass and return the interface aIID.
+ *
+ * @param aClass : ClassID of object instance requested
+ * @param aDelegate : Used for aggregation
+ * @param aIID : IID of interface requested
+ */
+ [noscript] voidPtr createInstance(in nsCIDRef aClass,
+ in nsISupports aDelegate,
+ in nsIIDRef aIID);
+
+ /**
+ * createInstanceByContractID
+ *
+ * Create an instance of the CID that implements aContractID and return the
+ * interface aIID. This is a convenience function that effectively does
+ * ContractIDToClassID() followed by CreateInstance().
+ *
+ * @param aContractID : aContractID of object instance requested
+ * @param aDelegate : Used for aggregation
+ * @param aIID : IID of interface requested
+ */
+ [noscript] voidPtr createInstanceByContractID(in string aContractID,
+ in nsISupports aDelegate,
+ in nsIIDRef IID);
+ /**
+ * registryLocationForSpec
+ *
+ * Given a file specification, return the registry representation of
+ * the filename. Files that are found relative to the components
+ * directory will have a registry representation
+ * "rel:<relative-native-path>" while filenames that are not, will have
+ * "abs:<full-native-path>".
+ */
+ string registryLocationForSpec(in nsIFile aSpec);
+
+ /**
+ * specForRegistyLocation
+ *
+ * Create a file specification for the registry representation (rel:/abs:)
+ * got via registryLocationForSpec.
+ */
+ nsIFile specForRegistryLocation(in string aLocation);
+
+ /**
+ * registerFactory
+ *
+ * Register a factory and ContractID associated with CID aClass
+ *
+ * @param aClass : CID of object
+ * @param aClassName : Class Name of CID
+ * @param aContractID : ContractID associated with CID aClass
+ * @param aFactory : Factory that will be registered for CID aClass
+ * @param aReplace : Boolean that indicates whether to replace a previous
+ * registration for the CID aClass.
+ */
+ void registerFactory(in nsCIDRef aClass, in string aClassName,
+ in string aContractID, in nsIFactory aFactory,
+ in boolean aReplace);
+
+ /**
+ * registerComponent
+ *
+ * Register a native dll module via its registry representation as returned
+ * by registryLocationForSpec() as the container of CID implemenation
+ * aClass and associate aContractID and aClassName to the CID aClass. Native
+ * dll component type is assumed.
+ *
+ * @param aClass : CID implemenation contained in module
+ * @param aClassName : Class name associated with CID aClass
+ * @param aContractID : ContractID associated with CID aClass
+ * @param aLocation : Location of module (dll). Format of this is the
+ * registry representation as returned by
+ * registryLocationForSpec()
+ * @param aReplace : Boolean that indicates whether to replace a previous
+ * module registration for aClass.
+ * @param aPersist : Remember this registration across sessions.
+ */
+ void registerComponent(in nsCIDRef aClass, in string aClassName,
+ in string aContractID, in string aLocation,
+ in boolean aReplace, in boolean aPersist);
+
+ /**
+ * registerComponentWithType
+ *
+ * Register a module's location via its registry representation
+ * as returned by registryLocationForSpec() as the container of CID implemenation
+ * aClass of type aType and associate aContractID and aClassName to the CID aClass.
+ *
+ * @param aClass : CID implemenation contained in module
+ * @param aClassName : Class name associated with CID aClass
+ * @param aContractID : ContractID associated with CID aClass
+ * @param aSpec : Filename spec for module's location.
+ * @param aLocation : Location of module of type aType. Format of this string
+ * is the registry representation as returned by
+ * registryLocationForSpec()
+ * @param aReplace : Boolean that indicates whether to replace a previous
+ * loader registration for aClass.
+ * @param aPersist : Remember this registration across sessions.
+ * @param aType : Component Type of CID aClass.
+ */
+ void registerComponentWithType(in nsCIDRef aClass, in string aClassName,
+ in string aContractID, in nsIFile aSpec,
+ in string aLocation, in boolean aReplace,
+ in boolean aPersist, in string aType);
+
+ /**
+ * registerComponentSpec
+ *
+ * Register a native dll module via its file specification as the container
+ * of CID implemenation aClass and associate aContractID and aClassName to the
+ * CID aClass. Native dll component type is assumed.
+ *
+ * @param aClass : CID implemenation contained in module
+ * @param aClassName : Class name associated with CID aClass
+ * @param aContractID : ContractID associated with CID aClass
+ * @param aLibrary : File specification Location of module (dll).
+ * @param aReplace : Boolean that indicates whether to replace a previous
+ * module registration for aClass.
+ * @param aPersist : Remember this registration across sessions.
+ */
+ void registerComponentSpec(in nsCIDRef aClass, in string aClassName,
+ in string aContractID, in nsIFile aLibrary,
+ in boolean aReplace, in boolean aPersist);
+
+ /**
+ * registerComponentLib
+ *
+ * Register a native dll module via its dll name (not full path) as the
+ * container of CID implemenation aClass and associate aContractID and aClassName
+ * to the CID aClass. Native dll component type is assumed and the system
+ * services will be used to load this dll.
+ *
+ * @param aClass : CID implemenation contained in module
+ * @param aClassName : Class name associated with CID aClass
+ * @param aContractID : ContractID associated with CID aClass
+ * @param aDllNameLocation : Dll name of module.
+ * @param aReplace : Boolean that indicates whether to replace a previous
+ * module registration for aClass.
+ * @param aPersist : Remember this registration across sessions.
+ */
+ void registerComponentLib(in nsCIDRef aClass, in string aClassName,
+ in string aContractID, in string aDllName,
+ in boolean aReplace, in boolean aPersist);
+
+ /**
+ * unregisterFactory
+ *
+ * Unregister a factory associated with CID aClass.
+ *
+ * @param aClass : ClassID being unregistered
+ * @param aFactory : Factory previously registered to create instances of
+ * ClassID aClass.
+ */
+ void unregisterFactory(in nsCIDRef aClass, in nsIFactory aFactory);
+
+ /**
+ * unregisterComponent
+ *
+ * Disassociate module aLocation represented as registry location as returned
+ * by registryLocationForSpec() as containing ClassID aClass.
+ *
+ * @param aClass : ClassID being unregistered
+ * @param aLocation : Location of module. Format of this is the registry
+ * representation as returned by registryLocationForSpec().
+ * Components of any type will be unregistered.
+ */
+ void unregisterComponent(in nsCIDRef aClass, in string aLocation);
+
+ /**
+ * unregisterComponentSpec
+ *
+ * Disassociate module references by file specification aLibrarySpec as
+ * containing ClassID aClass.
+ */
+ void unregisterComponentSpec(in nsCIDRef aClass, in nsIFile aLibrarySpec);
+
+ /**
+ * freeLibraries
+ *
+ * Enumerates all loaded modules and unloads unused modules.
+ */
+ void freeLibraries();
+
+ /**
+ * ID values for 'when'
+ */
+ const long NS_Startup = 0;
+ const long NS_Script = 1;
+ const long NS_Timer = 2;
+ const long NS_Shutdown = 3;
+
+ /**
+ * autoRegister
+ *
+ * Enumerates directory looking for modules of all types and registers
+ * modules who have changed (modtime or size) since the last time
+ * autoRegister() was invoked.
+ *
+ * @param when : ID values of when the call is being made.
+ * @param directory : Directory the will be enumerated.
+ */
+ void autoRegister(in long when, in nsIFile directory);
+
+ /**
+ * autoRegisterComponent
+ *
+ * Loads module using appropriate loader and gives it an opportunity to
+ * register its CIDs if module's modtime or size changed since the last
+ * time this was called.
+ *
+ * @param when : ID values of when the call is being made.
+ * @param aFileLocation : File specification of module.
+ */
+ void autoRegisterComponent(in long when, in nsIFile aFileLocation);
+
+ /**
+ * autoUnregisterComponent
+ *
+ * Loads module using approriate loader and gives it an opportunity to
+ * unregister its CIDs
+ */
+ void autoUnregisterComponent(in long when, in nsIFile aFileLocation);
+
+ /**
+ * isRegistered
+ *
+ * Returns true if a factory or module is registered for CID aClass.
+ *
+ * @param aClass : ClassID queried for registeration
+ * @return : true if a factory or module is registered for CID aClass.
+ * false otherwise.
+ */
+ boolean isRegistered(in nsCIDRef aClass);
+
+ /**
+ * enumerateCLSIDs
+ *
+ * Enumerate the list of all registered ClassIDs.
+ *
+ * @return : enumerator for ClassIDs.
+ */
+ nsIEnumerator enumerateCLSIDs();
+
+ /**
+ * enumerateContractIDs
+ *
+ * Enumerate the list of all registered ContractIDs.
+ *
+ * @return : enumerator for ContractIDs.
+ */
+ nsIEnumerator enumerateContractIDs();
+};
+
+%{ C++
+/* include after the class def'n, because it needs to see it. */
+#include "nsComponentManagerUtils.h"
+%} C++
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIComponentManagerUtils.h b/src/libs/xpcom18a4/xpcom/components/nsIComponentManagerUtils.h
new file mode 100644
index 00000000..a21ee7e3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIComponentManagerUtils.h
@@ -0,0 +1,43 @@
+/* -*- 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 XPCOM.
+ *
+ * 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 nsIComponentManagerUtils_h__
+#define nsIComponentManagerUtils_h__
+
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIComponentRegistrar.idl b/src/libs/xpcom18a4/xpcom/components/nsIComponentRegistrar.idl
new file mode 100644
index 00000000..2a4a55db
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIComponentRegistrar.idl
@@ -0,0 +1,243 @@
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is Netscape Communications.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * 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 ***** */
+
+/**
+ * The nsIComponentRegistrar interface.
+ * @status FROZEN
+ */
+
+#include "nsISupports.idl"
+
+interface nsIFile;
+interface nsIFactory;
+interface nsISimpleEnumerator;
+
+[scriptable, uuid(2417cbfe-65ad-48a6-b4b6-eb84db174392)]
+interface nsIComponentRegistrar : nsISupports
+{
+ /**
+ * autoRegister
+ *
+ * Register a component file or all component files in a directory.
+ *
+ * Component files must have an associated loader and export the required
+ * symbols which this loader defines. For example, if the given file is a
+ * native library (which is built into XPCOM), it must export the symbol
+ * "NSGetModule". Other loaders may have different semantics.
+ *
+ * This method may only be called from the main thread.
+ *
+ * @param aSpec : Filename spec for component file's location. If aSpec
+ * is a directory, then every component file in the
+ * directory will be registered.
+ * If the aSpec is null, then the application component's
+ * directory as defined by NS_XPCOM_COMPONENT_DIR will be
+ * registered (see nsIDirectoryService.idl)
+ *
+ * @return NS_OK : Registration was successful.
+ * NS_ERROR: Method failure.
+ */
+ void autoRegister(in nsIFile aSpec);
+
+ /**
+ * autoUnregister
+ *
+ * Unregister a component file or all component files in a directory.
+ * This method may only be called from the main thread.
+ *
+ * @param aSpec : Filename spec for component file's location. If aSpec
+ * is a directory, the every component file in the directory
+ * will be registered.
+ * If aSpec is null, then the application component's
+ * directory as defined by NS_XPCOM_COMPONENT_DIR will be
+ * registered. (see nsIDirectoryService.idl)
+ *
+ * @return NS_OK Unregistration was successful.
+ * NS_ERROR* Method failure.
+ */
+ void autoUnregister(in nsIFile aSpec);
+
+
+ /**
+ * registerFactory
+ *
+ * Register a factory with a given ContractID, CID and Class Name.
+ *
+ * @param aClass : CID of object
+ * @param aClassName : Class Name of CID
+ * @param aContractID : ContractID associated with CID aClass
+ * @param aFactory : Factory that will be registered for CID aClass
+ *
+ * @return NS_OK Registration was successful.
+ * NS_ERROR* method failure.
+ */
+ void registerFactory(in nsCIDRef aClass,
+ in string aClassName,
+ in string aContractID,
+ in nsIFactory aFactory);
+
+ /**
+ * unregisterFactory
+ *
+ * Unregister a factory associated with CID aClass.
+ *
+ * @param aClass : CID being unregistered
+ * @param aFactory : Factory previously registered to create instances of
+ * CID aClass.
+ *
+ * @return NS_OK Unregistration was successful.
+ * NS_ERROR* Method failure.
+ */
+ void unregisterFactory(in nsCIDRef aClass,
+ in nsIFactory aFactory);
+
+ /**
+ * registerFactoryLocation
+ *
+ * Register a factory with a given ContractID, CID and Class Name
+ *
+ * @param aClass : CID of object
+ * @param aClassName : Class Name of CID
+ * @param aContractID : ContractID associated with CID aClass
+ * @param aFile : Component File. This file must have an associated
+ * loader and export the required symbols which this
+ * loader specifies.
+ * @param aLoaderStr : Opaque loader specific string. This value is
+ * passed into the nsIModule's registerSelf
+ * callback and must be fowarded unmodified when
+ * registering factories via their location.
+ * @param aType : Component Type of CID aClass. This value is
+ * passed into the nsIModule's registerSelf
+ * callback and must be fowarded unmodified when
+ * registering factories via their location.
+ *
+ * @return NS_OK Registration was successful.
+ * NS_ERROR* Method failure.
+ */
+ void registerFactoryLocation(in nsCIDRef aClass,
+ in string aClassName,
+ in string aContractID,
+ in nsIFile aFile,
+ in string aLoaderStr,
+ in string aType);
+
+ /**
+ * unregisterFactoryLocation
+ *
+ * Unregister a factory associated with CID aClass.
+ *
+ * @param aClass : CID being unregistered
+ * @param aFile : Component File previously registered
+ *
+ * @return NS_OK Unregistration was successful.
+ * NS_ERROR* Method failure.
+ */
+ void unregisterFactoryLocation(in nsCIDRef aClass,
+ in nsIFile aFile);
+
+ /**
+ * isCIDRegistered
+ *
+ * Returns true if a factory is registered for the CID.
+ *
+ * @param aClass : CID queried for registeration
+ * @return : true if a factory is registered for CID
+ * false otherwise.
+ */
+ boolean isCIDRegistered(in nsCIDRef aClass);
+
+ /**
+ * isContractIDRegistered
+ *
+ * Returns true if a factory is registered for the contract id.
+ *
+ * @param aClass : contract id queried for registeration
+ * @return : true if a factory is registered for contract id
+ * false otherwise.
+ */
+ boolean isContractIDRegistered(in string aContractID);
+
+ /**
+ * enumerateCIDs
+ *
+ * Enumerate the list of all registered CIDs.
+ *
+ * @return : enumerator for CIDs. Elements of the enumeration can be QI'ed
+ * for the nsISupportsID interface. From the nsISupportsID, you
+ * can obtain the actual CID.
+ */
+ nsISimpleEnumerator enumerateCIDs();
+
+ /**
+ * enumerateContractIDs
+ *
+ * Enumerate the list of all registered ContractIDs.
+ *
+ * @return : enumerator for ContractIDs. Elements of the enumeration can be
+ * QI'ed for the nsISupportsCString interface. From the
+ * nsISupportsCString interface, you can obtain the actual
+ * Contract ID string.
+ */
+ nsISimpleEnumerator enumerateContractIDs();
+
+ /**
+ * CIDToContractID
+ *
+ * Returns the Contract ID for a given CID, if one exists and is registered.
+ *
+ * @return : Contract ID.
+ */
+ string CIDToContractID(in nsCIDRef aClass);
+
+ /**
+ * contractIDToCID
+ *
+ * Returns the CID for a given Contract ID, if one exists and is registered.
+ *
+ * @return : Contract ID.
+ */
+ nsCIDPtr contractIDToCID(in string aContractID);
+
+};
+
+
+
+
+
+
+
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIFactory.idl b/src/libs/xpcom18a4/xpcom/components/nsIFactory.idl
new file mode 100644
index 00000000..bda0b43a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIFactory.idl
@@ -0,0 +1,79 @@
+/* -*- 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"
+
+/**
+ * A class factory allows the creation of nsISupports derived
+ * components without specifying a concrete base class.
+ *
+ * @status FROZEN
+ */
+
+[scriptable, object, uuid(00000001-0000-0000-c000-000000000046)]
+interface nsIFactory : nsISupports {
+ /**
+ * Creates an instance of a component.
+ *
+ * @param aOuter Pointer to a component that wishes to be aggregated
+ * in the resulting instance. This will be nsnull if no
+ * aggregation is requested.
+ * @param iid The IID of the interface being requested in
+ * the component which is being currently created.
+ * @param result [out] Pointer to the newly created instance, if successful.
+ * @return NS_OK - Component successfully created and the interface
+ * being requested was successfully returned in result.
+ * NS_NOINTERFACE - Interface not accessible.
+ * NS_ERROR_NO_AGGREGATION - if an 'outer' object is supplied, but the
+ * component is not aggregatable.
+ * NS_ERROR* - Method failure.
+ */
+ void createInstance(in nsISupports aOuter, in nsIIDRef iid,
+ [retval, iid_is(iid)] out nsQIResult result);
+
+ /**
+ * LockFactory provides the client a way to keep the component
+ * in memory until it is finished with it. The client can call
+ * LockFactory(PR_TRUE) to lock the factory and LockFactory(PR_FALSE)
+ * to release the factory.
+ *
+ * @param lock - Must be PR_TRUE or PR_FALSE
+ * @return NS_OK - If the lock operation was successful.
+ * NS_ERROR* - Method failure.
+ */
+ void lockFactory(in PRBool lock);
+};
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIModule.idl b/src/libs/xpcom18a4/xpcom/components/nsIModule.idl
new file mode 100644
index 00000000..a71b9b13
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIModule.idl
@@ -0,0 +1,115 @@
+/* -*- 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 nsIFile;
+interface nsIComponentManager;
+
+/**
+ * The nsIModule interface.
+ * @status FROZEN
+ */
+
+[scriptable, uuid(7392D032-5371-11d3-994E-00805FD26FEE)]
+interface nsIModule : nsISupports
+{
+ /**
+ * Object Instance Creation
+ *
+ * Obtains a Class Object from a nsIModule for a given CID and IID pair.
+ * This class object can either be query to a nsIFactory or a may be
+ * query to a nsIClassInfo.
+ *
+ * @param aCompMgr : The global component manager
+ * @param aClass : ClassID of object instance requested
+ * @param aIID : IID of interface requested
+ *
+ */
+ void getClassObject(in nsIComponentManager aCompMgr,
+ in nsCIDRef aClass,
+ in nsIIDRef aIID,
+ [retval, iid_is(aIID)] out nsQIResult aResult);
+
+
+ /**
+ * One time registration callback
+ *
+ * When the nsIModule is discovered, this method will be
+ * called so that any setup registration can be preformed.
+ *
+ * @param aCompMgr : The global component manager
+ * @param aLocation : The location of the nsIModule on disk
+ * @param aLoaderStr: Opaque loader specific string
+ * @param aType : Loader Type being used to load this module
+ */
+ void registerSelf(in nsIComponentManager aCompMgr,
+ in nsIFile aLocation,
+ in string aLoaderStr,
+ in string aType);
+ /**
+ * One time unregistration callback
+ *
+ * When the nsIModule is being unregistered, this method will be
+ * called so that any unregistration can be preformed
+ *
+ * @param aCompMgr : The global component manager
+ * @param aLocation : The location of the nsIModule on disk
+ * @param aLoaderStr : Opaque loader specific string
+ *
+ */
+ void unregisterSelf(in nsIComponentManager aCompMgr,
+ in nsIFile aLocation,
+ in string aLoaderStr);
+
+ /**
+ * Module load management
+ *
+ * @param aCompMgr : The global component manager
+ *
+ * @return indicates to the caller if the module can be unloaded.
+ * Returning PR_TRUE isn't a guarantee that the module will be
+ * unloaded. It constitues only willingness of the module to be
+ * unloaded. It is very important to ensure that no outstanding
+ * references to the module's code/data exist before returning
+ * PR_TRUE.
+ * Returning PR_FALSE guaratees that the module wont be unloaded.
+ */
+ boolean canUnload(in nsIComponentManager aCompMgr);
+};
+
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsINativeComponentLoader.idl b/src/libs/xpcom18a4/xpcom/components/nsINativeComponentLoader.idl
new file mode 100644
index 00000000..c5d18111
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsINativeComponentLoader.idl
@@ -0,0 +1,70 @@
+/* -*- 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) 2003
+ * 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 nsIFile;
+
+[uuid(10d1a2a2-d816-458d-a4c3-0805ff0f7b31)]
+interface nsINativeComponentLoader : nsISupports
+{
+
+ /**
+ * addDependentLibrary
+ *
+ * This method informs the native component loader that the
+ * given component library referenced by |aFile| requires
+ * symbols that can be found in the library named |aLibName|.
+ *
+ * The native component loader is expected to resolve these
+ * external symobls prior to loading the component library.
+ *
+ * @param aFile
+ * The native component file location that is declaring a
+ * a dependency. This file is expected to be a DSO/DLL.
+ *
+ * @param aLibName
+ * This is a name of a library that the component requires.
+ * This file name is found in either the GRE bin directory
+ * or the application's bin directory. Full file path are
+ * also accepted. Passing nsnull for the |aLibName| will
+ * clear all dependencies. Note that non null aLibName
+ * values are expected to be in the native charset.
+ */
+
+ void addDependentLibrary(in nsIFile aFile, in string aLibName);
+};
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIServiceManager.idl b/src/libs/xpcom18a4/xpcom/components/nsIServiceManager.idl
new file mode 100644
index 00000000..200c2a69
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIServiceManager.idl
@@ -0,0 +1,119 @@
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is Netscape Communications.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * 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 "nsISupports.idl"
+
+/**
+ * The nsIServiceManager manager interface provides a means to obtain
+ * global services in an application. The service manager depends on the
+ * repository to find and instantiate factories to obtain services.
+ *
+ * Users of the service manager must first obtain a pointer to the global
+ * service manager by calling NS_GetServiceManager. After that,
+ * they can request specific services by calling GetService. When they are
+ * finished they can NS_RELEASE() the service as usual.
+ *
+ * A user of a service may keep references to particular services indefinitely
+ * and only must call Release when it shuts down.
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(8bb35ed9-e332-462d-9155-4a002ab5c958)]
+interface nsIServiceManager : nsISupports
+{
+ /**
+ * getServiceByContractID
+ *
+ * Returns the instance that implements aClass or aContractID and the
+ * interface aIID. This may result in the instance being created.
+ *
+ * @param aClass or aContractID : aClass or aContractID of object
+ * instance requested
+ * @param aIID : IID of interface requested
+ * @param result : resulting service
+ */
+ void getService(in nsCIDRef aClass,
+ in nsIIDRef aIID,
+ [iid_is(aIID),retval] out nsQIResult result);
+
+ void getServiceByContractID(in string aContractID,
+ in nsIIDRef aIID,
+ [iid_is(aIID),retval] out nsQIResult result);
+
+ /**
+ * isServiceInstantiated
+ *
+ * isServiceInstantiated will return a true if the service has already
+ * been created, otherwise false
+ *
+ * @param aClass or aContractID : aClass or aContractID of object
+ * instance requested
+ * @param aIID : IID of interface requested
+ * @param aIID : IID of interface requested
+ */
+ boolean isServiceInstantiated(in nsCIDRef aClass, in nsIIDRef aIID);
+ boolean isServiceInstantiatedByContractID(in string aContractID, in nsIIDRef aIID);
+};
+
+
+%{C++
+#define NS_ERROR_SERVICE_NOT_AVAILABLE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 22)
+/**
+ * @status DEPRECATED
+ */
+#define NS_ERROR_SERVICE_NOT_FOUND NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCOM, 22)
+/**
+ * @status DEPRECATED
+ */
+#define NS_ERROR_SERVICE_IN_USE NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCOM, 23)
+
+// Observing xpcom startup. If you component has not been created, it will be.
+#define NS_XPCOM_STARTUP_OBSERVER_ID "xpcom-startup"
+
+// Observing xpcom shutdown
+#define NS_XPCOM_SHUTDOWN_OBSERVER_ID "xpcom-shutdown"
+
+// Observing xpcom autoregistration. Topics will be 'start' and 'stop'.
+#define NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID "xpcom-autoregistration"
+
+#ifndef MOZILLA_STRICT_API
+#include "nsXPCOM.h"
+#include "nsIServiceManagerUtils.h"
+#include "nsIServiceManagerObsolete.h"
+#endif
+%}
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIServiceManagerObsolete.h b/src/libs/xpcom18a4/xpcom/components/nsIServiceManagerObsolete.h
new file mode 100644
index 00000000..dc229c76
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIServiceManagerObsolete.h
@@ -0,0 +1,250 @@
+/* -*- 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 XPCOM.
+ *
+ * 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 nsIServiceManagerObsolete_h___
+#define nsIServiceManagerObsolete_h___
+
+////////////////////////////////////////////////////////////////////
+//
+// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+//
+// Functions, classes, interfaces and types in this file are
+// obsolete. Use at your own risk.
+// Please see nsIServiceManager.idl for the supported interface
+// to the service manager.
+//
+////////////////////////////////////////////////////////////////////
+
+#include "nsIComponentManager.h"
+#include "nsID.h"
+
+#ifndef nsCOMPtr_h___
+#include "nsCOMPtr.h"
+#endif
+
+class nsIServiceManager;
+class nsIShutdownListener;
+class nsIDirectoryServiceProvider;
+
+class nsServiceManagerObsolete;
+
+#define NS_ISERVICEMANAGER_OBSOLETE_IID \
+{ /* cf0df3b0-3401-11d2-8163-006008119d7a */ \
+ 0xcf0df3b0, \
+ 0x3401, \
+ 0x11d2, \
+ {0x81, 0x63, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \
+}
+
+/**
+ * The nsIServiceManagerObsolete manager is obsolete. Please refer
+ * to nsIServiceManager.
+ */
+class nsIServiceManagerObsolete : public nsISupports {
+public:
+
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISERVICEMANAGER_OBSOLETE_IID);
+
+ /**
+ * RegisterService may be called explicitly to register a service
+ * with the service manager. If a service is not registered explicitly,
+ * the component manager will be used to create an instance according
+ * to the class ID specified.
+ */
+ NS_IMETHOD
+ RegisterService(const nsCID& aClass, nsISupports* aService) = 0;
+
+ /**
+ * Requests a service to be shut down, possibly unloading its DLL.
+ *
+ * @returns NS_OK - if shutdown was successful and service was unloaded,
+ * @returns NS_ERROR_SERVICE_NOT_FOUND - if shutdown failed because
+ * the service was not currently loaded
+ * @returns NS_ERROR_SERVICE_IN_USE - if shutdown failed because some
+ * user of the service wouldn't voluntarily release it by using
+ * a shutdown listener.
+ */
+ NS_IMETHOD
+ UnregisterService(const nsCID& aClass) = 0;
+
+ NS_IMETHOD
+ GetService(const nsCID& aClass, const nsIID& aIID,
+ nsISupports* *result,
+ nsIShutdownListener* shutdownListener = nsnull) = 0;
+
+ /* OBSOLETE: use NS_RELEASE(service) instead. */
+ NS_IMETHOD
+ ReleaseService(const nsCID& aClass, nsISupports* service,
+ nsIShutdownListener* shutdownListener = nsnull) = 0;
+
+ ////////////////////////////////////////////////////////////////////////////
+ // let's do it again, this time with ContractIDs...
+
+ NS_IMETHOD
+ RegisterService(const char* aContractID, nsISupports* aService) = 0;
+
+ NS_IMETHOD
+ UnregisterService(const char* aContractID) = 0;
+
+ NS_IMETHOD
+ GetService(const char* aContractID, const nsIID& aIID,
+ nsISupports* *result,
+ nsIShutdownListener* shutdownListener = nsnull) = 0;
+
+ /* OBSOLETE */
+ NS_IMETHOD
+ ReleaseService(const char* aContractID, nsISupports* service,
+ nsIShutdownListener* shutdownListener = nsnull) = 0;
+
+};
+
+// Interface to Global Services
+class NS_COM nsServiceManager {
+public:
+
+ static nsresult
+ RegisterService(const nsCID& aClass, nsISupports* aService);
+
+ static nsresult
+ UnregisterService(const nsCID& aClass);
+
+ static nsresult
+ GetService(const nsCID& aClass, const nsIID& aIID,
+ nsISupports* *result,
+ nsIShutdownListener* shutdownListener = nsnull);
+
+ /* OBSOLETE: use NS_RELEASE(service) instead. */
+ static nsresult
+ ReleaseService(const nsCID& aClass, nsISupports* service,
+ nsIShutdownListener* shutdownListener = nsnull);
+
+ ////////////////////////////////////////////////////////////////////////////
+ // let's do it again, this time with ContractIDs...
+
+ static nsresult
+ RegisterService(const char* aContractID, nsISupports* aService);
+
+ static nsresult
+ UnregisterService(const char* aContractID);
+
+ static nsresult
+ GetService(const char* aContractID, const nsIID& aIID,
+ nsISupports* *result,
+ nsIShutdownListener* shutdownListener = nsnull);
+
+ /* OBSOLETE: use NS_RELEASE(service) instead. */
+ static nsresult
+ ReleaseService(const char* aContractID, nsISupports* service,
+ nsIShutdownListener* shutdownListener = nsnull);
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ // These methods return really nsIServiceManagerObsolete, but they are
+ // statically cast to nsIServiceManager to preserve backwards compatiblity.
+ static nsresult GetGlobalServiceManager(nsIServiceManager* *result);
+ static nsresult ShutdownGlobalServiceManager(nsIServiceManager* *result);
+};
+
+
+#define NS_DECL_NSISERVICEMANAGEROBSOLETE \
+ NS_IMETHOD RegisterService(const nsCID& aClass, nsISupports* aService); \
+ NS_IMETHOD UnregisterService(const nsCID& aClass);\
+ NS_IMETHOD GetService(const nsCID& aClass, const nsIID& aIID, nsISupports* *result, nsIShutdownListener* shutdownListener);\
+ NS_IMETHOD ReleaseService(const nsCID& aClass, nsISupports* service, nsIShutdownListener* shutdownListener);\
+ NS_IMETHOD RegisterService(const char* aContractID, nsISupports* aService);\
+ NS_IMETHOD UnregisterService(const char* aContractID);\
+ NS_IMETHOD GetService(const char* aContractID, const nsIID& aIID, nsISupports* *result, nsIShutdownListener* shutdownListener);\
+ NS_IMETHOD ReleaseService(const char* aContractID, nsISupports* service, nsIShutdownListener* shutdownListener);
+
+////////////////////////////////////////////////////////////////////////////////
+
+#define NS_ISHUTDOWNLISTENER_IID \
+{ /* 56decae0-3406-11d2-8163-006008119d7a */ \
+ 0x56decae0, \
+ 0x3406, \
+ 0x11d2, \
+ {0x81, 0x63, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \
+}
+
+class nsIShutdownListener;
+
+
+template <class DestinationType>
+inline
+nsresult
+CallGetService( const nsCID &aClass,
+ nsIShutdownListener* shutdownListener,
+ DestinationType** aDestination)
+{
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ return nsServiceManager::GetService(aClass,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(nsISupports**, aDestination),
+ shutdownListener);
+}
+
+template <class DestinationType>
+inline
+nsresult
+CallGetService( const char *aContractID,
+ nsIShutdownListener* shutdownListener,
+ DestinationType** aDestination)
+{
+ NS_PRECONDITION(aContractID, "null parameter");
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ return nsServiceManager::GetService(aContractID,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(nsISupports**, aDestination),
+ shutdownListener);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+#endif /* nsIServiceManagerObsolete_h___ */
+
+
+
+
+
+
+
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsIServiceManagerUtils.h b/src/libs/xpcom18a4/xpcom/components/nsIServiceManagerUtils.h
new file mode 100644
index 00000000..b7b432af
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsIServiceManagerUtils.h
@@ -0,0 +1,185 @@
+/* -*- 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 XPCOM.
+ *
+ * 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 nsIServiceManagerUtils_h__
+#define nsIServiceManagerUtils_h__
+
+#include "nsIServiceManager.h"
+#include "nsIServiceManagerObsolete.h"
+#include "nsCOMPtr.h"
+
+////////////////////////////////////////////////////////////////////////////
+// Using servicemanager with COMPtrs
+class NS_COM nsGetServiceByCID : public nsCOMPtr_helper
+{
+ public:
+ nsGetServiceByCID( const nsCID& aCID, nsISupports* aServiceManager, nsresult* aErrorPtr )
+ : mCID(aCID),
+ mServiceManager( do_QueryInterface(aServiceManager) ),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+
+ private:
+ const nsCID& mCID;
+ nsCOMPtr<nsIServiceManager> mServiceManager;
+ nsresult* mErrorPtr;
+};
+
+inline
+const nsGetServiceByCID
+do_GetService( const nsCID& aCID, nsresult* error = 0 )
+{
+ return nsGetServiceByCID(aCID, 0, error);
+}
+
+inline
+const nsGetServiceByCID
+do_GetService( const nsCID& aCID, nsISupports* aServiceManager, nsresult* error = 0 )
+{
+ return nsGetServiceByCID(aCID, aServiceManager, error);
+}
+
+class NS_COM nsGetServiceByContractID : public nsCOMPtr_helper
+{
+ public:
+ nsGetServiceByContractID( const char* aContractID, nsISupports* aServiceManager, nsresult* aErrorPtr )
+ : mContractID(aContractID),
+ mServiceManager( do_QueryInterface(aServiceManager) ),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do
+ }
+ // Implement a dummy destructor to workaround linking issue on Solaris gcc 4.8.2 (see @bugref{5838})
+ ~nsGetServiceByContractID() {}
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+
+ private:
+ const char* mContractID;
+ nsCOMPtr<nsIServiceManager> mServiceManager;
+ nsresult* mErrorPtr;
+};
+
+inline
+const nsGetServiceByContractID
+do_GetService( const char* aContractID, nsresult* error = 0 )
+{
+ return nsGetServiceByContractID(aContractID, 0, error);
+}
+
+inline
+const nsGetServiceByContractID
+do_GetService( const char* aContractID, nsISupports* aServiceManager, nsresult* error = 0 )
+{
+ return nsGetServiceByContractID(aContractID, aServiceManager, error);
+}
+
+class nsGetServiceFromCategory : public nsCOMPtr_helper
+{
+ public:
+ nsGetServiceFromCategory(const char* aCategory, const char* aEntry,
+ nsISupports* aServiceManager,
+ nsresult* aErrorPtr)
+ : mCategory(aCategory),
+ mEntry(aEntry),
+ mServiceManager( do_QueryInterface(aServiceManager) ),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+ protected:
+ const char* mCategory;
+ const char* mEntry;
+ nsCOMPtr<nsIServiceManager> mServiceManager;
+ nsresult* mErrorPtr;
+};
+
+inline
+const nsGetServiceFromCategory
+do_GetServiceFromCategory( const char* category, const char* entry,
+ nsresult* error = 0)
+{
+ return nsGetServiceFromCategory(category, entry, 0, error);
+}
+
+// type-safe shortcuts for calling |GetService|
+template <class DestinationType>
+inline
+nsresult
+CallGetService( const nsCID &aClass,
+ DestinationType** aDestination)
+{
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ nsCOMPtr<nsIServiceManager> mgr;
+ nsresult rv = NS_GetServiceManager(getter_AddRefs(mgr));
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ return mgr->GetService(aClass,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+}
+
+template <class DestinationType>
+inline
+nsresult
+CallGetService( const char *aContractID,
+ DestinationType** aDestination)
+{
+ NS_PRECONDITION(aContractID, "null parameter");
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ nsCOMPtr<nsIServiceManager> mgr;
+ nsresult rv = NS_GetServiceManager(getter_AddRefs(mgr));
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ return mgr->GetServiceByContractID(aContractID,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+}
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/components/nsModule.h b/src/libs/xpcom18a4/xpcom/components/nsModule.h
new file mode 100644
index 00000000..56a06354
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsModule.h
@@ -0,0 +1,58 @@
+/* -*- 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
+ * Marco Pesenti Gritti <marco@gnome.org>
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * 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 nsModule_h__
+#define nsModule_h__
+
+#include "nsIModule.h"
+#include "nsIFile.h"
+#include "nsIComponentManager.h"
+
+// Exported Function from module dll to Create the nsIModule
+#define NS_GET_MODULE_SYMBOL "NSGetModule"
+
+extern "C" NS_EXPORT nsresult PR_CALLBACK
+NSGetModule(nsIComponentManager *aCompMgr,
+ nsIFile* location,
+ nsIModule** return_cobj);
+
+typedef nsresult (PR_CALLBACK *nsGetModuleProc)(nsIComponentManager *aCompMgr,
+ nsIFile* location,
+ nsIModule** return_cobj);
+
+
+#endif /* nsModule_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.cpp b/src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.cpp
new file mode 100644
index 00000000..a3fd5df8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.cpp
@@ -0,0 +1,1150 @@
+/* -*- 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) 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 *****
+ * 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 "prmem.h"
+#include "prerror.h"
+#include "prsystem.h" // PR_GetDirectorySeparator
+#include "nsNativeComponentLoader.h"
+#include "nsComponentManager.h"
+#include "nsCOMPtr.h"
+#include "nsIServiceManager.h"
+#include "nsIModule.h"
+#include "xcDll.h"
+#include "nsHashtable.h"
+#include "nsXPIDLString.h"
+#include "nsCRT.h"
+#include "nsIObserverService.h"
+
+#if defined(XP_MAC) // sdagley dougt fix
+#include <Files.h>
+#include <Errors.h>
+#include "nsILocalFileMac.h"
+#endif
+
+#include "prlog.h"
+extern PRLogModuleInfo *nsComponentManagerLog;
+
+static PRBool PR_CALLBACK
+DLLStore_Destroy(nsHashKey *aKey, void *aData, void* closure)
+{
+ nsDll* entry = NS_STATIC_CAST(nsDll*, aData);
+ delete entry;
+ return PR_TRUE;
+}
+
+nsNativeComponentLoader::nsNativeComponentLoader() :
+ mCompMgr(nsnull),
+ mLoadedDependentLibs(16, PR_TRUE),
+ mDllStore(nsnull, nsnull, DLLStore_Destroy,
+ nsnull, 256, PR_TRUE)
+{
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsNativeComponentLoader,
+ nsIComponentLoader,
+ nsINativeComponentLoader)
+
+NS_IMETHODIMP
+nsNativeComponentLoader::GetFactory(const nsIID & aCID,
+ const char *aLocation,
+ const char *aType,
+ nsIFactory **_retval)
+{
+ nsresult rv;
+
+ if (!_retval)
+ return NS_ERROR_NULL_POINTER;
+
+ /* use a hashtable of WeakRefs to store the factory object? */
+
+ /* Should this all live in xcDll? */
+ nsDll *dll;
+ rv = CreateDll(nsnull, aLocation, &dll);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (!dll)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (!dll->IsLoaded()) {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
+ ("nsNativeComponentLoader: loading \"%s\"",
+ displayPath.get()));
+#endif
+ if (!dll->Load()) {
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
+ ("nsNativeComponentLoader: load FAILED"));
+
+ char errorMsg[1024] = "<unknown; can't get error from NSPR>";
+
+ if (PR_GetErrorTextLength() < (int) sizeof(errorMsg))
+ PR_GetErrorText(errorMsg);
+
+ DumpLoadError(dll, "GetFactory", errorMsg);
+
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ /* Get service manager for factory */
+ nsCOMPtr<nsIServiceManager> serviceMgr;
+ rv = NS_GetServiceManager(getter_AddRefs(serviceMgr));
+ if (NS_FAILED(rv))
+ return rv; // XXX translate error code?
+
+ rv = GetFactoryFromModule(dll, aCID, _retval);
+
+ PR_LOG(nsComponentManagerLog, NS_SUCCEEDED(rv) ? PR_LOG_DEBUG : PR_LOG_ERROR,
+ ("nsNativeComponentLoader: Factory creation %s for %s",
+ (NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"),
+ aLocation));
+
+ // If the dll failed to get us a factory. But the dll registered that
+ // it would be able to create a factory for this CID. mmh!
+ // We cannot just delete the dll as the dll could be hosting
+ // other CID for which factory creation can pass.
+ // We will just let it be. The effect will be next time we try
+ // creating the object, we will query the dll again. Since the
+ // dll is loaded, this aint a big hit. So for optimized builds
+ // this is ok to limp along.
+ NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Factory creation failed");
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsNativeComponentLoader::Init(nsIComponentManager *aCompMgr, nsISupports *aReg)
+{
+ mCompMgr = aCompMgr;
+ if (!mCompMgr)
+ return NS_ERROR_INVALID_ARG;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNativeComponentLoader::AutoRegisterComponents(PRInt32 aWhen,
+ nsIFile *aDirectory)
+{
+#ifdef DEBUG
+ /* do we _really_ want to print this every time? */
+ fprintf(stderr, "nsNativeComponentLoader: autoregistering begins.\n");
+#endif
+
+ nsresult rv = RegisterComponentsInDir(aWhen, aDirectory);
+
+#ifdef DEBUG
+ fprintf(stderr, "nsNativeComponentLoader: autoregistering %s\n",
+ NS_FAILED(rv) ? "FAILED" : "succeeded");
+#endif
+
+ return rv;
+}
+
+nsresult
+nsNativeComponentLoader::RegisterComponentsInDir(PRInt32 when,
+ nsIFile *dir)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+ PRBool isDir = PR_FALSE;
+
+#if 0
+ // Going to many of these checks is a performance hit on the mac.
+ // Since these routines are called relatively infrequently and
+ // we will fail anyway down the line if a directory aint there,
+ // we are commenting this check out.
+
+ // Make sure we are dealing with a directory
+ rv = dir->IsDirectory(&isDir);
+ if (NS_FAILED(rv)) return rv;
+
+ if (!isDir)
+ return NS_ERROR_INVALID_ARG;
+#endif /* 0 */
+
+ // Create a directory iterator
+ nsCOMPtr<nsISimpleEnumerator> dirIterator;
+ rv = dir->GetDirectoryEntries(getter_AddRefs(dirIterator));
+
+ if (NS_FAILED(rv)) return rv;
+
+ // whip through the directory to register every file
+ nsCOMPtr<nsIFile> dirEntry;
+ PRBool more = PR_FALSE;
+
+ rv = dirIterator->HasMoreElements(&more);
+ if (NS_FAILED(rv)) return rv;
+ while (more == PR_TRUE)
+ {
+ rv = dirIterator->GetNext((nsISupports**)getter_AddRefs(dirEntry));
+ if (NS_SUCCEEDED(rv))
+ {
+ rv = dirEntry->IsDirectory(&isDir);
+ if (NS_SUCCEEDED(rv))
+ {
+ if (isDir == PR_TRUE)
+ {
+ // This is a directory. Grovel for components into the directory.
+#ifdef RT_OS_DARWIN // But not if it's a debug bundle.
+ nsCAutoString leafName;
+ rv = dirEntry->GetNativeLeafName(leafName);
+ if ( NS_FAILED(rv)
+ || leafName.Length() < sizeof(".dSYM")
+ || PL_strcasecmp(leafName.get() + (leafName.Length() - sizeof(".dSYM") + 1), ".dSYM"))
+#endif
+ rv = RegisterComponentsInDir(when, dirEntry);
+ }
+ else
+ {
+ PRBool registered;
+ // This is a file. Try to register it.
+ rv = AutoRegisterComponent(when, dirEntry, &registered);
+ }
+ }
+ }
+ rv = dirIterator->HasMoreElements(&more);
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ return rv;
+}
+
+static nsresult PR_CALLBACK
+nsFreeLibrary(nsDll *dll, nsIServiceManager *serviceMgr, PRInt32 when)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+
+ if (!dll || dll->IsLoaded() == PR_FALSE)
+ {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ // Get if the dll was marked for unload in an earlier round
+ PRBool dllMarkedForUnload = dll->IsMarkedForUnload();
+
+ // Reset dll marking for unload just in case we return with
+ // an error.
+ dll->MarkForUnload(PR_FALSE);
+
+ PRBool canUnload = PR_FALSE;
+
+ // Get the module object
+ nsCOMPtr<nsIModule> mobj;
+ /* XXXshaver cheat and use the global component manager */
+ rv = dll->GetModule(NS_STATIC_CAST(nsIComponentManager*, nsComponentManagerImpl::gComponentManager),
+ getter_AddRefs(mobj));
+ if (NS_SUCCEEDED(rv))
+ {
+ rv = mobj->CanUnload(nsComponentManagerImpl::gComponentManager, &canUnload);
+ }
+
+ mobj = nsnull; // Release our reference to the module object
+ // When shutting down, whether we can unload the dll or not,
+ // we will shutdown the dll to release any memory it has got
+ if (when == nsIComponentManagerObsolete::NS_Shutdown)
+ {
+ dll->Shutdown();
+ }
+
+ // Check error status on CanUnload() call
+ if (NS_FAILED(rv))
+ {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("nsNativeComponentLoader: nsIModule::CanUnload() returned error for %s.",
+ displayPath.get()));
+#endif
+ return rv;
+ }
+
+ if (canUnload)
+ {
+ if (dllMarkedForUnload)
+ {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
+ ("nsNativeComponentLoader: + Unloading \"%s\".", displayPath.get()));
+#endif
+
+#ifdef DEBUG_dougt
+ // XXX dlls aren't counting their outstanding instances correctly
+ // XXX hence, dont unload until this gets enforced.
+ rv = dll->Unload();
+#endif /* 0 */
+ }
+ else
+ {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
+ ("nsNativeComponentLoader: Ready for unload \"%s\".", displayPath.get()));
+#endif
+ }
+ }
+ else
+ {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsNativeComponentLoader: NOT ready for unload %s", displayPath.get()));
+#endif
+ rv = NS_ERROR_FAILURE;
+ }
+ return rv;
+}
+
+struct freeLibrariesClosure
+{
+ nsIServiceManager *serviceMgr;
+ PRInt32 when;
+};
+
+static PRBool PR_CALLBACK
+nsFreeLibraryEnum(nsHashKey *aKey, void *aData, void* closure)
+{
+ nsDll *dll = (nsDll *) aData;
+ struct freeLibrariesClosure *callData = (struct freeLibrariesClosure *) closure;
+ nsFreeLibrary(dll,
+ (callData ? callData->serviceMgr : NULL),
+ (callData ? callData->when : nsIComponentManagerObsolete::NS_Timer));
+ return PR_TRUE;
+}
+
+/*
+ * SelfRegisterDll
+ *
+ * Given a dll abstraction, this will load, selfregister the dll and
+ * unload the dll.
+ *
+ */
+nsresult
+nsNativeComponentLoader::SelfRegisterDll(nsDll *dll,
+ const char *registryLocation,
+ PRBool deferred)
+{
+ // Precondition: dll is not loaded already, unless we're deferred
+ PR_ASSERT(deferred || dll->IsLoaded() == PR_FALSE);
+
+ nsresult res;
+ nsCOMPtr<nsIServiceManager> serviceMgr;
+ res = NS_GetServiceManager(getter_AddRefs(serviceMgr));
+ if (NS_FAILED(res)) return res;
+
+ if (dll->Load() == PR_FALSE)
+ {
+ // Cannot load. Probably not a dll.
+ char errorMsg[1024] = "Cannot get error from nspr. Not enough memory.";
+ if (PR_GetErrorTextLength() < (int) sizeof(errorMsg))
+ PR_GetErrorText(errorMsg);
+
+ DumpLoadError(dll, "SelfRegisterDll", errorMsg);
+
+ return NS_ERROR_FAILURE;
+ }
+
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
+ ("nsNativeComponentLoader: Loaded \"%s\".", displayPath.get()));
+#endif
+
+ // Tell the module to self register
+ nsCOMPtr<nsIFile> fs;
+ nsCOMPtr<nsIModule> mobj;
+ res = dll->GetModule(mCompMgr, getter_AddRefs(mobj));
+ if (NS_SUCCEEDED(res))
+ {
+ /*************************************************************
+ * WARNING: Why are use introducing 'res2' here and then *
+ * later assigning it to 'res' rather than just using 'res'? *
+ * This is because this code turns up a code-generation bug *
+ * in VC6 on NT. Assigning to 'res' on the next line causes *
+ * the value of 'dll' to get nulled out! The two seem to be *
+ * getting aliased together during compilation. *
+ *************************************************************/
+ nsresult res2 = dll->GetDllSpec(getter_AddRefs(fs)); // don't change 'res2' -- see warning, above
+ if (NS_SUCCEEDED(res2)) {
+ // in the case of re-registering a component, we want to remove
+ // any optional data that this file may have had.
+ AddDependentLibrary(fs, nsnull);
+
+ res = mobj->RegisterSelf(mCompMgr, fs, registryLocation,
+ nativeComponentType);
+ }
+ else
+ {
+ res = res2; // don't take this out -- see warning, above
+
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("nsNativeComponentLoader: dll->GetDllSpec() on %s FAILED.",
+ displayPath.get()));
+#endif
+ }
+ mobj = NULL; // Force a release of the Module object before unload()
+ }
+
+ // Update the timestamp and size of the dll in registry
+ // Don't enter deferred modules in the registry, because it might only be
+ // able to register on some later autoreg, after another component has been
+ // installed.
+ if (res != NS_ERROR_FACTORY_REGISTER_AGAIN) {
+ PRInt64 modTime;
+ if (!fs)
+ return res;
+
+ fs->GetLastModifiedTime(&modTime);
+ nsCOMPtr<nsIComponentLoaderManager> manager = do_QueryInterface(mCompMgr);
+ if (!manager)
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIFile> fs;
+ res = dll->GetDllSpec(getter_AddRefs(fs));
+ if (NS_FAILED(res)) return res;
+
+ manager->SaveFileInfo(fs, registryLocation, modTime);
+ }
+
+ return res;
+}
+
+//
+// MOZ_DEMANGLE_SYMBOLS is only a linux + MOZ_DEBUG thing.
+//
+
+#if defined(MOZ_DEMANGLE_SYMBOLS)
+#include "nsTraceRefcntImpl.h" // for nsTraceRefcntImpl::DemangleSymbol()
+#endif
+
+nsresult
+nsNativeComponentLoader::DumpLoadError(nsDll *dll,
+ const char *aCallerName,
+ const char *aNsprErrorMsg)
+{
+ PR_ASSERT(aCallerName != NULL);
+
+ if (nsnull == dll || nsnull == aNsprErrorMsg)
+ return NS_OK;
+
+ nsCAutoString errorMsg(aNsprErrorMsg);
+
+#if defined(MOZ_DEMANGLE_SYMBOLS)
+ // Demangle undefined symbols
+ nsCAutoString undefinedMagicString("undefined symbol:");
+
+ PRInt32 offset = errorMsg.Find(undefinedMagicString, PR_TRUE);
+
+ if (offset != kNotFound)
+ {
+ nsCAutoString symbol(errorMsg);
+ nsCAutoString demangledSymbol;
+
+ symbol.Cut(0,offset);
+
+ symbol.Cut(0,undefinedMagicString.Length());
+
+ symbol.StripWhitespace();
+
+ char demangled[4096] = "\0";
+
+ nsTraceRefcntImpl::DemangleSymbol(symbol.get(),demangled,sizeof(demangled));
+
+ if (demangled && *demangled != '\0')
+ demangledSymbol = demangled;
+
+ if (!demangledSymbol.IsEmpty())
+ {
+ nsCAutoString tmp(errorMsg);
+
+
+ tmp.Cut(offset + undefinedMagicString.Length(),
+ tmp.Length() - offset - undefinedMagicString.Length());
+
+ tmp += " \n";
+
+ tmp += demangledSymbol;
+
+ errorMsg = tmp;
+ }
+ }
+#endif // MOZ_DEMANGLE_SYMBOLS
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+#ifdef DEBUG
+ fprintf(stderr,
+ "nsNativeComponentLoader: %s(%s) Load FAILED with error: %s\n",
+ aCallerName,
+ displayPath.get(),
+ errorMsg.get());
+#endif
+
+ // Do NSPR log
+#ifdef PR_LOGGING
+ PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
+ ("nsNativeComponentLoader: %s(%s) Load FAILED with error: %s",
+ aCallerName,
+ displayPath.get(),
+ errorMsg.get()));
+#endif
+ return NS_OK;
+}
+
+nsresult
+nsNativeComponentLoader::SelfUnregisterDll(nsDll *dll)
+{
+ nsresult res;
+ nsCOMPtr<nsIServiceManager> serviceMgr;
+ res = NS_GetServiceManager(getter_AddRefs(serviceMgr));
+ if (NS_FAILED(res)) return res;
+
+ if (dll->Load() == PR_FALSE)
+ {
+ // Cannot load. Probably not a dll.
+ return(NS_ERROR_FAILURE);
+ }
+
+ // Tell the module to self register
+ nsCOMPtr<nsIModule> mobj;
+ res = dll->GetModule(mCompMgr, getter_AddRefs(mobj));
+ if (NS_SUCCEEDED(res))
+ {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("nsNativeComponentLoader: %s using nsIModule to unregister self.", displayPath.get()));
+#endif
+ nsCOMPtr<nsIFile> fs;
+ res = dll->GetDllSpec(getter_AddRefs(fs));
+ if (NS_FAILED(res)) return res;
+ // Get registry location for spec
+ nsXPIDLCString registryName;
+
+ // what I want to do here is QI for a Component Registration Manager. Since this
+ // has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
+ nsCOMPtr<nsIComponentManagerObsolete> obsoleteManager = do_QueryInterface(mCompMgr, &res);
+ if (obsoleteManager)
+ res = obsoleteManager->RegistryLocationForSpec(fs, getter_Copies(registryName));
+
+ if (NS_FAILED(res)) return res;
+ mobj->UnregisterSelf(mCompMgr, fs, registryName);
+ }
+ return res;
+}
+
+nsresult
+nsNativeComponentLoader::AutoUnregisterComponent(PRInt32 when,
+ nsIFile *component,
+ PRBool *unregistered)
+{
+
+ nsresult rv = NS_ERROR_FAILURE;
+
+ *unregistered = PR_FALSE;
+
+ nsXPIDLCString persistentDescriptor;
+ // what I want to do here is QI for a Component Registration Manager. Since this
+ // has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
+ nsCOMPtr<nsIComponentManagerObsolete> obsoleteManager = do_QueryInterface(mCompMgr, &rv);
+ if (obsoleteManager)
+ rv = obsoleteManager->RegistryLocationForSpec(component,
+ getter_Copies(persistentDescriptor));
+ if (NS_FAILED(rv)) return rv;
+
+ // Notify observers, if any, of autoregistration work
+ nsCOMPtr<nsIObserverService> observerService =
+ do_GetService("@mozilla.org/observer-service;1", &rv);
+ if (NS_SUCCEEDED(rv))
+ {
+ nsCOMPtr<nsIServiceManager> mgr;
+ rv = NS_GetServiceManager(getter_AddRefs(mgr));
+ if (NS_SUCCEEDED(rv))
+ {
+ (void) observerService->NotifyObservers(mgr,
+ NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID,
+ NS_LITERAL_STRING("Unregistering native component").get());
+ }
+ }
+
+ nsDll *dll = NULL;
+ rv = CreateDll(component, persistentDescriptor, &dll);
+ if (NS_FAILED(rv) || dll == NULL) return rv;
+
+ rv = SelfUnregisterDll(dll);
+
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, NS_SUCCEEDED(rv) ? PR_LOG_DEBUG : PR_LOG_ERROR,
+ ("nsNativeComponentLoader: AutoUnregistration for %s %s.",
+ (NS_FAILED(rv) ? "FAILED" : "succeeded"), displayPath.get()));
+#endif
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Remove any autoreg info about this dll
+ nsCStringKey key(persistentDescriptor);
+ mDllStore.RemoveAndDelete(&key);
+
+ nsCOMPtr<nsIComponentLoaderManager> manager = do_QueryInterface(mCompMgr);
+ NS_ASSERTION(manager, "Something is terribly wrong");
+
+ manager->RemoveFileInfo(component, nsnull);
+
+ *unregistered = PR_TRUE;
+ return rv;
+}
+
+nsresult
+nsNativeComponentLoader::AutoRegisterComponent(PRInt32 when,
+ nsIFile *component,
+ PRBool *registered)
+{
+ nsresult rv;
+ if (!registered)
+ return NS_ERROR_NULL_POINTER;
+
+ *registered = PR_FALSE;
+
+#ifndef VBOX
+ /* this should be a pref or registry entry, or something */
+ static const char *ValidDllExtensions[] = {
+ ".dll", /* Windows */
+ ".so", /* Unix */
+ ".shlb", /* Mac ? */
+ ".dso", /* Unix ? */
+ ".dylib", /* Unix: Mach */
+ ".so.1.0", /* Unix: BSD */
+ ".sl", /* Unix: HP-UX */
+#if defined(VMS)
+ ".exe", /* Open VMS */
+#endif
+ ".dlm", /* new for all platforms */
+ NULL
+ };
+
+ *registered = PR_FALSE;
+
+#if 0
+ // This is a performance hit on mac. Since we have already checked
+ // this; plus is we dont, load will fail anyway later on, this
+ // is being commented out.
+
+ // Ensure we are dealing with a file as opposed to a dir
+ PRBool b = PR_FALSE;
+
+ rv = component->IsFile(&b);
+ if (NS_FAILED(rv) || !b)
+ return rv;
+#endif /* 0 */
+
+ // deal only with files that have a valid extension
+ PRBool validExtension = PR_FALSE;
+
+#if defined(XP_MAC) // sdagley dougt fix
+ // rjc - on Mac, check the file's type code (skip checking the creator code)
+
+ nsCOMPtr<nsILocalFileMac> localFileMac = do_QueryInterface(component);
+ if (localFileMac)
+ {
+ OSType type;
+ rv = localFileMac->GetFileType(&type);
+ if (NS_SUCCEEDED(rv))
+ {
+ // on Mac, Mozilla shared libraries are of type 'shlb'
+ // Note: we don't check the creator (which for Mozilla is 'MOZZ')
+ // so that 3rd party shared libraries will be noticed!
+ validExtension = ((type == 'shlb') || (type == 'NSPL'));
+ }
+ }
+
+#else
+ nsCAutoString leafName;
+ rv = component->GetNativeLeafName(leafName);
+ if (NS_FAILED(rv)) return rv;
+ int flen = leafName.Length();
+ for (int i=0; ValidDllExtensions[i] != NULL; i++)
+ {
+ int extlen = PL_strlen(ValidDllExtensions[i]);
+
+ // Does fullname end with this extension
+ if (flen >= extlen &&
+ !PL_strcasecmp(leafName.get() + (flen - extlen), ValidDllExtensions[i])
+ )
+ {
+ validExtension = PR_TRUE;
+ break;
+ }
+ }
+#endif
+
+ if (validExtension == PR_FALSE)
+ // Skip invalid extensions
+ return NS_OK;
+
+#else /* VBOX */
+ /* VBox: Only one valid suffix exist, so dispense with the the list. */
+# ifdef RT_OS_DARWIN
+# ifdef VBOX_IN_32_ON_64_MAIN_API
+ static const char s_szSuff[] = "-x86.dylib";
+# else
+ static const char s_szSuff[] = ".dylib";
+ static const char s_szSuffInvalid[] = "-x86.dylib";
+# endif
+# elif defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
+# ifdef VBOX_IN_32_ON_64_MAIN_API
+ static const char s_szSuff[] = "-x86.dll";
+#else
+ static const char s_szSuff[] = ".dll";
+ static const char s_szSuffInvalid[] = "-x86.dll";
+# endif
+# else
+# ifdef VBOX_IN_32_ON_64_MAIN_API
+ static const char s_szSuff[] = "-x86.so";
+#else
+ static const char s_szSuff[] = ".so";
+ static const char s_szSuffInvalid[] = "-x86.so";
+# endif
+# endif
+
+ nsCAutoString strLeafName;
+ rv = component->GetNativeLeafName(strLeafName);
+ if (NS_FAILED(rv))
+ return rv;
+ size_t cchLeafName = strLeafName.Length();
+ if ( cchLeafName <= sizeof(s_szSuff)
+ || PL_strcasecmp(strLeafName.get() + cchLeafName - sizeof(s_szSuff) + 1, s_szSuff))
+ {
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("Skipping '%s'...", strLeafName.get()));
+ return NS_OK; /* skip */
+ }
+# ifndef VBOX_IN_32_ON_64_MAIN_API
+ if ( cchLeafName >= sizeof(s_szSuffInvalid)
+ && !PL_strcasecmp(strLeafName.get() + cchLeafName - sizeof(s_szSuffInvalid) + 1, s_szSuffInvalid))
+ {
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("Skipping '%s' (#2)...", strLeafName.get()));
+ return NS_OK; /* skip */
+ }
+# endif
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("... '%s'", strLeafName.get()));
+#endif /* VBOX */
+
+ nsXPIDLCString persistentDescriptor;
+ // what I want to do here is QI for a Component Registration Manager. Since this
+ // has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
+ nsCOMPtr<nsIComponentManagerObsolete> obsoleteManager = do_QueryInterface(mCompMgr, &rv);
+ if (obsoleteManager)
+ rv = obsoleteManager->RegistryLocationForSpec(component,
+ getter_Copies(persistentDescriptor));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCStringKey key(persistentDescriptor);
+
+ // Get the registry representation of the dll, if any
+ nsDll *dll;
+ rv = CreateDll(component, persistentDescriptor, &dll);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (dll != NULL)
+ {
+ // We already have seen this dll. Check if this dll changed
+ if (!dll->HasChanged())
+ {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ // Dll hasn't changed. Skip.
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
+ ("nsNativeComponentLoader: + nsDll not changed \"%s\". Skipping...",
+ displayPath.get()));
+#endif
+ *registered = PR_TRUE;
+ return NS_OK;
+ }
+
+ // Aagh! the dll has changed since the last time we saw it.
+ // re-register dll
+
+
+ // Notify observers, if any, of autoregistration work
+ nsCOMPtr<nsIObserverService> observerService =
+ do_GetService("@mozilla.org/observer-service;1", &rv);
+ if (NS_SUCCEEDED(rv))
+ {
+ nsCOMPtr<nsIServiceManager> mgr;
+ rv = NS_GetServiceManager(getter_AddRefs(mgr));
+ if (NS_SUCCEEDED(rv))
+ {
+ // this string can't come from a string bundle, because we
+ // don't have string bundles yet.
+ NS_ConvertASCIItoUCS2 fileName("(no name)");
+
+ // get the file name
+ nsCOMPtr<nsIFile> dllSpec;
+ if (NS_SUCCEEDED(dll->GetDllSpec(getter_AddRefs(dllSpec))) && dllSpec)
+ {
+ dllSpec->GetLeafName(fileName);
+ }
+
+ // this string can't come from a string bundle, because we
+ // don't have string bundles yet.
+ (void) observerService->
+ NotifyObservers(mgr,
+ NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID,
+ PromiseFlatString(NS_LITERAL_STRING("Registering native component ") +
+ fileName).get());
+ }
+ }
+
+ if (dll->IsLoaded())
+ {
+ // We loaded the old version of the dll and now we find that the
+ // on-disk copy if newer. Try to unload the dll.
+ nsCOMPtr<nsIServiceManager> serviceMgr;
+ rv = NS_GetServiceManager(getter_AddRefs(serviceMgr));
+
+ rv = nsFreeLibrary(dll, serviceMgr, when);
+ if (NS_FAILED(rv))
+ {
+ // THIS IS THE WORST SITUATION TO BE IN.
+ // Dll doesn't want to be unloaded. Cannot re-register
+ // this dll.
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsNativeComponentLoader: *** Dll already loaded. "
+ "Cannot unload either. Hence cannot re-register "
+ "\"%s\". Skipping...", displayPath.get()));
+#endif
+ return rv;
+ }
+ else {
+ // dll doesn't have a CanUnload proc. Guess it is
+ // ok to unload it.
+ dll->Unload();
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
+ ("nsNativeComponentLoader: + Unloading \"%s\". (no CanUnloadProc).",
+ displayPath.get()));
+#endif
+ }
+
+ } // dll isloaded
+
+ // Sanity.
+ if (dll->IsLoaded())
+ {
+ // We went through all the above to make sure the dll
+ // is unloaded. And here we are with the dll still
+ // loaded. Whoever taught dp programming...
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsNativeComponentLoader: Dll still loaded. Cannot re-register "
+ "\"%s\". Skipping...", displayPath.get()));
+#endif
+ return NS_ERROR_FAILURE;
+ }
+ } // dll != NULL
+ else
+ {
+ // Create and add the dll to the mDllStore
+ // It is ok to do this even if the creation of nsDll
+ // didnt succeed. That way we wont do this again
+ // when we encounter the same dll.
+ dll = new nsDll(component, this);
+ if (dll == NULL)
+ return NS_ERROR_OUT_OF_MEMORY;
+ mDllStore.Put(&key, (void *) dll);
+ } // dll == NULL
+
+ // Either we are seeing the dll for the first time or the dll has
+ // changed since we last saw it and it is unloaded successfully.
+ //
+ // Now we can try register the dll for sure.
+ nsresult res = SelfRegisterDll(dll, persistentDescriptor, PR_FALSE);
+ if (NS_FAILED(res))
+ {
+ if (res == NS_ERROR_FACTORY_REGISTER_AGAIN) {
+ /* defer for later loading */
+ mDeferredComponents.AppendElement(dll);
+ *registered = PR_TRUE;
+ return NS_OK;
+ } else {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
+ ("nsNativeComponentLoader: Autoregistration FAILED for "
+ "\"%s\". Skipping...", displayPath.get()));
+#endif
+ return NS_ERROR_FACTORY_NOT_REGISTERED;
+ }
+ }
+ else
+ {
+#ifdef PR_LOGGING
+ nsXPIDLCString displayPath;
+ dll->GetDisplayPath(displayPath);
+
+ PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
+ ("nsNativeComponentLoader: Autoregistration Passed for "
+ "\"%s\".", displayPath.get()));
+#endif
+ // Marking dll along with modified time and size in the
+ // registry happens at PlatformRegister(). No need to do it
+ // here again.
+ *registered = PR_TRUE;
+ }
+ return NS_OK;
+}
+
+nsresult
+nsNativeComponentLoader::RegisterDeferredComponents(PRInt32 aWhen,
+ PRBool *aRegistered)
+{
+#ifdef DEBUG
+ fprintf(stderr, "nNCL: registering deferred (%d)\n",
+ mDeferredComponents.Count());
+#endif
+ *aRegistered = PR_FALSE;
+ if (!mDeferredComponents.Count())
+ return NS_OK;
+
+ for (int i = mDeferredComponents.Count() - 1; i >= 0; i--) {
+ nsDll *dll = NS_STATIC_CAST(nsDll *, mDeferredComponents[i]);
+ nsresult rv = SelfRegisterDll(dll,
+ nsnull,
+ PR_TRUE);
+ if (rv != NS_ERROR_FACTORY_REGISTER_AGAIN) {
+ if (NS_SUCCEEDED(rv))
+ *aRegistered = PR_TRUE;
+ mDeferredComponents.RemoveElementAt(i);
+ }
+ }
+#ifdef DEBUG
+ if (*aRegistered)
+ fprintf(stderr, "nNCL: registered deferred, %d left\n",
+ mDeferredComponents.Count());
+ else
+ fprintf(stderr, "nNCL: didn't register any components, %d left\n",
+ mDeferredComponents.Count());
+#endif
+ /* are there any fatal errors? */
+ return NS_OK;
+}
+
+nsresult
+nsNativeComponentLoader::OnRegister(const nsIID &aCID, const char *aType,
+ const char *aClassName,
+ const char *aContractID,
+ const char *aLocation,
+ PRBool aReplace,
+ PRBool aPersist)
+{
+ return NS_OK;
+}
+
+nsresult
+nsNativeComponentLoader::UnloadAll(PRInt32 aWhen)
+{
+ PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsNativeComponentLoader: Unloading...."));
+
+ struct freeLibrariesClosure callData;
+ callData.serviceMgr = NULL; // XXX need to get this as a parameter
+ callData.when = aWhen;
+
+ // Cycle through the dlls checking to see if they want to be unloaded
+ mDllStore.Enumerate(nsFreeLibraryEnum, &callData);
+ return NS_OK;
+}
+
+//
+// CreateDll
+// The only way to create a dll or get it from the dll cache. This will
+// be called in multiple situations:
+//
+// 1. Autoregister will create one for each dll it is trying to register. This
+// call will be passing a spec in.
+// {spec, NULL, 0, 0}
+//
+// 2. GetFactory() This will call CreateDll() with a null spec but will give
+// the registry represented name of the dll. If modtime and size are zero,
+// we will go the registry to find the right modtime and size.
+// {NULL, rel:libpref.so, 0, 0}
+//
+// 3. Prepopulation of dllCache A dll object created off a registry entry.
+// Specifically dll name is stored in rel: or abs: or lib: formats in the
+// registry along with its lastModTime and fileSize.
+// {NULL, rel:libpref.so, 8985659, 20987}
+nsresult
+nsNativeComponentLoader::CreateDll(nsIFile *aSpec,
+ const char *aLocation,
+ nsDll **aDll)
+{
+ nsDll *dll;
+ nsCOMPtr<nsIFile> dllSpec;
+ nsCOMPtr<nsIFile> spec;
+ nsresult rv;
+
+ nsCStringKey key(aLocation);
+ dll = (nsDll *)mDllStore.Get(&key);
+ if (dll)
+ {
+ *aDll = dll;
+ return NS_OK;
+ }
+
+ if (!aSpec)
+ {
+ // what I want to do here is QI for a Component Registration Manager. Since this
+ // has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
+ nsCOMPtr<nsIComponentManagerObsolete> obsoleteManager = do_QueryInterface(mCompMgr, &rv);
+ if (obsoleteManager)
+ rv = obsoleteManager->SpecForRegistryLocation(aLocation,
+ getter_AddRefs(spec));
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ else
+ {
+ spec = aSpec;
+ }
+
+ if (!dll)
+ {
+ dll = new nsDll(spec, this);
+ if (!dll)
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ *aDll = dll;
+ mDllStore.Put(&key, dll);
+ return NS_OK;
+}
+
+nsresult
+nsNativeComponentLoader::GetFactoryFromModule(nsDll *aDll, const nsCID &aCID,
+ nsIFactory **aFactory)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIModule> module;
+ rv = aDll->GetModule(mCompMgr, getter_AddRefs(module));
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ return module->GetClassObject(mCompMgr, aCID, NS_GET_IID(nsIFactory),
+ (void **)aFactory);
+}
+
+
+NS_IMETHODIMP
+nsNativeComponentLoader::AddDependentLibrary(nsIFile* aFile, const char* libName)
+{
+ nsCOMPtr<nsIComponentLoaderManager> manager = do_QueryInterface(mCompMgr);
+ if (!manager)
+ {
+ NS_WARNING("Something is terribly wrong");
+ return NS_ERROR_FAILURE;
+ }
+
+ // the native component loader uses the optional data
+ // to store a space delimited list of dependent library
+ // names
+
+ if (!libName)
+ {
+ manager->SetOptionalData(aFile, nsnull, nsnull);
+ return NS_OK;
+ }
+
+ nsXPIDLCString data;
+ manager->GetOptionalData(aFile, nsnull, getter_Copies(data));
+
+ if (!data.IsEmpty())
+ data.AppendLiteral(" ");
+
+ data.Append(nsDependentCString(libName));
+
+ manager->SetOptionalData(aFile, nsnull, data);
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.h b/src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.h
new file mode 100644
index 00000000..818596ec
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.h
@@ -0,0 +1,84 @@
+/* -*- 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) 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.h"
+#include "nsIComponentLoader.h"
+#include "nsIComponentManager.h"
+#include "nsDirectoryService.h"
+#include "nsCOMPtr.h"
+#include "nsHashtable.h"
+#include "nsVoidArray.h"
+#include "xcDll.h"
+#include "nsINativeComponentLoader.h"
+
+#ifndef nsNativeComponentLoader_h__
+#define nsNativeComponentLoader_h__
+
+class nsNativeComponentLoader : public nsIComponentLoader, public nsINativeComponentLoader {
+
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSICOMPONENTLOADER
+ NS_DECL_NSINATIVECOMPONENTLOADER
+
+ nsNativeComponentLoader();
+
+ nsIComponentManager* mCompMgr; // weak reference -- backpointer
+ nsHashtable mLoadedDependentLibs;
+
+ private:
+ nsObjectHashtable mDllStore;
+ nsVoidArray mDeferredComponents;
+
+ ~nsNativeComponentLoader() {}
+
+ NS_IMETHOD RegisterComponentsInDir(PRInt32 when, nsIFile *dir);
+
+ nsresult CreateDll(nsIFile *aSpec, const char *aLocation, nsDll **aDll);
+ nsresult SelfRegisterDll(nsDll *dll, const char *registryLocation,
+ PRBool deferred);
+ nsresult SelfUnregisterDll(nsDll *dll);
+ nsresult GetFactoryFromModule(nsDll *aDll, const nsCID &aCID,
+ nsIFactory **aFactory);
+
+ nsresult DumpLoadError(nsDll *dll,
+ const char *aCallerName,
+ const char *aNsprErrorMsg);
+};
+
+#endif /* nsNativeComponentLoader_h__ */
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsObsoleteModuleLoading.h b/src/libs/xpcom18a4/xpcom/components/nsObsoleteModuleLoading.h
new file mode 100644
index 00000000..da3e7a43
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsObsoleteModuleLoading.h
@@ -0,0 +1,27 @@
+
+#ifndef OBSOLETE_MODULE_LOADING
+/*
+ * Prototypes for dynamic library export functions. Your DLL/DSO needs to export
+ * these methods to play in the component world.
+ *
+ * THIS IS OBSOLETE. Look at nsIModule.idl
+ */
+
+extern "C" NS_EXPORT nsresult NSGetFactory(nsISupports* aServMgr,
+ const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFactory **aFactory);
+extern "C" NS_EXPORT PRBool NSCanUnload(nsISupports* aServMgr);
+extern "C" NS_EXPORT nsresult NSRegisterSelf(nsISupports* aServMgr, const char *fullpath);
+extern "C" NS_EXPORT nsresult NSUnregisterSelf(nsISupports* aServMgr, const char *fullpath);
+
+typedef nsresult (*nsFactoryProc)(nsISupports* aServMgr,
+ const nsCID &aClass,
+ const char *aClassName,
+ const char *aContractID,
+ nsIFactory **aFactory);
+typedef PRBool (*nsCanUnloadProc)(nsISupports* aServMgr);
+typedef nsresult (*nsRegisterProc)(nsISupports* aServMgr, const char *path);
+typedef nsresult (*nsUnregisterProc)(nsISupports* aServMgr, const char *path);
+#endif /* OBSOLETE_MODULE_LOADING */
diff --git a/src/libs/xpcom18a4/xpcom/components/nsServiceManagerObsolete.cpp b/src/libs/xpcom18a4/xpcom/components/nsServiceManagerObsolete.cpp
new file mode 100644
index 00000000..dd6856d6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsServiceManagerObsolete.cpp
@@ -0,0 +1,155 @@
+/* ***** 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.
+ *
+ * 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 "nsIServiceManager.h"
+#include "nsIServiceManagerObsolete.h"
+#include "nsComponentManager.h"
+
+extern PRBool gXPCOMShuttingDown;
+
+// Global service manager interface (see nsIServiceManagerObsolete.h)
+
+nsresult
+nsServiceManager::GetGlobalServiceManager(nsIServiceManager* *result)
+{
+ if (gXPCOMShuttingDown)
+ return NS_ERROR_UNEXPECTED;
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ return NS_ERROR_UNEXPECTED;
+
+ // this method does not addref for historical reasons.
+ // we return the nsIServiceManagerObsolete interface via a cast.
+ *result = (nsIServiceManager*) NS_STATIC_CAST(nsIServiceManagerObsolete*,
+ nsComponentManagerImpl::gComponentManager);
+ return NS_OK;
+}
+
+nsresult
+nsServiceManager::ShutdownGlobalServiceManager(nsIServiceManager* *result)
+{
+ return NS_OK;
+}
+
+nsresult
+nsServiceManager::GetService(const nsCID& aClass, const nsIID& aIID,
+ nsISupports* *result,
+ nsIShutdownListener* shutdownListener)
+{
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ return NS_ERROR_UNEXPECTED;
+
+ return nsComponentManagerImpl::gComponentManager->GetService(aClass, aIID, (void**)result);
+}
+
+nsresult
+nsServiceManager::ReleaseService(const nsCID& aClass, nsISupports* service,
+ nsIShutdownListener* shutdownListener)
+{
+ NS_IF_RELEASE(service);
+ return NS_OK;
+}
+
+nsresult
+nsServiceManager::RegisterService(const nsCID& aClass, nsISupports* aService)
+{
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ return NS_ERROR_UNEXPECTED;
+
+ return nsComponentManagerImpl::gComponentManager->RegisterService(aClass, aService);
+}
+
+nsresult
+nsServiceManager::UnregisterService(const nsCID& aClass)
+{
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ return NS_ERROR_UNEXPECTED;
+
+ return nsComponentManagerImpl::gComponentManager->UnregisterService(aClass);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// let's do it again, this time with ContractIDs...
+
+nsresult
+nsServiceManager::GetService(const char* aContractID, const nsIID& aIID,
+ nsISupports* *result,
+ nsIShutdownListener* shutdownListener)
+{
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ return NS_ERROR_UNEXPECTED;
+
+ return nsComponentManagerImpl::gComponentManager->GetServiceByContractID(aContractID, aIID, (void**)result);
+}
+
+nsresult
+nsServiceManager::ReleaseService(const char* aContractID, nsISupports* service,
+ nsIShutdownListener* shutdownListener)
+{
+ NS_RELEASE(service);
+ return NS_OK;
+}
+
+nsresult
+nsServiceManager::RegisterService(const char* aContractID, nsISupports* aService)
+{
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ return NS_ERROR_UNEXPECTED;
+
+ return nsComponentManagerImpl::gComponentManager->RegisterService(aContractID, aService);
+}
+
+nsresult
+nsServiceManager::UnregisterService(const char* aContractID)
+{
+ // Don't create the global service manager here because we might
+ // be shutting down, and releasing all the services in its
+ // destructor
+ if (gXPCOMShuttingDown)
+ return NS_OK;
+
+ if (nsComponentManagerImpl::gComponentManager == nsnull)
+ return NS_ERROR_UNEXPECTED;
+
+ return nsComponentManagerImpl::gComponentManager->UnregisterService(aContractID);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsStaticComponent.h b/src/libs/xpcom18a4/xpcom/components/nsStaticComponent.h
new file mode 100644
index 00000000..c770afdc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsStaticComponent.h
@@ -0,0 +1,52 @@
+/* -*- 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) 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 "nsIModule.h"
+#include "nsModule.h"
+
+struct nsStaticModuleInfo {
+ const char *name;
+ nsGetModuleProc getModule;
+};
+
+// Must be implemented by some part of the app, if we're building the
+// static component loader.
+extern "C" {
+typedef nsresult (PR_CALLBACK *NSGetStaticModuleInfoFunc)(nsStaticModuleInfo **info, PRUint32 *count);
+extern NS_COM NSGetStaticModuleInfoFunc NSGetStaticModuleInfo;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/components/nsStaticComponentLoader.cpp b/src/libs/xpcom18a4/xpcom/components/nsStaticComponentLoader.cpp
new file mode 100644
index 00000000..b17b74bb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/nsStaticComponentLoader.cpp
@@ -0,0 +1,317 @@
+/* -*- 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) 2000
+ * 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 "nsStaticComponent.h"
+#include "nsIComponentLoader.h"
+#include "nsVoidArray.h"
+#include "pldhash.h"
+#include NEW_H
+#include <stdio.h>
+
+struct StaticModuleInfo : public PLDHashEntryHdr {
+ nsStaticModuleInfo info;
+ nsCOMPtr<nsIModule> module;
+};
+
+class nsStaticComponentLoader : public nsIComponentLoader
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSICOMPONENTLOADER
+
+ nsStaticComponentLoader() :
+ mAutoRegistered(PR_FALSE), mLoadedInfo(PR_FALSE) {
+ }
+
+ static NS_HIDDEN_(PLDHashOperator) PR_CALLBACK
+ info_RegisterSelf(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg);
+
+private:
+ ~nsStaticComponentLoader() {
+ if (mInfoHash.ops)
+ PL_DHashTableFinish(&mInfoHash);
+ }
+
+protected:
+ nsresult GetModuleInfo();
+ nsresult GetInfoFor(const char *aLocation, StaticModuleInfo **retval);
+
+ PRBool mAutoRegistered;
+ PRBool mLoadedInfo;
+ nsCOMPtr<nsIComponentManager> mComponentMgr;
+ PLDHashTable mInfoHash;
+ static PLDHashTableOps sInfoHashOps;
+ nsVoidArray mDeferredComponents;
+};
+
+PR_STATIC_CALLBACK(void)
+info_ClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
+{
+ StaticModuleInfo *info = NS_STATIC_CAST(StaticModuleInfo *, entry);
+ info->module = 0;
+ info->~StaticModuleInfo();
+}
+
+PR_STATIC_CALLBACK(PRBool)
+info_InitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, const void *key)
+{
+ // Construct so that our nsCOMPtr is zeroed, etc.
+ new (NS_STATIC_CAST(void *, entry)) StaticModuleInfo();
+ return PR_TRUE;
+}
+
+/* static */ PLDHashTableOps nsStaticComponentLoader::sInfoHashOps = {
+ PL_DHashAllocTable, PL_DHashFreeTable,
+ PL_DHashGetKeyStub, PL_DHashStringKey, PL_DHashMatchStringKey,
+ PL_DHashMoveEntryStub, info_ClearEntry,
+ PL_DHashFinalizeStub, info_InitEntry
+};
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsStaticComponentLoader, nsIComponentLoader)
+
+NS_COM NSGetStaticModuleInfoFunc NSGetStaticModuleInfo;
+
+nsresult
+nsStaticComponentLoader::GetModuleInfo()
+{
+ if (mLoadedInfo)
+ return NS_OK;
+
+ if (!mInfoHash.ops) { // creation failed in init, why are we here?
+ NS_WARNING("operating on uninitialized static component loader");
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ if (! NSGetStaticModuleInfo) {
+ // We're a static build with no static modules to
+ // register. This can happen in shared uses (such as the GRE)
+ return NS_OK;
+ }
+
+ nsStaticModuleInfo *infoList;
+ PRUint32 count;
+ nsresult rv;
+ if (NS_FAILED(rv = (*NSGetStaticModuleInfo)(&infoList, &count)))
+ return rv;
+ for (PRUint32 i = 0; i < count; i++) {
+ StaticModuleInfo *info =
+ NS_STATIC_CAST(StaticModuleInfo *,
+ PL_DHashTableOperate(&mInfoHash, infoList[i].name,
+ PL_DHASH_ADD));
+ if (!info)
+ return NS_ERROR_OUT_OF_MEMORY;
+ info->info = infoList[i];
+ }
+
+ mLoadedInfo = PR_TRUE;
+ return NS_OK;
+}
+
+nsresult
+nsStaticComponentLoader::GetInfoFor(const char *aLocation,
+ StaticModuleInfo **retval)
+{
+ nsresult rv;
+ if (NS_FAILED(rv = GetModuleInfo()))
+ return rv;
+
+ StaticModuleInfo *info =
+ NS_STATIC_CAST(StaticModuleInfo *,
+ PL_DHashTableOperate(&mInfoHash, aLocation,
+ PL_DHASH_LOOKUP));
+
+ if (PL_DHASH_ENTRY_IS_FREE(info))
+ return NS_ERROR_FACTORY_NOT_REGISTERED;
+
+ if (!info->module) {
+ rv = info->info.getModule(mComponentMgr, nsnull,
+ getter_AddRefs(info->module));
+#ifdef DEBUG
+ fprintf(stderr, "nSCL: GetInfoFor(\"%s\"): %x\n", aLocation, rv);
+#endif
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ *retval = info;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticComponentLoader::Init(nsIComponentManager *mgr, nsISupports *aReg)
+{
+ mComponentMgr = mgr;
+ if (!PL_DHashTableInit(&mInfoHash, &sInfoHashOps, nsnull,
+ sizeof(StaticModuleInfo), 1024)) {
+ mInfoHash.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ return NS_OK;
+}
+
+PLDHashOperator PR_CALLBACK
+nsStaticComponentLoader::info_RegisterSelf(PLDHashTable *table,
+ PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg)
+{
+ nsStaticComponentLoader *loader = NS_STATIC_CAST(nsStaticComponentLoader *,
+ arg);
+ nsIComponentManager *mgr = loader->mComponentMgr;
+ StaticModuleInfo *info = NS_STATIC_CAST(StaticModuleInfo *, hdr);
+
+ nsresult rv;
+ if (!info->module) {
+ rv = info->info.getModule(mgr, nsnull, getter_AddRefs(info->module));
+#ifdef DEBUG
+ fprintf(stderr, "nSCL: getModule(\"%s\"): %x\n", info->info.name, rv);
+#endif
+ if (NS_FAILED(rv))
+ return PL_DHASH_NEXT; // oh well.
+ }
+
+ rv = info->module->RegisterSelf(mgr, nsnull, info->info.name,
+ staticComponentType);
+#ifdef DEBUG
+ fprintf(stderr, "nSCL: autoreg of \"%s\": %x\n", info->info.name, rv);
+#endif
+
+ if (rv == NS_ERROR_FACTORY_REGISTER_AGAIN)
+ loader->mDeferredComponents.AppendElement(info);
+
+ return PL_DHASH_NEXT;
+}
+
+NS_IMETHODIMP
+nsStaticComponentLoader::AutoRegisterComponents(PRInt32 when, nsIFile *dir)
+{
+ if (mAutoRegistered)
+ return NS_OK;
+
+ // if a directory has been explicitly specified, then return early. we
+ // don't load static components from disk ;)
+ if (dir)
+ return NS_OK;
+
+ nsresult rv;
+ if (NS_FAILED(rv = GetModuleInfo()))
+ return rv;
+
+ PL_DHashTableEnumerate(&mInfoHash, info_RegisterSelf, this);
+
+ mAutoRegistered = PR_TRUE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticComponentLoader::AutoUnregisterComponent(PRInt32 when,
+ nsIFile *component,
+ PRBool *retval)
+{
+ *retval = PR_FALSE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticComponentLoader::AutoRegisterComponent(PRInt32 when, nsIFile *component,
+ PRBool *retval)
+{
+ *retval = PR_FALSE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticComponentLoader::RegisterDeferredComponents(PRInt32 when,
+ PRBool *aRegistered)
+{
+ *aRegistered = PR_FALSE;
+ if (!mDeferredComponents.Count())
+ return NS_OK;
+
+ for (int i = mDeferredComponents.Count() - 1; i >= 0; i--) {
+ StaticModuleInfo *info = NS_STATIC_CAST(StaticModuleInfo *,
+ mDeferredComponents[i]);
+ nsresult rv = info->module->RegisterSelf(mComponentMgr, nsnull,
+ info->info.name,
+ staticComponentType);
+ if (rv != NS_ERROR_FACTORY_REGISTER_AGAIN) {
+ if (NS_SUCCEEDED(rv))
+ *aRegistered = PR_TRUE;
+ mDeferredComponents.RemoveElementAt(i);
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticComponentLoader::OnRegister(const nsCID &aCID, const char *aType,
+ const char *aClassName,
+ const char *aContractID,
+ const char *aLocation,
+ PRBool aReplace, PRBool aPersist)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticComponentLoader::UnloadAll(PRInt32 aWhen)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStaticComponentLoader::GetFactory(const nsCID &aCID, const char *aLocation,
+ const char *aType, nsIFactory **_retval)
+{
+ StaticModuleInfo *info;
+ nsresult rv;
+
+ if (NS_FAILED(rv = GetInfoFor(aLocation, &info)))
+ return rv;
+
+ return info->module->GetClassObject(mComponentMgr, aCID,
+ NS_GET_IID(nsIFactory),
+ (void **)_retval);
+}
+
+nsresult
+NS_NewStaticComponentLoader(nsIComponentLoader **retval)
+{
+ NS_IF_ADDREF(*retval = NS_STATIC_CAST(nsIComponentLoader *,
+ new nsStaticComponentLoader));
+ return *retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
diff --git a/src/libs/xpcom18a4/xpcom/components/xcDll.cpp b/src/libs/xpcom18a4/xpcom/components/xcDll.cpp
new file mode 100644
index 00000000..494cf174
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/xcDll.cpp
@@ -0,0 +1,457 @@
+/* -*- 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 ***** */
+
+/* nsDll
+ *
+ * Abstraction of a Dll. Stores modifiedTime and size for easy detection of
+ * change in dll.
+ *
+ * dp Suresh <dp@netscape.com>
+ */
+
+#include "xcDll.h"
+#include "nsDebug.h"
+#include "nsIComponentManager.h"
+#include "nsIComponentLoaderManager.h"
+#include "nsIModule.h"
+#include "nsILocalFile.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsDirectoryServiceUtils.h"
+#include "nsCOMPtr.h"
+#include "nsCRT.h"
+#include "nsString.h"
+#include "nsITimelineService.h"
+#include "nsModule.h"
+#ifdef DEBUG
+#if defined(VMS)
+#include <lib$routines.h>
+#include <ssdef.h>
+#elif defined(XP_MACOSX)
+#include <signal.h>
+#endif
+#endif /* defined(DEBUG) */
+
+#include "nsTraceRefcntImpl.h"
+
+#define UNLOAD_DEPENDENT_LIBS
+#ifdef HPUX
+#undef UNLOAD_DEPENDENT_LIBS
+#endif
+
+#include "nsNativeComponentLoader.h"
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+# include "nsMemory.h"
+#endif
+
+nsDll::nsDll(nsIFile *dllSpec, nsNativeComponentLoader *loader)
+ : m_dllSpec(do_QueryInterface(dllSpec)),
+ m_instance(NULL),
+ m_moduleObject(NULL),
+ m_loader(loader),
+ m_markForUnload(PR_FALSE)
+{
+ NS_ASSERTION(loader, "Null loader when creating a nsDLL");
+}
+
+nsDll::~nsDll(void)
+{
+ //#if DEBUG_dougt
+ // The dll gets deleted when the dllStore is destroyed. This happens on
+ // app shutdown. At that point, unloading dlls can cause crashes if we have
+ // - dll dependencies
+ // - callbacks
+ // - static dtors
+ // Hence turn it back on after all the above have been removed.
+ //Unload();
+ //#endif
+}
+
+void
+nsDll::GetDisplayPath(nsACString& aLeafName)
+{
+ m_dllSpec->GetNativeLeafName(aLeafName);
+
+ if (aLeafName.IsEmpty())
+ aLeafName.AssignLiteral("unknown!");
+}
+
+PRBool
+nsDll::HasChanged()
+{
+ nsCOMPtr<nsIComponentLoaderManager> manager = do_QueryInterface(m_loader->mCompMgr);
+ if (!manager)
+ return PR_TRUE;
+
+ // If mod date has changed, then dll has changed
+ PRInt64 currentDate;
+ nsresult rv = m_dllSpec->GetLastModifiedTime(&currentDate);
+ if (NS_FAILED(rv))
+ return PR_TRUE;
+ PRBool changed = PR_TRUE;
+ manager->HasFileChanged(m_dllSpec, nsnull, currentDate, &changed);
+ return changed;
+}
+
+PRBool nsDll::Load(void)
+{
+ if (m_instance != NULL)
+ {
+ // Already loaded
+ return (PR_TRUE);
+ }
+
+ if (m_dllSpec)
+ {
+#ifdef NS_BUILD_REFCNT_LOGGING
+ nsTraceRefcntImpl::SetActivityIsLegal(PR_FALSE);
+#endif
+
+ // Load any library dependencies
+ // The Component Loader Manager may hold onto some extra data
+ // set by either the native component loader or the native
+ // component. We assume that this data is a space delimited
+ // listing of dependent libraries which are required to be
+ // loaded prior to us loading the given component. Once, the
+ // component is loaded into memory, we can release our hold
+ // on the dependent libraries with the assumption that the
+ // component library holds a reference via the OS so loader.
+
+#if defined(XP_UNIX)
+ nsCOMPtr<nsIComponentLoaderManager> manager = do_QueryInterface(m_loader->mCompMgr);
+ if (!manager)
+ return PR_TRUE;
+
+ nsXPIDLCString extraData;
+ manager->GetOptionalData(m_dllSpec, nsnull, getter_Copies(extraData));
+
+#ifdef UNLOAD_DEPENDENT_LIBS
+ nsVoidArray dependentLibArray;
+#endif
+
+ // if there was any extra data, treat it as a listing of dependent libs
+ if (extraData != nsnull)
+ {
+ // all dependent libraries are suppose to be in the "gre" directory.
+ // note that the gre directory is the same as the "bin" directory,
+ // when there isn't a real "gre" found.
+
+ nsXPIDLCString path;
+ nsCOMPtr<nsIFile> file;
+ NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(file));
+
+ if (!file)
+ return NS_ERROR_FAILURE;
+
+ // we are talking about a file in the GRE dir. Lets append something
+ // stupid right now, so that later we can just set the leaf name.
+ file->AppendNative(NS_LITERAL_CSTRING("dummy"));
+
+# ifdef VBOX_USE_IPRT_IN_XPCOM
+ char *buffer = (char *)nsMemory::Clone(extraData, strlen(extraData) + 1);
+# else
+ char *buffer = strdup(extraData);
+# endif
+ if (!buffer)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ char* newStr;
+ char *token = nsCRT::strtok(buffer, " ", &newStr);
+ while (token!=nsnull)
+ {
+ nsCStringKey key(token);
+ if (m_loader->mLoadedDependentLibs.Get(&key)) {
+ token = nsCRT::strtok(newStr, " ", &newStr);
+ continue;
+ }
+
+ m_loader->mLoadedDependentLibs.Put(&key, (void*)1);
+
+ nsXPIDLCString libpath;
+ file->SetNativeLeafName(nsDependentCString(token));
+ file->GetNativePath(path);
+ if (!path)
+ return NS_ERROR_FAILURE;
+
+ // Load this dependent library with the global flag and stash
+ // the result for later so that we can unload it.
+ PRLibSpec libSpec;
+ libSpec.type = PR_LibSpec_Pathname;
+
+ // if the depend library path starts with a / we are
+ // going to assume that it is a full path and should
+ // be loaded without prepending the gre diretory
+ // location. We could have short circuited the
+ // SetNativeLeafName above, but this is clearer and
+ // the common case is a relative path.
+
+ if (token[0] == '/')
+ libSpec.value.pathname = token;
+ else
+ libSpec.value.pathname = path;
+
+ PRLibrary* lib = PR_LoadLibraryWithFlags(libSpec, PR_LD_LAZY|PR_LD_GLOBAL);
+ // if we couldn't load the dependent library. We did the best we
+ // can. Now just let us fail later if this really was a required
+ // dependency.
+#ifdef UNLOAD_DEPENDENT_LIBS
+ if (lib)
+ dependentLibArray.AppendElement((void*)lib);
+#endif
+
+ token = nsCRT::strtok(newStr, " ", &newStr);
+ }
+# ifdef VBOX_USE_IPRT_IN_XPCOM
+ nsMemory::Free(buffer);
+# else
+ free(buffer);
+# endif
+ }
+#endif
+
+ // load the component
+ nsCOMPtr<nsILocalFile> lf(do_QueryInterface(m_dllSpec));
+ NS_ASSERTION(lf, "nsIFile here must implement a nsILocalFile");
+ lf->Load(&m_instance);
+
+#if defined(XP_UNIX)
+ // Unload any of library dependencies we loaded earlier. The assumption
+ // here is that the component will have a "internal" reference count to
+ // the dependency library we just loaded.
+ // XXX should we unload later - or even at all?
+
+#ifdef UNLOAD_DEPENDENT_LIBS
+ if (extraData != nsnull)
+ {
+ PRInt32 arrayCount = dependentLibArray.Count();
+ for (PRInt32 index = 0; index < arrayCount; index++)
+ PR_UnloadLibrary((PRLibrary*)dependentLibArray.ElementAt(index));
+ }
+#endif
+#endif
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+ nsTraceRefcntImpl::SetActivityIsLegal(PR_TRUE);
+ if (m_instance) {
+ // Inform refcnt tracer of new library so that calls through the
+ // new library can be traced.
+ nsXPIDLCString displayPath;
+ GetDisplayPath(displayPath);
+ nsTraceRefcntImpl::LoadLibrarySymbols(displayPath.get(), m_instance);
+ }
+#endif
+ }
+
+#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
+ // Debugging help for components. Component dlls need to have their
+ // symbols loaded before we can put a breakpoint in the debugger.
+ // This will help figureing out the point when the dll was loaded.
+ nsXPIDLCString displayPath;
+ GetDisplayPath(displayPath);
+ BreakAfterLoad(displayPath.get());
+#endif
+
+ return ((m_instance == NULL) ? PR_FALSE : PR_TRUE);
+}
+
+PRBool nsDll::Unload(void)
+{
+ if (m_instance == NULL)
+ return (PR_FALSE);
+
+ // Shutdown the dll
+ Shutdown();
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+ nsTraceRefcntImpl::SetActivityIsLegal(PR_FALSE);
+#endif
+ PRStatus ret = PR_UnloadLibrary(m_instance);
+#ifdef NS_BUILD_REFCNT_LOGGING
+ nsTraceRefcntImpl::SetActivityIsLegal(PR_TRUE);
+#endif
+
+ if (ret == PR_SUCCESS)
+ {
+ m_instance = NULL;
+ return (PR_TRUE);
+ }
+ else
+ return (PR_FALSE);
+}
+
+void * nsDll::FindSymbol(const char *symbol)
+{
+ if (symbol == NULL)
+ return (NULL);
+
+ // If not already loaded, load it now.
+ if (Load() != PR_TRUE)
+ return (NULL);
+
+ return(PR_FindSymbol(m_instance, symbol));
+}
+
+
+// Component dll specific functions
+nsresult nsDll::GetDllSpec(nsIFile **fsobj)
+{
+ NS_ASSERTION(m_dllSpec, "m_dllSpec NULL");
+ NS_ASSERTION(fsobj, "xcDll::GetModule : Null argument" );
+
+ *fsobj = m_dllSpec;
+ NS_ADDREF(*fsobj);
+ return NS_OK;
+}
+
+nsresult nsDll::GetModule(nsISupports *servMgr, nsIModule **cobj)
+{
+ // using the backpointer of the loader.
+ nsIComponentManager* compMgr = m_loader->mCompMgr;
+ NS_ASSERTION(compMgr, "Global Component Manager is null" );
+ if (!compMgr) return NS_ERROR_UNEXPECTED;
+
+ NS_ASSERTION(cobj, "xcDll::GetModule : Null argument" );
+
+ if (m_moduleObject)
+ {
+ NS_ADDREF(m_moduleObject);
+ *cobj = m_moduleObject;
+ return NS_OK;
+ }
+
+ // If not already loaded, load it now.
+ if (Load() != PR_TRUE) return NS_ERROR_FAILURE;
+
+ // We need a nsIFile for location
+ if (!m_dllSpec)
+ {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsGetModuleProc proc =
+ (nsGetModuleProc) FindSymbol(NS_GET_MODULE_SYMBOL);
+
+ if (proc == NULL)
+ return NS_ERROR_FACTORY_NOT_LOADED;
+
+ nsresult rv = (*proc) (compMgr, m_dllSpec, &m_moduleObject);
+ if (NS_SUCCEEDED(rv))
+ {
+ NS_ADDREF(m_moduleObject);
+ *cobj = m_moduleObject;
+ }
+ return rv;
+}
+
+
+// These are used by BreakAfterLoad, below.
+#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
+static nsCString *sBreakList[16];
+static int sBreakListCount = 0;
+#endif
+
+nsresult nsDll::Shutdown(void)
+{
+ // Release the module object if we got one
+ nsrefcnt refcnt;
+ if (m_moduleObject)
+ {
+ NS_RELEASE2(m_moduleObject, refcnt);
+ NS_ASSERTION(refcnt == 0, "Dll moduleObject refcount non zero");
+ }
+#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
+ for (int i = 0; i < sBreakListCount; i++)
+ {
+ delete sBreakList[i];
+ sBreakList[i] = nsnull;
+ }
+ sBreakListCount = 0;
+#endif
+ return NS_OK;
+
+}
+#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
+void nsDll::BreakAfterLoad(const char *nsprPath)
+{
+ static PRBool firstTime = PR_TRUE;
+
+ // return if invalid input
+ if (!nsprPath || !*nsprPath) return;
+
+ // return if nothing to break on
+ if (!firstTime && sBreakListCount == 0) return;
+
+ if (firstTime)
+ {
+ firstTime = PR_FALSE;
+ // Form the list of dlls to break on load
+ nsCAutoString envList(getenv("XPCOM_BREAK_ON_LOAD"));
+ if (envList.IsEmpty()) return;
+ PRInt32 ofset = 0;
+ PRInt32 start = 0;
+ do
+ {
+ ofset = envList.FindChar(':', start);
+ sBreakList[sBreakListCount] = new nsCString();
+ envList.Mid(*(sBreakList[sBreakListCount]), start, ofset);
+ sBreakListCount++;
+ start = ofset + 1;
+ }
+ while (ofset != -1 && 16 > sBreakListCount); // avoiding vc6.0 compiler issue. count < thinks it is starting a template
+ }
+
+ // Find the dllname part of the string
+ nsCString currentPath(nsprPath);
+ PRInt32 lastSep = currentPath.RFindCharInSet(":\\/");
+
+ for (int i=0; i<sBreakListCount; i++)
+ if (currentPath.Find(*(sBreakList[i]), PR_TRUE, lastSep) > 0)
+ {
+ // Loading a dll that we want to break on
+ // Put your breakpoint here
+ fprintf(stderr, "...Loading module %s\n", nsprPath);
+ // Break in the debugger here.
+#if defined(__i386) && defined(__GNUC__)
+ asm("int $3");
+#elif defined(VMS)
+ lib$signal(SS$_DEBUG);
+#elif defined(XP_MACOSX)
+ raise(SIGTRAP);
+#endif
+ }
+ return;
+}
+#endif /* SHOULD_IMPLEMENT_BREAKAFTERLOAD */
diff --git a/src/libs/xpcom18a4/xpcom/components/xcDll.h b/src/libs/xpcom18a4/xpcom/components/xcDll.h
new file mode 100644
index 00000000..5de5b0eb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/components/xcDll.h
@@ -0,0 +1,121 @@
+/* -*- 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 ***** */
+
+/* Dll
+ *
+ * Programmatic representation of a dll. Stores modifiedTime and size for
+ * easy detection of change in dll.
+ *
+ * dp Suresh <dp@netscape.com>
+ */
+
+#ifndef xcDll_h__
+#define xcDll_h__
+
+#include "prio.h"
+#include "prlink.h"
+#include "nsISupports.h"
+#include "nsILocalFile.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+
+class nsNativeComponentLoader;
+
+#if defined(DEBUG) && !defined(XP_BEOS)
+#define SHOULD_IMPLEMENT_BREAKAFTERLOAD
+#endif
+
+class nsIModule;
+class nsIServiceManager;
+
+typedef enum nsDllStatus
+{
+ DLL_OK = 0,
+ DLL_NO_MEM = 1,
+ DLL_STAT_ERROR = 2,
+ DLL_NOT_FILE = 3,
+ DLL_INVALID_PARAM = 4
+} nsDllStatus;
+
+class nsDll
+{
+private:
+ nsCOMPtr<nsIFile> m_dllSpec;
+ PRLibrary *m_instance;
+ nsIModule *m_moduleObject;
+ nsNativeComponentLoader *m_loader;
+ PRBool m_markForUnload;
+
+ void Init(nsIFile *dllSpec);
+
+#ifdef SHOULD_IMPLEMENT_BREAKAFTERLOAD
+ void BreakAfterLoad(const char *nsprPath);
+#endif
+
+public:
+
+ nsDll(nsIFile *dllSpec, nsNativeComponentLoader* loader);
+ ~nsDll(void);
+
+ // Dll Loading
+ PRBool Load(void);
+ PRBool Unload(void);
+ PRBool IsLoaded(void)
+ {
+ return ((m_instance != 0) ? PR_TRUE : PR_FALSE);
+ }
+ void MarkForUnload(PRBool mark) { m_markForUnload = mark; }
+ PRBool IsMarkedForUnload(void) { return m_markForUnload; }
+
+ // Shutdown the dll. This will call any on unload hook for the dll.
+ // This wont unload the dll. Unload() implicitly calls Shutdown().
+ nsresult Shutdown(void);
+
+ void *FindSymbol(const char *symbol);
+
+ PRBool HasChanged(void);
+
+ void GetDisplayPath(nsACString& string);
+
+ PRLibrary *GetInstance(void) { return (m_instance); }
+
+ // NS_RELEASE() is required to be done on objects returned
+ nsresult GetDllSpec(nsIFile **dllSpec);
+ nsresult GetModule(nsISupports *servMgr, nsIModule **mobj);
+};
+
+#endif /* xcDll_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/doc/README b/src/libs/xpcom18a4/xpcom/doc/README
new file mode 100644
index 00000000..edef8772
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/doc/README
@@ -0,0 +1,8 @@
+<HTML>
+<HEAD>
+ <TITLE>READ ME</TITLE>
+</HEAD>
+<BODY>
+
+<H4><P>
+XPCOM documentation can be found at <a href="http://www.mozilla.org/projects/xpcom>www.mozilla.org/projects/xpcom</a>
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___ */
diff --git a/src/libs/xpcom18a4/xpcom/glue/.cvsignore b/src/libs/xpcom18a4/xpcom/glue/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/glue/Makefile.in b/src/libs/xpcom18a4/xpcom/glue/Makefile.in
new file mode 100644
index 00000000..a3b1f24d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/Makefile.in
@@ -0,0 +1,86 @@
+# ***** 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
+# 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 *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+include $(srcdir)/objs.mk
+
+DIRS = standalone
+
+MODULE = xpcom
+LIBRARY_NAME = xpcomglue_s
+
+REQUIRES = $(NULL)
+
+LOCAL_INCLUDES = \
+ -I$(srcdir)/../build \
+ $(NULL)
+
+CPPSRCS = \
+ $(XPCOM_GLUE_SRC_LCSRCS) \
+ $(NULL)
+
+SDK_HEADERS = \
+ nsIGenericFactory.h \
+ nsIInterfaceRequestorUtils.h \
+ nsISupportsImpl.h \
+ nsISupportsUtils.h \
+ nsIWeakReferenceUtils.h \
+ $(XPCOM_GLUE_SRC_LEXPORTS) \
+ $(NULL)
+
+SDK_LIBRARY = \
+ $(LIB_PREFIX)xpcomglue_s.$(LIB_SUFFIX) \
+ $(NULL)
+
+# 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
+
+# hack to work around objdir bustage
+export::
+ rm -f $(XPCOM_GLUE_SRC_CSRCS:.cpp=.$(OBJ_SUFFIX))
+
+DEFINES += \
+ -D_IMPL_NS_COM
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsCOMPtr.cpp b/src/libs/xpcom18a4/xpcom/glue/nsCOMPtr.cpp
new file mode 100644
index 00000000..cac3c6d4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsCOMPtr.cpp
@@ -0,0 +1,124 @@
+/* -*- 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):
+ * 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 ***** */
+
+#include "nsCOMPtr.h"
+
+nsresult
+nsQueryInterface::operator()( const nsIID& aIID, void** answer ) const
+ {
+ nsresult status;
+ if ( mRawPtr )
+ {
+ status = mRawPtr->QueryInterface(aIID, answer);
+#ifdef NSCAP_FEATURE_TEST_NONNULL_QUERY_SUCCEEDS
+ NS_WARN_IF_FALSE(NS_SUCCEEDED(status), "interface not found---were you expecting that?");
+#endif
+ }
+ else
+ status = NS_ERROR_NULL_POINTER;
+
+ return status;
+ }
+
+nsresult
+nsQueryInterfaceWithError::operator()( const nsIID& aIID, void** answer ) const
+ {
+ nsresult status;
+ if ( mRawPtr )
+ {
+ status = mRawPtr->QueryInterface(aIID, answer);
+#ifdef NSCAP_FEATURE_TEST_NONNULL_QUERY_SUCCEEDS
+ NS_WARN_IF_FALSE(NS_SUCCEEDED(status), "interface not found---were you expecting that?");
+#endif
+ }
+ else
+ status = NS_ERROR_NULL_POINTER;
+
+ if ( mErrorPtr )
+ *mErrorPtr = status;
+ return status;
+ }
+
+nsCOMPtr_base::~nsCOMPtr_base()
+ {
+ NSCAP_LOG_RELEASE(this, mRawPtr);
+ if ( mRawPtr )
+ NSCAP_RELEASE(this, mRawPtr);
+ }
+
+void
+nsCOMPtr_base::assign_with_AddRef( nsISupports* rawPtr )
+ {
+ if ( rawPtr )
+ NSCAP_ADDREF(this, rawPtr);
+ assign_assuming_AddRef(rawPtr);
+ }
+
+void
+nsCOMPtr_base::assign_from_qi( const nsQueryInterface qi, const nsIID& iid )
+ {
+ nsISupports* newRawPtr;
+ if ( NS_FAILED( qi(iid, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
+ newRawPtr = 0;
+ assign_assuming_AddRef(newRawPtr);
+ }
+
+void
+nsCOMPtr_base::assign_from_qi_with_error( const nsQueryInterfaceWithError& qi, const nsIID& iid )
+ {
+ nsISupports* newRawPtr;
+ if ( NS_FAILED( qi(iid, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
+ newRawPtr = 0;
+ assign_assuming_AddRef(newRawPtr);
+ }
+
+void
+nsCOMPtr_base::assign_from_helper( const nsCOMPtr_helper& helper, const nsIID& iid )
+ {
+ nsISupports* newRawPtr;
+ if ( NS_FAILED( helper(iid, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
+ newRawPtr = 0;
+ assign_assuming_AddRef(newRawPtr);
+ }
+
+void**
+nsCOMPtr_base::begin_assignment()
+ {
+ assign_assuming_AddRef(0);
+ return NS_REINTERPRET_CAST(void**, &mRawPtr);
+ }
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsCOMPtr.h b/src/libs/xpcom18a4/xpcom/glue/nsCOMPtr.h
new file mode 100644
index 00000000..b5a0fd78
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsCOMPtr.h
@@ -0,0 +1,1405 @@
+/* -*- 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):
+ * Scott Collins <scc@mozilla.org> (original author)
+ * 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 ***** */
+
+#ifndef nsCOMPtr_h___
+#define nsCOMPtr_h___
+
+/*
+ Having problems?
+
+ See the User Manual at:
+ http://www.mozilla.org/projects/xpcom/nsCOMPtr.html
+
+
+ nsCOMPtr
+ better than a raw pointer
+ for owning objects
+ -- scc
+*/
+
+
+ // Wrapping includes can speed up compiles (see "Large Scale C++ Software Design")
+#ifndef nsDebug_h___
+#include "nsDebug.h"
+ // for |NS_PRECONDITION|
+#endif
+
+#ifndef nsISupportsUtils_h__
+#include "nsISupportsUtils.h"
+ // for |nsresult|, |NS_ADDREF|, |NS_GET_IID| et al
+#endif
+
+#ifndef nscore_h___
+#include "nscore.h"
+ // for |NS_..._CAST|, |NS_COM|
+#endif
+
+
+/*
+ WARNING:
+ This file defines several macros for internal use only. These macros begin with the
+ prefix |NSCAP_|. Do not use these macros in your own code. They are for internal use
+ only for cross-platform compatibility, and are subject to change without notice.
+*/
+
+
+#ifdef _MSC_VER
+ #define NSCAP_FEATURE_INLINE_STARTASSIGNMENT
+ // under VC++, we win by inlining StartAssignment
+
+ // Also under VC++, at the highest warning level, we are overwhelmed with warnings
+ // about (unused) inline functions being removed. This is to be expected with
+ // templates, so we disable the warning.
+ #pragma warning( disable: 4514 )
+#endif
+
+#define NSCAP_FEATURE_USE_BASE
+
+#ifdef NS_DEBUG
+ #define NSCAP_FEATURE_TEST_DONTQUERY_CASES
+ #undef NSCAP_FEATURE_USE_BASE
+//#define NSCAP_FEATURE_TEST_NONNULL_QUERY_SUCCEEDS
+#endif
+
+ /*
+ |...TEST_DONTQUERY_CASES| and |...DEBUG_PTR_TYPES| introduce some code that is
+ problematic on a select few of our platforms, e.g., QNX. Therefore, I'm providing
+ a mechanism by which these features can be explicitly disabled from the command-line.
+ */
+
+#ifdef NSCAP_DISABLE_TEST_DONTQUERY_CASES
+ #undef NSCAP_FEATURE_TEST_DONTQUERY_CASES
+#endif
+
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
+ // Our use of nsCOMPtr_base::mRawPtr violates the C++ standard's aliasing
+ // rules. Mark it with the may_alias attribute so that gcc 3.3 and higher
+ // don't reorder instructions based on aliasing assumptions for
+ // this variable. Fortunately, gcc versions < 3.3 do not do any
+ // optimizations that break nsCOMPtr.
+
+ #define NS_MAY_ALIAS_PTR(t) t* __attribute__((__may_alias__))
+#else
+ #define NS_MAY_ALIAS_PTR(t) t*
+#endif
+
+#if defined(NSCAP_DISABLE_DEBUG_PTR_TYPES)
+ #define NSCAP_FEATURE_USE_BASE
+#endif
+
+
+#ifdef HAVE_CPP_BOOL
+ typedef bool NSCAP_BOOL;
+#else
+ typedef PRBool NSCAP_BOOL;
+#endif
+
+
+
+
+ /*
+ The following three macros (|NSCAP_ADDREF|, |NSCAP_RELEASE|, and |NSCAP_LOG_ASSIGNMENT|)
+ allow external clients the ability to add logging or other interesting debug facilities.
+ In fact, if you want |nsCOMPtr| to participate in the standard logging facility, you
+ provide (e.g., in "nsTraceRefcnt.h") suitable definitions
+
+ #define NSCAP_ADDREF(this, ptr) NS_ADDREF(ptr)
+ #define NSCAP_RELEASE(this, ptr) NS_RELEASE(ptr)
+ */
+
+#ifndef NSCAP_ADDREF
+ #define NSCAP_ADDREF(this, ptr) (ptr)->AddRef()
+#endif
+
+#ifndef NSCAP_RELEASE
+ #define NSCAP_RELEASE(this, ptr) (ptr)->Release()
+#endif
+
+ // Clients can define |NSCAP_LOG_ASSIGNMENT| to perform logging.
+#ifdef NSCAP_LOG_ASSIGNMENT
+ // Remember that |NSCAP_LOG_ASSIGNMENT| was defined by some client so that we know
+ // to instantiate |~nsGetterAddRefs| in turn to note the external assignment into
+ // the |nsCOMPtr|.
+ #define NSCAP_LOG_EXTERNAL_ASSIGNMENT
+#else
+ // ...otherwise, just strip it out of the code
+ #define NSCAP_LOG_ASSIGNMENT(this, ptr)
+#endif
+
+#ifndef NSCAP_LOG_RELEASE
+ #define NSCAP_LOG_RELEASE(this, ptr)
+#endif
+
+
+
+
+ /*
+ WARNING:
+ VC++4.2 is very picky. To compile under VC++4.2, the classes must be defined
+ in an order that satisfies:
+
+ nsDerivedSafe < nsCOMPtr
+ already_AddRefed < nsCOMPtr
+ nsCOMPtr < nsGetterAddRefs
+
+ The other compilers probably won't complain, so please don't reorder these
+ classes, on pain of breaking 4.2 compatibility.
+ */
+
+
+template <class T>
+class nsDerivedSafe : public T
+ /*
+ No client should ever see or have to type the name of this class. It is the
+ artifact that makes it a compile-time error to call |AddRef| and |Release|
+ on a |nsCOMPtr|. DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE.
+
+ See |nsCOMPtr::operator->|, |nsCOMPtr::operator*|, et al.
+
+ This type should be a nested class inside |nsCOMPtr<T>|.
+ */
+ {
+ private:
+#ifdef HAVE_CPP_ACCESS_CHANGING_USING
+ using T::AddRef;
+ using T::Release;
+#else
+ nsrefcnt AddRef(void);
+ nsrefcnt Release(void);
+#endif
+
+#if !defined(AIX) && !defined(IRIX)
+ void operator delete( void*, size_t ); // NOT TO BE IMPLEMENTED
+ // declaring |operator delete| private makes calling delete on an interface pointer a compile error
+#endif
+
+ nsDerivedSafe<T>& operator=( const T& ); // NOT TO BE IMPLEMENTED
+ // you may not call |operator=()| through a dereferenced |nsCOMPtr|, because you'd get the wrong one
+
+ /*
+ Compiler warnings and errors: nsDerivedSafe operator=() hides inherited operator=().
+ If you see that, that means somebody checked in a [XP]COM interface class that declares an
+ |operator=()|, and that's _bad_. So bad, in fact, that this declaration exists explicitly
+ to stop people from doing it.
+ */
+
+ protected:
+ nsDerivedSafe(); // NOT TO BE IMPLEMENTED
+ /*
+ This ctor exists to avoid compile errors and warnings about nsDeriviedSafe using the
+ default ctor but inheriting classes without an empty ctor. See bug 209667.
+ */
+ };
+
+#if !defined(HAVE_CPP_ACCESS_CHANGING_USING) && defined(NEED_CPP_UNUSED_IMPLEMENTATIONS)
+template <class T>
+nsrefcnt
+nsDerivedSafe<T>::AddRef()
+ {
+ return 0;
+ }
+
+template <class T>
+nsrefcnt
+nsDerivedSafe<T>::Release()
+ {
+ return 0;
+ }
+
+#endif
+
+
+
+template <class T>
+struct already_AddRefed
+ /*
+ ...cooperates with |nsCOMPtr| to allow you to assign in a pointer _without_
+ |AddRef|ing it. You might want to use this as a return type from a function
+ that produces an already |AddRef|ed pointer as a result.
+
+ See also |getter_AddRefs()|, |dont_AddRef()|, and |class nsGetterAddRefs|.
+
+ This type should be a nested class inside |nsCOMPtr<T>|.
+
+ Yes, |already_AddRefed| could have been implemented as an |nsCOMPtr_helper| to
+ avoid adding specialized machinery to |nsCOMPtr| ... but this is the simplest
+ case, and perhaps worth the savings in time and space that its specific
+ implementation affords over the more general solution offered by
+ |nsCOMPtr_helper|.
+ */
+ {
+ already_AddRefed( T* aRawPtr )
+ : mRawPtr(aRawPtr)
+ {
+ // nothing else to do here
+ }
+
+ T* get() const { return mRawPtr; }
+
+ T* mRawPtr;
+ };
+
+template <class T>
+inline
+const already_AddRefed<T>
+getter_AddRefs( T* aRawPtr )
+ /*
+ ...makes typing easier, because it deduces the template type, e.g.,
+ you write |dont_AddRef(fooP)| instead of |already_AddRefed<IFoo>(fooP)|.
+ */
+ {
+ return already_AddRefed<T>(aRawPtr);
+ }
+
+template <class T>
+inline
+const already_AddRefed<T>
+getter_AddRefs( const already_AddRefed<T> aAlreadyAddRefedPtr )
+ {
+ return aAlreadyAddRefedPtr;
+ }
+
+template <class T>
+inline
+const already_AddRefed<T>
+dont_AddRef( T* aRawPtr )
+ {
+ return already_AddRefed<T>(aRawPtr);
+ }
+
+template <class T>
+inline
+const already_AddRefed<T>
+dont_AddRef( const already_AddRefed<T> aAlreadyAddRefedPtr )
+ {
+ return aAlreadyAddRefedPtr;
+ }
+
+
+
+class nsCOMPtr_helper
+ /*
+ An |nsCOMPtr_helper| transforms commonly called getters into typesafe forms
+ that are more convenient to call, and more efficient to use with |nsCOMPtr|s.
+ Good candidates for helpers are |QueryInterface()|, |CreateInstance()|, etc.
+
+ Here are the rules for a helper:
+ - it implements |operator()| to produce an interface pointer
+ - (except for its name) |operator()| is a valid [XP]COM `getter'
+ - the interface pointer that it returns is already |AddRef()|ed (as from any good getter)
+ - it matches the type requested with the supplied |nsIID| argument
+ - its constructor provides an optional |nsresult*| that |operator()| can fill
+ in with an error when it is executed
+
+ See |class nsGetInterface| for an example.
+ */
+ {
+ public:
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const = 0;
+ };
+
+/*
+ |nsQueryInterface| could have been implemented as an |nsCOMPtr_helper| to
+ avoid adding specialized machinery in |nsCOMPtr|, But |do_QueryInterface|
+ is called often enough that the codesize savings are big enough to
+ warrant the specialcasing.
+*/
+
+class NS_COM nsQueryInterface
+ {
+ public:
+ nsQueryInterface( nsISupports* aRawPtr )
+ : mRawPtr(aRawPtr)
+ {
+ // nothing else to do here
+ }
+
+ nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
+
+ private:
+ nsISupports* mRawPtr;
+ };
+
+class NS_COM nsQueryInterfaceWithError
+ {
+ public:
+ nsQueryInterfaceWithError( nsISupports* aRawPtr, nsresult* error )
+ : mRawPtr(aRawPtr),
+ mErrorPtr(error)
+ {
+ // nothing else to do here
+ }
+
+ nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
+
+ private:
+ nsISupports* mRawPtr;
+ nsresult* mErrorPtr;
+ };
+
+inline
+nsQueryInterface
+do_QueryInterface( nsISupports* aRawPtr )
+ {
+ return nsQueryInterface(aRawPtr);
+ }
+
+inline
+nsQueryInterfaceWithError
+do_QueryInterface( nsISupports* aRawPtr, nsresult* error )
+ {
+ return nsQueryInterfaceWithError(aRawPtr, error);
+ }
+
+template <class T>
+inline
+void
+do_QueryInterface( already_AddRefed<T>& )
+ {
+ // This signature exists soley to _stop_ you from doing the bad thing.
+ // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
+ // someone else is an automatic leak. See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
+ }
+
+template <class T>
+inline
+void
+do_QueryInterface( already_AddRefed<T>&, nsresult* )
+ {
+ // This signature exists soley to _stop_ you from doing the bad thing.
+ // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
+ // someone else is an automatic leak. See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
+ }
+
+
+
+class nsCOMPtr_base
+ /*
+ ...factors implementation for all template versions of |nsCOMPtr|.
+
+ This should really be an |nsCOMPtr<nsISupports>|, but this wouldn't work
+ because unlike the
+
+ Here's the way people normally do things like this
+
+ template <class T> class Foo { ... };
+ template <> class Foo<void*> { ... };
+ template <class T> class Foo<T*> : private Foo<void*> { ... };
+ */
+ {
+ public:
+
+ nsCOMPtr_base( nsISupports* rawPtr = 0 )
+ : mRawPtr(rawPtr)
+ {
+ // nothing else to do here
+ }
+
+ NS_COM NS_FASTCALL ~nsCOMPtr_base();
+
+ NS_COM void NS_FASTCALL assign_with_AddRef( nsISupports* );
+ NS_COM void NS_FASTCALL assign_from_qi( const nsQueryInterface, const nsIID& );
+ NS_COM void NS_FASTCALL assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
+ NS_COM void NS_FASTCALL assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
+ NS_COM void** NS_FASTCALL begin_assignment();
+
+ protected:
+ NS_MAY_ALIAS_PTR(nsISupports) mRawPtr;
+
+ void
+ assign_assuming_AddRef( nsISupports* newPtr )
+ {
+ /*
+ |AddRef()|ing the new value (before entering this function) before
+ |Release()|ing the old lets us safely ignore the self-assignment case.
+ We must, however, be careful only to |Release()| _after_ doing the
+ assignment, in case the |Release()| leads to our _own_ destruction,
+ which would, in turn, cause an incorrect second |Release()| of our old
+ pointer. Thank <waterson@netscape.com> for discovering this.
+ */
+ nsISupports* oldPtr = mRawPtr;
+ mRawPtr = newPtr;
+ NSCAP_LOG_ASSIGNMENT(this, newPtr);
+ NSCAP_LOG_RELEASE(this, oldPtr);
+ if ( oldPtr )
+ NSCAP_RELEASE(this, oldPtr);
+ }
+ };
+
+// template <class T> class nsGetterAddRefs;
+
+template <class T>
+class nsCOMPtr
+#ifdef NSCAP_FEATURE_USE_BASE
+ : private nsCOMPtr_base
+#endif
+ {
+
+#ifdef NSCAP_FEATURE_USE_BASE
+ #define NSCAP_CTOR_BASE(x) nsCOMPtr_base(x)
+#else
+ #define NSCAP_CTOR_BASE(x) mRawPtr(x)
+
+ private:
+ void assign_with_AddRef( nsISupports* );
+ void assign_from_qi( const nsQueryInterface, const nsIID& );
+ void assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
+ void assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
+ void** begin_assignment();
+
+ void
+ assign_assuming_AddRef( T* newPtr )
+ {
+ T* oldPtr = mRawPtr;
+ mRawPtr = newPtr;
+ NSCAP_LOG_ASSIGNMENT(this, newPtr);
+ NSCAP_LOG_RELEASE(this, oldPtr);
+ if ( oldPtr )
+ NSCAP_RELEASE(this, oldPtr);
+ }
+
+ private:
+ T* mRawPtr;
+#endif
+
+ public:
+ typedef T element_type;
+
+#ifndef NSCAP_FEATURE_USE_BASE
+ ~nsCOMPtr()
+ {
+ NSCAP_LOG_RELEASE(this, mRawPtr);
+ if ( mRawPtr )
+ NSCAP_RELEASE(this, mRawPtr);
+ }
+#endif
+
+#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
+ void
+ Assert_NoQueryNeeded()
+ {
+ if ( mRawPtr )
+ {
+ nsCOMPtr<T> query_result( do_QueryInterface(mRawPtr) );
+ NS_ASSERTION(query_result.get() == mRawPtr, "QueryInterface needed");
+ }
+ }
+
+ #define NSCAP_ASSERT_NO_QUERY_NEEDED() Assert_NoQueryNeeded();
+#else
+ #define NSCAP_ASSERT_NO_QUERY_NEEDED()
+#endif
+
+
+ // Constructors
+
+ nsCOMPtr()
+ : NSCAP_CTOR_BASE(0)
+ // default constructor
+ {
+ NSCAP_LOG_ASSIGNMENT(this, 0);
+ }
+
+ nsCOMPtr( const nsCOMPtr<T>& aSmartPtr )
+ : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
+ // copy-constructor
+ {
+ if ( mRawPtr )
+ NSCAP_ADDREF(this, mRawPtr);
+ NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
+ }
+
+ nsCOMPtr( T* aRawPtr )
+ : NSCAP_CTOR_BASE(aRawPtr)
+ // construct from a raw pointer (of the right type)
+ {
+ if ( mRawPtr )
+ NSCAP_ADDREF(this, mRawPtr);
+ NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
+ NSCAP_ASSERT_NO_QUERY_NEEDED();
+ }
+
+ nsCOMPtr( const already_AddRefed<T>& aSmartPtr )
+ : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
+ // construct from |dont_AddRef(expr)|
+ {
+ NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
+ NSCAP_ASSERT_NO_QUERY_NEEDED();
+ }
+
+ nsCOMPtr( const nsQueryInterface qi )
+ : NSCAP_CTOR_BASE(0)
+ // construct from |do_QueryInterface(expr)|
+ {
+ NSCAP_LOG_ASSIGNMENT(this, 0);
+ assign_from_qi(qi, NS_GET_IID(T));
+ }
+
+ nsCOMPtr( const nsQueryInterfaceWithError& qi )
+ : NSCAP_CTOR_BASE(0)
+ // construct from |do_QueryInterface(expr, &rv)|
+ {
+ NSCAP_LOG_ASSIGNMENT(this, 0);
+ assign_from_qi_with_error(qi, NS_GET_IID(T));
+ }
+
+ nsCOMPtr( const nsCOMPtr_helper& helper )
+ : NSCAP_CTOR_BASE(0)
+ // ...and finally, anything else we might need to construct from
+ // can exploit the |nsCOMPtr_helper| facility
+ {
+ NSCAP_LOG_ASSIGNMENT(this, 0);
+ assign_from_helper(helper, NS_GET_IID(T));
+ NSCAP_ASSERT_NO_QUERY_NEEDED();
+ }
+
+
+ // Assignment operators
+
+ nsCOMPtr<T>&
+ operator=( const nsCOMPtr<T>& rhs )
+ // copy assignment operator
+ {
+ assign_with_AddRef(rhs.mRawPtr);
+ return *this;
+ }
+
+ nsCOMPtr<T>&
+ operator=( T* rhs )
+ // assign from a raw pointer (of the right type)
+ {
+ assign_with_AddRef(rhs);
+ NSCAP_ASSERT_NO_QUERY_NEEDED();
+ return *this;
+ }
+
+ nsCOMPtr<T>&
+ operator=( const already_AddRefed<T>& rhs )
+ // assign from |dont_AddRef(expr)|
+ {
+ assign_assuming_AddRef(rhs.mRawPtr);
+ NSCAP_ASSERT_NO_QUERY_NEEDED();
+ return *this;
+ }
+
+ nsCOMPtr<T>&
+ operator=( const nsQueryInterface rhs )
+ // assign from |do_QueryInterface(expr)|
+ {
+ assign_from_qi(rhs, NS_GET_IID(T));
+ return *this;
+ }
+
+ nsCOMPtr<T>&
+ operator=( const nsQueryInterfaceWithError& rhs )
+ // assign from |do_QueryInterface(expr, &rv)|
+ {
+ assign_from_qi_with_error(rhs, NS_GET_IID(T));
+ return *this;
+ }
+
+ nsCOMPtr<T>&
+ operator=( const nsCOMPtr_helper& rhs )
+ // ...and finally, anything else we might need to assign from
+ // can exploit the |nsCOMPtr_helper| facility.
+ {
+ assign_from_helper(rhs, NS_GET_IID(T));
+ NSCAP_ASSERT_NO_QUERY_NEEDED();
+ return *this;
+ }
+
+ void
+ swap( nsCOMPtr<T>& rhs )
+ // ...exchange ownership with |rhs|; can save a pair of refcount operations
+ {
+#ifdef NSCAP_FEATURE_USE_BASE
+ nsISupports* temp = rhs.mRawPtr;
+#else
+ T* temp = rhs.mRawPtr;
+#endif
+ NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
+ NSCAP_LOG_ASSIGNMENT(this, temp);
+ NSCAP_LOG_RELEASE(this, mRawPtr);
+ NSCAP_LOG_RELEASE(&rhs, temp);
+ rhs.mRawPtr = mRawPtr;
+ mRawPtr = temp;
+ // |rhs| maintains the same invariants, so we don't need to |NSCAP_ASSERT_NO_QUERY_NEEDED|
+ }
+
+ void
+ swap( T*& rhs )
+ // ...exchange ownership with |rhs|; can save a pair of refcount operations
+ {
+#ifdef NSCAP_FEATURE_USE_BASE
+ nsISupports* temp = rhs;
+#else
+ T* temp = rhs;
+#endif
+ NSCAP_LOG_ASSIGNMENT(this, temp);
+ NSCAP_LOG_RELEASE(this, mRawPtr);
+ rhs = NS_REINTERPRET_CAST(T*, mRawPtr);
+ mRawPtr = temp;
+ NSCAP_ASSERT_NO_QUERY_NEEDED();
+ }
+
+
+ // Other pointer operators
+
+ nsDerivedSafe<T>*
+ get() const
+ /*
+ Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<T>*() const|.
+ Use |get()| _only_ to resolve ambiguity.
+
+ Returns a |nsDerivedSafe<T>*| to deny clients the use of |AddRef| and |Release|.
+ */
+ {
+ return NS_REINTERPRET_CAST(nsDerivedSafe<T>*, mRawPtr);
+ }
+
+ operator nsDerivedSafe<T>*() const
+ /*
+ ...makes an |nsCOMPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|,
+ and |delete|) whenever it is used in a context where a raw pointer is expected. It is this operator
+ that makes an |nsCOMPtr| substitutable for a raw pointer.
+
+ Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity.
+ */
+ {
+ return get();
+ }
+
+ nsDerivedSafe<T>*
+ operator->() const
+ {
+ NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
+ return get();
+ }
+
+#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
+ // broken version for IRIX
+
+ nsCOMPtr<T>*
+ get_address() const
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return NS_CONST_CAST(nsCOMPtr<T>*, this);
+ }
+
+#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+ nsCOMPtr<T>*
+ get_address()
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return this;
+ }
+
+ const nsCOMPtr<T>*
+ get_address() const
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return this;
+ }
+
+#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+ public:
+ nsDerivedSafe<T>&
+ operator*() const
+ {
+ NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
+ return *get();
+ }
+
+#if 0
+ private:
+ friend class nsGetterAddRefs<T>;
+#endif
+
+ T**
+ StartAssignment()
+ {
+#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
+ return NS_REINTERPRET_CAST(T**, begin_assignment());
+#else
+ assign_assuming_AddRef(0);
+ return NS_REINTERPRET_CAST(T**, &mRawPtr);
+#endif
+ }
+ };
+
+
+
+ /*
+ Specializing |nsCOMPtr| for |nsISupports| allows us to use |nsCOMPtr<nsISupports>| the
+ same way people use |nsISupports*| and |void*|, i.e., as a `catch-all' pointer pointing
+ to any valid [XP]COM interface. Otherwise, an |nsCOMPtr<nsISupports>| would only be able
+ to point to the single [XP]COM-correct |nsISupports| instance within an object; extra
+ querying ensues. Clients need to be able to pass around arbitrary interface pointers,
+ without hassles, through intermediary code that doesn't know the exact type.
+ */
+
+NS_SPECIALIZE_TEMPLATE
+class nsCOMPtr<nsISupports>
+ : private nsCOMPtr_base
+ {
+ public:
+ typedef nsISupports element_type;
+
+ // Constructors
+
+ nsCOMPtr()
+ : nsCOMPtr_base(0)
+ // default constructor
+ {
+ NSCAP_LOG_ASSIGNMENT(this, 0);
+ }
+
+ nsCOMPtr( const nsCOMPtr<nsISupports>& aSmartPtr )
+ : nsCOMPtr_base(aSmartPtr.mRawPtr)
+ // copy constructor
+ {
+ if ( mRawPtr )
+ NSCAP_ADDREF(this, mRawPtr);
+ NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
+ }
+
+ nsCOMPtr( nsISupports* aRawPtr )
+ : nsCOMPtr_base(aRawPtr)
+ // construct from a raw pointer (of the right type)
+ {
+ if ( mRawPtr )
+ NSCAP_ADDREF(this, mRawPtr);
+ NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
+ }
+
+ nsCOMPtr( const already_AddRefed<nsISupports>& aSmartPtr )
+ : nsCOMPtr_base(aSmartPtr.mRawPtr)
+ // construct from |dont_AddRef(expr)|
+ {
+ NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
+ }
+
+ nsCOMPtr( const nsQueryInterface qi )
+ : nsCOMPtr_base(0)
+ // assign from |do_QueryInterface(expr)|
+ {
+ NSCAP_LOG_ASSIGNMENT(this, 0);
+ assign_from_qi(qi, NS_GET_IID(nsISupports));
+ }
+
+ nsCOMPtr( const nsQueryInterfaceWithError& qi )
+ : nsCOMPtr_base(0)
+ // assign from |do_QueryInterface(expr, &rv)|
+ {
+ NSCAP_LOG_ASSIGNMENT(this, 0);
+ assign_from_qi_with_error(qi, NS_GET_IID(nsISupports));
+ }
+
+ nsCOMPtr( const nsCOMPtr_helper& helper )
+ : nsCOMPtr_base(0)
+ // ...and finally, anything else we might need to construct from
+ // can exploit the |nsCOMPtr_helper| facility
+ {
+ NSCAP_LOG_ASSIGNMENT(this, 0);
+ assign_from_helper(helper, NS_GET_IID(nsISupports));
+ }
+
+
+ // Assignment operators
+
+ nsCOMPtr<nsISupports>&
+ operator=( const nsCOMPtr<nsISupports>& rhs )
+ // copy assignment operator
+ {
+ assign_with_AddRef(rhs.mRawPtr);
+ return *this;
+ }
+
+ nsCOMPtr<nsISupports>&
+ operator=( nsISupports* rhs )
+ // assign from a raw pointer (of the right type)
+ {
+ assign_with_AddRef(rhs);
+ return *this;
+ }
+
+ nsCOMPtr<nsISupports>&
+ operator=( const already_AddRefed<nsISupports>& rhs )
+ // assign from |dont_AddRef(expr)|
+ {
+ assign_assuming_AddRef(rhs.mRawPtr);
+ return *this;
+ }
+
+ nsCOMPtr<nsISupports>&
+ operator=( const nsQueryInterface rhs )
+ // assign from |do_QueryInterface(expr)|
+ {
+ assign_from_qi(rhs, NS_GET_IID(nsISupports));
+ return *this;
+ }
+
+ nsCOMPtr<nsISupports>&
+ operator=( const nsQueryInterfaceWithError& rhs )
+ // assign from |do_QueryInterface(expr, &rv)|
+ {
+ assign_from_qi_with_error(rhs, NS_GET_IID(nsISupports));
+ return *this;
+ }
+
+ nsCOMPtr<nsISupports>&
+ operator=( const nsCOMPtr_helper& rhs )
+ // ...and finally, anything else we might need to assign from
+ // can exploit the |nsCOMPtr_helper| facility.
+ {
+ assign_from_helper(rhs, NS_GET_IID(nsISupports));
+ return *this;
+ }
+
+ void
+ swap( nsCOMPtr<nsISupports>& rhs )
+ // ...exchange ownership with |rhs|; can save a pair of refcount operations
+ {
+ nsISupports* temp = rhs.mRawPtr;
+ NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
+ NSCAP_LOG_ASSIGNMENT(this, temp);
+ NSCAP_LOG_RELEASE(this, mRawPtr);
+ NSCAP_LOG_RELEASE(&rhs, temp);
+ rhs.mRawPtr = mRawPtr;
+ mRawPtr = temp;
+ }
+
+ void
+ swap( nsISupports*& rhs )
+ // ...exchange ownership with |rhs|; can save a pair of refcount operations
+ {
+ nsISupports* temp = rhs;
+ NSCAP_LOG_ASSIGNMENT(this, temp);
+ NSCAP_LOG_RELEASE(this, mRawPtr);
+ rhs = mRawPtr;
+ mRawPtr = temp;
+ }
+
+
+ // Other pointer operators
+
+ nsDerivedSafe<nsISupports>*
+ get() const
+ /*
+ Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<nsISupports>*() const|.
+ Use |get()| _only_ to resolve ambiguity.
+
+ Returns a |nsDerivedSafe<nsISupports>*| to deny clients the use of |AddRef| and |Release|.
+ */
+ {
+ return NS_REINTERPRET_CAST(nsDerivedSafe<nsISupports>*, mRawPtr);
+ }
+
+ operator nsDerivedSafe<nsISupports>*() const
+ /*
+ ...makes an |nsCOMPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|,
+ and |delete|) whenever it is used in a context where a raw pointer is expected. It is this operator
+ that makes an |nsCOMPtr| substitutable for a raw pointer.
+
+ Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity.
+ */
+ {
+ return get();
+ }
+
+ nsDerivedSafe<nsISupports>*
+ operator->() const
+ {
+ NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
+ return get();
+ }
+
+#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
+ // broken version for IRIX
+
+ nsCOMPtr<nsISupports>*
+ get_address() const
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return NS_CONST_CAST(nsCOMPtr<nsISupports>*, this);
+ }
+
+#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+ nsCOMPtr<nsISupports>*
+ get_address()
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return this;
+ }
+
+ const nsCOMPtr<nsISupports>*
+ get_address() const
+ // This is not intended to be used by clients. See |address_of|
+ // below.
+ {
+ return this;
+ }
+
+#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+ public:
+
+ nsDerivedSafe<nsISupports>&
+ operator*() const
+ {
+ NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
+ return *get();
+ }
+
+#if 0
+ private:
+ friend class nsGetterAddRefs<nsISupports>;
+#endif
+
+ nsISupports**
+ StartAssignment()
+ {
+#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
+ return NS_REINTERPRET_CAST(nsISupports**, begin_assignment());
+#else
+ assign_assuming_AddRef(0);
+ return NS_REINTERPRET_CAST(nsISupports**, &mRawPtr);
+#endif
+ }
+ };
+
+#ifndef NSCAP_FEATURE_USE_BASE
+template <class T>
+void
+nsCOMPtr<T>::assign_with_AddRef( nsISupports* rawPtr )
+ {
+ if ( rawPtr )
+ NSCAP_ADDREF(this, rawPtr);
+ assign_assuming_AddRef(NS_REINTERPRET_CAST(T*, rawPtr));
+ }
+
+template <class T>
+void
+nsCOMPtr<T>::assign_from_qi( const nsQueryInterface qi, const nsIID& aIID )
+ {
+ T* newRawPtr;
+ if ( NS_FAILED( qi(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
+ newRawPtr = 0;
+ assign_assuming_AddRef(newRawPtr);
+ }
+
+template <class T>
+void
+nsCOMPtr<T>::assign_from_qi_with_error( const nsQueryInterfaceWithError& qi, const nsIID& aIID )
+ {
+ T* newRawPtr;
+ if ( NS_FAILED( qi(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
+ newRawPtr = 0;
+ assign_assuming_AddRef(newRawPtr);
+ }
+
+template <class T>
+void
+nsCOMPtr<T>::assign_from_helper( const nsCOMPtr_helper& helper, const nsIID& aIID )
+ {
+ T* newRawPtr;
+ if ( NS_FAILED( helper(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
+ newRawPtr = 0;
+ assign_assuming_AddRef(newRawPtr);
+ }
+
+template <class T>
+void**
+nsCOMPtr<T>::begin_assignment()
+ {
+ assign_assuming_AddRef(0);
+ return NS_REINTERPRET_CAST(void**, &mRawPtr);
+ }
+#endif
+
+#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+// This is the broken version for IRIX, which can't handle the version below.
+
+template <class T>
+inline
+nsCOMPtr<T>*
+address_of( const nsCOMPtr<T>& aPtr )
+ {
+ return aPtr.get_address();
+ }
+
+#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+template <class T>
+inline
+nsCOMPtr<T>*
+address_of( nsCOMPtr<T>& aPtr )
+ {
+ return aPtr.get_address();
+ }
+
+template <class T>
+inline
+const nsCOMPtr<T>*
+address_of( const nsCOMPtr<T>& aPtr )
+ {
+ return aPtr.get_address();
+ }
+
+#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
+
+template <class T>
+class nsGetterAddRefs
+ /*
+ ...
+
+ This class is designed to be used for anonymous temporary objects in the
+ argument list of calls that return COM interface pointers, e.g.,
+
+ nsCOMPtr<IFoo> fooP;
+ ...->QueryInterface(iid, getter_AddRefs(fooP))
+
+ DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
+
+ When initialized with a |nsCOMPtr|, as in the example above, it returns
+ a |void**|, a |T**|, or an |nsISupports**| as needed, that the outer call (|QueryInterface| in this
+ case) can fill in.
+
+ This type should be a nested class inside |nsCOMPtr<T>|.
+ */
+ {
+ public:
+ explicit
+ nsGetterAddRefs( nsCOMPtr<T>& aSmartPtr )
+ : mTargetSmartPtr(aSmartPtr)
+ {
+ // nothing else to do
+ }
+
+#if defined(NSCAP_FEATURE_TEST_DONTQUERY_CASES) || defined(NSCAP_LOG_EXTERNAL_ASSIGNMENT)
+ ~nsGetterAddRefs()
+ {
+#ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
+ NSCAP_LOG_ASSIGNMENT(NS_REINTERPRET_CAST(void *, address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
+#endif
+
+#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
+ mTargetSmartPtr.Assert_NoQueryNeeded();
+#endif
+ }
+#endif
+
+ operator void**()
+ {
+ return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
+ }
+
+ operator nsISupports**()
+ {
+ return NS_REINTERPRET_CAST(nsISupports**, mTargetSmartPtr.StartAssignment());
+ }
+
+ operator T**()
+ {
+ return mTargetSmartPtr.StartAssignment();
+ }
+
+ T*&
+ operator*()
+ {
+ return *(mTargetSmartPtr.StartAssignment());
+ }
+
+ private:
+ nsCOMPtr<T>& mTargetSmartPtr;
+ };
+
+
+NS_SPECIALIZE_TEMPLATE
+class nsGetterAddRefs<nsISupports>
+ {
+ public:
+ explicit
+ nsGetterAddRefs( nsCOMPtr<nsISupports>& aSmartPtr )
+ : mTargetSmartPtr(aSmartPtr)
+ {
+ // nothing else to do
+ }
+
+#ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
+ ~nsGetterAddRefs()
+ {
+ NSCAP_LOG_ASSIGNMENT(NS_REINTERPRET_CAST(void *, address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
+ }
+#endif
+
+ operator void**()
+ {
+ return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
+ }
+
+ operator nsISupports**()
+ {
+ return mTargetSmartPtr.StartAssignment();
+ }
+
+ nsISupports*&
+ operator*()
+ {
+ return *(mTargetSmartPtr.StartAssignment());
+ }
+
+ private:
+ nsCOMPtr<nsISupports>& mTargetSmartPtr;
+ };
+
+
+template <class T>
+inline
+nsGetterAddRefs<T>
+getter_AddRefs( nsCOMPtr<T>& aSmartPtr )
+ /*
+ Used around a |nsCOMPtr| when
+ ...makes the class |nsGetterAddRefs<T>| invisible.
+ */
+ {
+ return nsGetterAddRefs<T>(aSmartPtr);
+ }
+
+
+
+ // Comparing two |nsCOMPtr|s
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs.get());
+ }
+
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs.get());
+ }
+
+
+ // Comparing an |nsCOMPtr| to a raw pointer
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const nsCOMPtr<T>& lhs, const U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) == rhs;
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const U* lhs, const nsCOMPtr<T>& rhs )
+ {
+ return lhs == NS_STATIC_CAST(const T*, rhs.get());
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const nsCOMPtr<T>& lhs, const U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) != rhs;
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const U* lhs, const nsCOMPtr<T>& rhs )
+ {
+ return lhs != NS_STATIC_CAST(const T*, rhs.get());
+ }
+
+ // To avoid ambiguities caused by the presence of builtin |operator==|s
+ // creating a situation where one of the |operator==| defined above
+ // has a better conversion for one argument and the builtin has a
+ // better conversion for the other argument, define additional
+ // |operator==| without the |const| on the raw pointer.
+ // See bug 65664 for details.
+
+// This is defined by an autoconf test, but VC++ also has a bug that
+// prevents us from using these. (It also, fortunately, has the bug
+// that we don't need them either.)
+#if defined(_MSC_VER) && (_MSC_VER < 1310)
+#define NSCAP_DONT_PROVIDE_NONCONST_OPEQ
+#endif
+
+#ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( const nsCOMPtr<T>& lhs, U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) == NS_CONST_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator==( U* lhs, const nsCOMPtr<T>& rhs )
+ {
+ return NS_CONST_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( const nsCOMPtr<T>& lhs, U* rhs )
+ {
+ return NS_STATIC_CAST(const T*, lhs.get()) != NS_CONST_CAST(const U*, rhs);
+ }
+
+template <class T, class U>
+inline
+NSCAP_BOOL
+operator!=( U* lhs, const nsCOMPtr<T>& rhs )
+ {
+ return NS_CONST_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
+ }
+#endif
+
+
+
+ // Comparing an |nsCOMPtr| to |0|
+
+class NSCAP_Zero;
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
+ // specifically to allow |smartPtr == 0|
+ {
+ return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
+ // specifically to allow |0 == smartPtr|
+ {
+ return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator!=( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
+ // specifically to allow |smartPtr != 0|
+ {
+ return NS_STATIC_CAST(const void*, lhs.get()) != NS_REINTERPRET_CAST(const void*, rhs);
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator!=( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
+ // specifically to allow |0 != smartPtr|
+ {
+ return NS_REINTERPRET_CAST(const void*, lhs) != NS_STATIC_CAST(const void*, rhs.get());
+ }
+
+
+#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
+
+ // We need to explicitly define comparison operators for `int'
+ // because the compiler is lame.
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( const nsCOMPtr<T>& lhs, int rhs )
+ // specifically to allow |smartPtr == 0|
+ {
+ return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
+ }
+
+template <class T>
+inline
+NSCAP_BOOL
+operator==( int lhs, const nsCOMPtr<T>& rhs )
+ // specifically to allow |0 == smartPtr|
+ {
+ return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
+ }
+
+#endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
+
+ // Comparing any two [XP]COM objects for identity
+
+inline
+NSCAP_BOOL
+SameCOMIdentity( nsISupports* lhs, nsISupports* rhs )
+ {
+ return nsCOMPtr<nsISupports>( do_QueryInterface(lhs) ) == nsCOMPtr<nsISupports>( do_QueryInterface(rhs) );
+ }
+
+
+
+template <class SourceType, class DestinationType>
+inline
+nsresult
+CallQueryInterface( nsCOMPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr )
+ {
+ return CallQueryInterface(aSourcePtr.get(), aDestPtr);
+ }
+
+#endif // !defined(nsCOMPtr_h___)
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsComponentManagerUtils.cpp b/src/libs/xpcom18a4/xpcom/glue/nsComponentManagerUtils.cpp
new file mode 100644
index 00000000..5733fc36
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsComponentManagerUtils.cpp
@@ -0,0 +1,133 @@
+/* -*- 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 nsXPCOM_h__
+#include "nsXPCOM.h"
+#endif
+
+#ifndef nsCOMPtr_h__
+#include "nsCOMPtr.h"
+#endif
+
+#include "nsComponentManagerUtils.h"
+#include "nsIServiceManagerUtils.h"
+
+nsresult
+nsCreateInstanceByCID::operator()( const nsIID& aIID, void** aInstancePtr ) const
+{
+ nsCOMPtr<nsIComponentManager> compMgr;
+ nsresult status = NS_GetComponentManager(getter_AddRefs(compMgr));
+ if (compMgr)
+ status = compMgr->CreateInstance(mCID, mOuter, aIID, aInstancePtr);
+ else if (NS_SUCCEEDED(status))
+ status = NS_ERROR_UNEXPECTED;
+
+ if ( NS_FAILED(status) )
+ *aInstancePtr = 0;
+
+ if ( mErrorPtr )
+ *mErrorPtr = status;
+ return status;
+}
+
+nsresult
+nsCreateInstanceByContractID::operator()( const nsIID& aIID, void** aInstancePtr ) const
+{
+ nsresult status;
+ if ( mContractID ) {
+ nsCOMPtr<nsIComponentManager> compMgr;
+ status = NS_GetComponentManager(getter_AddRefs(compMgr));
+ if (compMgr)
+ status = compMgr->CreateInstanceByContractID(mContractID, mOuter,
+ aIID, aInstancePtr);
+ else if (NS_SUCCEEDED(status))
+ status = NS_ERROR_UNEXPECTED;
+ }
+ else
+ status = NS_ERROR_NULL_POINTER;
+
+ if (NS_FAILED(status))
+ *aInstancePtr = 0;
+ if ( mErrorPtr )
+ *mErrorPtr = status;
+ return status;
+}
+
+
+nsresult
+nsGetServiceByCID::operator()( const nsIID& aIID, void** aInstancePtr ) const
+{
+ nsresult status = NS_ERROR_FAILURE;
+ if ( mServiceManager ) {
+ status = mServiceManager->GetService(mCID, aIID, (void**)aInstancePtr);
+ } else {
+ nsCOMPtr<nsIServiceManager> mgr;
+ NS_GetServiceManager(getter_AddRefs(mgr));
+ if (mgr)
+ status = mgr->GetService(mCID, aIID, (void**)aInstancePtr);
+ }
+ if ( NS_FAILED(status) )
+ *aInstancePtr = 0;
+
+ if ( mErrorPtr )
+ *mErrorPtr = status;
+ return status;
+}
+
+nsresult
+nsGetServiceByContractID::operator()( const nsIID& aIID, void** aInstancePtr ) const
+{
+ nsresult status = NS_ERROR_FAILURE;
+ if ( mServiceManager ) {
+ status = mServiceManager->GetServiceByContractID(mContractID, aIID, (void**)aInstancePtr);
+ } else {
+ nsCOMPtr<nsIServiceManager> mgr;
+ NS_GetServiceManager(getter_AddRefs(mgr));
+ if (mgr)
+ status = mgr->GetServiceByContractID(mContractID, aIID, (void**)aInstancePtr);
+ }
+
+ if ( NS_FAILED(status) )
+ *aInstancePtr = 0;
+
+ if ( mErrorPtr )
+ *mErrorPtr = status;
+ return status;
+}
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsDebug.cpp b/src/libs/xpcom18a4/xpcom/glue/nsDebug.cpp
new file mode 100644
index 00000000..9e947f30
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsDebug.cpp
@@ -0,0 +1,119 @@
+/* ***** 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
+ *
+ * The Initial Developer of the Original Code is Doug Turner <dougt@meer.net>
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * 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 "nsXPCOM.h"
+#include "nsXPCOMPrivate.h"
+#include "nsCOMPtr.h"
+#include "nsIServiceManager.h"
+#include "nsDebug.h"
+#include "nsDebugImpl.h"
+
+static nsIDebug* gDebugObject = nsnull;
+
+// Note: Although the machinery here is similar to nsMemory.cpp, we cannot use
+// NS_ASSERTION macros below because they end up in nsDebug::Assertion and
+// therefore may produce endless recursion.
+
+static NS_METHOD FreeDebugObject(void)
+{
+ NS_IF_RELEASE(gDebugObject);
+ return NS_OK;
+}
+
+#define ENSURE_DEBUGOBJECT \
+ (gDebugObject ? PR_TRUE : (PRBool)(SetupDebugObject() != nsnull))
+
+static nsIDebug* SetupDebugObject()
+{
+ if (!gDebugObject)
+ {
+ NS_GetDebug(&gDebugObject);
+ if (gDebugObject)
+ NS_RegisterXPCOMExitRoutine(FreeDebugObject, 0);
+ }
+ return gDebugObject;
+}
+
+#ifdef XPCOM_GLUE
+nsresult GlueStartupDebug()
+{
+ if (!gDebugObject)
+ {
+ NS_GetDebug(&gDebugObject);
+ if (!gDebugObject)
+ return NS_ERROR_FAILURE;
+ }
+ return NS_OK;
+}
+
+void GlueShutdownDebug()
+{
+ NS_IF_RELEASE(gDebugObject);
+}
+#endif
+
+NS_COM void nsDebug::Abort(const char* aFile, PRIntn aLine)
+{
+ if (!ENSURE_DEBUGOBJECT)
+ return;
+
+ gDebugObject->Abort(aFile, aLine);
+}
+
+NS_COM void nsDebug::Break(const char* aFile, PRIntn aLine)
+{
+ if (!ENSURE_DEBUGOBJECT)
+ return;
+
+ gDebugObject->Break(aFile, aLine);
+}
+
+NS_COM void nsDebug::Warning(const char* aStr,
+ const char* aFile,
+ PRIntn aLine)
+{
+ if (!ENSURE_DEBUGOBJECT)
+ return;
+ gDebugObject->Warning(aStr, aFile, aLine);
+}
+
+NS_COM void nsDebug::Assertion(const char* aStr, const char* aExpr,
+ const char* aFile, PRIntn aLine)
+{
+ if (!ENSURE_DEBUGOBJECT)
+ return;
+ gDebugObject->Assertion(aStr, aExpr, aFile, aLine);
+}
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsDebug.h b/src/libs/xpcom18a4/xpcom/glue/nsDebug.h
new file mode 100644
index 00000000..f2ed4c56
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsDebug.h
@@ -0,0 +1,276 @@
+/* -*- 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 nsDebug_h___
+#define nsDebug_h___
+
+#ifndef nscore_h___
+#include "nscore.h"
+#endif
+
+#ifndef nsError_h__
+#include "nsError.h"
+#endif
+
+#ifdef DEBUG
+#define NS_DEBUG
+#endif
+
+/**
+ * Namespace for debugging methods. Note that your code must use the
+ * macros defined later in this file so that the debug code can be
+ * conditionally compiled out.
+ */
+
+/* in case this is included by a C file */
+#ifdef __cplusplus
+
+class nsDebug {
+public:
+
+ /**
+ * Log a warning message to the debug log.
+ */
+ static NS_COM void Warning(const char* aMessage,
+ const char* aFile, PRIntn aLine);
+
+ /**
+ * Abort the executing program. This works on all architectures.
+ */
+ static NS_COM void Abort(const char* aFile, PRIntn aLine);
+
+ /**
+ * Break the executing program into the debugger.
+ */
+ static NS_COM void Break(const char* aFile, PRIntn aLine);
+
+ /**
+ * Log an assertion message to the debug log
+ */
+ static NS_COM void Assertion(const char* aStr, const char* aExpr,
+ const char* aFile, PRIntn aLine);
+};
+
+#ifdef DEBUG
+
+/**
+ * Abort the execution of the program if the expression evaluates to
+ * false.
+ *
+ * There is no status value returned from the macro.
+ *
+ * Note that the non-debug version of this macro does <b>not</b>
+ * evaluate the expression argument. Hence side effect statements
+ * as arguments to the macro will yield improper execution in a
+ * non-debug build. For example:
+ *
+ * NS_ABORT_IF_FALSE(0 == foo++, "yikes foo should be zero");
+ *
+ * Note also that the non-debug version of this macro does <b>not</b>
+ * evaluate the message argument.
+ */
+#define NS_ABORT_IF_FALSE(_expr, _msg) \
+ PR_BEGIN_MACRO \
+ if (!(_expr)) { \
+ nsDebug::Assertion(_msg, #_expr, __FILE__, __LINE__); \
+ } \
+ PR_END_MACRO
+
+/**
+ * Warn if a given condition is false.
+ *
+ * Program execution continues past the usage of this macro.
+ *
+ * Note also that the non-debug version of this macro does <b>not</b>
+ * evaluate the message argument.
+ */
+#define NS_WARN_IF_FALSE(_expr,_msg) \
+ PR_BEGIN_MACRO \
+ if (!(_expr)) { \
+ nsDebug::Assertion(_msg, #_expr, __FILE__, __LINE__); \
+ } \
+ PR_END_MACRO
+
+/**
+ * Test a precondition for truth. If the expression is not true then
+ * trigger a program failure.
+ */
+#define NS_PRECONDITION(expr, str) \
+ PR_BEGIN_MACRO \
+ if (!(expr)) { \
+ nsDebug::Assertion(str, #expr, __FILE__, __LINE__); \
+ } \
+ PR_END_MACRO
+
+/**
+ * Test an assertion for truth. If the expression is not true then
+ * trigger a program failure.
+ */
+#define NS_ASSERTION(expr, str) \
+ PR_BEGIN_MACRO \
+ if (!(expr)) { \
+ nsDebug::Assertion(str, #expr, __FILE__, __LINE__); \
+ } \
+ PR_END_MACRO
+
+/**
+ * Test a post-condition for truth. If the expression is not true then
+ * trigger a program failure.
+ */
+#define NS_POSTCONDITION(expr, str) \
+ PR_BEGIN_MACRO \
+ if (!(expr)) { \
+ nsDebug::Assertion(str, #expr, __FILE__, __LINE__); \
+ } \
+ PR_END_MACRO
+
+/**
+ * This macros triggers a program failure if executed. It indicates that
+ * an attempt was made to execute some unimplimented functionality.
+ */
+#define NS_NOTYETIMPLEMENTED(str) \
+ nsDebug::Assertion(str, "NotYetImplemented", __FILE__, __LINE__)
+
+/**
+ * This macros triggers a program failure if executed. It indicates that
+ * an attempt was made to execute some unimplimented functionality.
+ */
+#define NS_NOTREACHED(str) \
+ nsDebug::Assertion(str, "Not Reached", __FILE__, __LINE__)
+
+/**
+ * Log an error message.
+ */
+#define NS_ERROR(str) \
+ nsDebug::Assertion(str, "Error", __FILE__, __LINE__)
+
+/**
+ * Log a warning message.
+ */
+#define NS_WARNING(str) \
+ nsDebug::Warning(str, __FILE__, __LINE__)
+
+/**
+ * Trigger an abort
+ */
+#define NS_ABORT() \
+ nsDebug::Abort(__FILE__, __LINE__)
+
+/**
+ * Cause a break
+ */
+#define NS_BREAK() \
+ nsDebug::Break(__FILE__, __LINE__)
+
+#else /* NS_DEBUG */
+
+/**
+ * The non-debug version of these macros do not evaluate the
+ * expression or the message arguments to the macro.
+ */
+#define NS_ABORT_IF_FALSE(_expr, _msg) /* nothing */
+#define NS_WARN_IF_FALSE(_expr, _msg) /* nothing */
+#define NS_PRECONDITION(expr, str) /* nothing */
+#define NS_ASSERTION(expr, str) /* nothing */
+#define NS_POSTCONDITION(expr, str) /* nothing */
+#define NS_NOTYETIMPLEMENTED(str) /* nothing */
+#define NS_NOTREACHED(str) /* nothing */
+#define NS_ERROR(str) /* nothing */
+#define NS_WARNING(str) /* nothing */
+#define NS_ABORT() /* nothing */
+#define NS_BREAK() /* nothing */
+
+#endif /* ! NS_DEBUG */
+#endif /* __cplusplus */
+
+// Macros for checking the trueness of an expression passed in within an
+// interface implementation. These need to be compiled regardless of the
+// NS_DEBUG flag
+///////////////////////////////////////////////////////////////////////////////
+
+#define NS_ENSURE_TRUE(x, ret) \
+ PR_BEGIN_MACRO \
+ if (NS_UNLIKELY(!(x))) { \
+ NS_WARNING("NS_ENSURE_TRUE(" #x ") failed"); \
+ return ret; \
+ } \
+ PR_END_MACRO
+
+#define NS_ENSURE_FALSE(x, ret) \
+ NS_ENSURE_TRUE(!(x), ret)
+
+///////////////////////////////////////////////////////////////////////////////
+// Macros for checking results
+///////////////////////////////////////////////////////////////////////////////
+
+#define NS_ENSURE_SUCCESS(res, ret) \
+ NS_ENSURE_TRUE(NS_SUCCEEDED(res), ret)
+
+///////////////////////////////////////////////////////////////////////////////
+// Macros for checking state and arguments upon entering interface boundaries
+///////////////////////////////////////////////////////////////////////////////
+
+#define NS_ENSURE_ARG(arg) \
+ NS_ENSURE_TRUE(arg, NS_ERROR_INVALID_ARG)
+
+#define NS_ENSURE_ARG_POINTER(arg) \
+ NS_ENSURE_TRUE(arg, NS_ERROR_INVALID_POINTER)
+
+#define NS_ENSURE_ARG_MIN(arg, min) \
+ NS_ENSURE_TRUE((arg) >= min, NS_ERROR_INVALID_ARG)
+
+#define NS_ENSURE_ARG_MAX(arg, max) \
+ NS_ENSURE_TRUE((arg) <= max, NS_ERROR_INVALID_ARG)
+
+#define NS_ENSURE_ARG_RANGE(arg, min, max) \
+ NS_ENSURE_TRUE(((arg) >= min) && ((arg) <= max), NS_ERROR_INVALID_ARG)
+
+#define NS_ENSURE_STATE(state) \
+ NS_ENSURE_TRUE(state, NS_ERROR_UNEXPECTED)
+
+#define NS_ENSURE_NO_AGGREGATION(outer) \
+ NS_ENSURE_FALSE(outer, NS_ERROR_NO_AGGREGATION)
+
+#define NS_ENSURE_PROPER_AGGREGATION(outer, iid) \
+ NS_ENSURE_FALSE(outer && !iid.Equals(NS_GET_IID(nsISupports)), NS_ERROR_INVALID_ARG)
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define NS_CheckThreadSafe(owningThread, msg) \
+ NS_ASSERTION(owningThread == PR_GetCurrentThread(), msg)
+
+#endif /* nsDebug_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsGenericFactory.cpp b/src/libs/xpcom18a4/xpcom/glue/nsGenericFactory.cpp
new file mode 100644
index 00000000..2d791943
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsGenericFactory.cpp
@@ -0,0 +1,547 @@
+/* -*- 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 ***** */
+
+
+// DO NOT COPY THIS CODE INTO YOUR SOURCE! USE NS_IMPL_NSGETMODULE()
+
+#include "nsGenericFactory.h"
+#include "nsMemory.h"
+#include "nsCOMPtr.h"
+#include "nsIComponentManager.h"
+#include "nsIComponentRegistrar.h"
+
+#ifdef XPCOM_GLUE
+#include "nsXPCOMGlue.h"
+#include "nsXPCOMPrivate.h"
+#else
+#include "nsIInterfaceRequestorUtils.h"
+#include "nsINativeComponentLoader.h"
+#endif
+
+nsGenericFactory::nsGenericFactory(const nsModuleComponentInfo *info)
+ : mInfo(info)
+{
+ if (mInfo && mInfo->mClassInfoGlobal)
+ *mInfo->mClassInfoGlobal = NS_STATIC_CAST(nsIClassInfo *, this);
+}
+
+nsGenericFactory::~nsGenericFactory()
+{
+ if (mInfo) {
+ if (mInfo->mFactoryDestructor)
+ mInfo->mFactoryDestructor();
+ if (mInfo->mClassInfoGlobal)
+ *mInfo->mClassInfoGlobal = 0;
+ }
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS3(nsGenericFactory,
+ nsIGenericFactory,
+ nsIFactory,
+ nsIClassInfo)
+
+NS_IMETHODIMP nsGenericFactory::CreateInstance(nsISupports *aOuter,
+ REFNSIID aIID, void **aResult)
+{
+ if (mInfo->mConstructor) {
+ return mInfo->mConstructor(aOuter, aIID, aResult);
+ }
+
+ return NS_ERROR_FACTORY_NOT_REGISTERED;
+}
+
+NS_IMETHODIMP nsGenericFactory::LockFactory(PRBool aLock)
+{
+ // XXX do we care if (mInfo->mFlags & THREADSAFE)?
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsGenericFactory::GetInterfaces(PRUint32 *countp,
+ nsIID* **array)
+{
+ if (!mInfo->mGetInterfacesProc) {
+ *countp = 0;
+ *array = nsnull;
+ return NS_OK;
+ }
+ return mInfo->mGetInterfacesProc(countp, array);
+}
+
+NS_IMETHODIMP nsGenericFactory::GetHelperForLanguage(PRUint32 language,
+ nsISupports **helper)
+{
+ if (mInfo->mGetLanguageHelperProc)
+ return mInfo->mGetLanguageHelperProc(language, helper);
+ *helper = nsnull;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsGenericFactory::GetContractID(char **aContractID)
+{
+ if (mInfo->mContractID) {
+ *aContractID = (char *)nsMemory::Alloc(strlen(mInfo->mContractID) + 1);
+ if (!*aContractID)
+ return NS_ERROR_OUT_OF_MEMORY;
+ strcpy(*aContractID, mInfo->mContractID);
+ } else {
+ *aContractID = nsnull;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsGenericFactory::GetClassDescription(char * *aClassDescription)
+{
+ if (mInfo->mDescription) {
+ *aClassDescription = (char *)
+ nsMemory::Alloc(strlen(mInfo->mDescription) + 1);
+ if (!*aClassDescription)
+ return NS_ERROR_OUT_OF_MEMORY;
+ strcpy(*aClassDescription, mInfo->mDescription);
+ } else {
+ *aClassDescription = nsnull;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsGenericFactory::GetClassID(nsCID * *aClassID)
+{
+ *aClassID =
+ NS_REINTERPRET_CAST(nsCID*,
+ nsMemory::Clone(&mInfo->mCID, sizeof mInfo->mCID));
+ if (! *aClassID)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsGenericFactory::GetClassIDNoAlloc(nsCID *aClassID)
+{
+ *aClassID = mInfo->mCID;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsGenericFactory::GetImplementationLanguage(PRUint32 *langp)
+{
+ *langp = nsIProgrammingLanguage::CPLUSPLUS;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsGenericFactory::GetFlags(PRUint32 *flagsp)
+{
+ *flagsp = mInfo->mFlags;
+ return NS_OK;
+}
+
+// nsIGenericFactory: component-info accessors
+NS_IMETHODIMP nsGenericFactory::SetComponentInfo(const nsModuleComponentInfo *info)
+{
+ if (mInfo && mInfo->mClassInfoGlobal)
+ *mInfo->mClassInfoGlobal = 0;
+ mInfo = info;
+ if (mInfo && mInfo->mClassInfoGlobal)
+ *mInfo->mClassInfoGlobal = NS_STATIC_CAST(nsIClassInfo *, this);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsGenericFactory::GetComponentInfo(const nsModuleComponentInfo **infop)
+{
+ *infop = mInfo;
+ return NS_OK;
+}
+
+NS_METHOD nsGenericFactory::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
+{
+ // sorry, aggregation not spoken here.
+ nsresult res = NS_ERROR_NO_AGGREGATION;
+ if (outer == NULL) {
+ nsGenericFactory* factory = new nsGenericFactory;
+ if (factory != NULL) {
+ res = factory->QueryInterface(aIID, aInstancePtr);
+ if (res != NS_OK)
+ delete factory;
+ } else {
+ res = NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ return res;
+}
+
+NS_COM nsresult
+NS_NewGenericFactory(nsIGenericFactory* *result,
+ const nsModuleComponentInfo *info)
+{
+ nsresult rv;
+ nsIGenericFactory* fact;
+ rv = nsGenericFactory::Create(NULL, NS_GET_IID(nsIGenericFactory), (void**)&fact);
+ if (NS_FAILED(rv)) return rv;
+ rv = fact->SetComponentInfo(info);
+ if (NS_FAILED(rv)) goto error;
+ *result = fact;
+ return rv;
+
+ error:
+ NS_RELEASE(fact);
+ return rv;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+nsGenericModule::nsGenericModule(const char* moduleName, PRUint32 componentCount,
+ const nsModuleComponentInfo* components,
+ nsModuleConstructorProc ctor,
+ nsModuleDestructorProc dtor,
+ const char** aLibDepends)
+ : mInitialized(PR_FALSE),
+ mModuleName(moduleName),
+ mComponentCount(componentCount),
+ mComponents(components),
+ mFactoriesNotToBeRegistered(nsnull),
+ mCtor(ctor),
+ mDtor(dtor),
+ mLibraryDependencies(aLibDepends)
+{
+}
+
+nsGenericModule::~nsGenericModule()
+{
+ Shutdown();
+
+#ifdef XPCOM_GLUE
+ XPCOMGlueShutdown();
+#endif
+
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsGenericModule, nsIModule)
+
+nsresult
+nsGenericModule::AddFactoryNode(nsIGenericFactory* fact)
+{
+ if (!fact)
+ return NS_ERROR_FAILURE;
+
+ FactoryNode *node = new FactoryNode(fact, mFactoriesNotToBeRegistered);
+ if (!node)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ mFactoriesNotToBeRegistered = node;
+ return NS_OK;
+}
+
+
+// Perform our one-time intialization for this module
+nsresult
+nsGenericModule::Initialize(nsIComponentManager *compMgr)
+{
+ nsresult rv;
+
+ if (mInitialized) {
+ return NS_OK;
+ }
+
+ if (mCtor) {
+ rv = mCtor(this);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+
+#ifdef XPCOM_GLUE
+ rv = XPCOMGlueStartup(".");
+ if (NS_FAILED(rv))
+ return rv;
+#endif
+
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(compMgr, &rv);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Eagerly populate factory/class object hash for entries
+ // without constructors. If we didn't, the class object would
+ // never get created. Also create the factory, which doubles
+ // as the class object, if the EAGER_CLASSINFO flag was given.
+ // This allows objects to be created (within their modules)
+ // via operator new rather than CreateInstance, yet still be
+ // QI'able to nsIClassInfo.
+ const nsModuleComponentInfo* desc = mComponents;
+ for (PRUint32 i = 0; i < mComponentCount; i++) {
+ if (!desc->mConstructor ||
+ (desc->mFlags & nsIClassInfo::EAGER_CLASSINFO)) {
+ nsCOMPtr<nsIGenericFactory> fact;
+ nsresult rv = NS_NewGenericFactory(getter_AddRefs(fact), desc);
+ if (NS_FAILED(rv)) return rv;
+
+ // if we don't have a mConstructor, then we should not populate
+ // the component manager.
+ if (!desc->mConstructor) {
+ rv = AddFactoryNode(fact);
+ } else {
+ rv = registrar->RegisterFactory(desc->mCID,
+ desc->mDescription,
+ desc->mContractID,
+ fact);
+ }
+ if (NS_FAILED(rv)) return rv;
+ }
+ desc++;
+ }
+
+ mInitialized = PR_TRUE;
+ return NS_OK;
+}
+
+// Shutdown this module, releasing all of the module resources
+void
+nsGenericModule::Shutdown()
+{
+ // Free cached factories that were not registered.
+ FactoryNode* node;
+ while (mFactoriesNotToBeRegistered)
+ {
+ node = mFactoriesNotToBeRegistered->mNext;
+ delete mFactoriesNotToBeRegistered;
+ mFactoriesNotToBeRegistered = node;
+ }
+
+ if (mInitialized) {
+ mInitialized = PR_FALSE;
+
+ if (mDtor)
+ mDtor(this);
+ }
+}
+
+// Create a factory object for creating instances of aClass.
+NS_IMETHODIMP
+nsGenericModule::GetClassObject(nsIComponentManager *aCompMgr,
+ const nsCID& aClass,
+ const nsIID& aIID,
+ void** r_classObj)
+{
+ nsresult rv;
+
+ // Defensive programming: Initialize *r_classObj in case of error below
+ if (!r_classObj) {
+ return NS_ERROR_INVALID_POINTER;
+ }
+ *r_classObj = NULL;
+
+ // Do one-time-only initialization if necessary
+ if (!mInitialized) {
+ rv = Initialize(aCompMgr);
+ if (NS_FAILED(rv)) {
+ // Initialization failed! yikes!
+ return rv;
+ }
+ }
+
+ // Choose the appropriate factory, based on the desired instance
+ // class type (aClass).
+ const nsModuleComponentInfo* desc = mComponents;
+ for (PRUint32 i = 0; i < mComponentCount; i++) {
+ if (desc->mCID.Equals(aClass)) {
+ nsCOMPtr<nsIGenericFactory> fact;
+ rv = NS_NewGenericFactory(getter_AddRefs(fact), desc);
+ if (NS_FAILED(rv)) return rv;
+ return fact->QueryInterface(aIID, r_classObj);
+ }
+ desc++;
+ }
+ // not found in descriptions
+#ifndef XPCOM_GLUE
+#ifdef DEBUG
+ char* cs = aClass.ToString();
+ fprintf(stderr, "+++ nsGenericModule %s: unable to create factory for %s\n", mModuleName, cs);
+ // leak until we resolve the nsID Allocator.
+ // nsCRT::free(cs);
+#endif // XXX put in stop-gap so that we don't search for this one again
+#endif
+ return NS_ERROR_FACTORY_NOT_REGISTERED;
+}
+
+NS_IMETHODIMP
+nsGenericModule::RegisterSelf(nsIComponentManager *aCompMgr,
+ nsIFile* aPath,
+ const char* registryLocation,
+ const char* componentType)
+{
+ nsresult rv = NS_OK;
+
+#ifdef DEBUG
+ fprintf(stderr, "*** Registering %s components (all right -- a generic module!)\n", mModuleName);
+#endif
+
+ const nsModuleComponentInfo* cp = mComponents;
+ for (PRUint32 i = 0; i < mComponentCount; i++) {
+ // Register the component only if it has a constructor
+ if (cp->mConstructor) {
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(aCompMgr, &rv);
+ if (registrar)
+ rv = registrar->RegisterFactoryLocation(cp->mCID,
+ cp->mDescription,
+ cp->mContractID,
+ aPath,
+ registryLocation,
+ componentType);
+ if (NS_FAILED(rv)) {
+#ifdef DEBUG
+ fprintf(stderr, "nsGenericModule %s: unable to register %s component => %x\n",
+ mModuleName?mModuleName:"(null)", cp->mDescription?cp->mDescription:"(null)", rv);
+#endif
+ break;
+ }
+ }
+ // Call the registration hook of the component, if any
+ if (cp->mRegisterSelfProc)
+ {
+ rv = cp->mRegisterSelfProc(aCompMgr, aPath, registryLocation,
+ componentType, cp);
+ if (NS_FAILED(rv)) {
+#ifdef DEBUG
+ fprintf(stderr, "nsGenericModule %s: Register hook for %s component returned error => %x\n",
+ mModuleName?mModuleName:"(null)", cp->mDescription?cp->mDescription:"(null)", rv);
+#endif
+ break;
+ }
+ }
+ cp++;
+ }
+
+#ifndef XPCOM_GLUE
+ // We want to tell the component loader of any dependencies
+ // we have so that the loader can resolve them for us.
+
+ nsCOMPtr<nsINativeComponentLoader> loader = do_GetInterface(aCompMgr);
+ if (loader && mLibraryDependencies)
+ {
+ for(int i=0; mLibraryDependencies[i] != nsnull &&
+ mLibraryDependencies[i][0] != '\0'; i++)
+ {
+ loader->AddDependentLibrary(aPath,
+ mLibraryDependencies[i]);
+ }
+ loader = nsnull;
+ }
+#endif
+
+
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsGenericModule::UnregisterSelf(nsIComponentManager* aCompMgr,
+ nsIFile* aPath,
+ const char* registryLocation)
+{
+#ifdef DEBUG
+ fprintf(stderr, "*** Unregistering %s components (all right -- a generic module!)\n", mModuleName);
+#endif
+ const nsModuleComponentInfo* cp = mComponents;
+ for (PRUint32 i = 0; i < mComponentCount; i++) {
+ // Call the unregistration hook of the component, if any
+ if (cp->mUnregisterSelfProc)
+ {
+ cp->mUnregisterSelfProc(aCompMgr, aPath, registryLocation, cp);
+ }
+
+ // Unregister the component
+ nsresult rv;
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(aCompMgr, &rv);
+ if (registrar)
+ rv = registrar->UnregisterFactoryLocation(cp->mCID, aPath);
+ if (NS_FAILED(rv)) {
+#ifdef DEBUG
+ fprintf(stderr, "nsGenericModule %s: unable to unregister %s component => %x\n",
+ mModuleName, cp->mDescription, rv);
+#endif
+ }
+ cp++;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsGenericModule::CanUnload(nsIComponentManager *aCompMgr, PRBool *okToUnload)
+{
+ if (!okToUnload) {
+ return NS_ERROR_INVALID_POINTER;
+ }
+ *okToUnload = PR_FALSE;
+ return NS_ERROR_FAILURE;
+}
+
+NS_COM nsresult
+NS_NewGenericModule2(nsModuleInfo* info, nsIModule* *result)
+{
+ nsresult rv = NS_OK;
+
+ // Create and initialize the module instance
+ nsGenericModule *m =
+ new nsGenericModule(info->mModuleName, info->mCount, info->mComponents,
+ info->mCtor, info->mDtor, info->mLibraryDependencies);
+
+ if (!m)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Increase refcnt and store away nsIModule interface to m in result
+ NS_ADDREF(*result = m);
+ return rv;
+}
+
+NS_COM nsresult
+NS_NewGenericModule(const char* moduleName,
+ PRUint32 componentCount,
+ nsModuleComponentInfo* components,
+ nsModuleDestructorProc dtor,
+ nsIModule* *result)
+{
+ nsModuleInfo info;
+ memset(&info, 0, sizeof(info));
+
+ info.mVersion = NS_MODULEINFO_VERSION;
+ info.mModuleName = moduleName;
+ info.mComponents = components;
+ info.mCount = componentCount;
+ info.mDtor = dtor;
+ info.mLibraryDependencies = nsnull;
+
+ return NS_NewGenericModule2(&info, result);
+}
+
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsGenericFactory.h b/src/libs/xpcom18a4/xpcom/glue/nsGenericFactory.h
new file mode 100644
index 00000000..64afd0de
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsGenericFactory.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 nsGenericFactory_h___
+#define nsGenericFactory_h___
+
+#include "nsCOMPtr.h"
+#include "nsIGenericFactory.h"
+#include "nsIClassInfo.h"
+
+/**
+ * Most factories follow this simple pattern, so why not just use a function
+ * pointer for most creation operations?
+ */
+class nsGenericFactory : public nsIGenericFactory, public nsIClassInfo {
+public:
+ NS_DEFINE_STATIC_CID_ACCESSOR(NS_GENERICFACTORY_CID);
+
+ nsGenericFactory(const nsModuleComponentInfo *info = NULL);
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSICLASSINFO
+
+ /* nsIGenericFactory methods */
+ NS_IMETHOD SetComponentInfo(const nsModuleComponentInfo *info);
+ NS_IMETHOD GetComponentInfo(const nsModuleComponentInfo **infop);
+
+ NS_IMETHOD CreateInstance(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+ NS_IMETHOD LockFactory(PRBool aLock);
+
+ static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+private:
+ ~nsGenericFactory();
+
+ const nsModuleComponentInfo *mInfo;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#include "nsIModule.h"
+#include "plhash.h"
+
+class nsGenericModule : public nsIModule
+{
+public:
+ nsGenericModule(const char* moduleName,
+ PRUint32 componentCount,
+ const nsModuleComponentInfo* components,
+ nsModuleConstructorProc ctor,
+ nsModuleDestructorProc dtor,
+ const char** alibDepends);
+
+private:
+ ~nsGenericModule();
+
+public:
+ NS_DECL_ISUPPORTS
+
+ NS_DECL_NSIMODULE
+
+ struct FactoryNode
+ {
+ FactoryNode(nsIGenericFactory* fact, FactoryNode* next)
+ {
+ mFactory = fact;
+ mNext = next;
+ }
+ ~FactoryNode(){}
+
+ nsCOMPtr<nsIGenericFactory> mFactory;
+ FactoryNode* mNext;
+ };
+
+
+
+
+protected:
+ nsresult Initialize(nsIComponentManager* compMgr);
+
+ void Shutdown();
+ nsresult AddFactoryNode(nsIGenericFactory* fact);
+
+ PRBool mInitialized;
+ const char* mModuleName;
+ PRUint32 mComponentCount;
+ const nsModuleComponentInfo* mComponents;
+ FactoryNode* mFactoriesNotToBeRegistered;
+ nsModuleConstructorProc mCtor;
+ nsModuleDestructorProc mDtor;
+ const char** mLibraryDependencies;
+};
+
+#endif /* nsGenericFactory_h___ */
+
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsIGenericFactory.h b/src/libs/xpcom18a4/xpcom/glue/nsIGenericFactory.h
new file mode 100644
index 00000000..82506e8e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsIGenericFactory.h
@@ -0,0 +1,480 @@
+/* -*- 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 nsIGenericFactory_h___
+#define nsIGenericFactory_h___
+
+#include "nsIFactory.h"
+#include "nsIModule.h"
+#include "nsIClassInfo.h"
+#ifdef HAVE_DEPENDENT_LIBS
+#include "dependentLibs.h"
+#endif
+
+// {3bc97f01-ccdf-11d2-bab8-b548654461fc}
+#define NS_GENERICFACTORY_CID \
+ { 0x3bc97f01, 0xccdf, 0x11d2, \
+ { 0xba, 0xb8, 0xb5, 0x48, 0x65, 0x44, 0x61, 0xfc } }
+
+// {3bc97f00-ccdf-11d2-bab8-b548654461fc}
+#define NS_IGENERICFACTORY_IID \
+ { 0x3bc97f00, 0xccdf, 0x11d2, \
+ { 0xba, 0xb8, 0xb5, 0x48, 0x65, 0x44, 0x61, 0xfc } }
+
+#define NS_GENERICFACTORY_CONTRACTID "@mozilla.org/generic-factory;1"
+#define NS_GENERICFACTORY_CLASSNAME "Generic Factory"
+
+struct nsModuleComponentInfo; // forward declaration
+
+/**
+ * Provides a Generic nsIFactory implementation that can be used by
+ * DLLs with very simple factory needs.
+ */
+class nsIGenericFactory : public nsIFactory {
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IGENERICFACTORY_IID)
+
+ NS_IMETHOD SetComponentInfo(const nsModuleComponentInfo *info) = 0;
+ NS_IMETHOD GetComponentInfo(const nsModuleComponentInfo **infop) = 0;
+};
+
+NS_COM nsresult
+NS_NewGenericFactory(nsIGenericFactory **result,
+ const nsModuleComponentInfo *info);
+
+
+/** Component Callbacks **/
+
+ /**
+ * NSConstructorProcPtr
+ *
+ * This function will be used by the generic factory to create an
+ * instance of the given CID.
+ *
+ * @param aOuter : Pointer to a component that wishes to be aggregated
+ * in the resulting instance. This will be nsnull if no
+ * aggregation is requested.
+ * @param iid : The IID of the interface being requested in
+ * the component which is being currently created.
+ * @param result : [out] Pointer to the newly created instance, if successful.
+ *
+ * @return NS_OK Component successfully created and the interface
+ * being requested was successfully returned in result.
+ * NS_NOINTERFACE Interface not accessible.
+ * NS_ERROR_NO_AGGREGATION if an 'outer' object is supplied, but the
+ * component is not aggregatable.
+ * NS_ERROR* Method failure.
+ **/
+typedef NS_CALLBACK(NSConstructorProcPtr)(nsISupports *aOuter,
+ REFNSIID aIID,
+ void **aResult);
+
+/**
+ * NSRegisterSelfProcPtr
+ *
+ * One time registration call back. Allows you to perform registration
+ * specific activity like adding yourself to a category.
+ *
+ * @param aCompMgr : The global component manager
+ * @param aFile : Component File. This file must have an associated
+ * loader and export the required symbols which this
+ * loader defines.
+ * @param aLoaderStr : Opaque loader specific string. This value is
+ * passed into the nsIModule's registerSelf
+ * callback and must be fowarded unmodified when
+ * registering factories via their location.
+ * @param aType : Component Type of CID aClass. This value is
+ * passed into the nsIModule's registerSelf
+ * callback and must be fowarded unmodified when
+ * registering factories via their location.
+ * @param aInfo : Pointer to array of nsModuleComponentInfo
+ *
+ * @param aInfo
+ * @return NS_OK Registration was successful.
+ * NS_ERROR* Method failure.
+ **/
+typedef NS_CALLBACK(NSRegisterSelfProcPtr)(nsIComponentManager *aCompMgr,
+ nsIFile *aPath,
+ const char *aLoaderStr,
+ const char *aType,
+ const nsModuleComponentInfo *aInfo);
+
+/**
+ * NSUnregisterSelfProcPtr
+ *
+ * One time unregistration call back. Allows you to perform unregistration
+ * specific activity like removing yourself from a category.
+ *
+ * @param aCompMgr : The global component manager
+ * @param aFile : Component File. This file must have an associated
+ * loader and export the required symbols which this
+ * loader defines.
+ * @param aLoaderStr : Opaque loader specific string. This value is
+ * passed into the nsIModule's registerSelf
+ * callback and must be fowarded unmodified when
+ * registering factories via their location
+ * @param aInfo : Pointer to array of nsModuleComponentInfo
+ *
+ * @param aInfo
+ * @return NS_OK Registration was successful.
+ * NS_ERROR* Method failure.
+
+ **/
+typedef NS_CALLBACK(NSUnregisterSelfProcPtr)(nsIComponentManager *aCompMgr,
+ nsIFile *aPath,
+ const char *aLoaderStr,
+ const nsModuleComponentInfo *aInfo);
+
+/**
+ * NSFactoryDestructorProcPtr
+ *
+ * This function will be called when the factory is being destroyed.
+ *
+ **/
+typedef NS_CALLBACK(NSFactoryDestructorProcPtr)(void);
+
+
+/**
+ * NSGetInterfacesProcPtr
+ *
+ * This function is used to implement class info.
+ *
+ * Get an ordered list of the interface ids that instances of the class
+ * promise to implement. Note that nsISupports is an implicit member
+ * of any such list and need not be included.
+ *
+ * Should set *count = 0 and *array = null and return NS_OK if getting the
+ * list is not supported.
+ *
+ * @see nsIClassInfo.idl
+ **/
+typedef NS_CALLBACK(NSGetInterfacesProcPtr)(PRUint32 *countp,
+ nsIID* **array);
+
+/**
+ * NSGetLanguageHelperProcPtr
+ *
+ * This function is used to implement class info.
+ *
+ * Get a language mapping specific helper object that may assist in using
+ * objects of this class in a specific lanaguage. For instance, if asked
+ * for the helper for nsIProgrammingLanguage::JAVASCRIPT this might return
+ * an object that can be QI'd into the nsIXPCScriptable interface to assist
+ * XPConnect in supplying JavaScript specific behavior to callers of the
+ * instance object.
+ *
+ * @see: nsIClassInfo.idl, nsIProgrammingLanguage.idl
+ *
+ * Should return null if no helper available for given language.
+ **/
+typedef NS_CALLBACK(NSGetLanguageHelperProcPtr)(PRUint32 language,
+ nsISupports **helper);
+
+/**
+ * nsModuleComponentInfo
+ *
+ * Use this type to define a list of module component info to pass to
+ * NS_NewGenericModule.
+ *
+ * @param mDescription : Class Name of given object
+ * @param mCID : CID of given object
+ * @param mContractID : Contract ID of given object
+ * @param mConstructor : Constructor of given object
+ * @param mRegisterSelfProc : (optional) Registration Callback
+ * @param mUnregisterSelfProc : (optional) Unregistration Callback
+ * @param mFactoryDestructor : (optional) Destruction Callback
+ * @param mGetInterfacesProc : (optional) Interfaces Callback
+ * @param mGetLanguageHelperProc : (optional) Language Helper Callback
+ * @param mClassInfoGlobal : (optional) Global Class Info of given object
+ * @param mFlags : (optional) Class Info Flags @see nsIClassInfo
+ *
+ * E.g.:
+ * static nsModuleComponentInfo components[] = { ... };
+ *
+ * See xpcom/sample/nsSampleModule.cpp for more info.
+ */
+struct nsModuleComponentInfo {
+ const char* mDescription;
+ nsCID mCID;
+ const char* mContractID;
+ NSConstructorProcPtr mConstructor;
+ NSRegisterSelfProcPtr mRegisterSelfProc;
+ NSUnregisterSelfProcPtr mUnregisterSelfProc;
+ NSFactoryDestructorProcPtr mFactoryDestructor;
+ NSGetInterfacesProcPtr mGetInterfacesProc;
+ NSGetLanguageHelperProcPtr mGetLanguageHelperProc;
+ nsIClassInfo ** mClassInfoGlobal;
+ PRUint32 mFlags;
+};
+
+
+/** Module Callbacks **/
+
+
+/**
+ * nsModuleConstructorProc
+ *
+ * This function is called when the module is first being constructed.
+ * @param self module which is being constructed.
+ *
+ * @return NS_OK Construction successful.
+ * NS_ERROR* Method failure which will result in module not being
+ * loaded.
+ **/
+typedef nsresult (PR_CALLBACK *nsModuleConstructorProc) (nsIModule *self);
+
+
+/**
+ * nsModuleDestructorProc
+ *
+ * This function is called when the module is being destroyed.
+ * @param self module which is being destroyed.
+ *
+ **/
+typedef void (PR_CALLBACK *nsModuleDestructorProc) (nsIModule *self);
+
+/**
+ * nsModuleInfo
+ *
+ * Use this structure to define meta-information about the module
+ * itself, including the name, its components, and an optional
+ * module-level initialization or shutdown routine.
+ *
+ * @param mVersion : Module Info Version
+ * @param mModuleName : Module Name
+ * @param mComponents : Array of Components
+ * @param mCount : Count of mComponents
+ * @param mCtor : Module user defined constructor
+ * @param mDtor : Module user defined destructor
+ * @param mLibraryDependencies : array of library which this module is
+ * dependent on.
+ *
+ **/
+
+struct nsModuleInfo {
+ PRUint32 mVersion;
+ const char* mModuleName;
+ const nsModuleComponentInfo* mComponents;
+ PRUint32 mCount;
+ nsModuleConstructorProc mCtor;
+ nsModuleDestructorProc mDtor;
+ const char** mLibraryDependencies;
+};
+
+/**
+ * Rev this if you change the nsModuleInfo, and are worried about
+ * binary compatibility. (Ostensibly fix NS_NewGenericModule2() to deal
+ * with older rev's at the same time.)
+ */
+#define NS_MODULEINFO_VERSION 0x00015000UL // 1.5
+
+/**
+ * Create a new generic module. Use the NS_IMPL_NSGETMODULE macro, or
+ * one of its relatives, rather than using this directly.
+ */
+NS_COM nsresult
+NS_NewGenericModule2(nsModuleInfo *info, nsIModule* *result);
+
+/**
+ * Obsolete. Use NS_NewGenericModule2() instead.
+ */
+NS_COM nsresult
+NS_NewGenericModule(const char* moduleName,
+ PRUint32 componentCount,
+ nsModuleComponentInfo* components,
+ nsModuleDestructorProc dtor,
+ nsIModule* *result);
+
+#if defined(XPCOM_TRANSLATE_NSGM_ENTRY_POINT)
+# define NS_MODULEINFO nsModuleInfo
+# define NSMODULEINFO(_name) _name##_gModuleInfo
+# define NSGETMODULE_ENTRY_POINT(_info)
+# define NSDEPENDENT_LIBS(_name) const char* _name##_gDependlibs[]={DEPENDENT_LIBS "\0"};
+# define NSDEPENDENT_LIBS_NAME(_name) _name##_gDependlibs
+#else
+# define NS_MODULEINFO static nsModuleInfo
+# define NSMODULEINFO(_name) gModuleInfo
+# define NSDEPENDENT_LIBS(_name) static const char* gDependlibs[]={DEPENDENT_LIBS "\0"};
+# define NSDEPENDENT_LIBS_NAME(_name) gDependlibs
+# define NSGETMODULE_ENTRY_POINT(_info) \
+extern "C" NS_EXPORT nsresult \
+NSGetModule(nsIComponentManager *servMgr, \
+ nsIFile* location, \
+ nsIModule** result) \
+{ \
+ (void)servMgr; \
+ (void)location; \
+ return NS_NewGenericModule2(&(_info), result); \
+}
+#endif
+
+/**
+ * Ease of use Macros which define NSGetModule for your component.
+ * See xpcom/sample/nsSampleModule.cpp for more info.
+ *
+ **/
+
+#define NS_IMPL_NSGETMODULE(_name, _components) \
+ NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(_name, _components, nsnull, nsnull)
+
+#define NS_IMPL_NSGETMODULE_WITH_CTOR(_name, _components, _ctor) \
+ NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(_name, _components, _ctor, nsnull)
+
+#define NS_IMPL_NSGETMODULE_WITH_DTOR(_name, _components, _dtor) \
+ NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(_name, _components, nsnull, _dtor)
+
+#ifndef DEPENDENT_LIBS
+
+#define NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(_name, _components, _ctor, _dtor) \
+NS_MODULEINFO NSMODULEINFO(_name) = { \
+ NS_MODULEINFO_VERSION, \
+ (#_name), \
+ (_components), \
+ (sizeof(_components) / sizeof(_components[0])), \
+ (_ctor), \
+ (_dtor), \
+ (nsnull) \
+}; \
+NSGETMODULE_ENTRY_POINT(NSMODULEINFO(_name))
+
+#else // DEPENDENT_LIBS
+
+#define NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(_name, _components, _ctor, _dtor) \
+NSDEPENDENT_LIBS(_name) \
+NS_MODULEINFO NSMODULEINFO(_name) = { \
+ NS_MODULEINFO_VERSION, \
+ (#_name), \
+ (_components), \
+ (sizeof(_components) / sizeof(_components[0])), \
+ (_ctor), \
+ (_dtor), \
+ (NSDEPENDENT_LIBS_NAME(_name)) \
+}; \
+NSGETMODULE_ENTRY_POINT(NSMODULEINFO(_name))
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+
+#define NS_GENERIC_FACTORY_CONSTRUCTOR(_InstanceClass) \
+static NS_IMETHODIMP \
+_InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \
+ void **aResult) \
+{ \
+ nsresult rv; \
+ \
+ _InstanceClass * inst; \
+ \
+ *aResult = NULL; \
+ if (NULL != aOuter) { \
+ rv = NS_ERROR_NO_AGGREGATION; \
+ return rv; \
+ } \
+ \
+ NS_NEWXPCOM(inst, _InstanceClass); \
+ if (NULL == inst) { \
+ rv = NS_ERROR_OUT_OF_MEMORY; \
+ return rv; \
+ } \
+ NS_ADDREF(inst); \
+ rv = inst->QueryInterface(aIID, aResult); \
+ NS_RELEASE(inst); \
+ \
+ return rv; \
+} \
+
+
+#define NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(_InstanceClass, _InitMethod) \
+static NS_IMETHODIMP \
+_InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \
+ void **aResult) \
+{ \
+ nsresult rv; \
+ \
+ _InstanceClass * inst; \
+ \
+ *aResult = NULL; \
+ if (NULL != aOuter) { \
+ rv = NS_ERROR_NO_AGGREGATION; \
+ return rv; \
+ } \
+ \
+ NS_NEWXPCOM(inst, _InstanceClass); \
+ if (NULL == inst) { \
+ rv = NS_ERROR_OUT_OF_MEMORY; \
+ return rv; \
+ } \
+ NS_ADDREF(inst); \
+ rv = inst->_InitMethod(); \
+ if(NS_SUCCEEDED(rv)) { \
+ rv = inst->QueryInterface(aIID, aResult); \
+ } \
+ NS_RELEASE(inst); \
+ \
+ return rv; \
+} \
+
+// 'Constructor' that uses an existing getter function that gets a singleton.
+// NOTE: assumes that getter does an AddRef - so additional AddRef is not done.
+#define NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(_InstanceClass, _GetterProc) \
+static NS_IMETHODIMP \
+_InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \
+ void **aResult) \
+{ \
+ nsresult rv; \
+ \
+ _InstanceClass * inst; \
+ \
+ *aResult = NULL; \
+ if (NULL != aOuter) { \
+ rv = NS_ERROR_NO_AGGREGATION; \
+ return rv; \
+ } \
+ \
+ inst = _GetterProc(); \
+ if (NULL == inst) { \
+ rv = NS_ERROR_OUT_OF_MEMORY; \
+ return rv; \
+ } \
+ /* NS_ADDREF(inst); */ \
+ rv = inst->QueryInterface(aIID, aResult); \
+ NS_RELEASE(inst); \
+ \
+ return rv; \
+} \
+
+#endif /* nsIGenericFactory_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsIInterfaceRequestorUtils.cpp b/src/libs/xpcom18a4/xpcom/glue/nsIInterfaceRequestorUtils.cpp
new file mode 100644
index 00000000..b440c342
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsIInterfaceRequestorUtils.cpp
@@ -0,0 +1,64 @@
+/* -*- 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):
+ * 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 ***** */
+
+#include "nsIInterfaceRequestor.h"
+#include "nsIInterfaceRequestorUtils.h"
+
+nsresult
+nsGetInterface::operator()( const nsIID& aIID, void** aInstancePtr ) const
+{
+ nsresult status;
+
+ if ( mSource )
+ {
+ nsCOMPtr<nsIInterfaceRequestor> factoryPtr = do_QueryInterface(mSource, &status);
+ NS_ASSERTION(factoryPtr, "Did you know you were calling |do_GetInterface()| on an object that doesn't support the |nsIInterfaceRequestor| interface?");
+
+ if ( factoryPtr )
+ status = factoryPtr->GetInterface(aIID, aInstancePtr);
+
+ if ( NS_FAILED(status) )
+ *aInstancePtr = 0;
+ }
+ else
+ status = NS_ERROR_NULL_POINTER;
+
+ if ( mErrorPtr )
+ *mErrorPtr = status;
+ return status;
+}
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsIInterfaceRequestorUtils.h b/src/libs/xpcom18a4/xpcom/glue/nsIInterfaceRequestorUtils.h
new file mode 100644
index 00000000..e971dd4b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsIInterfaceRequestorUtils.h
@@ -0,0 +1,83 @@
+/* -*- Mode: IDL; 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 the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 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 ***** */
+
+#ifndef __nsInterfaceRequestorUtils_h
+#define __nsInterfaceRequestorUtils_h
+
+#include "nsCOMPtr.h"
+
+// a type-safe shortcut for calling the |GetInterface()| member function
+// T must inherit from nsIInterfaceRequestor, but the cast may be ambiguous.
+template <class T, class DestinationType>
+inline
+nsresult
+CallGetInterface( T* aSource, DestinationType** aDestination )
+ {
+ NS_PRECONDITION(aSource, "null parameter");
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ return aSource->GetInterface(NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+ }
+
+class NS_COM nsGetInterface : public nsCOMPtr_helper
+ {
+ public:
+ nsGetInterface( nsISupports* aSource, nsresult* error )
+ : mSource(aSource),
+ mErrorPtr(error)
+ {
+ // nothing else to do here
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+
+ private:
+ nsCOMPtr<nsISupports> mSource;
+ nsresult* mErrorPtr;
+ };
+
+inline
+const nsGetInterface
+do_GetInterface( nsISupports* aSource, nsresult* error = 0 )
+ {
+ return nsGetInterface(aSource, error);
+ }
+
+#endif // __nsInterfaceRequestorUtils_h
+
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsISupportsImpl.h b/src/libs/xpcom18a4/xpcom/glue/nsISupportsImpl.h
new file mode 100644
index 00000000..588a2c73
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsISupportsImpl.h
@@ -0,0 +1,1246 @@
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is Netscape Communications Corp.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * 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 nsISupportsImpl_h__
+#define nsISupportsImpl_h__
+
+#ifndef nscore_h___
+#include "nscore.h"
+#endif
+
+#ifndef nsISupportsBase_h__
+#include "nsISupportsBase.h"
+#endif
+
+#include "prthread.h" /* needed for thread-safety checks */
+#include "pratom.h" /* needed for PR_AtomicIncrement and PR_AtomicDecrement */
+
+#include "nsDebug.h"
+#include "nsTraceRefcnt.h"
+#ifdef VBOX
+# include "iprt/asm.h"
+# include "iprt/assert.h"
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// Macros to help detect thread-safety:
+
+#if defined(NS_DEBUG)
+
+class nsAutoOwningThread {
+public:
+ nsAutoOwningThread() { mThread = PR_GetCurrentThread(); }
+ void *GetThread() const { return mThread; }
+
+private:
+ void *mThread;
+};
+
+#define NS_DECL_OWNINGTHREAD nsAutoOwningThread _mOwningThread;
+#define NS_ASSERT_OWNINGTHREAD(_class) \
+ NS_CheckThreadSafe(_mOwningThread.GetThread(), #_class " not thread-safe")
+
+#else // !(defined(NS_DEBUG))
+
+#define NS_DECL_OWNINGTHREAD /* nothing */
+#define NS_ASSERT_OWNINGTHREAD(_class) ((void)0)
+
+#endif // !(defined(NS_DEBUG))
+
+class nsAutoRefCnt {
+
+ public:
+ nsAutoRefCnt() : mValue(0)
+#ifdef VBOX
+ , mState(0)
+#endif
+ {}
+ nsAutoRefCnt(nsrefcnt aValue) : mValue(aValue) {}
+
+ // only support prefix increment/decrement
+ nsrefcnt operator++() { return ++mValue; }
+ nsrefcnt operator--() { return --mValue; }
+
+ nsrefcnt operator=(nsrefcnt aValue) { return (mValue = aValue); }
+ operator nsrefcnt() const { return mValue; }
+ nsrefcnt get() const { return mValue; }
+#ifdef VBOX
+ nsrefcnt *ref() { return &mValue; }
+ PRUint32 getState() const { return mState; }
+ PRUint32 *refState() { return &mState; }
+#endif
+ private:
+ // do not define these to enforce the faster prefix notation
+ nsrefcnt operator++(int);
+ nsrefcnt operator--(int);
+ nsrefcnt mValue;
+#ifdef VBOX
+ PRUint32 mState;
+#endif
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Declare the reference count variable and the implementations of the
+ * AddRef and QueryInterface methods.
+ */
+
+#define NS_DECL_ISUPPORTS \
+public: \
+ NS_IMETHOD QueryInterface(REFNSIID aIID, \
+ void** aInstancePtr); \
+ NS_IMETHOD_(nsrefcnt) AddRef(void); \
+ NS_IMETHOD_(nsrefcnt) Release(void); \
+protected: \
+ nsAutoRefCnt mRefCnt; \
+ NS_DECL_OWNINGTHREAD \
+public:
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Previously used to initialize the reference count, but no longer needed.
+ *
+ * DEPRECATED.
+ */
+#define NS_INIT_ISUPPORTS() ((void)0)
+
+/**
+ * Use this macro to implement the AddRef method for a given <i>_class</i>
+ * @param _class The name of the class implementing the method
+ */
+#define NS_IMPL_ADDREF(_class) \
+NS_IMETHODIMP_(nsrefcnt) _class::AddRef(void) \
+{ \
+ NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); \
+ NS_ASSERT_OWNINGTHREAD(_class); \
+ ++mRefCnt; \
+ NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this)); \
+ return mRefCnt; \
+}
+
+/**
+ * Use this macro to implement the AddRef method for a given <i>_class</i>
+ * implemented as a wholly owned aggregated object intended to implement
+ * interface(s) for its owner
+ * @param _class The name of the class implementing the method
+ * @param _aggregator the owning/containing object
+ */
+#define NS_IMPL_ADDREF_USING_AGGREGATOR(_class, _aggregator) \
+NS_IMETHODIMP_(nsrefcnt) _class::AddRef(void) \
+{ \
+ NS_PRECONDITION(_aggregator, "null aggregator"); \
+ return (_aggregator)->AddRef(); \
+}
+
+/**
+ * Use this macro to implement the Release method for a given
+ * <i>_class</i>.
+ * @param _class The name of the class implementing the method
+ * @param _destroy A statement that is executed when the object's
+ * refcount drops to zero.
+ *
+ * For example,
+ *
+ * NS_IMPL_RELEASE_WITH_DESTROY(Foo, Destroy(this))
+ *
+ * will cause
+ *
+ * Destroy(this);
+ *
+ * to be invoked when the object's refcount drops to zero. This
+ * allows for arbitrary teardown activity to occur (e.g., deallocation
+ * of object allocated with placement new).
+ */
+#define NS_IMPL_RELEASE_WITH_DESTROY(_class, _destroy) \
+NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \
+{ \
+ NS_PRECONDITION(0 != mRefCnt, "dup release"); \
+ NS_ASSERT_OWNINGTHREAD(_class); \
+ --mRefCnt; \
+ NS_LOG_RELEASE(this, mRefCnt, #_class); \
+ if (mRefCnt == 0) { \
+ mRefCnt = 1; /* stabilize */ \
+ _destroy; \
+ return 0; \
+ } \
+ return mRefCnt; \
+}
+
+/**
+ * Use this macro to implement the Release method for a given <i>_class</i>
+ * @param _class The name of the class implementing the method
+ *
+ * A note on the 'stabilization' of the refcnt to one. At that point,
+ * the object's refcount will have gone to zero. The object's
+ * destructor may trigger code that attempts to QueryInterface() and
+ * Release() 'this' again. Doing so will temporarily increment and
+ * decrement the refcount. (Only a logic error would make one try to
+ * keep a permanent hold on 'this'.) To prevent re-entering the
+ * destructor, we make sure that no balanced refcounting can return
+ * the refcount to |0|.
+ */
+#define NS_IMPL_RELEASE(_class) \
+ NS_IMPL_RELEASE_WITH_DESTROY(_class, NS_DELETEXPCOM(this))
+
+/**
+ * Use this macro to implement the Release method for a given <i>_class</i>
+ * implemented as a wholly owned aggregated object intended to implement
+ * interface(s) for its owner
+ * @param _class The name of the class implementing the method
+ * @param _aggregator the owning/containing object
+ */
+#define NS_IMPL_RELEASE_USING_AGGREGATOR(_class, _aggregator) \
+NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \
+{ \
+ NS_PRECONDITION(_aggregator, "null aggregator"); \
+ return (_aggregator)->Release(); \
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+/*
+ * Some convenience macros for implementing QueryInterface
+ */
+
+/**
+ * This implements query interface with two assumptions: First, the
+ * class in question implements nsISupports and its own interface and
+ * nothing else. Second, the implementation of the class's primary
+ * inheritance chain leads to its own interface.
+ *
+ * @param _class The name of the class implementing the method
+ * @param _classiiddef The name of the #define symbol that defines the IID
+ * for the class (e.g. NS_ISUPPORTS_IID)
+ */
+
+#define NS_IMPL_QUERY_HEAD(_class) \
+NS_IMETHODIMP _class::QueryInterface(REFNSIID aIID, void** aInstancePtr) \
+{ \
+ NS_ASSERTION(aInstancePtr, \
+ "QueryInterface requires a non-NULL destination!"); \
+ nsISupports* foundInterface;
+
+#define NS_IMPL_QUERY_BODY(_interface) \
+ if ( aIID.Equals(NS_GET_IID(_interface)) ) \
+ foundInterface = NS_STATIC_CAST(_interface*, this); \
+ else
+
+#define NS_IMPL_QUERY_BODY_CONDITIONAL(_interface, condition) \
+ if ( (condition) && aIID.Equals(NS_GET_IID(_interface))) \
+ foundInterface = NS_STATIC_CAST(_interface*, this); \
+ else
+
+#define NS_IMPL_QUERY_BODY_AMBIGUOUS(_interface, _implClass) \
+ if ( aIID.Equals(NS_GET_IID(_interface)) ) \
+ foundInterface = NS_STATIC_CAST(_interface*, \
+ NS_STATIC_CAST(_implClass*, this)); \
+ else
+
+#define NS_IMPL_QUERY_BODY_AGGREGATED(_interface, _aggregate) \
+ if ( aIID.Equals(NS_GET_IID(_interface)) ) \
+ foundInterface = NS_STATIC_CAST(_interface*, _aggregate); \
+ else
+
+#define NS_IMPL_QUERY_TAIL_GUTS \
+ foundInterface = 0; \
+ nsresult status; \
+ if ( !foundInterface ) \
+ status = NS_NOINTERFACE; \
+ else \
+ { \
+ NS_ADDREF(foundInterface); \
+ status = NS_OK; \
+ } \
+ *aInstancePtr = foundInterface; \
+ return status; \
+}
+
+#define NS_IMPL_QUERY_TAIL_INHERITING(_baseclass) \
+ foundInterface = 0; \
+ nsresult status; \
+ if ( !foundInterface ) \
+ status = _baseclass::QueryInterface(aIID, (void**)&foundInterface); \
+ else \
+ { \
+ NS_ADDREF(foundInterface); \
+ status = NS_OK; \
+ } \
+ *aInstancePtr = foundInterface; \
+ return status; \
+}
+
+#define NS_IMPL_QUERY_TAIL_USING_AGGREGATOR(_aggregator) \
+ foundInterface = 0; \
+ nsresult status; \
+ if ( !foundInterface ) { \
+ NS_ASSERTION(_aggregator, "null aggregator"); \
+ status = _aggregator->QueryInterface(aIID, (void**)&foundInterface); \
+ } else \
+ { \
+ NS_ADDREF(foundInterface); \
+ status = NS_OK; \
+ } \
+ *aInstancePtr = foundInterface; \
+ return status; \
+}
+
+#define NS_IMPL_QUERY_TAIL(_supports_interface) \
+ NS_IMPL_QUERY_BODY_AMBIGUOUS(nsISupports, _supports_interface) \
+ NS_IMPL_QUERY_TAIL_GUTS
+
+
+ /*
+ This is the new scheme. Using this notation now will allow us to switch to
+ a table driven mechanism when it's ready. Note the difference between this
+ and the (currently) underlying NS_IMPL_QUERY_INTERFACE mechanism. You must
+ explicitly mention |nsISupports| when using the interface maps.
+ */
+#define NS_INTERFACE_MAP_BEGIN(_implClass) NS_IMPL_QUERY_HEAD(_implClass)
+#define NS_INTERFACE_MAP_ENTRY(_interface) NS_IMPL_QUERY_BODY(_interface)
+#define NS_INTERFACE_MAP_ENTRY_CONDITIONAL(_interface, condition) \
+ NS_IMPL_QUERY_BODY_CONDITIONAL(_interface, condition)
+#define NS_INTERFACE_MAP_ENTRY_AGGREGATED(_interface,_aggregate) \
+ NS_IMPL_QUERY_BODY_AGGREGATED(_interface,_aggregate)
+
+#define NS_INTERFACE_MAP_END NS_IMPL_QUERY_TAIL_GUTS
+#define NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(_interface, _implClass) \
+ NS_IMPL_QUERY_BODY_AMBIGUOUS(_interface, _implClass)
+#define NS_INTERFACE_MAP_END_INHERITING(_baseClass) \
+ NS_IMPL_QUERY_TAIL_INHERITING(_baseClass)
+#define NS_INTERFACE_MAP_END_AGGREGATED(_aggregator) \
+ NS_IMPL_QUERY_TAIL_USING_AGGREGATOR(_aggregator)
+
+#define NS_IMPL_QUERY_INTERFACE0(_class) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(nsISupports) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_QUERY_INTERFACE1(_class, _i1) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_QUERY_INTERFACE2(_class, _i1, _i2) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_QUERY_INTERFACE3(_class, _i1, _i2, _i3) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_QUERY_INTERFACE4(_class, _i1, _i2, _i3, _i4) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_QUERY_INTERFACE5(_class, _i1, _i2, _i3, _i4, _i5) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_QUERY_INTERFACE6(_class, _i1, _i2, _i3, _i4, _i5, _i6) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY(_i6) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_QUERY_INTERFACE7(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY(_i6) \
+ NS_INTERFACE_MAP_ENTRY(_i7) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_QUERY_INTERFACE8(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY(_i6) \
+ NS_INTERFACE_MAP_ENTRY(_i7) \
+ NS_INTERFACE_MAP_ENTRY(_i8) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_QUERY_INTERFACE9(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY(_i6) \
+ NS_INTERFACE_MAP_ENTRY(_i7) \
+ NS_INTERFACE_MAP_ENTRY(_i8) \
+ NS_INTERFACE_MAP_ENTRY(_i9) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_QUERY_INTERFACE10(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9, _i10) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY(_i6) \
+ NS_INTERFACE_MAP_ENTRY(_i7) \
+ NS_INTERFACE_MAP_ENTRY(_i8) \
+ NS_INTERFACE_MAP_ENTRY(_i9) \
+ NS_INTERFACE_MAP_ENTRY(_i10) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_QUERY_INTERFACE11(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9, _i10, _i11) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY(_i6) \
+ NS_INTERFACE_MAP_ENTRY(_i7) \
+ NS_INTERFACE_MAP_ENTRY(_i8) \
+ NS_INTERFACE_MAP_ENTRY(_i9) \
+ NS_INTERFACE_MAP_ENTRY(_i10) \
+ NS_INTERFACE_MAP_ENTRY(_i11) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_INTERFACE_MAP_END
+
+
+#define NS_IMPL_THREADSAFE_QUERY_INTERFACE0 NS_IMPL_QUERY_INTERFACE0
+#define NS_IMPL_THREADSAFE_QUERY_INTERFACE1 NS_IMPL_QUERY_INTERFACE1
+#define NS_IMPL_THREADSAFE_QUERY_INTERFACE2 NS_IMPL_QUERY_INTERFACE2
+#define NS_IMPL_THREADSAFE_QUERY_INTERFACE3 NS_IMPL_QUERY_INTERFACE3
+#define NS_IMPL_THREADSAFE_QUERY_INTERFACE4 NS_IMPL_QUERY_INTERFACE4
+#define NS_IMPL_THREADSAFE_QUERY_INTERFACE5 NS_IMPL_QUERY_INTERFACE5
+#define NS_IMPL_THREADSAFE_QUERY_INTERFACE6 NS_IMPL_QUERY_INTERFACE6
+#define NS_IMPL_THREADSAFE_QUERY_INTERFACE7 NS_IMPL_QUERY_INTERFACE7
+#define NS_IMPL_THREADSAFE_QUERY_INTERFACE8 NS_IMPL_QUERY_INTERFACE8
+#define NS_IMPL_THREADSAFE_QUERY_INTERFACE9 NS_IMPL_QUERY_INTERFACE9
+#define NS_IMPL_THREADSAFE_QUERY_INTERFACE10 NS_IMPL_QUERY_INTERFACE10
+#define NS_IMPL_THREADSAFE_QUERY_INTERFACE11 NS_IMPL_QUERY_INTERFACE11
+
+/**
+ * Declare that you're going to inherit from something that already
+ * implements nsISupports, but also implements an additional interface, thus
+ * causing an ambiguity. In this case you don't need another mRefCnt, you
+ * just need to forward the definitions to the appropriate superclass. E.g.
+ *
+ * class Bar : public Foo, public nsIBar { // both provide nsISupports
+ * public:
+ * NS_DECL_ISUPPORTS_INHERITED
+ * ...other nsIBar and Bar methods...
+ * };
+ */
+#define NS_DECL_ISUPPORTS_INHERITED \
+public: \
+ NS_IMETHOD QueryInterface(REFNSIID aIID, \
+ void** aInstancePtr); \
+ NS_IMETHOD_(nsrefcnt) AddRef(void); \
+ NS_IMETHOD_(nsrefcnt) Release(void); \
+
+/**
+ * These macros can be used in conjunction with NS_DECL_ISUPPORTS_INHERITED
+ * to implement the nsISupports methods, forwarding the invocations to a
+ * superclass that already implements nsISupports.
+ *
+ * Note that I didn't make these inlined because they're virtual methods.
+ */
+
+#define NS_IMPL_ADDREF_INHERITED(Class, Super) \
+NS_IMETHODIMP_(nsrefcnt) Class::AddRef(void) \
+{ \
+ return Super::AddRef(); \
+} \
+
+#define NS_IMPL_RELEASE_INHERITED(Class, Super) \
+NS_IMETHODIMP_(nsrefcnt) Class::Release(void) \
+{ \
+ return Super::Release(); \
+} \
+
+#define NS_IMPL_QUERY_INTERFACE_INHERITED0(Class, Super) \
+ NS_IMPL_QUERY_HEAD(Class) \
+ NS_IMPL_QUERY_TAIL_INHERITING(Super) \
+
+#define NS_IMPL_QUERY_INTERFACE_INHERITED1(Class, Super, i1) \
+ NS_IMPL_QUERY_HEAD(Class) \
+ NS_IMPL_QUERY_BODY(i1) \
+ NS_IMPL_QUERY_TAIL_INHERITING(Super) \
+
+#define NS_IMPL_QUERY_INTERFACE_INHERITED2(Class, Super, i1, i2) \
+ NS_IMPL_QUERY_HEAD(Class) \
+ NS_IMPL_QUERY_BODY(i1) \
+ NS_IMPL_QUERY_BODY(i2) \
+ NS_IMPL_QUERY_TAIL_INHERITING(Super) \
+
+#define NS_IMPL_QUERY_INTERFACE_INHERITED3(Class, Super, i1, i2, i3) \
+ NS_IMPL_QUERY_HEAD(Class) \
+ NS_IMPL_QUERY_BODY(i1) \
+ NS_IMPL_QUERY_BODY(i2) \
+ NS_IMPL_QUERY_BODY(i3) \
+ NS_IMPL_QUERY_TAIL_INHERITING(Super) \
+
+#define NS_IMPL_QUERY_INTERFACE_INHERITED4(Class, Super, i1, i2, i3, i4) \
+ NS_IMPL_QUERY_HEAD(Class) \
+ NS_IMPL_QUERY_BODY(i1) \
+ NS_IMPL_QUERY_BODY(i2) \
+ NS_IMPL_QUERY_BODY(i3) \
+ NS_IMPL_QUERY_BODY(i4) \
+ NS_IMPL_QUERY_TAIL_INHERITING(Super) \
+
+#define NS_IMPL_QUERY_INTERFACE_INHERITED5(Class,Super,i1,i2,i3,i4,i5) \
+ NS_IMPL_QUERY_HEAD(Class) \
+ NS_IMPL_QUERY_BODY(i1) \
+ NS_IMPL_QUERY_BODY(i2) \
+ NS_IMPL_QUERY_BODY(i3) \
+ NS_IMPL_QUERY_BODY(i4) \
+ NS_IMPL_QUERY_BODY(i5) \
+ NS_IMPL_QUERY_TAIL_INHERITING(Super) \
+
+#define NS_IMPL_QUERY_INTERFACE_INHERITED6(Class,Super,i1,i2,i3,i4,i5,i6) \
+ NS_IMPL_QUERY_HEAD(Class) \
+ NS_IMPL_QUERY_BODY(i1) \
+ NS_IMPL_QUERY_BODY(i2) \
+ NS_IMPL_QUERY_BODY(i3) \
+ NS_IMPL_QUERY_BODY(i4) \
+ NS_IMPL_QUERY_BODY(i5) \
+ NS_IMPL_QUERY_BODY(i6) \
+ NS_IMPL_QUERY_TAIL_INHERITING(Super) \
+
+/**
+ * Convenience macros for implementing all nsISupports methods for
+ * a simple class.
+ * @param _class The name of the class implementing the method
+ * @param _classiiddef The name of the #define symbol that defines the IID
+ * for the class (e.g. NS_ISUPPORTS_IID)
+ */
+
+#define NS_IMPL_ISUPPORTS0(_class) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE0(_class)
+
+#define NS_IMPL_ISUPPORTS1(_class, _interface) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE1(_class, _interface)
+
+#define NS_IMPL_ISUPPORTS2(_class, _i1, _i2) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE2(_class, _i1, _i2)
+
+#define NS_IMPL_ISUPPORTS3(_class, _i1, _i2, _i3) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE3(_class, _i1, _i2, _i3)
+
+#define NS_IMPL_ISUPPORTS4(_class, _i1, _i2, _i3, _i4) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE4(_class, _i1, _i2, _i3, _i4)
+
+#define NS_IMPL_ISUPPORTS5(_class, _i1, _i2, _i3, _i4, _i5) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE5(_class, _i1, _i2, _i3, _i4, _i5)
+
+#define NS_IMPL_ISUPPORTS6(_class, _i1, _i2, _i3, _i4, _i5, _i6) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE6(_class, _i1, _i2, _i3, _i4, _i5, _i6)
+
+#define NS_IMPL_ISUPPORTS7(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE7(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7)
+
+#define NS_IMPL_ISUPPORTS8(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE8(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8)
+
+#define NS_IMPL_ISUPPORTS9(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
+ _i9) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE9(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9)
+
+#define NS_IMPL_ISUPPORTS10(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
+ _i9, _i10) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE10(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
+ _i9, _i10)
+
+#define NS_IMPL_ISUPPORTS11(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
+ _i9, _i10, _i11) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE11(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
+ _i9, _i10, _i11)
+
+#define NS_IMPL_ISUPPORTS_INHERITED0(Class, Super) \
+ NS_IMPL_QUERY_INTERFACE_INHERITED0(Class, Super) \
+ NS_IMPL_ADDREF_INHERITED(Class, Super) \
+ NS_IMPL_RELEASE_INHERITED(Class, Super) \
+
+#define NS_IMPL_ISUPPORTS_INHERITED1(Class, Super, i1) \
+ NS_IMPL_QUERY_INTERFACE_INHERITED1(Class, Super, i1) \
+ NS_IMPL_ADDREF_INHERITED(Class, Super) \
+ NS_IMPL_RELEASE_INHERITED(Class, Super) \
+
+#define NS_IMPL_ISUPPORTS_INHERITED2(Class, Super, i1, i2) \
+ NS_IMPL_QUERY_INTERFACE_INHERITED2(Class, Super, i1, i2) \
+ NS_IMPL_ADDREF_INHERITED(Class, Super) \
+ NS_IMPL_RELEASE_INHERITED(Class, Super) \
+
+#define NS_IMPL_ISUPPORTS_INHERITED3(Class, Super, i1, i2, i3) \
+ NS_IMPL_QUERY_INTERFACE_INHERITED3(Class, Super, i1, i2, i3) \
+ NS_IMPL_ADDREF_INHERITED(Class, Super) \
+ NS_IMPL_RELEASE_INHERITED(Class, Super) \
+
+#define NS_IMPL_ISUPPORTS_INHERITED4(Class, Super, i1, i2, i3, i4) \
+ NS_IMPL_QUERY_INTERFACE_INHERITED4(Class, Super, i1, i2, i3, i4) \
+ NS_IMPL_ADDREF_INHERITED(Class, Super) \
+ NS_IMPL_RELEASE_INHERITED(Class, Super) \
+
+#define NS_IMPL_ISUPPORTS_INHERITED5(Class, Super, i1, i2, i3, i4, i5) \
+ NS_IMPL_QUERY_INTERFACE_INHERITED5(Class, Super, i1, i2, i3, i4, i5) \
+ NS_IMPL_ADDREF_INHERITED(Class, Super) \
+ NS_IMPL_RELEASE_INHERITED(Class, Super) \
+
+#define NS_IMPL_ISUPPORTS_INHERITED6(Class, Super, i1, i2, i3, i4, i5, i6) \
+ NS_IMPL_QUERY_INTERFACE_INHERITED6(Class, Super, i1, i2, i3, i4, i5, i6) \
+ NS_IMPL_ADDREF_INHERITED(Class, Super) \
+ NS_IMPL_RELEASE_INHERITED(Class, Super) \
+
+///////////////////////////////////////////////////////////////////////////////
+/**
+ *
+ * Threadsafe implementations of the ISupports convenience macros
+ *
+ */
+
+/**
+ * Use this macro to implement the AddRef method for a given <i>_class</i>
+ * @param _class The name of the class implementing the method
+ */
+
+#ifdef VBOX
+#define NS_IMPL_THREADSAFE_ADDREF(_class) \
+NS_IMETHODIMP_(nsrefcnt) _class::AddRef(void) \
+{ \
+ nsrefcnt count = mRefCnt.get(); \
+ PRUint32 state = mRefCnt.getState(); \
+ AssertReleaseMsg( state <= 1 \
+ && ( (state == 0 && count == 0) \
+ || (state == 1 && count < PR_UINT32_MAX/2)), \
+ ("AddRef: illegal refcnt=%u state=%d\n", count, state)); \
+ switch (state) \
+ { \
+ case 0: \
+ if (!ASMAtomicCmpXchgU32(mRefCnt.refState(), 1, 0)) \
+ AssertReleaseMsgFailed(("AddRef: racing for first increment\n")); \
+ count = ASMAtomicIncU32(mRefCnt.ref()); \
+ AssertReleaseMsg(count == 1, \
+ ("AddRef: unexpected refcnt=%u\n", count)); \
+ break; \
+ case 1: \
+ count = ASMAtomicIncU32(mRefCnt.ref()); \
+ AssertReleaseMsg(count <= PR_UINT32_MAX/2, \
+ ("AddRef: unexpected refcnt=%u\n", count)); \
+ break; \
+ case 2: \
+ AssertReleaseMsgFailed(("AddRef: freed object\n")); \
+ break; \
+ default: \
+ AssertReleaseMsgFailed(("AddRef: garbage object\n")); \
+ } \
+ NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \
+ return count; \
+}
+#else
+#define NS_IMPL_THREADSAFE_ADDREF(_class) \
+NS_IMETHODIMP_(nsrefcnt) _class::AddRef(void) \
+{ \
+ NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt"); \
+ nsrefcnt count; \
+ count = PR_AtomicIncrement((PRInt32*)&mRefCnt); \
+ NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \
+ return count; \
+}
+#endif
+
+/**
+ * Use this macro to implement the Release method for a given <i>_class</i>
+ * @param _class The name of the class implementing the method
+ */
+
+#ifdef VBOX
+#define NS_IMPL_THREADSAFE_RELEASE(_class) \
+NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \
+{ \
+ nsrefcnt count = mRefCnt.get(); \
+ PRUint32 state = mRefCnt.getState(); \
+ AssertReleaseMsg(state == 1 && count <= PR_UINT32_MAX/2, \
+ ("Release: illegal refcnt=%u state=%d\n", count, state)); \
+ switch (state) \
+ { \
+ case 0: \
+ AssertReleaseMsgFailed(("Release: new object\n")); \
+ break; \
+ case 1: \
+ count = ASMAtomicDecU32(mRefCnt.ref()); \
+ AssertReleaseMsg(count < PR_UINT32_MAX/2, \
+ ("Release: unexpected refcnt=%u\n", count)); \
+ if (count == 0) \
+ { \
+ if (!ASMAtomicCmpXchgU32(mRefCnt.refState(), 2, 1)) \
+ AssertReleaseMsgFailed(("Release: racing for state free\n")); \
+ /* Use better stabilization: reserve everything with top bit set. */ \
+ if (!ASMAtomicCmpXchgU32(mRefCnt.ref(), PR_UINT32_MAX/4*3, 0)) \
+ AssertReleaseMsgFailed(("Release: racing for refcnt stabilize\n")); \
+ NS_DELETEXPCOM(this); \
+ } \
+ break; \
+ case 2: \
+ AssertReleaseMsgFailed(("Release: freed object\n")); \
+ break; \
+ default: \
+ AssertReleaseMsgFailed(("Release: garbage object\n")); \
+ } \
+ NS_LOG_RELEASE(this, count, #_class); \
+ return count; \
+}
+#else
+#define NS_IMPL_THREADSAFE_RELEASE(_class) \
+NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \
+{ \
+ nsrefcnt count; \
+ NS_PRECONDITION(0 != mRefCnt, "dup release"); \
+ count = PR_AtomicDecrement((PRInt32 *)&mRefCnt); \
+ NS_LOG_RELEASE(this, count, #_class); \
+ if (0 == count) { \
+ mRefCnt = 1; /* stabilize */ \
+ /* enable this to find non-threadsafe destructors: */ \
+ /* NS_ASSERT_OWNINGTHREAD(_class); */ \
+ NS_DELETEXPCOM(this); \
+ return 0; \
+ } \
+ return count; \
+}
+#endif
+
+#define NS_IMPL_THREADSAFE_ISUPPORTS0(_class) \
+ NS_IMPL_THREADSAFE_ADDREF(_class) \
+ NS_IMPL_THREADSAFE_RELEASE(_class) \
+ NS_IMPL_THREADSAFE_QUERY_INTERFACE0(_class)
+
+#define NS_IMPL_THREADSAFE_ISUPPORTS1(_class, _interface) \
+ NS_IMPL_THREADSAFE_ADDREF(_class) \
+ NS_IMPL_THREADSAFE_RELEASE(_class) \
+ NS_IMPL_THREADSAFE_QUERY_INTERFACE1(_class, _interface)
+
+#define NS_IMPL_THREADSAFE_ISUPPORTS2(_class, _i1, _i2) \
+ NS_IMPL_THREADSAFE_ADDREF(_class) \
+ NS_IMPL_THREADSAFE_RELEASE(_class) \
+ NS_IMPL_THREADSAFE_QUERY_INTERFACE2(_class, _i1, _i2)
+
+#define NS_IMPL_THREADSAFE_ISUPPORTS3(_class, _i1, _i2, _i3) \
+ NS_IMPL_THREADSAFE_ADDREF(_class) \
+ NS_IMPL_THREADSAFE_RELEASE(_class) \
+ NS_IMPL_THREADSAFE_QUERY_INTERFACE3(_class, _i1, _i2, _i3)
+
+#define NS_IMPL_THREADSAFE_ISUPPORTS4(_class, _i1, _i2, _i3, _i4) \
+ NS_IMPL_THREADSAFE_ADDREF(_class) \
+ NS_IMPL_THREADSAFE_RELEASE(_class) \
+ NS_IMPL_THREADSAFE_QUERY_INTERFACE4(_class, _i1, _i2, _i3, _i4)
+
+#define NS_IMPL_THREADSAFE_ISUPPORTS5(_class, _i1, _i2, _i3, _i4, _i5) \
+ NS_IMPL_THREADSAFE_ADDREF(_class) \
+ NS_IMPL_THREADSAFE_RELEASE(_class) \
+ NS_IMPL_THREADSAFE_QUERY_INTERFACE5(_class, _i1, _i2, _i3, _i4, _i5)
+
+#define NS_IMPL_THREADSAFE_ISUPPORTS6(_class, _i1, _i2, _i3, _i4, _i5, _i6) \
+ NS_IMPL_THREADSAFE_ADDREF(_class) \
+ NS_IMPL_THREADSAFE_RELEASE(_class) \
+ NS_IMPL_THREADSAFE_QUERY_INTERFACE6(_class, _i1, _i2, _i3, _i4, _i5, _i6)
+
+#define NS_IMPL_THREADSAFE_ISUPPORTS7(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7) \
+ NS_IMPL_THREADSAFE_ADDREF(_class) \
+ NS_IMPL_THREADSAFE_RELEASE(_class) \
+ NS_IMPL_THREADSAFE_QUERY_INTERFACE7(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7)
+
+#define NS_IMPL_THREADSAFE_ISUPPORTS8(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8) \
+ NS_IMPL_THREADSAFE_ADDREF(_class) \
+ NS_IMPL_THREADSAFE_RELEASE(_class) \
+ NS_IMPL_THREADSAFE_QUERY_INTERFACE8(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8)
+
+#define NS_IMPL_THREADSAFE_ISUPPORTS9(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9) \
+ NS_IMPL_THREADSAFE_ADDREF(_class) \
+ NS_IMPL_THREADSAFE_RELEASE(_class) \
+ NS_IMPL_THREADSAFE_QUERY_INTERFACE9(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9)
+
+#define NS_IMPL_THREADSAFE_ISUPPORTS10(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9, _i10) \
+ NS_IMPL_THREADSAFE_ADDREF(_class) \
+ NS_IMPL_THREADSAFE_RELEASE(_class) \
+ NS_IMPL_THREADSAFE_QUERY_INTERFACE10(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9, _i10)
+
+#define NS_IMPL_THREADSAFE_ISUPPORTS11(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9, _i10, _i11) \
+ NS_IMPL_THREADSAFE_ADDREF(_class) \
+ NS_IMPL_THREADSAFE_RELEASE(_class) \
+ NS_IMPL_THREADSAFE_QUERY_INTERFACE11(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9, _i10, _i11)
+
+///////////////////////////////////////////////////////////////////////////////
+// Macros for implementing nsIClassInfo-related stuff.
+///////////////////////////////////////////////////////////////////////////////
+
+// include here instead of at the top because it requires the nsISupport decl
+#include "nsIClassInfo.h"
+
+#define NS_CLASSINFO_NAME(_class) _class##_classInfoGlobal
+#define NS_CI_INTERFACE_GETTER_NAME(_class) _class##_GetInterfacesHelper
+
+#define NS_DECL_CI_INTERFACE_GETTER(_class) \
+ extern NS_IMETHODIMP NS_CI_INTERFACE_GETTER_NAME(_class)(PRUint32 *, \
+ nsIID ***);
+
+#define NS_DECL_CLASSINFO(_class) \
+ NS_DECL_CI_INTERFACE_GETTER(_class) \
+ nsIClassInfo *NS_CLASSINFO_NAME(_class);
+
+#define NS_IMPL_QUERY_CLASSINFO(_class) \
+ if ( aIID.Equals(NS_GET_IID(nsIClassInfo)) ) { \
+ extern nsIClassInfo *NS_CLASSINFO_NAME(_class); \
+ foundInterface = NS_STATIC_CAST(nsIClassInfo*, NS_CLASSINFO_NAME(_class));\
+ } else
+
+#define NS_CLASSINFO_HELPER_BEGIN(_class, _c) \
+NS_IMETHODIMP \
+NS_CI_INTERFACE_GETTER_NAME(_class)(PRUint32 *count, nsIID ***array) \
+{ \
+ *count = _c; \
+ *array = (nsIID **)nsMemory::Alloc(sizeof (nsIID *) * _c);
+
+#define NS_CLASSINFO_HELPER_ENTRY(_i, _interface) \
+ (*array)[_i] = (nsIID *)nsMemory::Clone(&NS_GET_IID(_interface), \
+ sizeof(nsIID));
+
+#define NS_CLASSINFO_HELPER_END \
+ return NS_OK; \
+}
+
+#define NS_IMPL_CI_INTERFACE_GETTER1(_class, _interface) \
+ NS_CLASSINFO_HELPER_BEGIN(_class, 1) \
+ NS_CLASSINFO_HELPER_ENTRY(0, _interface) \
+ NS_CLASSINFO_HELPER_END
+
+#define NS_IMPL_QUERY_INTERFACE1_CI(_class, _i1) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_IMPL_QUERY_CLASSINFO(_class) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_ISUPPORTS1_CI(_class, _interface) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE1_CI(_class, _interface) \
+ NS_IMPL_CI_INTERFACE_GETTER1(_class, _interface)
+
+#define NS_IMPL_CI_INTERFACE_GETTER2(_class, _i1, _i2) \
+ NS_CLASSINFO_HELPER_BEGIN(_class, 2) \
+ NS_CLASSINFO_HELPER_ENTRY(0, _i1) \
+ NS_CLASSINFO_HELPER_ENTRY(1, _i2) \
+ NS_CLASSINFO_HELPER_END
+
+#define NS_IMPL_QUERY_INTERFACE2_CI(_class, _i1, _i2) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_IMPL_QUERY_CLASSINFO(_class) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_ISUPPORTS2_CI(_class, _i1, _i2) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE2_CI(_class, _i1, _i2) \
+ NS_IMPL_CI_INTERFACE_GETTER2(_class, _i1, _i2)
+
+#define NS_IMPL_CI_INTERFACE_GETTER3(_class, _i1, _i2, _i3) \
+ NS_CLASSINFO_HELPER_BEGIN(_class, 3) \
+ NS_CLASSINFO_HELPER_ENTRY(0, _i1) \
+ NS_CLASSINFO_HELPER_ENTRY(1, _i2) \
+ NS_CLASSINFO_HELPER_ENTRY(2, _i3) \
+ NS_CLASSINFO_HELPER_END
+
+#define NS_IMPL_QUERY_INTERFACE3_CI(_class, _i1, _i2, _i3) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_IMPL_QUERY_CLASSINFO(_class) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_ISUPPORTS3_CI(_class, _i1, _i2, _i3) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE3_CI(_class, _i1, _i2, _i3) \
+ NS_IMPL_CI_INTERFACE_GETTER3(_class, _i1, _i2, _i3)
+
+#define NS_IMPL_CI_INTERFACE_GETTER4(_class, _i1, _i2, _i3, _i4) \
+ NS_CLASSINFO_HELPER_BEGIN(_class, 4) \
+ NS_CLASSINFO_HELPER_ENTRY(0, _i1) \
+ NS_CLASSINFO_HELPER_ENTRY(1, _i2) \
+ NS_CLASSINFO_HELPER_ENTRY(2, _i3) \
+ NS_CLASSINFO_HELPER_ENTRY(3, _i4) \
+ NS_CLASSINFO_HELPER_END
+
+#define NS_IMPL_QUERY_INTERFACE4_CI(_class, _i1, _i2, _i3, _i4) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_IMPL_QUERY_CLASSINFO(_class) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_ISUPPORTS4_CI(_class, _i1, _i2, _i3, _i4) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE4_CI(_class, _i1, _i2, _i3, _i4) \
+ NS_IMPL_CI_INTERFACE_GETTER4(_class, _i1, _i2, _i3, _i4)
+
+#define NS_IMPL_CI_INTERFACE_GETTER5(_class, _i1, _i2, _i3, _i4, _i5) \
+ NS_CLASSINFO_HELPER_BEGIN(_class, 5) \
+ NS_CLASSINFO_HELPER_ENTRY(0, _i1) \
+ NS_CLASSINFO_HELPER_ENTRY(1, _i2) \
+ NS_CLASSINFO_HELPER_ENTRY(2, _i3) \
+ NS_CLASSINFO_HELPER_ENTRY(3, _i4) \
+ NS_CLASSINFO_HELPER_ENTRY(4, _i5) \
+ NS_CLASSINFO_HELPER_END
+
+#define NS_IMPL_QUERY_INTERFACE5_CI(_class, _i1, _i2, _i3, _i4, _i5) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_IMPL_QUERY_CLASSINFO(_class) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_ISUPPORTS5_CI(_class, _i1, _i2, _i3, _i4, _i5) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE5_CI(_class, _i1, _i2, _i3, _i4, _i5) \
+ NS_IMPL_CI_INTERFACE_GETTER5(_class, _i1, _i2, _i3, _i4, _i5)
+
+#define NS_IMPL_CI_INTERFACE_GETTER6(_class, _i1, _i2, _i3, _i4, _i5, _i6) \
+ NS_CLASSINFO_HELPER_BEGIN(_class, 6) \
+ NS_CLASSINFO_HELPER_ENTRY(0, _i1) \
+ NS_CLASSINFO_HELPER_ENTRY(1, _i2) \
+ NS_CLASSINFO_HELPER_ENTRY(2, _i3) \
+ NS_CLASSINFO_HELPER_ENTRY(3, _i4) \
+ NS_CLASSINFO_HELPER_ENTRY(4, _i5) \
+ NS_CLASSINFO_HELPER_ENTRY(5, _i6) \
+ NS_CLASSINFO_HELPER_END
+
+#define NS_IMPL_QUERY_INTERFACE6_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY(_i6) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_IMPL_QUERY_CLASSINFO(_class) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_ISUPPORTS6_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE6_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6) \
+ NS_IMPL_CI_INTERFACE_GETTER6(_class, _i1, _i2, _i3, _i4, _i5, _i6)
+
+#define NS_IMPL_CI_INTERFACE_GETTER7(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7) \
+ NS_CLASSINFO_HELPER_BEGIN(_class, 7) \
+ NS_CLASSINFO_HELPER_ENTRY(0, _i1) \
+ NS_CLASSINFO_HELPER_ENTRY(1, _i2) \
+ NS_CLASSINFO_HELPER_ENTRY(2, _i3) \
+ NS_CLASSINFO_HELPER_ENTRY(3, _i4) \
+ NS_CLASSINFO_HELPER_ENTRY(4, _i5) \
+ NS_CLASSINFO_HELPER_ENTRY(5, _i6) \
+ NS_CLASSINFO_HELPER_ENTRY(6, _i7) \
+ NS_CLASSINFO_HELPER_END
+
+#define NS_IMPL_QUERY_INTERFACE7_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY(_i6) \
+ NS_INTERFACE_MAP_ENTRY(_i7) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_IMPL_QUERY_CLASSINFO(_class) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_ISUPPORTS7_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE7_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7) \
+ NS_IMPL_CI_INTERFACE_GETTER7(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7)
+
+#define NS_IMPL_CI_INTERFACE_GETTER8(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8) \
+ NS_CLASSINFO_HELPER_BEGIN(_class, 8) \
+ NS_CLASSINFO_HELPER_ENTRY(0, _i1) \
+ NS_CLASSINFO_HELPER_ENTRY(1, _i2) \
+ NS_CLASSINFO_HELPER_ENTRY(2, _i3) \
+ NS_CLASSINFO_HELPER_ENTRY(3, _i4) \
+ NS_CLASSINFO_HELPER_ENTRY(4, _i5) \
+ NS_CLASSINFO_HELPER_ENTRY(5, _i6) \
+ NS_CLASSINFO_HELPER_ENTRY(6, _i7) \
+ NS_CLASSINFO_HELPER_ENTRY(7, _i8) \
+ NS_CLASSINFO_HELPER_END
+
+#define NS_IMPL_QUERY_INTERFACE8_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY(_i6) \
+ NS_INTERFACE_MAP_ENTRY(_i7) \
+ NS_INTERFACE_MAP_ENTRY(_i8) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_IMPL_QUERY_CLASSINFO(_class) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_ISUPPORTS8_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE8_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8) \
+ NS_IMPL_CI_INTERFACE_GETTER8(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8)
+
+#define NS_IMPL_CI_INTERFACE_GETTER9(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9) \
+ NS_CLASSINFO_HELPER_BEGIN(_class, 9) \
+ NS_CLASSINFO_HELPER_ENTRY(0, _i1) \
+ NS_CLASSINFO_HELPER_ENTRY(1, _i2) \
+ NS_CLASSINFO_HELPER_ENTRY(2, _i3) \
+ NS_CLASSINFO_HELPER_ENTRY(3, _i4) \
+ NS_CLASSINFO_HELPER_ENTRY(4, _i5) \
+ NS_CLASSINFO_HELPER_ENTRY(5, _i6) \
+ NS_CLASSINFO_HELPER_ENTRY(6, _i7) \
+ NS_CLASSINFO_HELPER_ENTRY(7, _i8) \
+ NS_CLASSINFO_HELPER_ENTRY(8, _i9) \
+ NS_CLASSINFO_HELPER_END
+
+#define NS_IMPL_QUERY_INTERFACE9_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY(_i6) \
+ NS_INTERFACE_MAP_ENTRY(_i7) \
+ NS_INTERFACE_MAP_ENTRY(_i8) \
+ NS_INTERFACE_MAP_ENTRY(_i9) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_IMPL_QUERY_CLASSINFO(_class) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_ISUPPORTS9_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \
+ _i8, _i9) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE9_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \
+ _i8, _i9) \
+ NS_IMPL_CI_INTERFACE_GETTER9(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \
+ _i8, _i9)
+
+#define NS_IMPL_CI_INTERFACE_GETTER10(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9, _i10) \
+ NS_CLASSINFO_HELPER_BEGIN(_class, 10) \
+ NS_CLASSINFO_HELPER_ENTRY(0, _i1) \
+ NS_CLASSINFO_HELPER_ENTRY(1, _i2) \
+ NS_CLASSINFO_HELPER_ENTRY(2, _i3) \
+ NS_CLASSINFO_HELPER_ENTRY(3, _i4) \
+ NS_CLASSINFO_HELPER_ENTRY(4, _i5) \
+ NS_CLASSINFO_HELPER_ENTRY(5, _i6) \
+ NS_CLASSINFO_HELPER_ENTRY(6, _i7) \
+ NS_CLASSINFO_HELPER_ENTRY(7, _i8) \
+ NS_CLASSINFO_HELPER_ENTRY(8, _i9) \
+ NS_CLASSINFO_HELPER_ENTRY(9, _i10) \
+ NS_CLASSINFO_HELPER_END
+
+#define NS_IMPL_CI_INTERFACE_GETTER11(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9, _i10, _i11) \
+ NS_CLASSINFO_HELPER_BEGIN(_class, 10) \
+ NS_CLASSINFO_HELPER_ENTRY(0, _i1) \
+ NS_CLASSINFO_HELPER_ENTRY(1, _i2) \
+ NS_CLASSINFO_HELPER_ENTRY(2, _i3) \
+ NS_CLASSINFO_HELPER_ENTRY(3, _i4) \
+ NS_CLASSINFO_HELPER_ENTRY(4, _i5) \
+ NS_CLASSINFO_HELPER_ENTRY(5, _i6) \
+ NS_CLASSINFO_HELPER_ENTRY(6, _i7) \
+ NS_CLASSINFO_HELPER_ENTRY(7, _i8) \
+ NS_CLASSINFO_HELPER_ENTRY(8, _i9) \
+ NS_CLASSINFO_HELPER_ENTRY(9, _i10) \
+ NS_CLASSINFO_HELPER_ENTRY(10, _i11) \
+ NS_CLASSINFO_HELPER_END
+
+#define NS_IMPL_QUERY_INTERFACE10_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9, _i10) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY(_i6) \
+ NS_INTERFACE_MAP_ENTRY(_i7) \
+ NS_INTERFACE_MAP_ENTRY(_i8) \
+ NS_INTERFACE_MAP_ENTRY(_i9) \
+ NS_INTERFACE_MAP_ENTRY(_i10) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_IMPL_QUERY_CLASSINFO(_class) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_QUERY_INTERFACE11_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
+ _i7, _i8, _i9, _i10, _i11) \
+ NS_INTERFACE_MAP_BEGIN(_class) \
+ NS_INTERFACE_MAP_ENTRY(_i1) \
+ NS_INTERFACE_MAP_ENTRY(_i2) \
+ NS_INTERFACE_MAP_ENTRY(_i3) \
+ NS_INTERFACE_MAP_ENTRY(_i4) \
+ NS_INTERFACE_MAP_ENTRY(_i5) \
+ NS_INTERFACE_MAP_ENTRY(_i6) \
+ NS_INTERFACE_MAP_ENTRY(_i7) \
+ NS_INTERFACE_MAP_ENTRY(_i8) \
+ NS_INTERFACE_MAP_ENTRY(_i9) \
+ NS_INTERFACE_MAP_ENTRY(_i10) \
+ NS_INTERFACE_MAP_ENTRY(_i11) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
+ NS_IMPL_QUERY_CLASSINFO(_class) \
+ NS_INTERFACE_MAP_END
+
+#define NS_IMPL_ISUPPORTS10_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \
+ _i8, _i9, _i10) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE10_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \
+ _i8, _i9, _i10) \
+ NS_IMPL_CI_INTERFACE_GETTER10(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \
+ _i8, _i9, _i10)
+
+#define NS_IMPL_ISUPPORTS11_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \
+ _i8, _i9, _i10, _i11) \
+ NS_IMPL_ADDREF(_class) \
+ NS_IMPL_RELEASE(_class) \
+ NS_IMPL_QUERY_INTERFACE11_CI(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \
+ _i8, _i9, _i10, _i11) \
+ NS_IMPL_CI_INTERFACE_GETTER11(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \
+ _i8, _i9, _i10, _i11)
+
+#define NS_INTERFACE_MAP_END_THREADSAFE NS_IMPL_QUERY_TAIL_GUTS
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsISupportsUtils.h b/src/libs/xpcom18a4/xpcom/glue/nsISupportsUtils.h
new file mode 100644
index 00000000..d8d002b1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsISupportsUtils.h
@@ -0,0 +1,230 @@
+/* -*- 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>
+ * Scott Collins <scc@ScottCollins.net>
+ * Dan Mosedale <dmose@mozilla.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 ***** */
+
+#ifndef nsISupportsUtils_h__
+#define nsISupportsUtils_h__
+
+#ifndef nscore_h___
+#include "nscore.h"
+#endif
+
+#ifndef nsISupportsBase_h__
+#include "nsISupportsBase.h"
+#endif
+
+#ifndef nsError_h__
+#include "nsError.h"
+#endif
+
+#ifndef nsDebug_h___
+#include "nsDebug.h"
+#endif
+
+#ifndef nsISupportsImpl_h__
+#include "nsISupportsImpl.h"
+#endif
+
+/**
+ * Macro for instantiating a new object that implements nsISupports.
+ * Note that you can only use this if you adhere to the no arguments
+ * constructor com policy (which you really should!).
+ * @param _result Where the new instance pointer is stored
+ * @param _type The type of object to call "new" with.
+ */
+#define NS_NEWXPCOM(_result,_type) \
+ PR_BEGIN_MACRO \
+ _result = new _type(); \
+ PR_END_MACRO
+
+/**
+ * Macro for deleting an object that implements nsISupports.
+ * @param _ptr The object to delete.
+ */
+#define NS_DELETEXPCOM(_ptr) \
+ PR_BEGIN_MACRO \
+ delete (_ptr); \
+ PR_END_MACRO
+
+/**
+ * Macro for adding a reference to an interface.
+ * @param _ptr The interface pointer.
+ */
+#define NS_ADDREF(_ptr) \
+ (_ptr)->AddRef()
+
+/**
+ * Macro for adding a reference to this. This macro should be used
+ * because NS_ADDREF (when tracing) may require an ambiguous cast
+ * from the pointers primary type to nsISupports. This macro sidesteps
+ * that entire problem.
+ */
+#define NS_ADDREF_THIS() \
+ AddRef()
+
+
+extern "C++" {
+// ...because some one is accidentally including this file inside
+// an |extern "C"|
+
+
+// Making this a |inline| |template| allows |expr| to be evaluated only once,
+// yet still denies you the ability to |AddRef()| an |nsCOMPtr|.
+template <class T>
+inline
+nsrefcnt
+ns_if_addref( T expr )
+{
+ return expr ? expr->AddRef() : 0;
+}
+
+} /* extern "C++" */
+
+/**
+ * Macro for adding a reference to an interface that checks for NULL.
+ * @param _expr The interface pointer.
+ */
+#define NS_IF_ADDREF(_expr) ns_if_addref(_expr)
+
+/*
+ * Given these declarations, it explicitly OK and efficient to end a `getter' with:
+ *
+ * NS_IF_ADDREF(*result = mThing);
+ *
+ * even if |mThing| is an |nsCOMPtr|. If |mThing| is an |nsCOMPtr|, however, it is still
+ * _illegal_ to say |NS_IF_ADDREF(mThing)|.
+ */
+
+/**
+ * Macro for releasing a reference to an interface.
+ * @param _ptr The interface pointer.
+ */
+#define NS_RELEASE(_ptr) \
+ PR_BEGIN_MACRO \
+ (_ptr)->Release(); \
+ (_ptr) = 0; \
+ PR_END_MACRO
+
+/**
+ * Macro for releasing a reference to an interface.
+ * @param _ptr The interface pointer.
+ */
+#define NS_RELEASE_THIS() \
+ Release()
+
+/**
+ * Macro for releasing a reference to an interface, except that this
+ * macro preserves the return value from the underlying Release call.
+ * The interface pointer argument will only be NULLed if the reference count
+ * goes to zero.
+ *
+ * @param _ptr The interface pointer.
+ */
+#define NS_RELEASE2(_ptr,_rv) \
+ PR_BEGIN_MACRO \
+ _rv = (_ptr)->Release(); \
+ if (0 == (_rv)) (_ptr) = 0; \
+ PR_END_MACRO
+
+/**
+ * Macro for releasing a reference to an interface that checks for NULL;
+ * @param _ptr The interface pointer.
+ */
+#define NS_IF_RELEASE(_ptr) \
+ PR_BEGIN_MACRO \
+ if (_ptr) { \
+ (_ptr)->Release(); \
+ (_ptr) = 0; \
+ } \
+ PR_END_MACRO
+
+/*
+ * Often you have to cast an implementation pointer, e.g., |this|, to an
+ * |nsISupports*|, but because you have multiple inheritance, a simple cast
+ * is ambiguous. One could simply say, e.g., (given a base |nsIBase|),
+ * |NS_STATIC_CAST(nsIBase*, this)|; but that disguises the fact that what
+ * you are really doing is disambiguating the |nsISupports|. You could make
+ * that more obvious with a double cast, e.g., |NS_STATIC_CAST(nsISupports*,
+ * NS_STATIC_CAST(nsIBase*, this))|, but that is bulky and harder to read...
+ *
+ * The following macro is clean, short, and obvious. In the example above,
+ * you would use it like this: |NS_ISUPPORTS_CAST(nsIBase*, this)|.
+ */
+
+#define NS_ISUPPORTS_CAST(__unambiguousBase, __expr) \
+ NS_STATIC_CAST(nsISupports*, NS_STATIC_CAST(__unambiguousBase, __expr))
+
+extern "C++" {
+// ...because some one is accidentally including this file inside
+// an |extern "C"|
+
+class nsISupports;
+
+template <class T>
+struct nsCOMTypeInfo
+{
+ static const nsIID& GetIID() { return T::GetIID(); }
+};
+
+NS_SPECIALIZE_TEMPLATE
+struct nsCOMTypeInfo<nsISupports>
+{
+ static const nsIID& GetIID() {
+ static const nsIID iid_NS_ISUPPORTS_IID = NS_ISUPPORTS_IID; return iid_NS_ISUPPORTS_IID;
+ }
+};
+
+#define NS_GET_IID(T) nsCOMTypeInfo<T>::GetIID()
+
+// a type-safe shortcut for calling the |QueryInterface()| member function
+template <class T, class DestinationType>
+inline
+nsresult
+CallQueryInterface( T* aSource, DestinationType** aDestination )
+{
+ NS_PRECONDITION(aSource, "null parameter");
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ return aSource->QueryInterface(NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+}
+
+} // extern "C++"
+
+#endif /* __nsISupportsUtils_h */
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsIWeakReferenceUtils.h b/src/libs/xpcom18a4/xpcom/glue/nsIWeakReferenceUtils.h
new file mode 100644
index 00000000..17d1bd79
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsIWeakReferenceUtils.h
@@ -0,0 +1,162 @@
+/* -*- 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> (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 nsIWeakReferenceUtils_h__
+#define nsIWeakReferenceUtils_h__
+
+#ifndef nsCOMPtr_h__
+#include "nsCOMPtr.h"
+#endif
+
+typedef nsCOMPtr<nsIWeakReference> nsWeakPtr;
+
+/**
+ *
+ */
+
+// a type-safe shortcut for calling the |QueryReferent()| member function
+// T must inherit from nsIWeakReference, but the cast may be ambiguous.
+template <class T, class DestinationType>
+inline
+nsresult
+CallQueryReferent( T* aSource, DestinationType** aDestination )
+ {
+ NS_PRECONDITION(aSource, "null parameter");
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ return aSource->QueryReferent(NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+ }
+
+
+class NS_COM nsQueryReferent : public nsCOMPtr_helper
+ {
+ public:
+ nsQueryReferent( nsIWeakReference* aWeakPtr, nsresult* error )
+ : mWeakPtr(aWeakPtr),
+ mErrorPtr(error)
+ {
+ // nothing else to do here
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
+
+ private:
+ nsIWeakReference* mWeakPtr;
+ nsresult* mErrorPtr;
+ };
+
+inline
+const nsQueryReferent
+do_QueryReferent( nsIWeakReference* aRawPtr, nsresult* error = 0 )
+ {
+ return nsQueryReferent(aRawPtr, error);
+ }
+
+
+
+class NS_COM nsGetWeakReference : public nsCOMPtr_helper
+ {
+ public:
+ nsGetWeakReference( nsISupports* aRawPtr, nsresult* error )
+ : mRawPtr(aRawPtr),
+ mErrorPtr(error)
+ {
+ // nothing else to do here
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+
+ private:
+ nsISupports* mRawPtr;
+ nsresult* mErrorPtr;
+ };
+
+ /**
+ * |do_GetWeakReference| is a convenience function that bundles up all the work needed
+ * to get a weak reference to an arbitrary object, i.e., the |QueryInterface|, test, and
+ * call through to |GetWeakReference|, and put it into your |nsCOMPtr|.
+ * It is specifically designed to cooperate with |nsCOMPtr| (or |nsWeakPtr|) like so:
+ * |nsWeakPtr myWeakPtr = do_GetWeakReference(aPtr);|.
+ */
+inline
+const nsGetWeakReference
+do_GetWeakReference( nsISupports* aRawPtr, nsresult* error = 0 )
+ {
+ return nsGetWeakReference(aRawPtr, error);
+ }
+
+inline
+void
+do_GetWeakReference( nsIWeakReference* aRawPtr, nsresult* error = 0 )
+ {
+ // This signature exists soley to _stop_ you from doing a bad thing.
+ // Saying |do_GetWeakReference()| on a weak reference itself,
+ // is very likely to be a programmer error.
+ }
+
+template <class T>
+inline
+void
+do_GetWeakReference( already_AddRefed<T>& )
+ {
+ // This signature exists soley to _stop_ you from doing the bad thing.
+ // Saying |do_GetWeakReference()| on a pointer that is not otherwise owned by
+ // someone else is an automatic leak. See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
+ }
+
+template <class T>
+inline
+void
+do_GetWeakReference( already_AddRefed<T>&, nsresult* )
+ {
+ // This signature exists soley to _stop_ you from doing the bad thing.
+ // Saying |do_GetWeakReference()| on a pointer that is not otherwise owned by
+ // someone else is an automatic leak. See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
+ }
+
+
+
+ /**
+ * Deprecated, use |do_GetWeakReference| instead.
+ */
+extern NS_COM
+nsIWeakReference*
+NS_GetWeakReference( nsISupports* , nsresult* aResult=0 );
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsMemory.cpp b/src/libs/xpcom18a4/xpcom/glue/nsMemory.cpp
new file mode 100644
index 00000000..2449c58e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsMemory.cpp
@@ -0,0 +1,151 @@
+/* -*- 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 "nsXPCOM.h"
+#include "nsMemory.h"
+#include "nsXPCOMPrivate.h"
+
+static nsIMemory* gMemory = nsnull;
+
+static NS_METHOD FreeGlobalMemory(void)
+{
+ NS_ASSERTION(gMemory, "must be not null after SetupGlobalMemory");
+ NS_IF_RELEASE(gMemory);
+ return NS_OK;
+}
+
+#define ENSURE_ALLOCATOR \
+ (gMemory ? PR_TRUE : (PRBool)(SetupGlobalMemory() != nsnull))
+
+static nsIMemory*
+SetupGlobalMemory()
+{
+ NS_ASSERTION(!gMemory, "must be called once");
+ if (!gMemory)
+ {
+ NS_GetMemoryManager(&gMemory);
+ NS_ASSERTION(gMemory, "can't get memory manager!");
+ if (gMemory)
+ NS_RegisterXPCOMExitRoutine(FreeGlobalMemory, 0);
+ }
+ return gMemory;
+}
+
+#ifdef XPCOM_GLUE
+nsresult GlueStartupMemory()
+{
+ NS_ASSERTION(!gMemory, "must be called once");
+ if (!gMemory)
+ {
+ NS_GetMemoryManager(&gMemory);
+ NS_ASSERTION(gMemory, "can't get memory manager!");
+ if (!gMemory)
+ return NS_ERROR_FAILURE;
+ }
+ return NS_OK;
+}
+
+void GlueShutdownMemory()
+{
+ NS_IF_RELEASE(gMemory);
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// nsMemory static helper routines
+
+NS_COM void*
+nsMemory::Alloc(PRSize size)
+{
+ if (!ENSURE_ALLOCATOR)
+ return nsnull;
+
+ return gMemory->Alloc(size);
+}
+
+NS_COM void*
+nsMemory::Realloc(void* ptr, PRSize size)
+{
+ if (!ENSURE_ALLOCATOR)
+ return nsnull;
+
+ return gMemory->Realloc(ptr, size);
+}
+
+NS_COM void
+nsMemory::Free(void* ptr)
+{
+ if (!ENSURE_ALLOCATOR)
+ return;
+
+ gMemory->Free(ptr);
+}
+
+NS_COM nsresult
+nsMemory::HeapMinimize(PRBool aImmediate)
+{
+ if (!ENSURE_ALLOCATOR)
+ return NS_ERROR_FAILURE;
+
+ return gMemory->HeapMinimize(aImmediate);
+}
+
+NS_COM void*
+nsMemory::Clone(const void* ptr, PRSize size)
+{
+ if (!ENSURE_ALLOCATOR)
+ return nsnull;
+
+ void* newPtr = gMemory->Alloc(size);
+ if (newPtr)
+ memcpy(newPtr, ptr, size);
+ return newPtr;
+}
+
+NS_COM nsIMemory*
+nsMemory::GetGlobalMemoryService()
+{
+ if (!ENSURE_ALLOCATOR)
+ return nsnull;
+
+ nsIMemory* result = gMemory;
+ NS_IF_ADDREF(result);
+ return result;
+}
+
+//----------------------------------------------------------------------
+
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsMemory.h b/src/libs/xpcom18a4/xpcom/glue/nsMemory.h
new file mode 100644
index 00000000..4ee48bf0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsMemory.h
@@ -0,0 +1,154 @@
+/* -*- 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 nsMemory_h__
+#define nsMemory_h__
+
+#include "nsIMemory.h"
+
+#define NS_MEMORY_CONTRACTID "@mozilla.org/xpcom/memory-service;1"
+#define NS_MEMORY_CLASSNAME "Global Memory Service"
+#define NS_MEMORY_CID \
+{ /* 30a04e40-38e7-11d4-8cf5-0060b0fc14a3 */ \
+ 0x30a04e40, \
+ 0x38e7, \
+ 0x11d4, \
+ {0x8c, 0xf5, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3} \
+}
+
+
+/**
+ * Static helper routines to manage memory. These routines allow easy access
+ * to xpcom's built-in (global) nsIMemory implementation, without needing
+ * to go through the service manager to get it. However this requires clients
+ * to link with the xpcom DLL.
+ *
+ * This class is not threadsafe and is intented for use only on the main
+ * thread.
+ */
+class nsMemory
+{
+public:
+ static NS_COM void* Alloc(size_t size);
+ static NS_COM void* Realloc(void* ptr, size_t size);
+ static NS_COM void Free(void* ptr);
+ static NS_COM nsresult HeapMinimize(PRBool aImmediate);
+ static NS_COM void* Clone(const void* ptr, size_t size);
+ static NS_COM nsIMemory* GetGlobalMemoryService(); // AddRefs
+};
+
+/**
+ * Macro to free all elements of an XPCOM array of a given size using
+ * freeFunc, then frees the array itself using nsMemory::Free().
+ *
+ * Note that this macro (and its wrappers) can be used to deallocate a
+ * partially- or completely-built array while unwinding an error
+ * condition inside the XPCOM routine that was going to return the
+ * array. For this to work on a partially-built array, your code
+ * needs to be building the array from index 0 upwards, and simply
+ * pass the number of elements that have already been built (and thus
+ * need to be freed) as |size|.
+ *
+ * Thanks to <alecf@netscape.com> for suggesting this form, which
+ * allows the macro to be used with NS_RELEASE / NS_RELEASE_IF in
+ * addition to nsMemory::Free.
+ *
+ * @param size Number of elements in the array. If not a constant, this
+ * should be a PRInt32. Note that this means this macro
+ * will not work if size >= 2^31.
+ * @param array The array to be freed.
+ * @param freeFunc The function or macro to be used to free it.
+ * For arrays of nsISupports (or any class derived
+ * from it), NS_IF_RELEASE (or NS_RELEASE) should be
+ * passed as freeFunc. For most (all?) other pointer
+ * types (including XPCOM strings and wstrings),
+ * nsMemory::Free should be used, since the
+ * shared-allocator (nsMemory) is what will have been
+ * used to allocate the memory.
+ */
+#define NS_FREE_XPCOM_POINTER_ARRAY(size, array, freeFunc) \
+ PR_BEGIN_MACRO \
+ PRInt32 iter_ = PRInt32(size); \
+ while (--iter_ >= 0) \
+ freeFunc((array)[iter_]); \
+ nsMemory::Free((array)); \
+ PR_END_MACRO
+
+// convenience macros for commonly used calls. mmmmm. syntactic sugar.
+
+/**
+ * Macro to free arrays of non-refcounted objects allocated by the
+ * shared allocator (nsMemory) such as strings and wstrings. A
+ * convenience wrapper around NS_FREE_XPCOM_POINTER_ARRAY.
+ *
+ * @param size Number of elements in the array. If not a constant, this
+ * should be a PRInt32. Note that this means this macro
+ * will not work if size >= 2^31.
+ * @param array The array to be freed.
+ */
+#define NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(size, array) \
+ NS_FREE_XPCOM_POINTER_ARRAY((size), (array), nsMemory::Free)
+
+/**
+ * Macro to free an array of pointers to nsISupports (or classes
+ * derived from it). A convenience wrapper around
+ * NS_FREE_XPCOM_POINTER_ARRAY.
+ *
+ * Note that if you know that none of your nsISupports pointers are
+ * going to be 0, you can gain a bit of speed by calling
+ * NS_FREE_XPCOM_POINTER_ARRAY directly and using NS_RELEASE as your
+ * free function.
+ *
+ * @param size Number of elements in the array. If not a constant, this
+ * should be a PRInt32. Note that this means this macro
+ * will not work if size >= 2^31.
+ * @param array The array to be freed.
+ */
+#define NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(size, array) \
+ NS_FREE_XPCOM_POINTER_ARRAY((size), (array), NS_IF_RELEASE)
+
+/**
+ * Helpful array length function for calculating the length of a
+ * statically declared array.
+ */
+
+#define NS_ARRAY_LENGTH(array_) \
+ (sizeof(array_)/sizeof(array_[0]))
+
+
+#endif // nsMemory_h__
+
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsServiceManagerUtils.h b/src/libs/xpcom18a4/xpcom/glue/nsServiceManagerUtils.h
new file mode 100644
index 00000000..b225b6a2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsServiceManagerUtils.h
@@ -0,0 +1,183 @@
+/* -*- 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 XPCOM.
+ *
+ * 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 nsIServiceManagerUtils_h__
+#define nsIServiceManagerUtils_h__
+
+#include "nsIServiceManager.h"
+#include "nsIServiceManagerObsolete.h"
+#include "nsCOMPtr.h"
+
+////////////////////////////////////////////////////////////////////////////
+// Using servicemanager with COMPtrs
+class NS_COM nsGetServiceByCID : public nsCOMPtr_helper
+{
+ public:
+ nsGetServiceByCID( const nsCID& aCID, nsISupports* aServiceManager, nsresult* aErrorPtr )
+ : mCID(aCID),
+ mServiceManager( do_QueryInterface(aServiceManager) ),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+
+ private:
+ const nsCID& mCID;
+ nsCOMPtr<nsIServiceManager> mServiceManager;
+ nsresult* mErrorPtr;
+};
+
+inline
+const nsGetServiceByCID
+do_GetService( const nsCID& aCID, nsresult* error = 0 )
+{
+ return nsGetServiceByCID(aCID, 0, error);
+}
+
+inline
+const nsGetServiceByCID
+do_GetService( const nsCID& aCID, nsISupports* aServiceManager, nsresult* error = 0 )
+{
+ return nsGetServiceByCID(aCID, aServiceManager, error);
+}
+
+class NS_COM nsGetServiceByContractID : public nsCOMPtr_helper
+{
+ public:
+ nsGetServiceByContractID( const char* aContractID, nsISupports* aServiceManager, nsresult* aErrorPtr )
+ : mContractID(aContractID),
+ mServiceManager( do_QueryInterface(aServiceManager) ),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+
+ private:
+ const char* mContractID;
+ nsCOMPtr<nsIServiceManager> mServiceManager;
+ nsresult* mErrorPtr;
+};
+
+inline
+const nsGetServiceByContractID
+do_GetService( const char* aContractID, nsresult* error = 0 )
+{
+ return nsGetServiceByContractID(aContractID, 0, error);
+}
+
+inline
+const nsGetServiceByContractID
+do_GetService( const char* aContractID, nsISupports* aServiceManager, nsresult* error = 0 )
+{
+ return nsGetServiceByContractID(aContractID, aServiceManager, error);
+}
+
+class nsGetServiceFromCategory : public nsCOMPtr_helper
+{
+ public:
+ nsGetServiceFromCategory(const char* aCategory, const char* aEntry,
+ nsISupports* aServiceManager,
+ nsresult* aErrorPtr)
+ : mCategory(aCategory),
+ mEntry(aEntry),
+ mServiceManager( do_QueryInterface(aServiceManager) ),
+ mErrorPtr(aErrorPtr)
+ {
+ // nothing else to do
+ }
+
+ virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
+ protected:
+ const char* mCategory;
+ const char* mEntry;
+ nsCOMPtr<nsIServiceManager> mServiceManager;
+ nsresult* mErrorPtr;
+};
+
+inline
+const nsGetServiceFromCategory
+do_GetServiceFromCategory( const char* category, const char* entry,
+ nsresult* error = 0)
+{
+ return nsGetServiceFromCategory(category, entry, 0, error);
+}
+
+// type-safe shortcuts for calling |GetService|
+template <class DestinationType>
+inline
+nsresult
+CallGetService( const nsCID &aClass,
+ DestinationType** aDestination)
+{
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ nsCOMPtr<nsIServiceManager> mgr;
+ nsresult rv = NS_GetServiceManager(getter_AddRefs(mgr));
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ return mgr->GetService(aClass,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+}
+
+template <class DestinationType>
+inline
+nsresult
+CallGetService( const char *aContractID,
+ DestinationType** aDestination)
+{
+ NS_PRECONDITION(aContractID, "null parameter");
+ NS_PRECONDITION(aDestination, "null parameter");
+
+ nsCOMPtr<nsIServiceManager> mgr;
+ nsresult rv = NS_GetServiceManager(getter_AddRefs(mgr));
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ return mgr->GetServiceByContractID(aContractID,
+ NS_GET_IID(DestinationType),
+ NS_REINTERPRET_CAST(void**, aDestination));
+}
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsTraceRefcnt.cpp b/src/libs/xpcom18a4/xpcom/glue/nsTraceRefcnt.cpp
new file mode 100644
index 00000000..14e9469b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsTraceRefcnt.cpp
@@ -0,0 +1,125 @@
+/* ***** 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
+ *
+ * The Initial Developer of the Original Code is Doug Turner <dougt@meer.net>
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * 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 "nsXPCOM.h"
+#include "nsXPCOMPrivate.h"
+#include "nsCOMPtr.h"
+#include "nsIServiceManager.h"
+#include "nsTraceRefcnt.h"
+#include "nsTraceRefcntImpl.h"
+
+static nsITraceRefcnt* gTraceRefcntObject = nsnull;
+
+static NS_METHOD FreeTraceRefcntObject(void)
+{
+ NS_IF_RELEASE(gTraceRefcntObject);
+ return NS_OK;
+}
+
+#define ENSURE_TRACEOBJECT \
+ (gTraceRefcntObject || SetupTraceRefcntObject() != nsnull)
+
+static nsITraceRefcnt* SetupTraceRefcntObject()
+{
+ NS_GetTraceRefcnt(&gTraceRefcntObject);
+ if (gTraceRefcntObject)
+ NS_RegisterXPCOMExitRoutine(FreeTraceRefcntObject, 0);
+ return gTraceRefcntObject;
+}
+
+#ifdef XPCOM_GLUE
+nsresult GlueStartupTraceRefcnt()
+{
+ NS_GetTraceRefcnt(&gTraceRefcntObject);
+ if (!gTraceRefcntObject)
+ return NS_ERROR_FAILURE;
+ return NS_OK;
+}
+
+void GlueShutdownTraceRefcnt()
+{
+ NS_IF_RELEASE(gTraceRefcntObject);
+}
+#endif
+
+NS_COM void
+nsTraceRefcnt::LogAddRef(void * aPtr, nsrefcnt aNewRefcnt, const char *aTypeName, PRUint32 aInstanceSize)
+{
+ if (!ENSURE_TRACEOBJECT)
+ return;
+ gTraceRefcntObject->LogAddRef(aPtr, aNewRefcnt, aTypeName, aInstanceSize);
+}
+
+NS_COM void
+nsTraceRefcnt::LogRelease(void * aPtr, nsrefcnt aNewRefcnt, const char *aTypeName)
+{
+ if (!ENSURE_TRACEOBJECT)
+ return;
+ gTraceRefcntObject->LogRelease(aPtr, aNewRefcnt, aTypeName);
+}
+
+NS_COM void
+nsTraceRefcnt::LogCtor(void * aPtr, const char *aTypeName, PRUint32 aInstanceSize)
+{
+ if (!ENSURE_TRACEOBJECT)
+ return;
+ gTraceRefcntObject->LogCtor(aPtr, aTypeName, aInstanceSize);
+}
+
+NS_COM void
+nsTraceRefcnt::LogDtor(void * aPtr, const char *aTypeName, PRUint32 aInstanceSize)
+{
+ if (!ENSURE_TRACEOBJECT)
+ return;
+ gTraceRefcntObject->LogDtor(aPtr, aTypeName, aInstanceSize);
+}
+
+NS_COM void
+nsTraceRefcnt::LogAddCOMPtr(void * aPtr, nsISupports *aObject)
+{
+ if (!ENSURE_TRACEOBJECT)
+ return;
+ gTraceRefcntObject->LogAddCOMPtr(aPtr, aObject);
+}
+
+NS_COM void
+nsTraceRefcnt::LogReleaseCOMPtr(void * aPtr, nsISupports *aObject)
+{
+ if (!ENSURE_TRACEOBJECT)
+ return;
+ gTraceRefcntObject->LogReleaseCOMPtr(aPtr, aObject);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsTraceRefcnt.h b/src/libs/xpcom18a4/xpcom/glue/nsTraceRefcnt.h
new file mode 100644
index 00000000..afafda4b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsTraceRefcnt.h
@@ -0,0 +1,135 @@
+/* -*- 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):
+ * 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 ***** */
+#ifndef nsTraceRefcnt_h___
+#define nsTraceRefcnt_h___
+
+#include "nscore.h"
+
+class nsISupports;
+
+// By default refcnt logging is not part of the build.
+#undef NS_BUILD_REFCNT_LOGGING
+
+#if (defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING))
+// Make refcnt logging part of the build. This doesn't mean that
+// actual logging will occur (that requires a separate enable; see
+// nsTraceRefcnt.h for more information).
+#define NS_BUILD_REFCNT_LOGGING 1
+#endif
+
+// If NO_BUILD_REFCNT_LOGGING is defined then disable refcnt logging
+// in the build. This overrides FORCE_BUILD_REFCNT_LOGGING.
+#if defined(NO_BUILD_REFCNT_LOGGING)
+#undef NS_BUILD_REFCNT_LOGGING
+#endif
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+
+#define NS_LOG_ADDREF(_p, _rc, _type, _size) \
+ nsTraceRefcnt::LogAddRef((_p), (_rc), (_type), (PRUint32) (_size))
+
+#define NS_LOG_RELEASE(_p, _rc, _type) \
+ nsTraceRefcnt::LogRelease((_p), (_rc), (_type))
+
+#define MOZ_DECL_CTOR_COUNTER(_type)
+
+#define MOZ_COUNT_CTOR(_type) \
+PR_BEGIN_MACRO \
+ nsTraceRefcnt::LogCtor((void*)this, #_type, sizeof(*this)); \
+PR_END_MACRO
+
+#define MOZ_COUNT_DTOR(_type) \
+PR_BEGIN_MACRO \
+ nsTraceRefcnt::LogDtor((void*)this, #_type, sizeof(*this)); \
+PR_END_MACRO
+
+#ifdef HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR // from autoconf (XXX needs to be
+ // set for non-autoconf platforms)
+
+// nsCOMPtr.h allows these macros to be defined by clients
+// These logging functions require dynamic_cast<void *>, so we don't
+// define these macros if we don't have dynamic_cast.
+#define NSCAP_LOG_ASSIGNMENT(_c, _p) \
+ if (_p) \
+ nsTraceRefcnt::LogAddCOMPtr((_c),NS_STATIC_CAST(nsISupports*,_p))
+
+#define NSCAP_LOG_RELEASE(_c, _p) \
+ if (_p) \
+ nsTraceRefcnt::LogReleaseCOMPtr((_c), NS_STATIC_CAST(nsISupports*,_p))
+
+#endif /* HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR */
+
+#else /* !NS_BUILD_REFCNT_LOGGING */
+
+#define NS_LOG_ADDREF(_p, _rc, _type, _size)
+#define NS_LOG_RELEASE(_p, _rc, _type)
+#define MOZ_DECL_CTOR_COUNTER(_type)
+#define MOZ_COUNT_CTOR(_type)
+#define MOZ_COUNT_DTOR(_type)
+
+#endif /* NS_BUILD_REFCNT_LOGGING */
+
+//----------------------------------------------------------------------
+
+/**
+ * Note: The implementations for these methods are no-ops in a build
+ * where NS_BUILD_REFCNT_LOGGING is disabled.
+ */
+class nsTraceRefcnt {
+public:
+ static NS_COM void LogAddRef(void* aPtr,
+ nsrefcnt aNewRefCnt,
+ const char* aTypeName,
+ PRUint32 aInstanceSize);
+
+ static NS_COM void LogRelease(void* aPtr,
+ nsrefcnt aNewRefCnt,
+ const char* aTypeName);
+
+ static NS_COM void LogCtor(void* aPtr, const char* aTypeName,
+ PRUint32 aInstanceSize);
+
+ static NS_COM void LogDtor(void* aPtr, const char* aTypeName,
+ PRUint32 aInstanceSize);
+
+ static NS_COM void LogAddCOMPtr(void *aCOMPtr, nsISupports *aObject);
+
+ static NS_COM void LogReleaseCOMPtr(void *aCOMPtr, nsISupports *aObject);
+
+};
+#endif /* nsTraceRefcnt_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsWeakReference.cpp b/src/libs/xpcom18a4/xpcom/glue/nsWeakReference.cpp
new file mode 100644
index 00000000..76d9f593
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsWeakReference.cpp
@@ -0,0 +1,169 @@
+/* -*- 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 the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@netscape.com>
+ * 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 ***** */
+
+// nsWeakReference.cpp
+
+#include "nsWeakReference.h"
+#include "nsCOMPtr.h"
+
+nsresult
+nsQueryReferent::operator()( const nsIID& aIID, void** answer ) const
+ {
+ nsresult status;
+ if ( mWeakPtr )
+ {
+ if ( NS_FAILED(status = mWeakPtr->QueryReferent(aIID, answer)) )
+ *answer = 0;
+ }
+ else
+ status = NS_ERROR_NULL_POINTER;
+
+ if ( mErrorPtr )
+ *mErrorPtr = status;
+ return status;
+ }
+
+nsresult
+nsGetWeakReference::operator()( const nsIID&, void** aResult ) const
+ {
+ nsresult status;
+ // nsIWeakReference** result = &NS_STATIC_CAST(nsIWeakReference*, *aResult);
+ *aResult = 0;
+
+ if ( mRawPtr )
+ {
+ nsCOMPtr<nsISupportsWeakReference> factoryPtr = do_QueryInterface(mRawPtr, &status);
+ NS_ASSERTION(factoryPtr, "Oops! You're asking for a weak reference to an object that doesn't support that.");
+ if ( factoryPtr )
+ {
+ nsIWeakReference* temp;
+ status = factoryPtr->GetWeakReference(&temp);
+ *aResult = temp;
+ }
+ // else, |status| has already been set by |do_QueryInterface|
+ }
+ else
+ status = NS_ERROR_NULL_POINTER;
+
+ if ( mErrorPtr )
+ *mErrorPtr = status;
+ return status;
+ }
+
+
+NS_COM nsIWeakReference* // or else |already_AddRefed<nsIWeakReference>|
+NS_GetWeakReference( nsISupports* aInstancePtr, nsresult* aErrorPtr )
+ {
+ void* result = 0;
+ nsGetWeakReference(aInstancePtr, aErrorPtr)(NS_GET_IID(nsIWeakReference), &result);
+ return NS_STATIC_CAST(nsIWeakReference*, result);
+ }
+
+NS_COM nsresult
+nsSupportsWeakReference::GetWeakReference( nsIWeakReference** aInstancePtr )
+ {
+ if ( !aInstancePtr )
+ return NS_ERROR_NULL_POINTER;
+
+ if ( !mProxy )
+ mProxy = new nsWeakReference(this);
+ *aInstancePtr = mProxy;
+
+ nsresult status;
+ if ( !*aInstancePtr )
+ status = NS_ERROR_OUT_OF_MEMORY;
+ else
+ {
+ NS_ADDREF(*aInstancePtr);
+ status = NS_OK;
+ }
+
+ return status;
+ }
+
+NS_IMETHODIMP_(nsrefcnt)
+nsWeakReference::AddRef()
+ {
+ return ++mRefCount;
+ }
+
+NS_IMETHODIMP_(nsrefcnt)
+nsWeakReference::Release()
+ {
+ nsrefcnt temp = --mRefCount;
+ if ( !mRefCount )
+ delete this;
+ return temp;
+ }
+
+NS_IMETHODIMP
+nsWeakReference::QueryInterface( const nsIID& aIID, void** aInstancePtr )
+ {
+ NS_ASSERTION(aInstancePtr, "QueryInterface requires a non-NULL destination!");
+
+ if ( !aInstancePtr )
+ return NS_ERROR_NULL_POINTER;
+
+ nsISupports* foundInterface;
+ if ( aIID.Equals(NS_GET_IID(nsIWeakReference)) )
+ foundInterface = NS_STATIC_CAST(nsIWeakReference*, this);
+ else if ( aIID.Equals(NS_GET_IID(nsISupports)) )
+ foundInterface = NS_STATIC_CAST(nsISupports*, this);
+ else
+ foundInterface = 0;
+
+ nsresult status;
+ if ( !foundInterface )
+ status = NS_NOINTERFACE;
+ else
+ {
+ NS_ADDREF(foundInterface);
+ status = NS_OK;
+ }
+
+ *aInstancePtr = foundInterface;
+ return status;
+ }
+
+NS_IMETHODIMP
+nsWeakReference::QueryReferent( const nsIID& aIID, void** aInstancePtr )
+ {
+ return mReferent ? mReferent->QueryInterface(aIID, aInstancePtr) : NS_ERROR_NULL_POINTER;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/glue/nsWeakReference.h b/src/libs/xpcom18a4/xpcom/glue/nsWeakReference.h
new file mode 100644
index 00000000..96e63f22
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/nsWeakReference.h
@@ -0,0 +1,150 @@
+/* -*- 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 the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * 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 ***** */
+
+#ifndef nsWeakReference_h__
+#define nsWeakReference_h__
+
+// nsWeakReference.h
+
+#include "nsIWeakReference.h"
+
+class nsWeakReference;
+
+#undef IMETHOD_VISIBILITY
+#define IMETHOD_VISIBILITY NS_VISIBILITY_DEFAULT
+
+class NS_COM nsSupportsWeakReference : public nsISupportsWeakReference
+ {
+ public:
+ nsSupportsWeakReference()
+ : mProxy(0)
+ {
+ // nothing else to do here
+ }
+
+ NS_DECL_NSISUPPORTSWEAKREFERENCE
+
+ protected:
+ inline ~nsSupportsWeakReference();
+
+ private:
+ friend class nsWeakReference;
+
+ void
+ NoticeProxyDestruction()
+ // ...called (only) by an |nsWeakReference| from _its_ dtor.
+ {
+ mProxy = 0;
+ }
+
+ nsWeakReference* mProxy;
+
+ protected:
+
+ inline void ClearWeakReferences();
+ PRBool HasWeakReferences() const {return mProxy != 0;}
+ };
+
+#undef IMETHOD_VISIBILITY
+#define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN
+
+class NS_COM nsWeakReference : public nsIWeakReference
+ {
+ public:
+ // nsISupports...
+ NS_IMETHOD_(nsrefcnt) AddRef();
+ NS_IMETHOD_(nsrefcnt) Release();
+ NS_IMETHOD QueryInterface( const nsIID&, void** );
+
+ // nsIWeakReference...
+ NS_DECL_NSIWEAKREFERENCE
+
+ private:
+ friend class nsSupportsWeakReference;
+
+ nsWeakReference( nsSupportsWeakReference* referent )
+ : mRefCount(0),
+ mReferent(referent)
+ // ...I can only be constructed by an |nsSupportsWeakReference|
+ {
+ // nothing else to do here
+ }
+
+ ~nsWeakReference()
+ // ...I will only be destroyed by calling |delete| myself.
+ {
+ if ( mReferent )
+ mReferent->NoticeProxyDestruction();
+ }
+
+ void
+ NoticeReferentDestruction()
+ // ...called (only) by an |nsSupportsWeakReference| from _its_ dtor.
+ {
+ mReferent = 0;
+ }
+
+ nsrefcnt mRefCount;
+ nsSupportsWeakReference* mReferent;
+ };
+
+inline
+void
+nsSupportsWeakReference::ClearWeakReferences()
+ /*
+ Usually being called from |nsSupportsWeakReference::~nsSupportsWeakReference|
+ will be good enough, but you may have a case where you need to call disconnect
+ your weak references in an outer destructor (to prevent some client holding a
+ weak reference from re-entering your destructor).
+ */
+ {
+ if ( mProxy )
+ {
+ mProxy->NoticeReferentDestruction();
+ mProxy = 0;
+ }
+ }
+
+inline
+nsSupportsWeakReference::~nsSupportsWeakReference()
+ {
+ ClearWeakReferences();
+ }
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/glue/objs.mk b/src/libs/xpcom18a4/xpcom/glue/objs.mk
new file mode 100644
index 00000000..d6d04a5a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/objs.mk
@@ -0,0 +1,60 @@
+# ***** 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.
+#
+# 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 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 *****
+
+XPCOM_GLUE_SRC_LCSRCS = \
+ nsCOMPtr.cpp \
+ nsComponentManagerUtils.cpp \
+ nsDebug.cpp \
+ nsGenericFactory.cpp \
+ nsIInterfaceRequestorUtils.cpp \
+ nsMemory.cpp \
+ nsTraceRefcnt.cpp \
+ nsWeakReference.cpp \
+ $(NULL) \
+
+XPCOM_GLUE_SRC_LEXPORTS = \
+ nsCOMPtr.h \
+ nsDebug.h \
+ nsGenericFactory.h \
+ nsIGenericFactory.h \
+ nsMemory.h \
+ nsTraceRefcnt.h \
+ nsWeakReference.h \
+ $(NULL)
+
+
+
+XPCOM_GLUE_SRC_CSRCS := $(addprefix $(topsrcdir)/xpcom/glue/, $(XPCOM_GLUE_SRC_LCSRCS))
diff --git a/src/libs/xpcom18a4/xpcom/glue/standalone/.cvsignore b/src/libs/xpcom18a4/xpcom/glue/standalone/.cvsignore
new file mode 100644
index 00000000..a0182c1f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/standalone/.cvsignore
@@ -0,0 +1,8 @@
+Makefile
+nsCOMPtr.cpp
+nsDebug.cpp
+nsGenericFactory.cpp
+nsIInterfaceRequestorUtils.cpp
+nsMemory.cpp
+nsWeakReference.cpp
+nsComponentManagerUtils.cpp
diff --git a/src/libs/xpcom18a4/xpcom/glue/standalone/Makefile.in b/src/libs/xpcom18a4/xpcom/glue/standalone/Makefile.in
new file mode 100644
index 00000000..ae23d8e0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/standalone/Makefile.in
@@ -0,0 +1,88 @@
+# ***** 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.
+#
+# 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 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
+include $(srcdir)/../objs.mk
+
+MODULE = xpcom
+LIBRARY_NAME = xpcomglue
+
+REQUIRES = string \
+ $(NULL)
+
+LOCAL_INCLUDES = \
+ -I$(srcdir)/../../build \
+ $(NULL)
+
+CPPSRCS = \
+ $(XPCOM_GLUE_SRC_LCSRCS) \
+ nsXPCOMGlue.cpp \
+ nsGREDirServiceProvider.cpp \
+ $(NULL)
+
+SDK_HEADERS = \
+ nsXPCOMGlue.h \
+ $(NULL)
+
+SDK_LIBRARY = \
+ $(LIB_PREFIX)xpcomglue.$(LIB_SUFFIX) \
+ $(NULL)
+
+# 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
+
+GARBAGE += $(XPCOM_GLUE_SRC_LCSRCS) $(wildcard *.$(OBJ_SUFFIX))
+
+ifeq ($(OS_ARCH),WINNT)
+GARBAGE += $(addprefix $(srcdir)/,$(XPCOM_GLUE_SRC_LCSRCS))
+endif
+
+SRCS_IN_OBJDIR = 1
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(XPCOM_GLUE_SRC_CSRCS)
+ $(INSTALL) $^ .
+
+DEFINES += -DXPCOM_GLUE
diff --git a/src/libs/xpcom18a4/xpcom/glue/standalone/nsGREDirServiceProvider.cpp b/src/libs/xpcom18a4/xpcom/glue/standalone/nsGREDirServiceProvider.cpp
new file mode 100644
index 00000000..4a1247eb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/standalone/nsGREDirServiceProvider.cpp
@@ -0,0 +1,596 @@
+/* -*- 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 Communicator.
+ *
+ * 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):
+ * Sean Su <ssu@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 "nsBuildID.h"
+
+#include "nsEmbedString.h"
+#include "nsXPCOMPrivate.h"
+#include "nsXPCOMGlue.h"
+#include "nsILocalFile.h"
+#include "nsIDirectoryService.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsCOMPtr.h"
+
+#include "nspr.h"
+#include "plstr.h"
+
+#ifdef XP_WIN32
+#include <windows.h>
+#include <stdlib.h>
+#elif defined(XP_OS2)
+#define INCL_DOS
+#include <os2.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "prenv.h"
+#elif defined(XP_MACOSX)
+#include <Processes.h>
+#include <CFBundle.h>
+#elif defined(XP_UNIX)
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <dlfcn.h>
+#include "prenv.h"
+#elif defined(XP_BEOS)
+#include <FindDirectory.h>
+#include <Path.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <OS.h>
+#include <image.h>
+#include "prenv.h"
+#endif
+
+#include <sys/stat.h>
+
+#include "nsGREDirServiceProvider.h"
+
+PRBool GRE_GetCurrentProcessDirectory(char* buffer);
+PRBool GRE_GetPathFromConfigDir(const char* dirname, char* buffer);
+PRBool GRE_GetPathFromConfigFile(const char* dirname, char* buffer);
+
+//*****************************************************************************
+// nsGREDirServiceProvider::nsISupports
+//*****************************************************************************
+
+NS_IMPL_ISUPPORTS1(nsGREDirServiceProvider, nsIDirectoryServiceProvider)
+
+//*****************************************************************************
+// nsGREDirServiceProvider::nsIDirectoryServiceProvider
+//*****************************************************************************
+
+NS_IMETHODIMP
+nsGREDirServiceProvider::GetFile(const char *prop, PRBool *persistant, nsIFile **_retval)
+{
+ *_retval = nsnull;
+ *persistant = PR_TRUE;
+
+ //---------------------------------------------------------------
+ // Note that by returning a valid localFile's for NS_GRE_DIR,
+ // your app is indicating to XPCOM that it found a GRE version
+ // with which it's compatible with and intends to be "run against"
+ // that GRE.
+ //
+ // Please see http://www.mozilla.org/projects/embedding/GRE.html
+ // for more info on GRE.
+ //---------------------------------------------------------------
+ if(strcmp(prop, NS_GRE_DIR) == 0)
+ {
+ nsILocalFile* lfile = nsnull;
+ nsresult rv = GRE_GetGREDirectory(&lfile);
+ *_retval = lfile;
+ return rv;
+ }
+
+ return NS_ERROR_FAILURE;
+}
+
+//*****************************************************************************
+// Implementations from nsXPCOMGlue.h and helper functions.
+//*****************************************************************************
+
+PRBool
+GRE_GetCurrentProcessDirectory(char* buffer)
+{
+ *buffer = '\0';
+
+#ifdef XP_WIN
+ if ( ::GetModuleFileName(0, buffer, MAXPATHLEN) ) {
+ // chop of the executable name by finding the rightmost backslash
+ char* lastSlash = PL_strrchr(buffer, '\\');
+ if (lastSlash) {
+ *(lastSlash) = '\0';
+ return PR_TRUE;
+ }
+ }
+
+#elif defined(XP_MACOSX)
+ // Works even if we're not bundled.
+ CFBundleRef appBundle = CFBundleGetMainBundle();
+ if (appBundle != nsnull)
+ {
+ CFURLRef bundleURL = CFBundleCopyExecutableURL(appBundle);
+ if (bundleURL != nsnull)
+ {
+ CFURLRef parentURL = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, bundleURL);
+ if (parentURL)
+ {
+ CFStringRef path = CFURLCopyFileSystemPath(parentURL, kCFURLPOSIXPathStyle);
+ if (path)
+ {
+ CFStringGetCString(path, buffer, MAXPATHLEN, kCFStringEncodingUTF8);
+ CFRelease(path);
+ }
+ CFRelease(parentURL);
+ }
+ CFRelease(bundleURL);
+ }
+#if 0 /* bird: Causes crashes in objc_msgSend() later if released. I dunno why really.
+ Something could be seriously screwed up somewhere else, but this'll have
+ to do for now. (appBundle isn't released in the other place it's used.) */
+ CFRelease(appBundle);
+#endif
+ }
+ if (*buffer) return PR_TRUE;
+
+#elif defined(XP_UNIX)
+
+#if 0 /* we need .so location. */
+ // Actually we have a way on linux.
+ static volatile bool fPathSet = false;
+ static char szPath[MAXPATHLEN];
+ if (!fPathSet)
+ {
+ char buf2[MAXPATHLEN + 3];
+ buf2[0] = '\0';
+
+ /*
+ * Env.var. VBOX_XPCOM_HOME first.
+ */
+ char *psz = PR_GetEnv("VBOX_XPCOM_HOME");
+ if (psz)
+ {
+ if (strlen(psz) < MAXPATHLEN)
+ {
+ if (!realpath(psz, buf2))
+ strcpy(buf2, psz);
+ strcat(buf2, "/x"); /* for the filename stripping */
+ }
+ }
+
+ /*
+ * The dynamic loader.
+ */
+ if (!buf2[0])
+ {
+ Dl_info DlInfo = {0};
+ if ( !dladdr((const void *)GRE_GetCurrentProcessDirectory, &DlInfo)
+ && DlInfo.dli_fname)
+ {
+ if (!realpath(DlInfo.dli_fname, buf2))
+ buf2[0] = '\0';
+ }
+ }
+
+ /*
+ * Executable location.
+ */
+ if (!buf2[0])
+ {
+ char buf[MAXPATHLEN];
+ int cchLink = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
+ if (cchLink > 0 || cchLink != sizeof(buf) - 1)
+ {
+ buf[cchLink] = '\0';
+ if (!realpath(buf, buf2))
+ buf2[0] = '\0';
+ }
+ }
+
+ /*
+ * Copy to static buffer on success.
+ */
+ if (buf2[0])
+ {
+ char *p = strrchr(buf2, '/');
+ if (p)
+ {
+ p[p == buf2] = '\0';
+ #ifdef DEBUG
+ printf("debug: (1) VBOX_XPCOM_HOME=%s\n", buf2);
+ #endif
+ strcpy(szPath, buf2);
+ fPathSet = true;
+ }
+ }
+ }
+ if (fPathSet)
+ {
+ strcpy(buffer, szPath);
+ return PR_TRUE;
+ }
+#endif
+
+ // In the absence of a good way to get the executable directory let
+ // us try this for unix:
+ // - if VBOX_XPCOM_HOME is defined, that is it
+ // - else give the current directory
+
+ // The MOZ_DEFAULT_VBOX_XPCOM_HOME variable can be set at configure time with
+ // a --with-default-mozilla-five-home=foo autoconf flag.
+ //
+ // The idea here is to allow for builds that have a default VBOX_XPCOM_HOME
+ // regardless of the environment. This makes it easier to write apps that
+ // embed mozilla without having to worry about setting up the environment
+ //
+ // We do this py putenv()ing the default value into the environment. Note that
+ // we only do this if it is not already set.
+#ifdef MOZ_DEFAULT_VBOX_XPCOM_HOME
+ if (PR_GetEnv("VBOX_XPCOM_HOME") == nsnull)
+ {
+ putenv("VBOX_XPCOM_HOME=" MOZ_DEFAULT_VBOX_XPCOM_HOME);
+ }
+#endif
+
+ char *moz5 = PR_GetEnv("VBOX_XPCOM_HOME");
+
+ if (moz5 && *moz5)
+ {
+ if (!realpath(moz5, buffer))
+ strcpy(buffer, moz5);
+
+ return PR_TRUE;
+ }
+ else
+ {
+#if defined(DEBUG)
+ static PRBool firstWarning = PR_TRUE;
+
+ if(firstWarning) {
+ // Warn that VBOX_XPCOM_HOME not set, once.
+ printf("Warning: VBOX_XPCOM_HOME not set.\n");
+ firstWarning = PR_FALSE;
+ }
+#endif /* DEBUG */
+
+ // Fall back to current directory.
+ if (getcwd(buffer, MAXPATHLEN))
+ {
+ return PR_TRUE;
+ }
+ }
+
+#elif defined(XP_OS2)
+ PPIB ppib;
+ PTIB ptib;
+ char* p;
+ DosGetInfoBlocks( &ptib, &ppib);
+ DosQueryModuleName( ppib->pib_hmte, MAXPATHLEN, buffer);
+ p = strrchr( buffer, '\\'); // XXX DBCS misery
+ if (p) {
+ *p = '\0';
+ return PR_TRUE;
+ }
+
+#elif defined(XP_BEOS)
+
+ char *moz5 = getenv("VBOX_XPCOM_HOME");
+ if (moz5)
+ {
+ strcpy(buffer, moz5);
+ return PR_TRUE;
+ }
+ else
+ {
+ int32 cookie = 0;
+ image_info info;
+ char *p;
+ *buffer = 0;
+ if(get_next_image_info(0, &cookie, &info) == B_OK)
+ {
+ strcpy(buffer, info.name);
+ if((p = strrchr(buffer, '/')) != 0)
+ {
+ *p = 0;
+
+ return PR_TRUE;
+ }
+ }
+ }
+
+#endif
+
+ return PR_FALSE;
+}
+
+/**
+ * the GRE location is stored in a static buffer so that we don't have
+ * to compute it multiple times.
+ */
+
+static char sGRELocation[MAXPATHLEN] = "";
+
+extern "C" char const *
+GRE_GetGREPath()
+{
+ // we've already done this...
+ if (*sGRELocation)
+ return sGRELocation;
+
+ char buffer[MAXPATHLEN];
+
+ // If the xpcom library exists in the current process directory,
+ // then we will not use any GRE. The assumption here is that the
+ // GRE is in the same directory as the executable.
+ if (GRE_GetCurrentProcessDirectory(buffer)) {
+ PRUint32 pathlen = strlen(buffer);
+ strcpy(buffer + pathlen, XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL);
+
+ struct stat libStat;
+ int statResult = stat(buffer, &libStat);
+
+ if (statResult != -1) {
+ //found our xpcom lib in the current process directory
+ buffer[pathlen] = '\0';
+ strcpy(sGRELocation, buffer);
+ return sGRELocation;
+ }
+ }
+
+ // if GRE_HOME is in the environment, use that GRE
+ const char* env = PR_GetEnv("GRE_HOME");
+ if (env && *env) {
+#if XP_UNIX
+ if (!realpath(env, sGRELocation))
+ strcpy(sGRELocation, env);
+#elif XP_WIN32
+ if (!_fullpath(sGRELocation, env, MAXPATHLEN))
+ strcpy(sGRELocation, env);
+#endif
+ // xxxbsmedberg: it would help that other platforms had a "make absolute" function
+ return sGRELocation;
+ }
+
+ // the Gecko bits that sit next to the application or in the LD_LIBRARY_PATH
+ env = PR_GetEnv("USE_LOCAL_GRE");
+ if (env && *env)
+ return nsnull;
+
+#if XP_UNIX
+ // check in the HOME directory
+ env = PR_GetEnv("HOME");
+ if (env && *env) {
+# ifdef VBOX
+ snprintf(buffer, sizeof(buffer), "%s" XPCOM_FILE_PATH_SEPARATOR GRE_CONF_NAME, env);
+# else
+ sprintf(buffer, "%s" XPCOM_FILE_PATH_SEPARATOR GRE_CONF_NAME, env);
+# endif
+
+ if (GRE_GetPathFromConfigFile(buffer, sGRELocation)) {
+ return sGRELocation;
+ }
+ }
+#endif
+
+ env = PR_GetEnv("MOZ_GRE_CONF");
+ if (env) {
+ if (GRE_GetPathFromConfigFile(env, sGRELocation)) {
+ return sGRELocation;
+ }
+ }
+
+#if XP_UNIX
+ // Look for a group of config files in /etc/gre.d/
+ if (GRE_GetPathFromConfigDir(GRE_CONF_DIR, sGRELocation)) {
+ return sGRELocation;
+ }
+
+ // Look for a global /etc/gre.conf file
+ if (GRE_GetPathFromConfigFile(GRE_CONF_PATH, sGRELocation)) {
+ return sGRELocation;
+ }
+#endif
+
+#if XP_WIN32
+ char szKey[256];
+ HKEY hRegKey = NULL;
+ DWORD dwLength = MAXPATHLEN;
+
+ // A couple of key points here:
+ // 1. Note the usage of the "Software\\Mozilla\\GRE" subkey - this allows
+ // us to have multiple versions of GREs on the same machine by having
+ // subkeys such as 1.0, 1.1, 2.0 etc. under it.
+ // 2. In this sample below we're looking for the location of GRE version 1.2
+ // i.e. we're compatible with GRE 1.2 and we're trying to find it's install
+ // location.
+ //
+ // Please see http://www.mozilla.org/projects/embedding/GRE.html for
+ // more info.
+ //
+ strcpy(szKey, GRE_WIN_REG_LOC GRE_BUILD_ID);
+
+ if (::RegOpenKeyEx(HKEY_CURRENT_USER, szKey, 0, KEY_QUERY_VALUE, &hRegKey) == ERROR_SUCCESS) {
+ if (::RegQueryValueEx(hRegKey, "GreHome", NULL, NULL, (BYTE *)sGRELocation, &dwLength) != ERROR_SUCCESS) {
+ *sGRELocation = '\0';
+ }
+ ::RegCloseKey(hRegKey);
+
+ if (*sGRELocation)
+ return sGRELocation;
+ }
+
+ if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_QUERY_VALUE, &hRegKey) == ERROR_SUCCESS) {
+ if (::RegQueryValueEx(hRegKey, "GreHome", NULL, NULL, (BYTE *)sGRELocation, &dwLength) != ERROR_SUCCESS) {
+ *sGRELocation = '\0';
+ }
+ ::RegCloseKey(hRegKey);
+
+ if (*sGRELocation)
+ return sGRELocation;
+ }
+#endif
+
+ return nsnull;
+}
+
+PRBool
+GRE_GetPathFromConfigDir(const char* dirname, char* buffer)
+{
+ // Open the directory provided and try to read any files in that
+ // directory that end with .conf. We look for an entry that might
+ // point to the GRE that we're interested in.
+ PRDir *dir = PR_OpenDir(dirname);
+ if (!dir)
+ return nsnull;
+
+ PRBool found = PR_FALSE;
+ PRDirEntry *entry;
+
+ while (!found && (entry = PR_ReadDir(dir, PR_SKIP_BOTH))) {
+
+ // Only look for files that end in .conf
+ char *offset = PL_strrstr(entry->name, ".conf");
+ if (!offset)
+ continue;
+
+ if (offset != entry->name + strlen(entry->name) - 5)
+ continue;
+
+ nsEmbedCString fullPath;
+ NS_CStringAppendData(fullPath, dirname);
+ NS_CStringAppendData(fullPath, XPCOM_FILE_PATH_SEPARATOR);
+ NS_CStringAppendData(fullPath, entry->name);
+
+ found = GRE_GetPathFromConfigFile(fullPath.get(), buffer);
+ }
+
+ PR_CloseDir(dir);
+
+ return found;
+}
+
+PRBool
+GRE_GetPathFromConfigFile(const char* filename, char* pathBuffer)
+{
+ *pathBuffer = '\0';
+ char buffer[1024];
+ FILE *cfg;
+ PRBool foundHeader = PR_FALSE;
+ PRInt32 versionLen = sizeof(GRE_BUILD_ID)-1;
+
+ if((cfg=fopen(filename,"r"))==nsnull) {
+ return nsnull;
+ }
+
+ while (fgets(buffer, 1024, cfg) != nsnull) {
+ // skip over comment lines and blank lines
+ if (buffer[0] == '#' || buffer[0] == '\n') {
+ continue;
+ }
+
+ // we found a section heading, check to see if it is the one we are intersted in.
+ if (buffer[0] == '[') {
+ if (!strncmp (buffer+1, GRE_BUILD_ID, versionLen)) {
+ foundHeader = PR_TRUE;
+ }
+ continue;
+ }
+
+ if (foundHeader && !strncmp (buffer, "GRE_PATH=", 9)) {
+ strcpy(pathBuffer, buffer + 9);
+ // kill the line feed if any
+ PRInt32 len = strlen(pathBuffer);
+ len--;
+
+ if (pathBuffer[len] == '\n')
+ pathBuffer[len] = '\0';
+ break;
+ }
+ }
+ fclose(cfg);
+ return (*pathBuffer != '\0');
+}
+
+extern "C" nsresult
+GRE_GetGREDirectory(nsILocalFile* *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ nsresult rv = NS_ERROR_FAILURE;
+
+ // Get the path of the GRE which is compatible with our embedding application
+ // from the registry
+
+ const char *pGREDir = GRE_GetGREPath();
+ if(pGREDir) {
+ nsCOMPtr<nsILocalFile> tempLocal;
+ nsEmbedCString leaf;
+ NS_CStringSetData(leaf, pGREDir);
+ rv = NS_NewNativeLocalFile(leaf, PR_TRUE, getter_AddRefs(tempLocal));
+
+ if (NS_SUCCEEDED(rv)) {
+ *_retval = tempLocal;
+ NS_ADDREF(*_retval);
+ }
+ }
+ return rv;
+}
+
+static char sXPCOMPath[MAXPATHLEN];
+
+extern "C" const char*
+GRE_GetXPCOMPath()
+{
+ const char* grePath = GRE_GetGREPath();
+
+ if (!grePath) {
+ grePath = PR_GetEnv("VBOX_XPCOM_HOME");
+ if (!grePath || !*grePath) {
+ return nsnull;
+ }
+ }
+
+#ifdef VBOX
+ snprintf(sXPCOMPath, sizeof(sXPCOMPath), "%s" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL, grePath);
+#else
+ sprintf(sXPCOMPath, "%s" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL, grePath);
+#endif
+
+ return sXPCOMPath;
+}
diff --git a/src/libs/xpcom18a4/xpcom/glue/standalone/nsGREDirServiceProvider.h b/src/libs/xpcom18a4/xpcom/glue/standalone/nsGREDirServiceProvider.h
new file mode 100644
index 00000000..0638a127
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/standalone/nsGREDirServiceProvider.h
@@ -0,0 +1,68 @@
+/* ***** 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.
+ *
+ * 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):
+ * Sean Su <ssu@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 nsGREDirServiceProvider_h_
+#define nsGREDirServiceProvider_h_
+
+#include "nsIDirectoryService.h"
+
+#ifndef MAXPATHLEN
+#ifdef _MAX_PATH
+#define MAXPATHLEN _MAX_PATH
+#elif defined(CCHMAXPATH)
+#define MAXPATHLEN CCHMAXPATH
+#else
+#define MAXPATHLEN 1024
+#endif
+#endif
+
+/**
+ * the directoryserviceprovider used by GRE_Startup when calling NS_InitXPCOM2
+ */
+class nsGREDirServiceProvider : public nsIDirectoryServiceProvider
+{
+public:
+ nsGREDirServiceProvider() { }
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIDIRECTORYSERVICEPROVIDER
+
+private:
+ ~nsGREDirServiceProvider() { }
+};
+
+#endif // nsGREDirServiceProvider.h
diff --git a/src/libs/xpcom18a4/xpcom/glue/standalone/nsXPCOMGlue.cpp b/src/libs/xpcom18a4/xpcom/glue/standalone/nsXPCOMGlue.cpp
new file mode 100644
index 00000000..091538fa
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/standalone/nsXPCOMGlue.cpp
@@ -0,0 +1,524 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:set ts=4 sw=4 et cindent: */
+/* ***** 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 "nsXPCOMGlue.h"
+
+#include "nspr.h"
+#include "nsMemory.h"
+#include "nsGREDirServiceProvider.h"
+#include "nsXPCOMPrivate.h"
+#include <stdlib.h>
+#ifdef VBOX
+# include <limits.h>
+#endif
+
+#if XP_WIN32
+#include <windows.h>
+#endif
+
+void GRE_AddGREToEnvironment();
+
+// functions provided by nsMemory.cpp and nsDebug.cpp
+nsresult GlueStartupMemory();
+void GlueShutdownMemory();
+nsresult GlueStartupDebug();
+void GlueShutdownDebug();
+
+static PRLibrary *xpcomLib;
+static XPCOMFunctions xpcomFunctions;
+
+extern "C"
+nsresult XPCOMGlueStartup(const char* xpcomFile)
+{
+#ifdef XPCOM_GLUE_NO_DYNAMIC_LOADING
+ return NS_OK;
+#else
+ nsresult rv = NS_OK;
+ GetFrozenFunctionsFunc function = nsnull;
+
+ xpcomFunctions.version = XPCOM_GLUE_VERSION;
+ xpcomFunctions.size = sizeof(XPCOMFunctions);
+
+ //
+ // if xpcomFile == ".", then we assume xpcom is already loaded, and we'll
+ // use NSPR to find NS_GetFrozenFunctions from the list of already loaded
+ // libraries.
+ //
+ // otherwise, we try to load xpcom and then look for NS_GetFrozenFunctions.
+ // if xpcomFile == NULL, then we try to load xpcom by name w/o a fully
+ // qualified path.
+ //
+
+ if (xpcomFile && (xpcomFile[0] == '.' && xpcomFile[1] == '\0')) {
+ function = (GetFrozenFunctionsFunc)
+ PR_FindSymbolAndLibrary("NS_GetFrozenFunctions", &xpcomLib);
+ if (!function) {
+ // The symbol was not found, so failover to loading XPCOM_DLL,
+ // and look for the symbol there. See bug 240986 for details.
+ xpcomFile = nsnull;
+ }
+ else {
+ char *libPath = PR_GetLibraryFilePathname(XPCOM_DLL, (PRFuncPtr) function);
+ if (!libPath)
+ rv = NS_ERROR_FAILURE;
+ else {
+ rv = (*function)(&xpcomFunctions, libPath);
+ PR_Free(libPath);
+ }
+ }
+ }
+
+ if (!function) {
+ PRLibSpec libSpec;
+
+ libSpec.type = PR_LibSpec_Pathname;
+ if (!xpcomFile)
+ libSpec.value.pathname = XPCOM_DLL;
+ else
+ libSpec.value.pathname = xpcomFile;
+
+ xpcomLib = PR_LoadLibraryWithFlags(libSpec, PR_LD_LAZY|PR_LD_GLOBAL);
+#ifdef RT_OS_DARWIN /* vbox */
+ /* works around bundle problem. */
+ if (!xpcomLib) {
+ const char *home = PR_GetEnv("VBOX_XPCOM_HOME");
+ if (home) {
+ char path[PATH_MAX];
+ snprintf(path, sizeof(path), "%s/%s", home, libSpec.value.pathname);
+ libSpec.value.pathname = path;
+ xpcomLib = PR_LoadLibraryWithFlags(libSpec, PR_LD_LAZY|PR_LD_GLOBAL);
+ }
+ }
+#endif
+ if (!xpcomLib)
+ return NS_ERROR_FAILURE;
+
+ function = (GetFrozenFunctionsFunc) PR_FindSymbol(xpcomLib, "NS_GetFrozenFunctions");
+
+ if (!function)
+ rv = NS_ERROR_FAILURE;
+ else
+ rv = (*function)(&xpcomFunctions, libSpec.value.pathname);
+ }
+
+ if (NS_FAILED(rv))
+ goto bail;
+
+ rv = GlueStartupDebug();
+ if (NS_FAILED(rv))
+ goto bail;
+
+ // startup the nsMemory
+ rv = GlueStartupMemory();
+ if (NS_FAILED(rv)) {
+ GlueShutdownDebug();
+ goto bail;
+ }
+
+ GRE_AddGREToEnvironment();
+ return NS_OK;
+
+bail:
+ PR_UnloadLibrary(xpcomLib);
+ xpcomLib = nsnull;
+ memset(&xpcomFunctions, 0, sizeof(xpcomFunctions));
+ return NS_ERROR_FAILURE;
+#endif
+}
+
+extern "C"
+nsresult XPCOMGlueShutdown()
+{
+#ifdef XPCOM_GLUE_NO_DYNAMIC_LOADING
+ return NS_OK;
+#else
+
+ GlueShutdownMemory();
+
+ GlueShutdownDebug();
+
+ if (xpcomLib) {
+ PR_UnloadLibrary(xpcomLib);
+ xpcomLib = nsnull;
+ }
+
+ memset(&xpcomFunctions, 0, sizeof(xpcomFunctions));
+ return NS_OK;
+#endif
+}
+
+#ifndef XPCOM_GLUE_NO_DYNAMIC_LOADING
+extern "C" NS_COM nsresult
+NS_InitXPCOM2(nsIServiceManager* *result,
+ nsIFile* binDirectory,
+ nsIDirectoryServiceProvider* appFileLocationProvider)
+{
+ if (!xpcomFunctions.init)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.init(result, binDirectory, appFileLocationProvider);
+}
+
+extern "C" NS_COM nsresult
+NS_ShutdownXPCOM(nsIServiceManager* servMgr)
+{
+ if (!xpcomFunctions.shutdown)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.shutdown(servMgr);
+}
+
+extern "C" NS_COM nsresult
+NS_GetServiceManager(nsIServiceManager* *result)
+{
+ if (!xpcomFunctions.getServiceManager)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.getServiceManager(result);
+}
+
+extern "C" NS_COM nsresult
+NS_GetComponentManager(nsIComponentManager* *result)
+{
+ if (!xpcomFunctions.getComponentManager)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.getComponentManager(result);
+}
+
+extern "C" NS_COM nsresult
+NS_GetComponentRegistrar(nsIComponentRegistrar* *result)
+{
+ if (!xpcomFunctions.getComponentRegistrar)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.getComponentRegistrar(result);
+}
+
+extern "C" NS_COM nsresult
+NS_GetMemoryManager(nsIMemory* *result)
+{
+ if (!xpcomFunctions.getMemoryManager)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.getMemoryManager(result);
+}
+
+extern "C" NS_COM nsresult
+NS_NewLocalFile(const nsAString &path, PRBool followLinks, nsILocalFile* *result)
+{
+ if (!xpcomFunctions.newLocalFile)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.newLocalFile(path, followLinks, result);
+}
+
+extern "C" NS_COM nsresult
+NS_NewNativeLocalFile(const nsACString &path, PRBool followLinks, nsILocalFile* *result)
+{
+ if (!xpcomFunctions.newNativeLocalFile)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.newNativeLocalFile(path, followLinks, result);
+}
+
+extern "C" NS_COM nsresult
+NS_RegisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine, PRUint32 priority)
+{
+ if (!xpcomFunctions.registerExitRoutine)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.registerExitRoutine(exitRoutine, priority);
+}
+
+extern "C" NS_COM nsresult
+NS_UnregisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine)
+{
+ if (!xpcomFunctions.unregisterExitRoutine)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.unregisterExitRoutine(exitRoutine);
+}
+
+extern "C" NS_COM nsresult
+NS_GetDebug(nsIDebug* *result)
+{
+ if (!xpcomFunctions.getDebug)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.getDebug(result);
+}
+
+
+extern "C" NS_COM nsresult
+NS_GetTraceRefcnt(nsITraceRefcnt* *result)
+{
+ if (!xpcomFunctions.getTraceRefcnt)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.getTraceRefcnt(result);
+}
+
+
+extern "C" NS_COM nsresult
+NS_StringContainerInit(nsStringContainer &aStr)
+{
+ if (!xpcomFunctions.stringContainerInit)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.stringContainerInit(aStr);
+}
+
+extern "C" NS_COM void
+NS_StringContainerFinish(nsStringContainer &aStr)
+{
+ if (xpcomFunctions.stringContainerFinish)
+ xpcomFunctions.stringContainerFinish(aStr);
+}
+
+extern "C" NS_COM PRUint32
+NS_StringGetData(const nsAString &aStr, const PRUnichar **aBuf, PRBool *aTerm)
+{
+ if (!xpcomFunctions.stringGetData) {
+ *aBuf = nsnull;
+ return 0;
+ }
+ return xpcomFunctions.stringGetData(aStr, aBuf, aTerm);
+}
+
+extern "C" NS_COM PRUnichar *
+NS_StringCloneData(const nsAString &aStr)
+{
+ if (!xpcomFunctions.stringCloneData)
+ return nsnull;
+ return xpcomFunctions.stringCloneData(aStr);
+}
+
+extern "C" NS_COM nsresult
+NS_StringSetData(nsAString &aStr, const PRUnichar *aBuf, PRUint32 aCount)
+{
+ if (!xpcomFunctions.stringSetData)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ return xpcomFunctions.stringSetData(aStr, aBuf, aCount);
+}
+
+extern "C" NS_COM nsresult
+NS_StringSetDataRange(nsAString &aStr, PRUint32 aCutStart, PRUint32 aCutLength,
+ const PRUnichar *aBuf, PRUint32 aCount)
+{
+ if (!xpcomFunctions.stringSetDataRange)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.stringSetDataRange(aStr, aCutStart, aCutLength, aBuf, aCount);
+}
+
+extern "C" NS_COM nsresult
+NS_StringCopy(nsAString &aDest, const nsAString &aSrc)
+{
+ if (!xpcomFunctions.stringCopy)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.stringCopy(aDest, aSrc);
+}
+
+
+extern "C" NS_COM nsresult
+NS_CStringContainerInit(nsCStringContainer &aStr)
+{
+ if (!xpcomFunctions.cstringContainerInit)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.cstringContainerInit(aStr);
+}
+
+extern "C" NS_COM void
+NS_CStringContainerFinish(nsCStringContainer &aStr)
+{
+ if (xpcomFunctions.cstringContainerFinish)
+ xpcomFunctions.cstringContainerFinish(aStr);
+}
+
+extern "C" NS_COM PRUint32
+NS_CStringGetData(const nsACString &aStr, const char **aBuf, PRBool *aTerm)
+{
+ if (!xpcomFunctions.cstringGetData) {
+ *aBuf = nsnull;
+ return 0;
+ }
+ return xpcomFunctions.cstringGetData(aStr, aBuf, aTerm);
+}
+
+extern "C" NS_COM char *
+NS_CStringCloneData(const nsACString &aStr)
+{
+ if (!xpcomFunctions.cstringCloneData)
+ return nsnull;
+ return xpcomFunctions.cstringCloneData(aStr);
+}
+
+extern "C" NS_COM nsresult
+NS_CStringSetData(nsACString &aStr, const char *aBuf, PRUint32 aCount)
+{
+ if (!xpcomFunctions.cstringSetData)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.cstringSetData(aStr, aBuf, aCount);
+}
+
+extern "C" NS_COM nsresult
+NS_CStringSetDataRange(nsACString &aStr, PRUint32 aCutStart, PRUint32 aCutLength,
+ const char *aBuf, PRUint32 aCount)
+{
+ if (!xpcomFunctions.cstringSetDataRange)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.cstringSetDataRange(aStr, aCutStart, aCutLength, aBuf, aCount);
+}
+
+extern "C" NS_COM nsresult
+NS_CStringCopy(nsACString &aDest, const nsACString &aSrc)
+{
+ if (!xpcomFunctions.cstringCopy)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.cstringCopy(aDest, aSrc);
+}
+
+extern "C" NS_COM nsresult
+NS_CStringToUTF16(const nsACString &aSrc, PRUint32 aSrcEncoding, nsAString &aDest)
+{
+ if (!xpcomFunctions.cstringToUTF16)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.cstringToUTF16(aSrc, aSrcEncoding, aDest);
+}
+
+extern "C" NS_COM nsresult
+NS_UTF16ToCString(const nsAString &aSrc, PRUint32 aDestEncoding, nsACString &aDest)
+{
+ if (!xpcomFunctions.utf16ToCString)
+ return NS_ERROR_NOT_INITIALIZED;
+ return xpcomFunctions.utf16ToCString(aSrc, aDestEncoding, aDest);
+}
+
+#endif // #ifndef XPCOM_GLUE_NO_DYNAMIC_LOADING
+
+
+static char sEnvString[MAXPATHLEN*10];
+static char* spEnvString = 0;
+
+void
+GRE_AddGREToEnvironment()
+{
+ const char* grePath = GRE_GetGREPath();
+ char szPath[MAXPATHLEN];
+ if (!grePath)
+ return;
+
+ const char* path = PR_GetEnv(XPCOM_SEARCH_KEY);
+ if (!path)
+ path = "";
+#ifdef VBOX
+ else
+ {
+ /* sEnvString is part of the environment because of putenv().
+ * path is only temporarily used and not argument of putenv() itself */
+ snprintf(szPath, sizeof(szPath), "%s", path);
+ path = szPath;
+ }
+#endif
+
+ if (spEnvString) PR_smprintf_free(spEnvString);
+
+ /**
+ * if the PATH string is longer than our static buffer, allocate a
+ * buffer for the environment string. This buffer will be leaked at shutdown!
+ */
+ if (strlen(grePath) + strlen(path) +
+ sizeof(XPCOM_SEARCH_KEY) + sizeof(XPCOM_ENV_PATH_SEPARATOR) > MAXPATHLEN*10) {
+ if (PR_smprintf(XPCOM_SEARCH_KEY "=%s" XPCOM_ENV_PATH_SEPARATOR "%s",
+ grePath,
+ path)) {
+ PR_SetEnv(spEnvString);
+ }
+ } else {
+ if (sprintf(sEnvString,
+ XPCOM_SEARCH_KEY "=%s" XPCOM_ENV_PATH_SEPARATOR "%s",
+ grePath,
+ path) > 0) {
+ PR_SetEnv(sEnvString);
+ }
+ }
+
+#if XP_WIN32
+ // On windows, the current directory is searched before the
+ // PATH environment variable. This is a very bad thing
+ // since libraries in the cwd will be picked up before
+ // any that are in either the application or GRE directory.
+
+ if (grePath) {
+ SetCurrentDirectory(grePath);
+ }
+#endif
+}
+
+
+// Default GRE startup/shutdown code
+
+extern "C"
+nsresult GRE_Startup()
+{
+ const char* xpcomLocation = GRE_GetXPCOMPath();
+
+ // Startup the XPCOM Glue that links us up with XPCOM.
+ nsresult rv = XPCOMGlueStartup(xpcomLocation);
+
+ if (NS_FAILED(rv)) {
+ NS_WARNING("gre: XPCOMGlueStartup failed");
+ return rv;
+ }
+
+ nsGREDirServiceProvider *provider = new nsGREDirServiceProvider();
+ if ( !provider ) {
+ NS_WARNING("GRE_Startup failed");
+ XPCOMGlueShutdown();
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ nsCOMPtr<nsIServiceManager> servMan;
+ NS_ADDREF( provider );
+ rv = NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, provider);
+ NS_RELEASE(provider);
+
+ if ( NS_FAILED(rv) || !servMan) {
+ NS_WARNING("gre: NS_InitXPCOM failed");
+ XPCOMGlueShutdown();
+ return rv;
+ }
+
+ return NS_OK;
+}
+
+extern "C"
+nsresult GRE_Shutdown()
+{
+ NS_ShutdownXPCOM(nsnull);
+ XPCOMGlueShutdown();
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/glue/standalone/nsXPCOMGlue.h b/src/libs/xpcom18a4/xpcom/glue/standalone/nsXPCOMGlue.h
new file mode 100644
index 00000000..6044e084
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/glue/standalone/nsXPCOMGlue.h
@@ -0,0 +1,109 @@
+/* -*- 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 "nscore.h"
+
+class nsILocalFile;
+
+/**
+ * Initialize the XPCOM glue by dynamically linking against the XPCOM
+ * shared library indicated by xpcomFile.
+ */
+
+extern "C"
+nsresult XPCOMGlueStartup(const char* xpcomFile);
+
+
+/**
+ * Finish the XPCOM glue after it is no longer needed.
+ */
+
+extern "C"
+nsresult XPCOMGlueShutdown();
+
+
+/**
+ * Locate the path of a compatible GRE.
+ *
+ * @return string buffer pointing to the GRE path (without a trailing
+ * directory separator). Callers do no need to free this buffer.
+ */
+
+extern "C"
+char const * GRE_GetGREPath();
+
+
+/**
+ * Locate the path of a compatible GRE. This is returned as an
+ * nsILocalFile instead of a char*.
+ *
+ * @param _retval Ordinary XPCOM getter, returns an addrefed interface.
+ */
+
+extern "C"
+nsresult GRE_GetGREDirectory(nsILocalFile* *_retval);
+
+
+/**
+ * Locate the path of the XPCOM binary of a compatible GRE.
+ * The result of this function is normally passed directly to
+ * XPCOMGlueStartup.
+ *
+ * @return string buffer pointing to the XPCOM DLL path. Callers do
+ * not need to free this buffer.
+ */
+
+extern "C"
+char const * GRE_GetXPCOMPath();
+
+
+/**
+ * Embedding applications which don't need a custom
+ * directoryserviceprovider may use GRE_Startup to start the XPCOM
+ * glue and initialize the GRE in one step.
+ */
+
+extern "C"
+nsresult GRE_Startup();
+
+
+/**
+ * Shut down XPCOM and the XPCOM glue in one step.
+ */
+
+extern "C"
+nsresult GRE_Shutdown();
diff --git a/src/libs/xpcom18a4/xpcom/io/.cvsignore b/src/libs/xpcom18a4/xpcom/io/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/io/Makefile.in b/src/libs/xpcom18a4/xpcom/io/Makefile.in
new file mode 100644
index 00000000..ed2f3f6d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/Makefile.in
@@ -0,0 +1,175 @@
+#
+# ***** 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_io
+LIBRARY_NAME = xpcomio_s
+GRE_MODULE = 1
+REQUIRES = string \
+ $(NULL)
+
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+REQUIRES += macmorefiles
+endif
+
+CPPSRCS = \
+ nsAppFileLocationProvider.cpp \
+ nsBinaryStream.cpp \
+ nsByteArrayInputStream.cpp \
+ nsDirectoryService.cpp \
+ nsEscape.cpp \
+ nsFastLoadFile.cpp \
+ nsFastLoadService.cpp \
+ nsInputStreamTee.cpp \
+ nsLinebreakConverter.cpp \
+ nsLocalFileCommon.cpp \
+ nsMultiplexInputStream.cpp \
+ nsPipe3.cpp \
+ nsStreamUtils.cpp \
+ nsScriptableInputStream.cpp \
+ nsSegmentedBuffer.cpp \
+ SpecialSystemDirectory.cpp \
+ nsStorageStream.cpp \
+ nsStringStream.cpp \
+ nsUnicharInputStream.cpp \
+ nsNativeCharsetUtils.cpp \
+ $(NULL)
+
+ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
+CPPSRCS += nsLocalFileOS2.cpp
+else
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+CPPSRCS += nsLocalFileOSX.cpp
+else
+ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
+CPPSRCS += nsLocalFileWin.cpp
+else
+CPPSRCS += nsLocalFileUnix.cpp
+endif # windows
+endif # mac
+endif # OS2
+
+EXPORTS = \
+ nsAppDirectoryServiceDefs.h \
+ nsDirectoryService.h \
+ nsDirectoryServiceUtils.h \
+ nsEscape.h \
+ nsFastLoadPtr.h \
+ nsFastLoadService.h \
+ nsIUnicharInputStream.h \
+ nsLinebreakConverter.h \
+ nsLocalFile.h \
+ nsMultiplexInputStream.h \
+ nsScriptableInputStream.h \
+ nsStorageStream.h \
+ nsStringIO.h \
+ nsStringStream.h \
+ nsStreamUtils.h \
+ nsNativeCharsetUtils.h \
+ $(NULL)
+
+ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
+EXPORTS += nsLocalFileOS2.h
+else
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+EXPORTS += nsLocalFileOSX.h
+else
+ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
+EXPORTS += nsLocalFileWin.h
+else
+EXPORTS += nsLocalFileUnix.h
+endif # windows
+endif # mac
+endif # os2
+
+XPIDLSRCS = \
+ nsIBinaryInputStream.idl \
+ nsIBinaryOutputStream.idl \
+ nsIByteArrayInputStream.idl \
+ nsIFastLoadFileControl.idl \
+ nsIFastLoadService.idl \
+ nsIInputStreamTee.idl \
+ nsILineInputStream.idl \
+ nsIMultiplexInputStream.idl \
+ nsIObjectInputStream.idl \
+ nsIObjectOutputStream.idl \
+ nsIPipe.idl \
+ nsISeekableStream.idl \
+ nsIStorageStream.idl \
+ nsIStringStream.idl \
+ nsIStreamBufferAccess.idl \
+ nsIAsyncInputStream.idl \
+ nsIAsyncOutputStream.idl \
+ $(NULL)
+
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+XPIDLSRCS += nsILocalFileMac.idl
+endif
+
+SDK_XPIDLSRCS = \
+ nsIDirectoryService.idl \
+ nsIFile.idl \
+ nsILocalFile.idl \
+ nsIInputStream.idl \
+ nsIOutputStream.idl \
+ nsIScriptableInputStream.idl \
+ $(NULL)
+
+SDK_HEADERS = \
+ nsDirectoryServiceDefs.h \
+ $(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
+
+LOCAL_INCLUDES = -I..
diff --git a/src/libs/xpcom18a4/xpcom/io/SpecialSystemDirectory.cpp b/src/libs/xpcom18a4/xpcom/io/SpecialSystemDirectory.cpp
new file mode 100644
index 00000000..5d1bc4fd
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/SpecialSystemDirectory.cpp
@@ -0,0 +1,770 @@
+/* -*- 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):
+ * Doug Turner <dougt@netscape.com>
+ * IBM Corp.
+ *
+ * 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 "SpecialSystemDirectory.h"
+#include "nsString.h"
+#include "nsDependentString.h"
+
+
+#ifdef XP_MAC
+
+#include <Folders.h>
+#include <Files.h>
+#include <Memory.h>
+#include <Processes.h>
+#include <Gestalt.h>
+#include "nsIInternetConfigService.h"
+
+
+#if UNIVERSAL_INTERFACES_VERSION < 0x0340
+ enum {
+ kSystemDomain = -32766, /* Read-only system hierarchy.*/
+ kLocalDomain = -32765, /* All users of a single machine have access to these resources.*/
+ kNetworkDomain = -32764, /* All users configured to use a common network server has access to these resources.*/
+ kUserDomain = -32763, /* Read/write. Resources that are private to the user.*/
+ kClassicDomain = -32762, /* Domain referring to the currently configured Classic System Folder*/
+
+ kDomainLibraryFolderType = FOUR_CHAR_CODE('dlib')
+ };
+#endif
+
+#elif defined(XP_WIN)
+
+#include <windows.h>
+#include <shlobj.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#elif defined(XP_OS2)
+
+#define MAX_PATH _MAX_PATH
+#define INCL_WINWORKPLACE
+#define INCL_DOSMISC
+#define INCL_DOSMODULEMGR
+#define INCL_DOSPROCESS
+#define INCL_WINSHELLDATA
+#include <os2.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "prenv.h"
+
+#elif defined(XP_UNIX)
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include "prenv.h"
+# if defined(XP_MACOSX) && defined(VBOX_WITH_NEWER_OSX_SDK)
+# include <Folders.h>
+# endif
+
+#elif defined(XP_BEOS)
+
+#include <FindDirectory.h>
+#include <Path.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <OS.h>
+#include <image.h>
+#include "prenv.h"
+
+#endif
+
+#if defined(VMS)
+#include <unixlib.h>
+#endif
+
+
+
+#if defined (XP_WIN)
+typedef BOOL (WINAPI * GetSpecialPathProc) (HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate);
+GetSpecialPathProc gGetSpecialPathProc = NULL;
+static HINSTANCE gShell32DLLInst = NULL;
+#endif
+NS_COM void StartupSpecialSystemDirectory()
+{
+#if defined (XP_WIN)
+ /* On windows, the old method to get file locations is incredibly slow.
+ As of this writing, 3 calls to GetWindowsFolder accounts for 3% of mozilla
+ startup. Replacing these older calls with a single call to SHGetSpecialFolderPath
+ effectively removes these calls from the performace radar. We need to
+ support the older way of file location lookup on systems that do not have
+ IE4. (Note: gets the ansi version: SHGetSpecialFolderPathA).
+ */
+ gShell32DLLInst = LoadLibrary("Shell32.dll");
+ if(gShell32DLLInst)
+ {
+ gGetSpecialPathProc = (GetSpecialPathProc) GetProcAddress(gShell32DLLInst,
+ "SHGetSpecialFolderPathA");
+ }
+#endif
+}
+
+NS_COM void ShutdownSpecialSystemDirectory()
+{
+#if defined (XP_WIN)
+ if (gShell32DLLInst)
+ {
+ FreeLibrary(gShell32DLLInst);
+ gShell32DLLInst = NULL;
+ gGetSpecialPathProc = NULL;
+ }
+#endif
+}
+
+#if defined (XP_WIN)
+
+//----------------------------------------------------------------------------------------
+static nsresult GetWindowsFolder(int folder, nsILocalFile** aFile)
+//----------------------------------------------------------------------------------------
+{
+ if (gGetSpecialPathProc) {
+ TCHAR path[MAX_PATH];
+ HRESULT result = gGetSpecialPathProc(NULL, path, folder, true);
+
+ if (!SUCCEEDED(result))
+ return NS_ERROR_FAILURE;
+
+ // Append the trailing slash
+ int len = strlen(path);
+ if (len>1 && path[len-1] != '\\')
+ {
+ path[len] = '\\';
+ path[len + 1] = '\0';
+ }
+
+ return NS_NewNativeLocalFile(nsDependentCString(path),
+ PR_TRUE,
+ aFile);
+ }
+
+ nsresult rv = NS_ERROR_FAILURE;
+ LPMALLOC pMalloc = NULL;
+ LPSTR pBuffer = NULL;
+ LPITEMIDLIST pItemIDList = NULL;
+ int len;
+
+ // Get the shell's allocator.
+ if (!SUCCEEDED(SHGetMalloc(&pMalloc)))
+ return NS_ERROR_FAILURE;
+
+ // Allocate a buffer
+ if ((pBuffer = (LPSTR) pMalloc->Alloc(MAX_PATH + 2)) == NULL)
+ return NS_ERROR_FAILURE;
+
+ // Get the PIDL for the folder.
+ if (!SUCCEEDED(SHGetSpecialFolderLocation(
+ NULL, folder, &pItemIDList)))
+ goto Clean;
+
+ if (!SUCCEEDED(SHGetPathFromIDList(pItemIDList, pBuffer)))
+ goto Clean;
+
+ // Append the trailing slash
+ len = strlen(pBuffer);
+ pBuffer[len] = '\\';
+ pBuffer[len + 1] = '\0';
+
+ // Assign the directory
+ rv = NS_NewNativeLocalFile(nsDependentCString(pBuffer),
+ PR_TRUE,
+ aFile);
+
+Clean:
+ // Clean up.
+ if (pItemIDList)
+ pMalloc->Free(pItemIDList);
+ if (pBuffer)
+ pMalloc->Free(pBuffer);
+
+ pMalloc->Release();
+
+ return rv;
+}
+
+#endif // XP_WIN
+
+
+
+
+nsresult
+GetSpecialSystemDirectory(SystemDirectories aSystemSystemDirectory,
+ nsILocalFile** aFile)
+{
+#ifdef XP_MAC
+ OSErr err;
+ short vRefNum;
+ long dirID;
+#endif
+
+ switch (aSystemSystemDirectory)
+ {
+ case OS_DriveDirectory:
+#if defined (XP_WIN)
+ {
+ char path[_MAX_PATH];
+ PRInt32 len = GetWindowsDirectory( path, _MAX_PATH );
+ if (len)
+ {
+ if ( path[1] == ':' && path[2] == '\\' )
+ path[3] = 0;
+ }
+
+ return NS_NewNativeLocalFile(nsDependentCString(path),
+ PR_TRUE,
+ aFile);
+ }
+#elif defined(XP_OS2)
+ {
+ ULONG ulBootDrive = 0;
+ char buffer[] = " :\\OS2\\";
+ DosQuerySysInfo( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE,
+ &ulBootDrive, sizeof ulBootDrive);
+ buffer[0] = 'A' - 1 + ulBootDrive; // duh, 1-based index...
+
+ return NS_NewNativeLocalFile(nsDependentCString(buffer),
+ PR_TRUE,
+ aFile);
+ }
+#elif defined(XP_MAC)
+ {
+ return nsIFileFromOSType(kVolumeRootFolderType, aFile);
+ }
+#else
+ return NS_NewNativeLocalFile(nsDependentCString("/"),
+ PR_TRUE,
+ aFile);
+
+#endif
+
+ case OS_TemporaryDirectory:
+#if defined (XP_WIN)
+ {
+ char path[_MAX_PATH];
+ DWORD len = GetTempPath(_MAX_PATH, path);
+ return NS_NewNativeLocalFile(nsDependentCString(path),
+ PR_TRUE,
+ aFile);
+ }
+#elif defined(XP_OS2)
+ {
+ char buffer[CCHMAXPATH] = "";
+ char *c = getenv( "TMP");
+ if( c) strcpy( buffer, c);
+ else
+ {
+ c = getenv( "TEMP");
+ if( c) strcpy( buffer, c);
+ }
+
+ return NS_NewNativeLocalFile(nsDependentCString(buffer),
+ PR_TRUE,
+ aFile);
+ }
+#elif defined(XP_MAC)
+ return nsIFileFromOSType(kTemporaryFolderType, aFile);
+
+#elif defined(XP_MACOSX)
+ {
+ return GetOSXFolderType(kUserDomain, kTemporaryFolderType, aFile);
+ }
+
+#elif defined(XP_UNIX) || defined(XP_BEOS)
+ {
+ static const char *tPath = nsnull;
+ if (!tPath) {
+ tPath = PR_GetEnv("TMPDIR");
+ if (!tPath || !*tPath) {
+ tPath = PR_GetEnv("TMP");
+ if (!tPath || !*tPath) {
+ tPath = PR_GetEnv("TEMP");
+ if (!tPath || !*tPath) {
+ tPath = "/tmp/";
+ }
+ }
+ }
+ }
+ return NS_NewNativeLocalFile(nsDependentCString(tPath),
+ PR_TRUE,
+ aFile);
+ }
+#else
+ break;
+#endif
+
+#if defined(XP_MAC)
+ case Mac_SystemDirectory:
+ return nsIFileFromOSType(kSystemFolderType, aFile);
+
+ case Mac_DesktopDirectory:
+ return nsIFileFromOSType(kDesktopFolderType, aFile);
+
+ case Mac_TrashDirectory:
+ return nsIFileFromOSType(kTrashFolderType, aFile);
+
+ case Mac_StartupDirectory:
+ return nsIFileFromOSType(kStartupFolderType, aFile);
+
+ case Mac_ShutdownDirectory:
+ return nsIFileFromOSType(kShutdownFolderType, aFile);
+
+ case Mac_AppleMenuDirectory:
+ return nsIFileFromOSType(kAppleMenuFolderType, aFile);
+
+ case Mac_ControlPanelDirectory:
+ return nsIFileFromOSType(kControlPanelFolderType, aFile);
+
+ case Mac_ExtensionDirectory:
+ return nsIFileFromOSType(kExtensionFolderType, aFile);
+
+ case Mac_FontsDirectory:
+ return nsIFileFromOSType(kFontsFolderType, aFile);
+
+ case Mac_ClassicPreferencesDirectory:
+ {
+ // whether Mac OS X or pre-Mac OS X, return Classic's Prefs folder
+ short domain;
+ long response;
+ err = ::Gestalt(gestaltSystemVersion, &response);
+ domain = (!err && response >= 0x00001000) ? kClassicDomain : kOnSystemDisk;
+ err = ::FindFolder(domain, kPreferencesFolderType, true, &vRefNum, &dirID);
+ if (!err) {
+ err = ::FSMakeFSSpec(vRefNum, dirID, "\p", &mSpec);
+ }
+ return NS_FILE_RESULT(err);
+ }
+
+ case Mac_PreferencesDirectory:
+ {
+ // if Mac OS X, return Mac OS X's Prefs folder
+ // if pre-Mac OS X, return Mac OS's Prefs folder
+ err = ::FindFolder(kOnSystemDisk, kPreferencesFolderType, true, &vRefNum, &dirID);
+ if (!err) {
+ err = ::FSMakeFSSpec(vRefNum, dirID, "\p", &mSpec);
+ }
+ return NS_FILE_RESULT(err);
+ }
+
+ case Mac_DocumentsDirectory:
+ return nsIFileFromOSType(kDocumentsFolderType, aFile);
+
+ case Mac_InternetSearchDirectory:
+ return nsIFileFromOSType(kInternetSearchSitesFolderType, aFile);
+
+ case Mac_DefaultDownloadDirectory:
+ return nsIFileFromOSType(kDefaultDownloadFolderType, aFile);
+
+ case Mac_UserLibDirectory:
+ {
+ FSSpec spec;
+ err = ::FindFolder(kUserDomain, kDomainLibraryFolderType, true, &vRefNum, &dirID);
+ if (!err) {
+ err = ::FSMakeFSSpec(vRefNum, dirID, "\p", &spec);
+ }
+
+ return NS_NewLocalFileWithFSSpec(&spec, PR_FALUE, aFile);
+ }
+#endif
+
+#if defined (XP_WIN)
+ case Win_SystemDirectory:
+ {
+ char path[_MAX_PATH];
+ PRInt32 len = GetSystemDirectory( path, _MAX_PATH );
+
+ // Need enough space to add the trailing backslash
+ if (len > _MAX_PATH-2)
+ break;
+ path[len] = '\\';
+ path[len+1] = '\0';
+
+ return NS_NewNativeLocalFile(nsDependentCString(path),
+ PR_TRUE,
+ aFile);
+ }
+
+ case Win_WindowsDirectory:
+ {
+ char path[_MAX_PATH];
+ PRInt32 len = GetWindowsDirectory( path, _MAX_PATH );
+
+ // Need enough space to add the trailing backslash
+ if (len > _MAX_PATH-2)
+ break;
+
+ path[len] = '\\';
+ path[len+1] = '\0';
+
+ return NS_NewNativeLocalFile(nsDependentCString(path),
+ PR_TRUE,
+ aFile);
+ }
+
+ case Win_HomeDirectory:
+ {
+ char path[_MAX_PATH];
+ if (GetEnvironmentVariable(TEXT("HOME"), path, _MAX_PATH) > 0)
+ {
+ PRInt32 len = strlen(path);
+ // Need enough space to add the trailing backslash
+ if (len > _MAX_PATH - 2)
+ break;
+
+ path[len] = '\\';
+ path[len+1] = '\0';
+
+ return NS_NewNativeLocalFile(nsDependentCString(path),
+ PR_TRUE,
+ aFile);
+ }
+
+ if (GetEnvironmentVariable(TEXT("HOMEDRIVE"), path, _MAX_PATH) > 0)
+ {
+ char temp[_MAX_PATH];
+ if (GetEnvironmentVariable(TEXT("HOMEPATH"), temp, _MAX_PATH) > 0)
+ strncat(path, temp, _MAX_PATH);
+
+ PRInt32 len = strlen(path);
+
+ // Need enough space to add the trailing backslash
+ if (len > _MAX_PATH - 2)
+ break;
+
+ path[len] = '\\';
+ path[len+1] = '\0';
+
+ return NS_NewNativeLocalFile(nsDependentCString(path),
+ PR_TRUE,
+ aFile);
+ }
+ }
+ case Win_Desktop:
+ {
+ return GetWindowsFolder(CSIDL_DESKTOP, aFile);
+ }
+ case Win_Programs:
+ {
+ return GetWindowsFolder(CSIDL_PROGRAMS, aFile);
+ }
+ case Win_Controls:
+ {
+ return GetWindowsFolder(CSIDL_CONTROLS, aFile);
+ }
+ case Win_Printers:
+ {
+ return GetWindowsFolder(CSIDL_PRINTERS, aFile);
+ }
+ case Win_Personal:
+ {
+ return GetWindowsFolder(CSIDL_PERSONAL, aFile);
+ }
+ case Win_Favorites:
+ {
+ return GetWindowsFolder(CSIDL_FAVORITES, aFile);
+ }
+ case Win_Startup:
+ {
+ return GetWindowsFolder(CSIDL_STARTUP, aFile);
+ }
+ case Win_Recent:
+ {
+ return GetWindowsFolder(CSIDL_RECENT, aFile);
+ }
+ case Win_Sendto:
+ {
+ return GetWindowsFolder(CSIDL_SENDTO, aFile);
+ }
+ case Win_Bitbucket:
+ {
+ return GetWindowsFolder(CSIDL_BITBUCKET, aFile);
+ }
+ case Win_Startmenu:
+ {
+ return GetWindowsFolder(CSIDL_STARTMENU, aFile);
+ }
+ case Win_Desktopdirectory:
+ {
+ return GetWindowsFolder(CSIDL_DESKTOPDIRECTORY, aFile);
+ }
+ case Win_Drives:
+ {
+ return GetWindowsFolder(CSIDL_DRIVES, aFile);
+ }
+ case Win_Network:
+ {
+ return GetWindowsFolder(CSIDL_NETWORK, aFile);
+ }
+ case Win_Nethood:
+ {
+ return GetWindowsFolder(CSIDL_NETHOOD, aFile);
+ }
+ case Win_Fonts:
+ {
+ return GetWindowsFolder(CSIDL_FONTS, aFile);
+ }
+ case Win_Templates:
+ {
+ return GetWindowsFolder(CSIDL_TEMPLATES, aFile);
+ }
+ case Win_Common_Startmenu:
+ {
+ return GetWindowsFolder(CSIDL_COMMON_STARTMENU, aFile);
+ }
+ case Win_Common_Programs:
+ {
+ return GetWindowsFolder(CSIDL_COMMON_PROGRAMS, aFile);
+ }
+ case Win_Common_Startup:
+ {
+ return GetWindowsFolder(CSIDL_COMMON_STARTUP, aFile);
+ }
+ case Win_Common_Desktopdirectory:
+ {
+ return GetWindowsFolder(CSIDL_COMMON_DESKTOPDIRECTORY, aFile);
+ }
+ case Win_Appdata:
+ {
+ return GetWindowsFolder(CSIDL_APPDATA, aFile);
+ }
+ case Win_Printhood:
+ {
+ return GetWindowsFolder(CSIDL_PRINTHOOD, aFile);
+ }
+ case Win_Cookies:
+ {
+ return GetWindowsFolder(CSIDL_COOKIES, aFile);
+ }
+#endif // XP_WIN
+
+#if defined(XP_UNIX)
+ case Unix_LocalDirectory:
+ return NS_NewNativeLocalFile(nsDependentCString("/usr/local/netscape/"),
+ PR_TRUE,
+ aFile);
+ case Unix_LibDirectory:
+ return NS_NewNativeLocalFile(nsDependentCString("/usr/local/lib/netscape/"),
+ PR_TRUE,
+ aFile);
+
+ case Unix_HomeDirectory:
+#ifdef VMS
+ {
+ char *pHome;
+ pHome = getenv("HOME");
+ if (*pHome == '/') {
+ return NS_NewNativeLocalFile(nsDependentCString(pHome),
+ PR_TRUE,
+ aFile);
+
+ }
+ else
+ {
+ return NS_NewNativeLocalFile(nsDependentCString(decc$translate_vms(pHome)),
+ PR_TRUE,
+ aFile);
+ }
+ }
+#else
+ return NS_NewNativeLocalFile(nsDependentCString(PR_GetEnv("HOME")),
+ PR_TRUE,
+ aFile);
+
+#endif
+
+#endif
+
+#ifdef XP_BEOS
+ case BeOS_SettingsDirectory:
+ {
+ char path[MAXPATHLEN];
+ find_directory(B_USER_SETTINGS_DIRECTORY, 0, 0, path, MAXPATHLEN);
+ // Need enough space to add the trailing backslash
+ int len = strlen(path);
+ if (len > MAXPATHLEN-2)
+ break;
+ path[len] = '/';
+ path[len+1] = '\0';
+ return NS_NewNativeLocalFile(nsDependentCString(path),
+ PR_TRUE,
+ aFile);
+ }
+
+ case BeOS_HomeDirectory:
+ {
+ char path[MAXPATHLEN];
+ find_directory(B_USER_DIRECTORY, 0, 0, path, MAXPATHLEN);
+ // Need enough space to add the trailing backslash
+ int len = strlen(path);
+ if (len > MAXPATHLEN-2)
+ break;
+ path[len] = '/';
+ path[len+1] = '\0';
+
+ return NS_NewNativeLocalFile(nsDependentCString(path),
+ PR_TRUE,
+ aFile);
+ }
+
+ case BeOS_DesktopDirectory:
+ {
+ char path[MAXPATHLEN];
+ find_directory(B_DESKTOP_DIRECTORY, 0, 0, path, MAXPATHLEN);
+ // Need enough space to add the trailing backslash
+ int len = strlen(path);
+ if (len > MAXPATHLEN-2)
+ break;
+ path[len] = '/';
+ path[len+1] = '\0';
+
+ return NS_NewNativeLocalFile(nsDependentCString(path),
+ PR_TRUE,
+ aFile);
+ }
+
+ case BeOS_SystemDirectory:
+ {
+ char path[MAXPATHLEN];
+ find_directory(B_BEOS_DIRECTORY, 0, 0, path, MAXPATHLEN);
+ // Need enough space to add the trailing backslash
+ int len = strlen(path);
+ if (len > MAXPATHLEN-2)
+ break;
+ path[len] = '/';
+ path[len+1] = '\0';
+
+ return NS_NewNativeLocalFile(nsDependentCString(path),
+ PR_TRUE,
+ aFile);
+ }
+#endif
+#ifdef XP_OS2
+ case OS2_SystemDirectory:
+ {
+ ULONG ulBootDrive = 0;
+ char buffer[] = " :\\OS2\\System\\";
+ DosQuerySysInfo( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE,
+ &ulBootDrive, sizeof ulBootDrive);
+ buffer[0] = 'A' - 1 + ulBootDrive; // duh, 1-based index...
+
+ return NS_NewNativeLocalFile(nsDependentCString(buffer),
+ PR_TRUE,
+ aFile);
+ }
+
+ case OS2_OS2Directory:
+ {
+ ULONG ulBootDrive = 0;
+ char buffer[] = " :\\OS2\\";
+ DosQuerySysInfo( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE,
+ &ulBootDrive, sizeof ulBootDrive);
+ buffer[0] = 'A' - 1 + ulBootDrive; // duh, 1-based index...
+
+ return NS_NewNativeLocalFile(nsDependentCString(buffer),
+ PR_TRUE,
+ aFile);
+ }
+
+ case OS2_HomeDirectory:
+ {
+ nsresult rv;
+ char *tPath = PR_GetEnv("MOZILLA_HOME");
+ char buffer[CCHMAXPATH];
+ /* If MOZILLA_HOME is not set, use GetCurrentProcessDirectory */
+ /* To ensure we get a long filename system */
+ if (!tPath || !*tPath) {
+ PPIB ppib;
+ PTIB ptib;
+ DosGetInfoBlocks( &ptib, &ppib);
+ DosQueryModuleName( ppib->pib_hmte, CCHMAXPATH, buffer);
+ *strrchr( buffer, '\\') = '\0'; // XXX DBCS misery
+ tPath = buffer;
+ }
+ rv = NS_NewNativeLocalFile(nsDependentCString(tPath),
+ PR_TRUE,
+ aFile);
+
+ PrfWriteProfileString(HINI_USERPROFILE, "Mozilla", "Home", tPath);
+ return rv;
+ }
+
+ case OS2_DesktopDirectory:
+ {
+ char szPath[CCHMAXPATH + 1];
+ BOOL fSuccess;
+ fSuccess = WinQueryActiveDesktopPathname (szPath, sizeof(szPath));
+ int len = strlen (szPath);
+ if (len > CCHMAXPATH -1)
+ break;
+ szPath[len] = '\\';
+ szPath[len + 1] = '\0';
+
+ return NS_NewNativeLocalFile(nsDependentCString(szPath),
+ PR_TRUE,
+ aFile);
+ }
+#endif
+ default:
+ break;
+ }
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+#if defined (XP_MACOSX)
+nsresult
+GetOSXFolderType(short aDomain, OSType aFolderType, nsILocalFile **localFile)
+{
+ OSErr err;
+ FSRef fsRef;
+ nsresult rv = NS_ERROR_FAILURE;
+
+ err = ::FSFindFolder(aDomain, aFolderType, kCreateFolder, &fsRef);
+ if (err == noErr)
+ {
+ NS_NewLocalFile(EmptyString(), PR_TRUE, localFile);
+ nsCOMPtr<nsILocalFileMac> localMacFile(do_QueryInterface(*localFile));
+ if (localMacFile)
+ rv = localMacFile->InitWithFSRef(&fsRef);
+ }
+ return rv;
+}
+#endif
+
diff --git a/src/libs/xpcom18a4/xpcom/io/SpecialSystemDirectory.h b/src/libs/xpcom18a4/xpcom/io/SpecialSystemDirectory.h
new file mode 100644
index 00000000..b4aaf30e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/SpecialSystemDirectory.h
@@ -0,0 +1,136 @@
+/* -*- 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 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):
+ * Doug Turner <dougt@netscape.com>
+ * IBM Corp.
+ *
+ * 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 _SPECIALSYSTEMDIRECTORY_H_
+#define _SPECIALSYSTEMDIRECTORY_H_
+
+#include "nscore.h"
+#include "nsILocalFile.h"
+
+#if defined(XP_MAC) || defined(XP_MACOSX)
+# ifndef VBOX_WITH_NEWER_OSX_SDK
+# include <Types.h>
+# endif
+#include "nsILocalFileMac.h"
+#include "prenv.h"
+#endif
+
+
+extern NS_COM void StartupSpecialSystemDirectory();
+extern NS_COM void ShutdownSpecialSystemDirectory();
+
+
+enum SystemDirectories {
+ OS_DriveDirectory = 1,
+ OS_TemporaryDirectory = 2,
+ OS_CurrentProcessDirectory= 3,
+ OS_CurrentWorkingDirectory= 4,
+ XPCOM_CurrentProcessComponentDirectory= 5,
+ XPCOM_CurrentProcessComponentRegistry= 6,
+
+ Moz_BinDirectory = 100 ,
+ Mac_SystemDirectory = 101,
+ Mac_DesktopDirectory = 102,
+ Mac_TrashDirectory = 103,
+ Mac_StartupDirectory = 104,
+ Mac_ShutdownDirectory = 105,
+ Mac_AppleMenuDirectory = 106,
+ Mac_ControlPanelDirectory = 107,
+ Mac_ExtensionDirectory = 108,
+ Mac_FontsDirectory = 109,
+ Mac_ClassicPreferencesDirectory = 110,
+ Mac_DocumentsDirectory = 111,
+ Mac_InternetSearchDirectory = 112,
+ Mac_DefaultDownloadDirectory = 113,
+ Mac_UserLibDirectory = 114,
+ Mac_PreferencesDirectory = 115,
+
+ Win_SystemDirectory = 201,
+ Win_WindowsDirectory = 202,
+ Win_HomeDirectory = 203,
+ Win_Desktop = 204,
+ Win_Programs = 205,
+ Win_Controls = 206,
+ Win_Printers = 207,
+ Win_Personal = 208,
+ Win_Favorites = 209,
+ Win_Startup = 210,
+ Win_Recent = 211,
+ Win_Sendto = 212,
+ Win_Bitbucket = 213,
+ Win_Startmenu = 214,
+ Win_Desktopdirectory = 215,
+ Win_Drives = 216,
+ Win_Network = 217,
+ Win_Nethood = 218,
+ Win_Fonts = 219,
+ Win_Templates = 220,
+ Win_Common_Startmenu = 221,
+ Win_Common_Programs = 222,
+ Win_Common_Startup = 223,
+ Win_Common_Desktopdirectory = 224,
+ Win_Appdata = 225,
+ Win_Printhood = 226,
+ Win_Cookies = 227,
+
+ Unix_LocalDirectory = 301,
+ Unix_LibDirectory = 302,
+ Unix_HomeDirectory = 303,
+
+ BeOS_SettingsDirectory = 401,
+ BeOS_HomeDirectory = 402,
+ BeOS_DesktopDirectory = 403,
+ BeOS_SystemDirectory = 404,
+
+ OS2_SystemDirectory = 501,
+ OS2_OS2Directory = 502,
+ OS2_DesktopDirectory = 503,
+ OS2_HomeDirectory = 504
+};
+
+nsresult
+GetSpecialSystemDirectory(SystemDirectories aSystemSystemDirectory,
+ nsILocalFile** aFile);
+#if defined(XP_MACOSX)
+nsresult
+GetOSXFolderType(short aDomain, OSType aFolderType, nsILocalFile **localFile);
+#endif
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/io/macDirectoryCopy.c b/src/libs/xpcom18a4/xpcom/io/macDirectoryCopy.c
new file mode 100644
index 00000000..838dffa2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/macDirectoryCopy.c
@@ -0,0 +1,784 @@
+/*
+** Apple Macintosh Developer Technical Support
+**
+** DirectoryCopy: A robust, general purpose directory copy routine.
+**
+** by Jim Luther, Apple Developer Technical Support Emeritus
+**
+** File: DirectoryCopy.c
+**
+** Copyright © 1992-1998 Apple Computer, Inc.
+** All rights reserved.
+**
+** You may incorporate this sample code into your applications without
+** restriction, though the sample code has been provided "AS IS" and the
+** responsibility for its operation is 100% yours. However, what you are
+** not permitted to do is to redistribute the source as "DSC Sample Code"
+** after having made changes. If you're going to re-distribute the source,
+** we require that you make it clear in the source that the code was
+** descended from Apple Sample Code, but that you've made changes.
+*/
+
+// Modified to allow renaming the destination folder
+
+#include <Types.h>
+#include <Errors.h>
+#include <Memory.h>
+#include <Files.h>
+#include <Script.h>
+
+#define __COMPILINGMOREFILES
+
+#include "MoreFiles.h"
+#include "MoreFilesExtras.h"
+#include "MoreDesktopMgr.h"
+#include "FileCopy.h"
+#include "MacDirectoryCopy.h"
+#include <string.h>
+
+
+/*****************************************************************************/
+
+enum
+{
+ getNextItemOp = 1, /* couldn't access items in this directory - no access privileges */
+ copyDirCommentOp = 2, /* couldn't copy directory's Finder comment */
+ copyDirAccessPrivsOp = 3, /* couldn't copy directory's AFP access privileges */
+ copyDirFMAttributesOp = 4, /* couldn't copy directory's File Manager attributes */
+ dirCreateOp = 5, /* couldn't create destination directory */
+ fileCopyOp = 6 /* couldn't copy file */
+};
+
+/*****************************************************************************/
+
+
+
+#define CallCopyErrProc(userRoutine, error, failedOperation, srcVRefNum, srcDirID, srcName, dstVRefNum, dstDirID, dstName) \
+ (*(userRoutine))((error), (failedOperation), (srcVRefNum), (srcDirID), (srcName), (dstVRefNum), (dstDirID), (dstName))
+
+/*****************************************************************************/
+
+typedef pascal Boolean (*CopyFilterProcPtr) (const CInfoPBRec * const cpbPtr);
+
+/* ¦ Prototype for the CopyFilterProc function.
+ This is the prototype for the CopyFilterProc function called by
+ FilteredDirectoryCopy and GetLevelSize. If true is returned,
+ the file/folder is included in the copy, otherwise it is excluded.
+
+ pb input: Points to the CInfoPBRec for the item under consideration.
+
+ __________
+
+ Also see: FilteredDirectoryCopy, FSpFilteredDirectoryCopy
+*/
+
+#define CallCopyFilterProc(userRoutine, cpbPtr) (*(userRoutine))((cpbPtr))
+
+
+
+/*****************************************************************************/
+
+/* local constants */
+
+enum
+{
+ dirCopyBigCopyBuffSize = 0x00004000,
+ dirCopyMinCopyBuffSize = 0x00000200
+};
+
+
+/*****************************************************************************/
+
+/* local data structures */
+
+/* The EnumerateGlobals structure is used to minimize the amount of
+** stack space used when recursively calling CopyLevel and to hold
+** global information that might be needed at any time. */
+
+#if PRAGMA_STRUCT_ALIGN
+#pragma options align=mac68k
+#endif
+struct EnumerateGlobals
+{
+ Ptr copyBuffer; /* pointer to buffer used for file copy operations */
+ long bufferSize; /* the size of the copy buffer */
+ CopyErrProcPtr errorHandler; /* pointer to error handling function */
+ CopyFilterProcPtr copyFilterProc; /* pointer to filter function */
+ OSErr error; /* temporary holder of results - saves 2 bytes of stack each level */
+ Boolean bailout; /* set to true to by error handling function if fatal error */
+ short destinationVRefNum; /* the destination vRefNum */
+ Str63 itemName; /* the name of the current item */
+ CInfoPBRec myCPB; /* the parameter block used for PBGetCatInfo calls */
+};
+#if PRAGMA_STRUCT_ALIGN
+#pragma options align=reset
+#endif
+
+typedef struct EnumerateGlobals EnumerateGlobals;
+typedef EnumerateGlobals *EnumerateGlobalsPtr;
+
+
+/* The PreflightGlobals structure is used to minimize the amount of
+** stack space used when recursively calling GetLevelSize and to hold
+** global information that might be needed at any time. */
+
+#if PRAGMA_STRUCT_ALIGN
+#pragma options align=mac68k
+#endif
+struct PreflightGlobals
+{
+ OSErr result; /* temporary holder of results - saves 2 bytes of stack each level */
+ Str63 itemName; /* the name of the current item */
+ CInfoPBRec myCPB; /* the parameter block used for PBGetCatInfo calls */
+
+ unsigned long dstBlksPerAllocBlk; /* the number of 512 byte blocks per allocation block on destination */
+
+ unsigned long allocBlksNeeded; /* the total number of allocation blocks needed */
+
+ unsigned long tempBlocks; /* temporary storage for calculations (save some stack space) */
+ CopyFilterProcPtr copyFilterProc; /* pointer to filter function */
+};
+#if PRAGMA_STRUCT_ALIGN
+#pragma options align=reset
+#endif
+
+typedef struct PreflightGlobals PreflightGlobals;
+typedef PreflightGlobals *PreflightGlobalsPtr;
+
+/*****************************************************************************/
+
+/* static prototypes */
+
+static void GetLevelSize(long currentDirID,
+ PreflightGlobals *theGlobals);
+
+static OSErr PreflightDirectoryCopySpace(short srcVRefNum,
+ long srcDirID,
+ short dstVRefNum,
+ CopyFilterProcPtr copyFilterProc,
+ Boolean *spaceOK);
+
+static void CopyLevel(long sourceDirID,
+ long dstDirID,
+ EnumerateGlobals *theGlobals);
+
+/*****************************************************************************/
+
+static void GetLevelSize(long currentDirID,
+ PreflightGlobals *theGlobals)
+{
+ short index = 1;
+
+ do
+ {
+ theGlobals->myCPB.dirInfo.ioFDirIndex = index;
+ theGlobals->myCPB.dirInfo.ioDrDirID = currentDirID; /* we need to do this every time */
+ /* through, since GetCatInfo */
+ /* returns ioFlNum in this field */
+ theGlobals->result = PBGetCatInfoSync(&theGlobals->myCPB);
+ if ( theGlobals->result == noErr )
+ {
+ if ( (theGlobals->copyFilterProc == NULL) ||
+ CallCopyFilterProc(theGlobals->copyFilterProc, &theGlobals->myCPB) ) /* filter if filter proc was supplied */
+ {
+ /* Either there's no filter proc OR the filter proc says to use this item */
+ if ( (theGlobals->myCPB.dirInfo.ioFlAttrib & ioDirMask) != 0 )
+ {
+ /* we have a directory */
+
+ GetLevelSize(theGlobals->myCPB.dirInfo.ioDrDirID, theGlobals); /* recurse */
+ theGlobals->result = noErr; /* clear error return on way back */
+ }
+ else
+ {
+ /* We have a file - add its allocation blocks to allocBlksNeeded. */
+ /* Since space on Mac OS disks is always allocated in allocation blocks, */
+ /* this takes into account rounding up to the end of an allocation block. */
+
+ /* get number of 512-byte blocks needed for data fork */
+ if ( ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlLgLen & 0x000001ff) != 0 )
+ {
+ theGlobals->tempBlocks = ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlLgLen >> 9) + 1;
+ }
+ else
+ {
+ theGlobals->tempBlocks = (unsigned long)theGlobals->myCPB.hFileInfo.ioFlLgLen >> 9;
+ }
+ /* now, calculate number of new allocation blocks needed for the data fork and add it to the total */
+ if ( theGlobals->tempBlocks % theGlobals->dstBlksPerAllocBlk )
+ {
+ theGlobals->allocBlksNeeded += (theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk) + 1;
+ }
+ else
+ {
+ theGlobals->allocBlksNeeded += theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk;
+ }
+
+ /* get number of 512-byte blocks needed for resource fork */
+ if ( ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlRLgLen & 0x000001ff) != 0 )
+ {
+ theGlobals->tempBlocks = ((unsigned long)theGlobals->myCPB.hFileInfo.ioFlRLgLen >> 9) + 1;
+ }
+ else
+ {
+ theGlobals->tempBlocks = (unsigned long)theGlobals->myCPB.hFileInfo.ioFlRLgLen >> 9;
+ }
+ /* now, calculate number of new allocation blocks needed for the resource fork and add it to the total */
+ if ( theGlobals->tempBlocks % theGlobals->dstBlksPerAllocBlk )
+ {
+ theGlobals->allocBlksNeeded += (theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk) + 1;
+ }
+ else
+ {
+ theGlobals->allocBlksNeeded += theGlobals->tempBlocks / theGlobals->dstBlksPerAllocBlk;
+ }
+ }
+ }
+ }
+ ++index;
+ } while ( theGlobals->result == noErr );
+}
+
+/*****************************************************************************/
+
+static OSErr PreflightDirectoryCopySpace(short srcVRefNum,
+ long srcDirID,
+ short dstVRefNum,
+ CopyFilterProcPtr copyFilterProc,
+ Boolean *spaceOK)
+{
+ XVolumeParam pb;
+ OSErr error;
+ unsigned long dstFreeBlocks;
+ PreflightGlobals theGlobals;
+
+ error = XGetVolumeInfoNoName(NULL, dstVRefNum, &pb);
+ if ( error == noErr )
+ {
+ /* Convert freeBytes to free disk blocks (512-byte blocks) */
+#if (UNIVERSAL_INTERFACES_VERSION >= 0x0330)
+ dstFreeBlocks = (pb.ioVFreeBytes >> 9);
+#else
+ dstFreeBlocks = (pb.ioVFreeBytes.hi << 23) + (pb.ioVFreeBytes.lo >> 9);
+#endif
+ /* get allocation block size (always multiple of 512) and divide by 512
+ to get number of 512-byte blocks per allocation block */
+ theGlobals.dstBlksPerAllocBlk = ((unsigned long)pb.ioVAlBlkSiz >> 9);
+
+ theGlobals.allocBlksNeeded = 0;
+
+ theGlobals.myCPB.dirInfo.ioNamePtr = theGlobals.itemName;
+ theGlobals.myCPB.dirInfo.ioVRefNum = srcVRefNum;
+
+ theGlobals.copyFilterProc = copyFilterProc;
+
+ GetLevelSize(srcDirID, &theGlobals);
+
+ /* Is there enough room on the destination volume for the source file? */
+ /* Note: This will work because the largest number of disk blocks supported */
+ /* on a 2TB volume is 0xffffffff and (allocBlksNeeded * dstBlksPerAllocBlk) */
+ /* will always be less than 0xffffffff. */
+ *spaceOK = ((theGlobals.allocBlksNeeded * theGlobals.dstBlksPerAllocBlk) <= dstFreeBlocks);
+ }
+
+ return ( error );
+}
+
+/*****************************************************************************/
+
+static void CopyLevel(long sourceDirID,
+ long dstDirID,
+ EnumerateGlobals *theGlobals)
+{
+ long currentSrcDirID;
+ long newDirID;
+ short index = 1;
+
+ do
+ {
+ /* Get next source item at the current directory level */
+
+ theGlobals->myCPB.dirInfo.ioFDirIndex = index;
+ theGlobals->myCPB.dirInfo.ioDrDirID = sourceDirID;
+ theGlobals->error = PBGetCatInfoSync(&theGlobals->myCPB);
+
+ if ( theGlobals->error == noErr )
+ {
+ if ( (theGlobals->copyFilterProc == NULL) ||
+ CallCopyFilterProc(theGlobals->copyFilterProc, &theGlobals->myCPB) ) /* filter if filter proc was supplied */
+ {
+ /* Either there's no filter proc OR the filter proc says to use this item */
+
+ /* We have an item. Is it a file or directory? */
+ if ( (theGlobals->myCPB.hFileInfo.ioFlAttrib & ioDirMask) != 0 )
+ {
+ /* We have a directory */
+
+ /* Create a new directory at the destination. No errors allowed! */
+ theGlobals->error = DirCreate(theGlobals->destinationVRefNum, dstDirID, theGlobals->itemName, &newDirID);
+ if ( theGlobals->error == noErr )
+ {
+ /* Save the current source directory ID where we can get it when we come back
+ ** from recursion land. */
+ currentSrcDirID = theGlobals->myCPB.dirInfo.ioDrDirID;
+
+ /* Dive again (copy the directory level we just found below this one) */
+ CopyLevel(theGlobals->myCPB.dirInfo.ioDrDirID, newDirID, theGlobals);
+
+ if ( !theGlobals->bailout )
+ {
+ /* Copy comment from old to new directory. */
+ /* Ignore the result because we really don't care if it worked or not. */
+ (void) DTCopyComment(theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL, theGlobals->destinationVRefNum, newDirID, NULL);
+
+ /* Copy directory attributes (dates, etc.) to newDirID. */
+ /* No errors allowed */
+ theGlobals->error = CopyFileMgrAttributes(theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL, theGlobals->destinationVRefNum, newDirID, NULL, true);
+
+ /* handle any errors from CopyFileMgrAttributes */
+ if ( theGlobals->error != noErr )
+ {
+ if ( theGlobals->errorHandler != NULL )
+ {
+ theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, copyDirFMAttributesOp,
+ theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL,
+ theGlobals->destinationVRefNum, newDirID, NULL);
+ }
+ else
+ {
+ /* If you don't handle the errors with an error handler, */
+ /* then the copy stops here. */
+ theGlobals->bailout = true;
+ }
+ }
+ }
+ }
+ else /* error handling for DirCreate */
+ {
+ if ( theGlobals->errorHandler != NULL )
+ {
+ theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, dirCreateOp,
+ theGlobals->myCPB.dirInfo.ioVRefNum, currentSrcDirID, NULL,
+ theGlobals->destinationVRefNum, dstDirID, theGlobals->itemName);
+ }
+ else
+ {
+ /* If you don't handle the errors with an error handler, */
+ /* then the copy stops here. */
+ theGlobals->bailout = true;
+ }
+ }
+
+ if ( !theGlobals->bailout )
+ {
+ /* clear error return on way back if we aren't bailing out */
+ theGlobals->error = noErr;
+ }
+ }
+ else
+ {
+ /* We have a file, so copy it */
+
+ theGlobals->error = FileCopy(theGlobals->myCPB.hFileInfo.ioVRefNum,
+ theGlobals->myCPB.hFileInfo.ioFlParID,
+ theGlobals->itemName,
+ theGlobals->destinationVRefNum,
+ dstDirID,
+ NULL,
+ NULL,
+ theGlobals->copyBuffer,
+ theGlobals->bufferSize,
+ false);
+
+ /* handle any errors from FileCopy */
+ if ( theGlobals->error != noErr )
+ {
+ if ( theGlobals->errorHandler != NULL )
+ {
+ theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, fileCopyOp,
+ theGlobals->myCPB.hFileInfo.ioVRefNum, theGlobals->myCPB.hFileInfo.ioFlParID, theGlobals->itemName,
+ theGlobals->destinationVRefNum, dstDirID, NULL);
+ if ( !theGlobals->bailout )
+ {
+ /* If the CopyErrProc handled the problem, clear the error here */
+ theGlobals->error = noErr;
+ }
+ }
+ else
+ {
+ /* If you don't handle the errors with an error handler, */
+ /* then the copy stops here. */
+ theGlobals->bailout = true;
+ }
+ }
+ }
+ }
+ }
+ else
+ { /* error handling for PBGetCatInfo */
+ /* it's normal to get a fnfErr when indexing; that only means you've hit the end of the directory */
+ if ( theGlobals->error != fnfErr )
+ {
+ if ( theGlobals->errorHandler != NULL )
+ {
+ theGlobals->bailout = CallCopyErrProc(theGlobals->errorHandler, theGlobals->error, getNextItemOp,
+ theGlobals->myCPB.dirInfo.ioVRefNum, sourceDirID, NULL, 0, 0, NULL);
+ if ( !theGlobals->bailout )
+ {
+ /* If the CopyErrProc handled the problem, clear the error here */
+ theGlobals->error = noErr;
+ }
+ }
+ else
+ {
+ /* If you don't handle the errors with an error handler, */
+ /* then the copy stops here. */
+ theGlobals->bailout = true;
+ }
+ }
+ }
+ ++index; /* prepare to get next item */
+ } while ( (theGlobals->error == noErr) && (!theGlobals->bailout) ); /* time to fall back a level? */
+}
+
+/*****************************************************************************/
+
+pascal OSErr FilteredDirectoryCopy(short srcVRefNum,
+ long srcDirID,
+ ConstStr255Param srcName,
+ short dstVRefNum,
+ long dstDirID,
+ ConstStr255Param dstName,
+ void *copyBufferPtr,
+ long copyBufferSize,
+ Boolean preflight,
+ CopyErrProcPtr copyErrHandler,
+ CopyFilterProcPtr copyFilterProc, ConstStr255Param newName );
+/* ¦ Make a copy of a directory structure in a new location with item filtering.
+ The FilteredDirectoryCopy function makes a copy of a directory
+ structure in a new location. If copyBufferPtr <> NIL, it points to
+ a buffer of copyBufferSize that is used to copy files data. The
+ larger the supplied buffer, the faster the copy. If
+ copyBufferPtr = NIL, then this routine allocates a buffer in the
+ application heap. If you pass a copy buffer to this routine, make
+ its size a multiple of 512 ($200) bytes for optimum performance.
+
+ The optional copyFilterProc parameter lets a routine you define
+ decide what files or directories are copied to the destination.
+
+ FilteredDirectoryCopy normally creates a new directory *in* the
+ specified destination directory and copies the source directory's
+ content into the new directory. However, if root parent directory
+ (fsRtParID) is passed as the dstDirID parameter and NULL is
+ passed as the dstName parameter, DirectoryCopy renames the
+ destination volume to the source directory's name (truncating
+ if the name is longer than 27 characters) and copies the source
+ directory's content into the destination volume's root directory.
+ This special case is supported by FilteredDirectoryCopy, but
+ not by FSpFilteredDirectoryCopy since with FSpFilteredDirectoryCopy,
+ the dstName parameter can not be NULL.
+
+ srcVRefNum input: Source volume specification.
+ srcDirID input: Source directory ID.
+ srcName input: Source directory name, or nil if
+ srcDirID specifies the directory.
+ dstVRefNum input: Destination volume specification.
+ dstDirID input: Destination directory ID.
+ dstName input: Destination directory name, or nil if
+ dstDirID specifies the directory.
+ copyBufferPtr input: Points to a buffer of copyBufferSize that
+ is used the i/o buffer for the copy or
+ nil if you want DirectoryCopy to allocate its
+ own buffer in the application heap.
+ copyBufferSize input: The size of the buffer pointed to
+ by copyBufferPtr.
+ preflight input: If true, DirectoryCopy makes sure there are
+ enough allocation blocks on the destination
+ volume to hold the directory's files before
+ starting the copy.
+ copyErrHandler input: A pointer to the routine you want called if an
+ error condition is detected during the copy, or
+ nil if you don't want to handle error conditions.
+ If you don't handle error conditions, the first
+ error will cause the copy to quit and
+ DirectoryCopy will return the error.
+ Error handling is recommended...
+ copyFilterProc input: A pointer to the filter routine you want called
+ for each item in the source directory, or NULL
+ if you don't want to filter.
+
+ Result Codes
+ noErr 0 No error
+ readErr Ð19 Driver does not respond to read requests
+ writErr Ð20 Driver does not respond to write requests
+ badUnitErr Ð21 Driver reference number does not
+ match unit table
+ unitEmptyErr Ð22 Driver reference number specifies a
+ nil handle in unit table
+ abortErr Ð27 Request aborted by KillIO
+ notOpenErr Ð28 Driver not open
+ dskFulErr -34 Destination volume is full
+ nsvErr -35 No such volume
+ ioErr -36 I/O error
+ bdNamErr -37 Bad filename
+ tmfoErr -42 Too many files open
+ fnfErr -43 Source file not found, or destination
+ directory does not exist
+ wPrErr -44 Volume locked by hardware
+ fLckdErr -45 File is locked
+ vLckdErr -46 Destination volume is read-only
+ fBsyErr -47 The source or destination file could
+ not be opened with the correct access
+ modes
+ dupFNErr -48 Destination file already exists
+ opWrErr -49 File already open for writing
+ paramErr -50 No default volume or function not
+ supported by volume
+ permErr -54 File is already open and cannot be opened using specified deny modes
+ memFullErr -108 Copy buffer could not be allocated
+ dirNFErr -120 Directory not found or incomplete pathname
+ wrgVolTypErr -123 Function not supported by volume
+ afpAccessDenied -5000 User does not have the correct access
+ afpDenyConflict -5006 The source or destination file could
+ not be opened with the correct access
+ modes
+ afpObjectTypeErr -5025 Source is a directory, directory not found
+ or incomplete pathname
+
+ __________
+
+ Also see: CopyErrProcPtr, CopyFilterProcPtr, FSpFilteredDirectoryCopy,
+ DirectoryCopy, FSpDirectoryCopy, FileCopy, FSpFileCopy
+*/
+
+/*****************************************************************************/
+
+pascal OSErr FilteredDirectoryCopy(short srcVRefNum,
+ long srcDirID,
+ ConstStr255Param srcName,
+ short dstVRefNum,
+ long dstDirID,
+ ConstStr255Param dstName,
+ void *copyBufferPtr,
+ long copyBufferSize,
+ Boolean preflight,
+ CopyErrProcPtr copyErrHandler,
+ CopyFilterProcPtr copyFilterProc, ConstStr255Param newName)
+{
+ EnumerateGlobals theGlobals;
+ Boolean isDirectory;
+ OSErr error;
+ Boolean ourCopyBuffer = false;
+ Str63 srcDirName, oldDiskName;
+ Boolean spaceOK;
+
+ /* Make sure a copy buffer is allocated. */
+ if ( copyBufferPtr == NULL )
+ {
+ /* The caller didn't supply a copy buffer so grab one from the application heap.
+ ** Try to get a big copy buffer, if we can't, try for a 512-byte buffer.
+ ** If 512 bytes aren't available, we're in trouble. */
+ copyBufferSize = dirCopyBigCopyBuffSize;
+ copyBufferPtr = NewPtr(copyBufferSize);
+ if ( copyBufferPtr == NULL )
+ {
+ copyBufferSize = dirCopyMinCopyBuffSize;
+ copyBufferPtr = NewPtr(copyBufferSize);
+ if ( copyBufferPtr == NULL )
+ {
+ return ( memFullErr );
+ }
+ }
+ ourCopyBuffer = true;
+ }
+
+ /* Get the real dirID where we're copying from and make sure it is a directory. */
+ error = GetDirectoryID(srcVRefNum, srcDirID, srcName, &srcDirID, &isDirectory);
+ if ( error != noErr )
+ {
+ goto ErrorExit;
+ }
+ if ( !isDirectory )
+ {
+ error = dirNFErr;
+ goto ErrorExit;
+ }
+
+ /* Special case destination if it is the root parent directory. */
+ /* Since you can't create the root directory, this is needed if */
+ /* you want to copy a directory's content to a disk's root directory. */
+ if ( (dstDirID == fsRtParID) && (dstName == NULL) )
+ {
+ dstDirID = fsRtParID;
+ isDirectory = true;
+ error = noErr;
+ }
+ else
+ {
+ /* Get the real dirID where we're going to put the copy and make sure it is a directory. */
+ error = GetDirectoryID(dstVRefNum, dstDirID, dstName, &dstDirID, &isDirectory);
+ if ( error != noErr )
+ {
+ goto ErrorExit;
+ }
+ if ( !isDirectory )
+ {
+ error = dirNFErr;
+ goto ErrorExit;
+ }
+ }
+
+ /* Get the real vRefNum of both the source and destination */
+ error = DetermineVRefNum(srcName, srcVRefNum, &srcVRefNum);
+ if ( error != noErr )
+ {
+ goto ErrorExit;
+ }
+ error = DetermineVRefNum(dstName, dstVRefNum, &dstVRefNum);
+ if ( error != noErr )
+ {
+ goto ErrorExit;
+ }
+
+ if ( preflight )
+ {
+ error = PreflightDirectoryCopySpace(srcVRefNum, srcDirID, dstVRefNum, copyFilterProc, &spaceOK);
+ if ( error != noErr )
+ {
+ goto ErrorExit;
+ }
+ if ( !spaceOK )
+ {
+ error = dskFulErr; /* not enough room on destination */
+ goto ErrorExit;
+ }
+ }
+
+ /* Create the new directory in the destination directory with the */
+ /* same name as the source directory. */
+ /*
+ if newName is not empty use it rather than the original dir name.
+ */
+ if ( newName[0] == 0 )
+ {
+ error = GetDirName(srcVRefNum, srcDirID, srcDirName);
+ if ( error != noErr )
+ {
+ goto ErrorExit;
+ }
+ }
+ else
+ {
+ memcpy(srcDirName, newName, 32 );
+
+ }
+ /* Again, special case destination if the destination is the */
+ /* root parent directory. This time, we'll rename the disk to */
+ /* the source directory name. */
+ if ( dstDirID == fsRtParID )
+ {
+ /* Get the current name of the destination disk */
+ error = GetDirName(dstVRefNum, fsRtDirID, oldDiskName);
+ if ( error == noErr )
+ {
+ /* Shorten the name if it's too long to be the volume name */
+ TruncPString(srcDirName, srcDirName, 27);
+
+ /* Rename the disk */
+ error = HRename(dstVRefNum, fsRtParID, oldDiskName, srcDirName);
+ /* and copy to the root directory */
+ dstDirID = fsRtDirID;
+ }
+ }
+ else
+ {
+ error = DirCreate(dstVRefNum, dstDirID, srcDirName, &dstDirID);
+ }
+ if ( error != noErr )
+ {
+ /* handle any errors from DirCreate */
+ if ( copyErrHandler != NULL )
+ {
+ if ( CallCopyErrProc(copyErrHandler, error, dirCreateOp,
+ srcVRefNum, srcDirID, NULL,
+ dstVRefNum, dstDirID, srcDirName) )
+ {
+ goto ErrorExit;
+ }
+ else
+ {
+ /* If the CopyErrProc handled the problem, clear the error here */
+ /* and continue */
+ error = noErr;
+ }
+ }
+ else
+ {
+ /* If you don't handle the errors with an error handler, */
+ /* then the copy stops here. */
+ goto ErrorExit;
+ }
+ }
+
+ /* dstDirID is now the newly created directory! */
+
+ /* Set up the globals we need to access from the recursive routine. */
+ theGlobals.copyBuffer = (Ptr)copyBufferPtr;
+ theGlobals.bufferSize = copyBufferSize;
+ theGlobals.destinationVRefNum = dstVRefNum; /* so we can get to it always */
+ theGlobals.myCPB.hFileInfo.ioNamePtr = (StringPtr)&theGlobals.itemName;
+ theGlobals.myCPB.hFileInfo.ioVRefNum = srcVRefNum;
+ theGlobals.errorHandler = copyErrHandler;
+ theGlobals.bailout = false;
+ theGlobals.copyFilterProc = copyFilterProc;
+
+ /* Here we go into recursion land... */
+ CopyLevel(srcDirID, dstDirID, &theGlobals);
+ error = theGlobals.error; /* get the result */
+
+ if ( !theGlobals.bailout )
+ {
+ /* Copy comment from source to destination directory. */
+ /* Ignore the result because we really don't care if it worked or not. */
+ (void) DTCopyComment(srcVRefNum, srcDirID, NULL, dstVRefNum, dstDirID, NULL);
+
+ /* Copy the File Manager attributes */
+ error = CopyFileMgrAttributes(srcVRefNum, srcDirID, NULL,
+ dstVRefNum, dstDirID, NULL, true);
+
+ /* handle any errors from CopyFileMgrAttributes */
+ if ( (error != noErr) && (copyErrHandler != NULL) )
+ {
+ theGlobals.bailout = CallCopyErrProc(copyErrHandler, error, copyDirFMAttributesOp,
+ srcVRefNum, srcDirID, NULL,
+ dstVRefNum, dstDirID, NULL);
+ }
+ }
+
+ErrorExit:
+ /* Get rid of the copy buffer if we allocated it. */
+ if ( ourCopyBuffer )
+ {
+ DisposePtr((Ptr)copyBufferPtr);
+ }
+
+ return ( error );
+}
+
+
+/*****************************************************************************/
+
+
+pascal OSErr MacFSpDirectoryCopyRename(const FSSpec *srcSpec,
+ const FSSpec *dstSpec,
+ ConstStr255Param newName,
+ void *copyBufferPtr,
+ long copyBufferSize,
+ Boolean preflight,
+ CopyErrProcPtr copyErrHandler)
+{
+ return ( FilteredDirectoryCopy(srcSpec->vRefNum, srcSpec->parID, srcSpec->name,
+ dstSpec->vRefNum, dstSpec->parID, dstSpec->name,
+ copyBufferPtr, copyBufferSize, preflight,
+ copyErrHandler, NULL, newName) );
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/macDirectoryCopy.h b/src/libs/xpcom18a4/xpcom/io/macDirectoryCopy.h
new file mode 100644
index 00000000..361c820e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/macDirectoryCopy.h
@@ -0,0 +1,158 @@
+/*
+** Apple Macintosh Developer Technical Support
+**
+** DirectoryCopy: A robust, general purpose directory copy routine.
+**
+** by Jim Luther, Apple Developer Technical Support Emeritus
+**
+** File: DirectoryCopy.h
+**
+** Copyright © 1992-1998 Apple Computer, Inc.
+** All rights reserved.
+**
+** You may incorporate this sample code into your applications without
+** restriction, though the sample code has been provided "AS IS" and the
+** responsibility for its operation is 100% yours. However, what you are
+** not permitted to do is to redistribute the source as "DSC Sample Code"
+** after having made changes. If you're going to re-distribute the source,
+** we require that you make it clear in the source that the code was
+** descended from Apple Sample Code, but that you've made changes.
+*/
+
+// Modified to allow renaming the destination folder
+
+#ifndef __MACDIRECTORYCOPY__
+#define __MACDIRECTORYCOPY__
+
+#include <Types.h>
+#include <Files.h>
+
+#include "Optimization.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef pascal Boolean (*CopyErrProcPtr) (OSErr error,
+ short failedOperation,
+ short srcVRefNum,
+ long srcDirID,
+ ConstStr255Param srcName,
+ short dstVRefNum,
+ long dstDirID,
+ ConstStr255Param dstName);
+/* ¦ Prototype for the CopyErrProc function DirectoryCopy calls.
+ This is the prototype for the CopyErrProc function DirectoryCopy
+ calls if an error condition is detected sometime during the copy. If
+ CopyErrProc returns false, then DirectoryCopy attempts to continue with
+ the directory copy operation. If CopyErrProc returns true, then
+ DirectoryCopy stops the directory copy operation.
+
+ error input: The error result code that caused CopyErrProc to
+ be called.
+ failedOperation input: The operation that returned an error to
+ DirectoryCopy.
+ srcVRefNum input: Source volume specification.
+ srcDirID input: Source directory ID.
+ srcName input: Source file or directory name, or nil if
+ srcDirID specifies the directory.
+ dstVRefNum input: Destination volume specification.
+ dstDirID input: Destination directory ID.
+ dstName input: Destination file or directory name, or nil if
+ dstDirID specifies the directory.
+
+ __________
+
+ Also see: FilteredDirectoryCopy, FSpFilteredDirectoryCopy, DirectoryCopy, FSpDirectoryCopy
+*/
+
+pascal OSErr MacFSpDirectoryCopyRename(const FSSpec *srcSpec,
+ const FSSpec *dstSpec,
+ ConstStr255Param newName,
+ void *copyBufferPtr,
+ long copyBufferSize,
+ Boolean preflight,
+ CopyErrProcPtr copyErrHandler);
+/* ¦ Make a copy of a directory structure in a new location.
+ The FSpDirectoryCopy function makes a copy of a directory structure in a
+ new location. If copyBufferPtr <> NIL, it points to a buffer of
+ copyBufferSize that is used to copy files data. The larger the
+ supplied buffer, the faster the copy. If copyBufferPtr = NIL, then this
+ routine allocates a buffer in the application heap. If you pass a
+ copy buffer to this routine, make its size a multiple of 512
+ ($200) bytes for optimum performance.
+
+ srcSpec input: An FSSpec record specifying the directory to copy.
+ dstSpec input: An FSSpec record specifying destination directory
+ of the copy.
+ copyBufferPtr input: Points to a buffer of copyBufferSize that
+ is used the i/o buffer for the copy or
+ nil if you want DirectoryCopy to allocate its
+ own buffer in the application heap.
+ copyBufferSize input: The size of the buffer pointed to
+ by copyBufferPtr.
+ preflight input: If true, FSpDirectoryCopy makes sure there are
+ enough allocation blocks on the destination
+ volume to hold the directory's files before
+ starting the copy.
+ copyErrHandler input: A pointer to the routine you want called if an
+ error condition is detected during the copy, or
+ nil if you don't want to handle error conditions.
+ If you don't handle error conditions, the first
+ error will cause the copy to quit and
+ DirectoryCopy will return the error.
+ Error handling is recommended...
+
+ Result Codes
+ noErr 0 No error
+ readErr Ð19 Driver does not respond to read requests
+ writErr Ð20 Driver does not respond to write requests
+ badUnitErr Ð21 Driver reference number does not
+ match unit table
+ unitEmptyErr Ð22 Driver reference number specifies a
+ nil handle in unit table
+ abortErr Ð27 Request aborted by KillIO
+ notOpenErr Ð28 Driver not open
+ dskFulErr -34 Destination volume is full
+ nsvErr -35 No such volume
+ ioErr -36 I/O error
+ bdNamErr -37 Bad filename
+ tmfoErr -42 Too many files open
+ fnfErr -43 Source file not found, or destination
+ directory does not exist
+ wPrErr -44 Volume locked by hardware
+ fLckdErr -45 File is locked
+ vLckdErr -46 Destination volume is read-only
+ fBsyErr -47 The source or destination file could
+ not be opened with the correct access
+ modes
+ dupFNErr -48 Destination file already exists
+ opWrErr -49 File already open for writing
+ paramErr -50 No default volume or function not
+ supported by volume
+ permErr -54 File is already open and cannot be opened using specified deny modes
+ memFullErr -108 Copy buffer could not be allocated
+ dirNFErr -120 Directory not found or incomplete pathname
+ wrgVolTypErr -123 Function not supported by volume
+ afpAccessDenied -5000 User does not have the correct access
+ afpDenyConflict -5006 The source or destination file could
+ not be opened with the correct access
+ modes
+ afpObjectTypeErr -5025 Source is a directory, directory not found
+ or incomplete pathname
+
+ __________
+
+ Also see: CopyErrProcPtr, DirectoryCopy, FilteredDirectoryCopy,
+ FSpFilteredDirectoryCopy, FileCopy, FSpFileCopy
+*/
+
+/*****************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+#include "OptimizationEnd.h"
+
+#endif /* __DIRECTORYCOPY__ */
diff --git a/src/libs/xpcom18a4/xpcom/io/nsAppDirectoryServiceDefs.h b/src/libs/xpcom18a4/xpcom/io/nsAppDirectoryServiceDefs.h
new file mode 100644
index 00000000..768cb38f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsAppDirectoryServiceDefs.h
@@ -0,0 +1,120 @@
+/* -*- 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) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Conrad Carlen conrad@ingress.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 nsAppDirectoryServiceDefs_h___
+#define nsAppDirectoryServiceDefs_h___
+
+//========================================================================================
+//
+// Defines property names for directories available from standard nsIDirectoryServiceProviders.
+// These keys are not guaranteed to exist because the nsIDirectoryServiceProviders which
+// provide them are optional.
+//
+// Keys whose definition ends in "DIR" or "FILE" return a single nsIFile (or subclass).
+// Keys whose definition ends in "LIST" return an nsISimpleEnumerator which enumerates a
+// list of file objects.
+//
+// System and XPCOM level properties are defined in nsDirectoryServiceDefs.h.
+//
+//========================================================================================
+
+
+// --------------------------------------------------------------------------------------
+// Files and directories which exist on a per-product basis
+// --------------------------------------------------------------------------------------
+
+#define NS_APP_APPLICATION_REGISTRY_FILE "AppRegF"
+#define NS_APP_APPLICATION_REGISTRY_DIR "AppRegD"
+
+#define NS_APP_DEFAULTS_50_DIR "DefRt" // The root dir of all defaults dirs
+#define NS_APP_PREF_DEFAULTS_50_DIR "PrfDef"
+#define NS_APP_PROFILE_DEFAULTS_50_DIR "profDef" // The profile defaults of the "current"
+ // locale. Should be first choice.
+#define NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR "ProfDefNoLoc" // The profile defaults of the "default"
+ // installed locale. Second choice
+ // when above is not available.
+
+#define NS_APP_USER_PROFILES_ROOT_DIR "DefProfRt" // The dir where user profile dirs get created.
+
+#define NS_APP_RES_DIR "ARes"
+#define NS_APP_CHROME_DIR "AChrom"
+#define NS_APP_PLUGINS_DIR "APlugns" // Deprecated - use NS_APP_PLUGINS_DIR_LIST
+#define NS_APP_SEARCH_DIR "SrchPlugns"
+
+#define NS_APP_CHROME_DIR_LIST "AChromDL"
+#define NS_APP_PLUGINS_DIR_LIST "APluginsDL"
+
+// --------------------------------------------------------------------------------------
+// Files and directories which exist on a per-profile basis
+// These locations are typically provided by the profile mgr
+// --------------------------------------------------------------------------------------
+
+// In a shared profile environment, prefixing a profile-relative
+// key with NS_SHARED returns a location that is shared by
+// other users of the profile. Without this prefix, the consumer
+// has exclusive access to this location.
+
+#define NS_SHARED "SHARED"
+
+#define NS_APP_PREFS_50_DIR "PrefD" // Directory which contains user prefs
+#define NS_APP_PREFS_50_FILE "PrefF"
+#define NS_APP_PREFS_DEFAULTS_DIR_LIST "PrefDL"
+
+#define NS_APP_USER_PROFILE_50_DIR "ProfD"
+
+#define NS_APP_USER_CHROME_DIR "UChrm"
+
+#define NS_APP_LOCALSTORE_50_FILE "LclSt"
+#define NS_APP_HISTORY_50_FILE "UHist"
+#define NS_APP_USER_PANELS_50_FILE "UPnls"
+#define NS_APP_USER_MIMETYPES_50_FILE "UMimTyp"
+#define NS_APP_CACHE_PARENT_DIR "cachePDir"
+
+#define NS_APP_BOOKMARKS_50_FILE "BMarks"
+
+#define NS_APP_DOWNLOADS_50_FILE "DLoads"
+
+#define NS_APP_SEARCH_50_FILE "SrchF"
+
+#define NS_APP_MAIL_50_DIR "MailD"
+#define NS_APP_IMAP_MAIL_50_DIR "IMapMD"
+#define NS_APP_NEWS_50_DIR "NewsD"
+#define NS_APP_MESSENGER_FOLDER_CACHE_50_DIR "MFCaD"
+
+#define NS_APP_INSTALL_CLEANUP_DIR "XPIClnupD" //location of xpicleanup.dat xpicleanup.exe
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/io/nsAppFileLocationProvider.cpp b/src/libs/xpcom18a4/xpcom/io/nsAppFileLocationProvider.cpp
new file mode 100644
index 00000000..9d4f785d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsAppFileLocationProvider.cpp
@@ -0,0 +1,608 @@
+/* -*- 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) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Conrad Carlen <conrad@ingress.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 "nsAppFileLocationProvider.h"
+#include "nsAppDirectoryServiceDefs.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsIAtom.h"
+#include "nsILocalFile.h"
+#include "nsString.h"
+#include "nsXPIDLString.h"
+#include "nsISimpleEnumerator.h"
+#include "prenv.h"
+#include "nsCRT.h"
+
+#if (defined(XP_MAC) || defined(XP_MACOSX)) && !defined(VBOX_MACOSX_FOLLOWS_UNIX_IO)
+#include <Folders.h>
+#include <Script.h>
+#include <Processes.h>
+#include <Gestalt.h>
+#include "nsILocalFileMac.h"
+#elif defined(XP_OS2)
+#define INCL_DOSPROCESS
+#define INCL_DOSMODULEMGR
+#include <os2.h>
+#elif defined(XP_WIN)
+#include <windows.h>
+#include <shlobj.h>
+#elif defined(XP_UNIX)
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#elif defined(XP_BEOS)
+#include <sys/param.h>
+#include <kernel/image.h>
+#include <storage/FindDirectory.h>
+#endif
+
+
+// WARNING: These hard coded names need to go away. They need to
+// come from localizable resources
+
+#if defined(XP_MAC) || defined(XP_MACOSX)
+#define APP_REGISTRY_NAME NS_LITERAL_CSTRING("Application Registry")
+#define ESSENTIAL_FILES NS_LITERAL_CSTRING("Essential Files")
+#elif defined(XP_WIN) || defined(XP_OS2)
+#define APP_REGISTRY_NAME NS_LITERAL_CSTRING("registry.dat")
+#else
+#define APP_REGISTRY_NAME NS_LITERAL_CSTRING("appreg")
+#endif
+
+// define default product directory
+#ifdef XP_MAC
+#define DEFAULT_PRODUCT_DIR NS_LITERAL_CSTRING("Mozilla")
+#else
+#define DEFAULT_PRODUCT_DIR NS_LITERAL_CSTRING(MOZ_USER_DIR)
+#endif
+
+// Locally defined keys used by nsAppDirectoryEnumerator
+#define NS_ENV_PLUGINS_DIR "EnvPlugins" // env var MOZ_PLUGIN_PATH
+#define NS_USER_PLUGINS_DIR "UserPlugins"
+
+#if defined(XP_MAC) || defined(XP_MACOSX)
+#define NS_MACOSX_USER_PLUGIN_DIR "OSXUserPlugins"
+#define NS_MACOSX_LOCAL_PLUGIN_DIR "OSXLocalPlugins"
+#define NS_MAC_CLASSIC_PLUGIN_DIR "MacSysPlugins"
+#endif
+
+#if defined(XP_MAC)
+#define DEFAULTS_DIR_NAME NS_LITERAL_CSTRING("Defaults")
+#define DEFAULTS_PREF_DIR_NAME NS_LITERAL_CSTRING("Pref")
+#define DEFAULTS_PROFILE_DIR_NAME NS_LITERAL_CSTRING("Profile")
+#define RES_DIR_NAME NS_LITERAL_CSTRING("Res")
+#define CHROME_DIR_NAME NS_LITERAL_CSTRING("Chrome")
+#define PLUGINS_DIR_NAME NS_LITERAL_CSTRING("Plug-ins")
+#define SEARCH_DIR_NAME NS_LITERAL_CSTRING("Search Plugins")
+#else
+#define DEFAULTS_DIR_NAME NS_LITERAL_CSTRING("defaults")
+#define DEFAULTS_PREF_DIR_NAME NS_LITERAL_CSTRING("pref")
+#define DEFAULTS_PROFILE_DIR_NAME NS_LITERAL_CSTRING("profile")
+#define RES_DIR_NAME NS_LITERAL_CSTRING("res")
+#define CHROME_DIR_NAME NS_LITERAL_CSTRING("chrome")
+#define PLUGINS_DIR_NAME NS_LITERAL_CSTRING("plugins")
+#define SEARCH_DIR_NAME NS_LITERAL_CSTRING("searchplugins")
+#endif
+
+//*****************************************************************************
+// nsAppFileLocationProvider::Constructor/Destructor
+//*****************************************************************************
+
+nsAppFileLocationProvider::nsAppFileLocationProvider()
+{
+}
+
+//*****************************************************************************
+// nsAppFileLocationProvider::nsISupports
+//*****************************************************************************
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsAppFileLocationProvider, nsIDirectoryServiceProvider, nsIDirectoryServiceProvider2)
+
+//*****************************************************************************
+// nsAppFileLocationProvider::nsIDirectoryServiceProvider
+//*****************************************************************************
+
+NS_IMETHODIMP
+nsAppFileLocationProvider::GetFile(const char *prop, PRBool *persistant, nsIFile **_retval)
+{
+ nsCOMPtr<nsILocalFile> localFile;
+ nsresult rv = NS_ERROR_FAILURE;
+
+ NS_ENSURE_ARG(prop);
+ *_retval = nsnull;
+ *persistant = PR_TRUE;
+
+#if (defined (XP_MAC) || defined(XP_MACOSX)) && !defined(VBOX_MACOSX_FOLLOWS_UNIX_IO)
+ short foundVRefNum;
+ SInt32 foundDirID;
+ FSSpec fileSpec;
+ nsCOMPtr<nsILocalFileMac> macFile;
+#endif
+
+ if (nsCRT::strcmp(prop, NS_APP_APPLICATION_REGISTRY_DIR) == 0)
+ {
+ rv = GetProductDirectory(getter_AddRefs(localFile));
+ }
+ else if (nsCRT::strcmp(prop, NS_APP_APPLICATION_REGISTRY_FILE) == 0)
+ {
+ rv = GetProductDirectory(getter_AddRefs(localFile));
+ if (NS_SUCCEEDED(rv))
+ rv = localFile->AppendNative(APP_REGISTRY_NAME);
+ }
+ else if (nsCRT::strcmp(prop, NS_APP_DEFAULTS_50_DIR) == 0)
+ {
+ rv = CloneMozBinDirectory(getter_AddRefs(localFile));
+ if (NS_SUCCEEDED(rv))
+ rv = localFile->AppendRelativeNativePath(DEFAULTS_DIR_NAME);
+ }
+ else if (nsCRT::strcmp(prop, NS_APP_PREF_DEFAULTS_50_DIR) == 0)
+ {
+ rv = CloneMozBinDirectory(getter_AddRefs(localFile));
+ if (NS_SUCCEEDED(rv)) {
+ rv = localFile->AppendRelativeNativePath(DEFAULTS_DIR_NAME);
+ if (NS_SUCCEEDED(rv))
+ rv = localFile->AppendRelativeNativePath(DEFAULTS_PREF_DIR_NAME);
+ }
+ }
+ else if (nsCRT::strcmp(prop, NS_APP_PROFILE_DEFAULTS_50_DIR) == 0 ||
+ nsCRT::strcmp(prop, NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR) == 0)
+ {
+ rv = CloneMozBinDirectory(getter_AddRefs(localFile));
+ if (NS_SUCCEEDED(rv)) {
+ rv = localFile->AppendRelativeNativePath(DEFAULTS_DIR_NAME);
+ if (NS_SUCCEEDED(rv))
+ rv = localFile->AppendRelativeNativePath(DEFAULTS_PROFILE_DIR_NAME);
+ }
+ }
+ else if (nsCRT::strcmp(prop, NS_APP_USER_PROFILES_ROOT_DIR) == 0)
+ {
+ rv = GetDefaultUserProfileRoot(getter_AddRefs(localFile));
+ }
+ else if (nsCRT::strcmp(prop, NS_APP_RES_DIR) == 0)
+ {
+ rv = CloneMozBinDirectory(getter_AddRefs(localFile));
+ if (NS_SUCCEEDED(rv))
+ rv = localFile->AppendRelativeNativePath(RES_DIR_NAME);
+ }
+ else if (nsCRT::strcmp(prop, NS_APP_CHROME_DIR) == 0)
+ {
+ rv = CloneMozBinDirectory(getter_AddRefs(localFile));
+ if (NS_SUCCEEDED(rv))
+ rv = localFile->AppendRelativeNativePath(CHROME_DIR_NAME);
+ }
+ else if (nsCRT::strcmp(prop, NS_APP_PLUGINS_DIR) == 0)
+ {
+ rv = CloneMozBinDirectory(getter_AddRefs(localFile));
+ if (NS_SUCCEEDED(rv))
+ rv = localFile->AppendRelativeNativePath(PLUGINS_DIR_NAME);
+ }
+#if (defined(XP_MAC) || defined(XP_MACOSX)) && !defined(VBOX_MACOSX_FOLLOWS_UNIX_IO)
+ else if (nsCRT::strcmp(prop, NS_MACOSX_USER_PLUGIN_DIR) == 0)
+ {
+ if (!(::FindFolder(kUserDomain,
+ kInternetPlugInFolderType,
+ kDontCreateFolder, &foundVRefNum, &foundDirID)) &&
+ !(::FSMakeFSSpec(foundVRefNum, foundDirID, "\p", &fileSpec))) {
+ rv = NS_NewLocalFileWithFSSpec(&fileSpec, PR_TRUE, getter_AddRefs(macFile));
+ if (NS_SUCCEEDED(rv))
+ localFile = macFile;
+ }
+ }
+ else if (nsCRT::strcmp(prop, NS_MACOSX_LOCAL_PLUGIN_DIR) == 0)
+ {
+ if (!(::FindFolder(kLocalDomain,
+ kInternetPlugInFolderType,
+ kDontCreateFolder, &foundVRefNum, &foundDirID)) &&
+ !(::FSMakeFSSpec(foundVRefNum, foundDirID, "\p", &fileSpec))) {
+ rv = NS_NewLocalFileWithFSSpec(&fileSpec, PR_TRUE, getter_AddRefs(macFile));
+ if (NS_SUCCEEDED(rv))
+ localFile = macFile;
+ }
+ }
+ else if (nsCRT::strcmp(prop, NS_MAC_CLASSIC_PLUGIN_DIR) == 0)
+ {
+ if (!(::FindFolder(kOnAppropriateDisk,
+ kInternetPlugInFolderType,
+ kDontCreateFolder, &foundVRefNum, &foundDirID)) &&
+ !(::FSMakeFSSpec(foundVRefNum, foundDirID, "\p", &fileSpec))) {
+ rv = NS_NewLocalFileWithFSSpec(&fileSpec, PR_TRUE, getter_AddRefs(macFile));
+ if (NS_SUCCEEDED(rv))
+ localFile = macFile;
+ }
+ }
+#else
+ else if (nsCRT::strcmp(prop, NS_ENV_PLUGINS_DIR) == 0)
+ {
+ NS_ERROR("Don't use nsAppFileLocationProvider::GetFile(NS_ENV_PLUGINS_DIR, ...). "
+ "Use nsAppFileLocationProvider::GetFiles(...).");
+ const char *pathVar = PR_GetEnv("VBOX_XPCOM_PLUGIN_PATH");
+ if (pathVar)
+ rv = NS_NewNativeLocalFile(nsDependentCString(pathVar), PR_TRUE, getter_AddRefs(localFile));
+ }
+ else if (nsCRT::strcmp(prop, NS_USER_PLUGINS_DIR) == 0)
+ {
+ rv = GetProductDirectory(getter_AddRefs(localFile));
+ if (NS_SUCCEEDED(rv))
+ rv = localFile->AppendRelativeNativePath(PLUGINS_DIR_NAME);
+ }
+#endif
+ else if (nsCRT::strcmp(prop, NS_APP_SEARCH_DIR) == 0)
+ {
+ rv = CloneMozBinDirectory(getter_AddRefs(localFile));
+ if (NS_SUCCEEDED(rv))
+ rv = localFile->AppendRelativeNativePath(SEARCH_DIR_NAME);
+ }
+ else if (nsCRT::strcmp(prop, NS_APP_INSTALL_CLEANUP_DIR) == 0)
+ {
+ // This is cloned so that embeddors will have a hook to override
+ // with their own cleanup dir. See bugzilla bug #105087
+ rv = CloneMozBinDirectory(getter_AddRefs(localFile));
+#ifdef XP_MAC
+ if (NS_SUCCEEDED(rv))
+ rv = localFile->AppendNative(ESSENTIAL_FILES);
+#endif
+
+ }
+
+ if (localFile && NS_SUCCEEDED(rv))
+ return localFile->QueryInterface(NS_GET_IID(nsIFile), (void**)_retval);
+
+ return rv;
+}
+
+
+NS_METHOD nsAppFileLocationProvider::CloneMozBinDirectory(nsILocalFile **aLocalFile)
+{
+ NS_ENSURE_ARG_POINTER(aLocalFile);
+ nsresult rv;
+
+ if (!mMozBinDirectory)
+ {
+ // Get the mozilla bin directory
+ // 1. Check the directory service first for NS_XPCOM_CURRENT_PROCESS_DIR
+ // This will be set if a directory was passed to NS_InitXPCOM
+ // 2. If that doesn't work, set it to be the current process directory
+ nsCOMPtr<nsIProperties>
+ directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = directoryService->Get(NS_XPCOM_CURRENT_PROCESS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(mMozBinDirectory));
+ if (NS_FAILED(rv)) {
+ rv = directoryService->Get(NS_OS_CURRENT_PROCESS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(mMozBinDirectory));
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ }
+
+ nsCOMPtr<nsIFile> aFile;
+ rv = mMozBinDirectory->Clone(getter_AddRefs(aFile));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCOMPtr<nsILocalFile> lfile = do_QueryInterface (aFile);
+ if (!lfile)
+ return NS_ERROR_FAILURE;
+
+ NS_IF_ADDREF(*aLocalFile = lfile);
+ return NS_OK;
+}
+
+
+//----------------------------------------------------------------------------------------
+// GetProductDirectory - Gets the directory which contains the application data folder
+//
+// UNIX : ~/.mozilla/
+// WIN : <Application Data folder on user's machine>\Mozilla
+// Mac : :Documents:Mozilla:
+//----------------------------------------------------------------------------------------
+NS_METHOD nsAppFileLocationProvider::GetProductDirectory(nsILocalFile **aLocalFile)
+{
+ NS_ENSURE_ARG_POINTER(aLocalFile);
+
+ nsresult rv;
+ PRBool exists;
+ nsCOMPtr<nsILocalFile> localDir;
+
+#if defined(XP_MAC)
+ nsCOMPtr<nsIProperties> directoryService =
+ do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
+ if (NS_FAILED(rv)) return rv;
+ OSErr err;
+ long response;
+ err = ::Gestalt(gestaltSystemVersion, &response);
+ const char *prop = (!err && response >= 0x00001000) ? NS_MAC_USER_LIB_DIR : NS_MAC_DOCUMENTS_DIR;
+ rv = directoryService->Get(prop, NS_GET_IID(nsILocalFile), getter_AddRefs(localDir));
+ if (NS_FAILED(rv)) return rv;
+#elif defined(XP_MACOSX) && !defined(VBOX_MACOSX_FOLLOWS_UNIX_IO)
+ FSRef fsRef;
+ OSErr err = ::FSFindFolder(kUserDomain, kDomainLibraryFolderType, kCreateFolder, &fsRef);
+ if (err) return NS_ERROR_FAILURE;
+ NS_NewLocalFile(EmptyString(), PR_TRUE, getter_AddRefs(localDir));
+ if (!localDir) return NS_ERROR_FAILURE;
+ nsCOMPtr<nsILocalFileMac> localDirMac(do_QueryInterface(localDir));
+ rv = localDirMac->InitWithFSRef(&fsRef);
+ if (NS_FAILED(rv)) return rv;
+#elif defined(XP_OS2)
+ nsCOMPtr<nsIProperties> directoryService =
+ do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
+ if (NS_FAILED(rv)) return rv;
+ rv = directoryService->Get(NS_OS2_HOME_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(localDir));
+ if (NS_FAILED(rv)) return rv;
+#elif defined(XP_WIN)
+ nsCOMPtr<nsIProperties> directoryService =
+ do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
+ if (NS_FAILED(rv)) return rv;
+ rv = directoryService->Get(NS_WIN_APPDATA_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(localDir));
+ if (NS_SUCCEEDED(rv))
+ rv = localDir->Exists(&exists);
+ if (NS_FAILED(rv) || !exists)
+ {
+ // On some Win95 machines, NS_WIN_APPDATA_DIR does not exist - revert to NS_WIN_WINDOWS_DIR
+ localDir = nsnull;
+ rv = directoryService->Get(NS_WIN_WINDOWS_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(localDir));
+ }
+ if (NS_FAILED(rv)) return rv;
+#elif defined(XP_UNIX)
+ rv = NS_NewNativeLocalFile(nsDependentCString(PR_GetEnv("HOME")), PR_TRUE, getter_AddRefs(localDir));
+ if (NS_FAILED(rv)) return rv;
+#elif defined(XP_BEOS)
+ char path[MAXPATHLEN];
+ find_directory(B_USER_SETTINGS_DIRECTORY, 0, 0, path, MAXPATHLEN);
+ // Need enough space to add the trailing backslash
+ int len = strlen(path);
+ if (len > MAXPATHLEN-2)
+ return NS_ERROR_FAILURE;
+ path[len] = '/';
+ path[len+1] = '\0';
+ rv = NS_NewNativeLocalFile(nsDependentCString(path), PR_TRUE, getter_AddRefs(localDir));
+ if (NS_FAILED(rv)) return rv;
+#else
+#error dont_know_how_to_get_product_dir_on_your_platform
+#endif
+
+ rv = localDir->AppendRelativeNativePath(DEFAULT_PRODUCT_DIR);
+ if (NS_FAILED(rv)) return rv;
+ rv = localDir->Exists(&exists);
+ if (NS_SUCCEEDED(rv) && !exists)
+ rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
+ if (NS_FAILED(rv)) return rv;
+
+ *aLocalFile = localDir;
+ NS_ADDREF(*aLocalFile);
+
+ return rv;
+}
+
+
+//----------------------------------------------------------------------------------------
+// GetDefaultUserProfileRoot - Gets the directory which contains each user profile dir
+//
+// UNIX : ~/.mozilla/
+// WIN : <Application Data folder on user's machine>\Mozilla\Profiles
+// Mac : :Documents:Mozilla:Profiles:
+//----------------------------------------------------------------------------------------
+NS_METHOD nsAppFileLocationProvider::GetDefaultUserProfileRoot(nsILocalFile **aLocalFile)
+{
+ NS_ENSURE_ARG_POINTER(aLocalFile);
+
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> localDir;
+
+ rv = GetProductDirectory(getter_AddRefs(localDir));
+ if (NS_FAILED(rv)) return rv;
+
+#if defined(XP_MAC) || defined(XP_MACOSX) || defined(XP_OS2) || defined(XP_WIN)
+ // These 3 platforms share this part of the path - do them as one
+ rv = localDir->AppendRelativeNativePath(NS_LITERAL_CSTRING("Profiles"));
+ if (NS_FAILED(rv)) return rv;
+
+ PRBool exists;
+ rv = localDir->Exists(&exists);
+ if (NS_SUCCEEDED(rv) && !exists)
+ rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0775);
+ if (NS_FAILED(rv)) return rv;
+#endif
+
+ *aLocalFile = localDir;
+ NS_ADDREF(*aLocalFile);
+
+ return rv;
+}
+
+//*****************************************************************************
+// nsAppFileLocationProvider::nsIDirectoryServiceProvider2
+//*****************************************************************************
+
+class nsAppDirectoryEnumerator : public nsISimpleEnumerator
+{
+ public:
+ NS_DECL_ISUPPORTS
+
+ /**
+ * aKeyList is a null-terminated list of properties which are provided by aProvider
+ * They do not need to be publicly defined keys.
+ */
+ nsAppDirectoryEnumerator(nsIDirectoryServiceProvider *aProvider,
+ const char* aKeyList[]) :
+ mProvider(aProvider),
+ mCurrentKey(aKeyList)
+ {
+ }
+
+ NS_IMETHOD HasMoreElements(PRBool *result)
+ {
+ while (!mNext && *mCurrentKey)
+ {
+ PRBool dontCare;
+ nsCOMPtr<nsIFile> testFile;
+ (void)mProvider->GetFile(*mCurrentKey++, &dontCare, getter_AddRefs(testFile));
+ // Don't return a file which does not exist.
+ PRBool exists;
+ if (testFile && NS_SUCCEEDED(testFile->Exists(&exists)) && exists)
+ mNext = testFile;
+ }
+ *result = mNext != nsnull;
+ return NS_OK;
+ }
+
+ NS_IMETHOD GetNext(nsISupports **result)
+ {
+ NS_ENSURE_ARG_POINTER(result);
+ *result = nsnull;
+
+ PRBool hasMore;
+ HasMoreElements(&hasMore);
+ if (!hasMore)
+ return NS_ERROR_FAILURE;
+
+ *result = mNext;
+ NS_IF_ADDREF(*result);
+ mNext = nsnull;
+
+ return *result ? NS_OK : NS_ERROR_FAILURE;
+ }
+
+ // Virtual destructor since subclass nsPathsDirectoryEnumerator
+ // does not re-implement Release()
+
+ virtual ~nsAppDirectoryEnumerator()
+ {
+ }
+
+ protected:
+ nsIDirectoryServiceProvider *mProvider;
+ const char** mCurrentKey;
+ nsCOMPtr<nsIFile> mNext;
+};
+
+NS_IMPL_ISUPPORTS1(nsAppDirectoryEnumerator, nsISimpleEnumerator)
+
+/* nsPathsDirectoryEnumerator and PATH_SEPARATOR
+ * are not used on MacOS/X. */
+
+#if defined(XP_WIN) || defined(XP_OS2)/* Win32, Win16, and OS/2 */
+#define PATH_SEPARATOR ';'
+#else /*if defined(XP_UNIX) || defined(XP_BEOS)*/
+#define PATH_SEPARATOR ':'
+#endif
+
+class nsPathsDirectoryEnumerator : public nsAppDirectoryEnumerator
+{
+ public:
+ /**
+ * aKeyList is a null-terminated list.
+ * The first element is a path list.
+ * The remainder are properties provided by aProvider.
+ * They do not need to be publicly defined keys.
+ */
+ nsPathsDirectoryEnumerator(nsIDirectoryServiceProvider *aProvider,
+ const char* aKeyList[]) :
+ nsAppDirectoryEnumerator(aProvider, aKeyList+1),
+ mEndPath(aKeyList[0])
+ {
+ }
+
+ NS_IMETHOD HasMoreElements(PRBool *result)
+ {
+ if (mEndPath)
+ while (!mNext && *mEndPath)
+ {
+ const char *pathVar = mEndPath;
+ do { ++mEndPath; } while (*mEndPath && *mEndPath != PATH_SEPARATOR);
+
+ nsCOMPtr<nsILocalFile> localFile;
+ NS_NewNativeLocalFile(Substring(pathVar, mEndPath),
+ PR_TRUE,
+ getter_AddRefs(localFile));
+ if (*mEndPath == PATH_SEPARATOR)
+ ++mEndPath;
+ // Don't return a "file" (directory) which does not exist.
+ PRBool exists;
+ if (localFile &&
+ NS_SUCCEEDED(localFile->Exists(&exists)) &&
+ exists)
+ mNext = localFile;
+ }
+ if (mNext)
+ *result = PR_TRUE;
+ else
+ nsAppDirectoryEnumerator::HasMoreElements(result);
+
+ return NS_OK;
+ }
+
+ protected:
+ const char *mEndPath;
+};
+
+NS_IMETHODIMP
+nsAppFileLocationProvider::GetFiles(const char *prop, nsISimpleEnumerator **_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = nsnull;
+ nsresult rv = NS_ERROR_FAILURE;
+
+ if (!nsCRT::strcmp(prop, NS_APP_PLUGINS_DIR_LIST))
+ {
+#if (defined(XP_MAC) || defined(XP_MACOSX)) && !defined(VBOX_MACOSX_FOLLOWS_UNIX_IO)
+ static const char* osXKeys[] = { NS_APP_PLUGINS_DIR, NS_MACOSX_USER_PLUGIN_DIR, NS_MACOSX_LOCAL_PLUGIN_DIR, nsnull };
+ static const char* os9Keys[] = { NS_APP_PLUGINS_DIR, NS_MAC_CLASSIC_PLUGIN_DIR, nsnull };
+ static const char** keys;
+
+ if (!keys) {
+ OSErr err;
+ SInt32 response;
+ err = ::Gestalt(gestaltSystemVersion, &response);
+ keys = (!err && response >= 0x00001000) ? osXKeys : os9Keys;
+ }
+
+ *_retval = new nsAppDirectoryEnumerator(this, keys);
+#else
+ static const char* keys[] = { nsnull, NS_APP_PLUGINS_DIR, nsnull };
+ if (!keys[0] && !(keys[0] = PR_GetEnv("VBOX_XPCOM_PLUGIN_PATH"))) {
+ static const char nullstr = 0;
+ keys[0] = &nullstr;
+ }
+ *_retval = new nsPathsDirectoryEnumerator(this, keys);
+#endif
+ NS_IF_ADDREF(*_retval);
+ rv = *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+ }
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsAppFileLocationProvider.h b/src/libs/xpcom18a4/xpcom/io/nsAppFileLocationProvider.h
new file mode 100644
index 00000000..677ae00e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsAppFileLocationProvider.h
@@ -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 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) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Conrad Carlen <conrad@ingress.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 "nsIDirectoryService.h"
+#include "nsILocalFile.h"
+
+class nsIFile;
+
+//*****************************************************************************
+// class nsAppFileLocationProvider
+//*****************************************************************************
+
+class nsAppFileLocationProvider : public nsIDirectoryServiceProvider2
+{
+public:
+ nsAppFileLocationProvider();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIDIRECTORYSERVICEPROVIDER
+ NS_DECL_NSIDIRECTORYSERVICEPROVIDER2
+
+private:
+ ~nsAppFileLocationProvider() {}
+
+protected:
+ NS_METHOD CloneMozBinDirectory(nsILocalFile **aLocalFile);
+ NS_METHOD GetProductDirectory(nsILocalFile **aLocalFile);
+ NS_METHOD GetDefaultUserProfileRoot(nsILocalFile **aLocalFile);
+
+ nsCOMPtr<nsILocalFile> mMozBinDirectory;
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsBinaryStream.cpp b/src/libs/xpcom18a4/xpcom/io/nsBinaryStream.cpp
new file mode 100644
index 00000000..bc60eea3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsBinaryStream.cpp
@@ -0,0 +1,663 @@
+/* -*- 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-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 ***** */
+
+/**
+ * This file contains implementations of the nsIBinaryInputStream and
+ * nsIBinaryOutputStream interfaces. Together, these interfaces allows reading
+ * and writing of primitive data types (integers, floating-point values,
+ * booleans, etc.) to a stream in a binary, untagged, fixed-endianness format.
+ * This might be used, for example, to implement network protocols or to
+ * produce architecture-neutral binary disk files, i.e. ones that can be read
+ * and written by both big-endian and little-endian platforms. Output is
+ * written in big-endian order (high-order byte first), as this is traditional
+ * network order.
+ *
+ * @See nsIBinaryInputStream
+ * @See nsIBinaryOutputStream
+ */
+#include <string.h>
+#include "nsBinaryStream.h"
+#include "nsCRT.h"
+#include "nsIStreamBufferAccess.h"
+#include "nsMemory.h"
+#include "prlong.h"
+#include "nsGenericFactory.h"
+
+NS_IMPL_ISUPPORTS3(nsBinaryOutputStream, nsIObjectOutputStream, nsIBinaryOutputStream, nsIOutputStream)
+
+NS_IMETHODIMP
+nsBinaryOutputStream::Flush() { return mOutputStream->Flush(); }
+
+NS_IMETHODIMP
+nsBinaryOutputStream::Close() { return mOutputStream->Close(); }
+
+NS_IMETHODIMP
+nsBinaryOutputStream::Write(const char *aBuf, PRUint32 aCount, PRUint32 *aActualBytes)
+{
+ return mOutputStream->Write(aBuf, aCount, aActualBytes);
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval)
+{
+ NS_NOTREACHED("WriteFrom");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval)
+{
+ NS_NOTREACHED("WriteSegments");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::IsNonBlocking(PRBool *aNonBlocking)
+{
+ return mOutputStream->IsNonBlocking(aNonBlocking);
+}
+
+nsresult
+nsBinaryOutputStream::WriteFully(const char *aBuf, PRUint32 aCount)
+{
+ nsresult rv;
+ PRUint32 bytesWritten;
+
+ rv = mOutputStream->Write(aBuf, aCount, &bytesWritten);
+ if (NS_FAILED(rv)) return rv;
+ if (bytesWritten != aCount)
+ return NS_ERROR_FAILURE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::SetOutputStream(nsIOutputStream *aOutputStream)
+{
+ NS_ENSURE_ARG_POINTER(aOutputStream);
+ mOutputStream = aOutputStream;
+ mBufferAccess = do_QueryInterface(aOutputStream);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteBoolean(PRBool aBoolean)
+{
+ return Write8(aBoolean);
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::Write8(PRUint8 aByte)
+{
+ return WriteFully((const char*)&aByte, sizeof aByte);
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::Write16(PRUint16 a16)
+{
+ a16 = NS_SWAP16(a16);
+ return WriteFully((const char*)&a16, sizeof a16);
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::Write32(PRUint32 a32)
+{
+ a32 = NS_SWAP32(a32);
+ return WriteFully((const char*)&a32, sizeof a32);
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::Write64(PRUint64 a64)
+{
+ nsresult rv;
+ PRUint32 bytesWritten;
+
+ a64 = NS_SWAP64(a64);
+ rv = Write(NS_REINTERPRET_CAST(char*, &a64), sizeof a64, &bytesWritten);
+ if (NS_FAILED(rv)) return rv;
+ if (bytesWritten != sizeof a64)
+ return NS_ERROR_FAILURE;
+ return rv;
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteFloat(float aFloat)
+{
+ NS_ASSERTION(sizeof(float) == sizeof (PRUint32),
+ "False assumption about sizeof(float)");
+ return Write32(*NS_REINTERPRET_CAST(PRUint32*, &aFloat));
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteDouble(double aDouble)
+{
+ NS_ASSERTION(sizeof(double) == sizeof(PRUint64),
+ "False assumption about sizeof(double)");
+ return Write64(*NS_REINTERPRET_CAST(PRUint64*, &aDouble));
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteStringZ(const char *aString)
+{
+ PRUint32 length;
+ nsresult rv;
+
+ length = strlen(aString);
+ rv = Write32(length);
+ if (NS_FAILED(rv)) return rv;
+ return WriteFully(aString, length);
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteWStringZ(const PRUnichar* aString)
+{
+ PRUint32 length, byteCount;
+ nsresult rv;
+
+ length = nsCRT::strlen(aString);
+ rv = Write32(length);
+ if (NS_FAILED(rv)) return rv;
+
+ if (length == 0)
+ return NS_OK;
+ byteCount = length * sizeof(PRUnichar);
+
+#ifdef IS_BIG_ENDIAN
+ rv = WriteBytes(NS_REINTERPRET_CAST(const char*, aString), byteCount);
+#else
+ // XXX use WriteSegments here to avoid copy!
+ PRUnichar *copy, temp[64];
+ if (length <= 64) {
+ copy = temp;
+ } else {
+ copy = NS_REINTERPRET_CAST(PRUnichar*, nsMemory::Alloc(byteCount));
+ if (!copy)
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ NS_ASSERTION((PRUptrdiff(aString) & 0x1) == 0, "aString not properly aligned");
+ for (PRUint32 i = 0; i < length; i++)
+ copy[i] = NS_SWAP16(aString[i]);
+ rv = WriteBytes(NS_REINTERPRET_CAST(const char*, copy), byteCount);
+ if (copy != temp)
+ nsMemory::Free(copy);
+#endif
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteUtf8Z(const PRUnichar* aString)
+{
+ NS_NOTREACHED("WriteUtf8Z");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteBytes(const char *aString, PRUint32 aLength)
+{
+ nsresult rv;
+ PRUint32 bytesWritten;
+
+ rv = Write(aString, aLength, &bytesWritten);
+ if (NS_FAILED(rv)) return rv;
+ if (bytesWritten != aLength)
+ return NS_ERROR_FAILURE;
+ return rv;
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteByteArray(PRUint8 *aBytes, PRUint32 aLength)
+{
+ return WriteBytes(NS_REINTERPRET_CAST(char *, aBytes), aLength);
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteObject(nsISupports* aObject, PRBool aIsStrongRef)
+{
+ NS_NOTREACHED("WriteObject");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteSingleRefObject(nsISupports* aObject)
+{
+ NS_NOTREACHED("WriteSingleRefObject");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteCompoundObject(nsISupports* aObject,
+ const nsIID& aIID,
+ PRBool aIsStrongRef)
+{
+ NS_NOTREACHED("WriteCompoundObject");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsBinaryOutputStream::WriteID(const nsIID& aIID)
+{
+ NS_NOTREACHED("WriteID");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP_(char*)
+nsBinaryOutputStream::GetBuffer(PRUint32 aLength, PRUint32 aAlignMask)
+{
+ if (mBufferAccess)
+ return mBufferAccess->GetBuffer(aLength, aAlignMask);
+ return nsnull;
+}
+
+NS_IMETHODIMP_(void)
+nsBinaryOutputStream::PutBuffer(char* aBuffer, PRUint32 aLength)
+{
+ if (mBufferAccess)
+ mBufferAccess->PutBuffer(aBuffer, aLength);
+}
+
+NS_IMPL_ISUPPORTS3(nsBinaryInputStream, nsIObjectInputStream, nsIBinaryInputStream, nsIInputStream)
+
+NS_IMETHODIMP
+nsBinaryInputStream::Available(PRUint32* aResult)
+{
+ return mInputStream->Available(aResult);
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::Read(char* aBuffer, PRUint32 aCount, PRUint32 *aNumRead)
+{
+ return mInputStream->Read(aBuffer, aCount, aNumRead);
+}
+
+
+// when forwarding ReadSegments to mInputStream, we need to make sure
+// 'this' is being passed to the writer each time. To do this, we need
+// a thunking function which keeps the real input stream around.
+
+// the closure wrapper
+struct ReadSegmentsClosure {
+ nsIInputStream* mRealInputStream;
+ void* mRealClosure;
+ nsWriteSegmentFun mRealWriter;
+};
+
+// the thunking function
+static NS_METHOD
+ReadSegmentForwardingThunk(nsIInputStream* aStream,
+ void *aClosure,
+ const char* aFromSegment,
+ PRUint32 aToOffset,
+ PRUint32 aCount,
+ PRUint32 *aWriteCount)
+{
+ ReadSegmentsClosure* thunkClosure =
+ NS_REINTERPRET_CAST(ReadSegmentsClosure*, aClosure);
+
+ return thunkClosure->mRealWriter(thunkClosure->mRealInputStream,
+ thunkClosure->mRealClosure,
+ aFromSegment, aToOffset,
+ aCount, aWriteCount);
+}
+
+
+NS_IMETHODIMP
+nsBinaryInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval)
+{
+ ReadSegmentsClosure thunkClosure = { this, closure, writer };
+
+ return mInputStream->ReadSegments(ReadSegmentForwardingThunk, &thunkClosure, count, _retval);
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::IsNonBlocking(PRBool *aNonBlocking)
+{
+ return mInputStream->IsNonBlocking(aNonBlocking);
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::Close() { return mInputStream->Close(); }
+
+NS_IMETHODIMP
+nsBinaryInputStream::SetInputStream(nsIInputStream *aInputStream)
+{
+ NS_ENSURE_ARG_POINTER(aInputStream);
+ mInputStream = aInputStream;
+ mBufferAccess = do_QueryInterface(aInputStream);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::ReadBoolean(PRBool* aBoolean)
+{
+ PRUint8 byteResult;
+ nsresult rv = Read8(&byteResult);
+ *aBoolean = byteResult;
+ return rv;
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::Read8(PRUint8* aByte)
+{
+ nsresult rv;
+ PRUint32 bytesRead;
+
+ rv = Read(NS_REINTERPRET_CAST(char*, aByte), sizeof(*aByte), &bytesRead);
+ if (NS_FAILED(rv)) return rv;
+ if (bytesRead != 1)
+ return NS_ERROR_FAILURE;
+ return rv;
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::Read16(PRUint16* a16)
+{
+ nsresult rv;
+ PRUint32 bytesRead;
+
+ rv = Read(NS_REINTERPRET_CAST(char*, a16), sizeof *a16, &bytesRead);
+ if (NS_FAILED(rv)) return rv;
+ if (bytesRead != sizeof *a16)
+ return NS_ERROR_FAILURE;
+ *a16 = NS_SWAP16(*a16);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::Read32(PRUint32* a32)
+{
+ nsresult rv;
+ PRUint32 bytesRead;
+
+ rv = Read(NS_REINTERPRET_CAST(char*, a32), sizeof *a32, &bytesRead);
+ if (NS_FAILED(rv)) return rv;
+ if (bytesRead != sizeof *a32)
+ return NS_ERROR_FAILURE;
+ *a32 = NS_SWAP32(*a32);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::Read64(PRUint64* a64)
+{
+ nsresult rv;
+ PRUint32 bytesRead;
+
+ rv = Read(NS_REINTERPRET_CAST(char*, a64), sizeof *a64, &bytesRead);
+ if (NS_FAILED(rv)) return rv;
+ if (bytesRead != sizeof *a64)
+ return NS_ERROR_FAILURE;
+ *a64 = NS_SWAP64(*a64);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::ReadFloat(float* aFloat)
+{
+ NS_ASSERTION(sizeof(float) == sizeof (PRUint32),
+ "False assumption about sizeof(float)");
+ return Read32(NS_REINTERPRET_CAST(PRUint32*, aFloat));
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::ReadDouble(double* aDouble)
+{
+ NS_ASSERTION(sizeof(double) == sizeof(PRUint64),
+ "False assumption about sizeof(double)");
+ return Read64(NS_REINTERPRET_CAST(PRUint64*, aDouble));
+}
+
+static NS_METHOD
+WriteSegmentToCString(nsIInputStream* aStream,
+ void *aClosure,
+ const char* aFromSegment,
+ PRUint32 aToOffset,
+ PRUint32 aCount,
+ PRUint32 *aWriteCount)
+{
+ nsACString* outString = NS_STATIC_CAST(nsACString*,aClosure);
+
+ outString->Append(aFromSegment, aCount);
+
+ *aWriteCount = aCount;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::ReadCString(nsACString& aString)
+{
+ nsresult rv;
+ PRUint32 length, bytesRead;
+
+ rv = Read32(&length);
+ if (NS_FAILED(rv)) return rv;
+
+ aString.Truncate();
+ rv = ReadSegments(WriteSegmentToCString, &aString, length, &bytesRead);
+ if (NS_FAILED(rv)) return rv;
+
+ if (bytesRead != length)
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+
+// sometimes, WriteSegmentToString will be handed an odd-number of
+// bytes, which means we only have half of the last PRUnichar
+struct WriteStringClosure {
+ PRUnichar *mWriteCursor;
+ PRPackedBool mHasCarryoverByte;
+ char mCarryoverByte;
+};
+
+// there are a few cases we have to account for here:
+// * even length buffer, no carryover - easy, just append
+// * odd length buffer, no carryover - the last byte needs to be saved
+// for carryover
+// * odd length buffer, with carryover - first byte needs to be used
+// with the carryover byte, and
+// the rest of the even length
+// buffer is appended as normal
+// * even length buffer, with carryover - the first byte needs to be
+// used with the previous carryover byte.
+// this gives you an odd length buffer,
+// so you have to save the last byte for
+// the next carryover
+
+
+// same version of the above, but with correct casting and endian swapping
+static NS_METHOD
+WriteSegmentToString(nsIInputStream* aStream,
+ void *aClosure,
+ const char* aFromSegment,
+ PRUint32 aToOffset,
+ PRUint32 aCount,
+ PRUint32 *aWriteCount)
+{
+ NS_PRECONDITION(aCount > 0, "Why are we being told to write 0 bytes?");
+ NS_PRECONDITION(sizeof(PRUnichar) == 2, "We can't handle other sizes!");
+
+ WriteStringClosure* closure = NS_STATIC_CAST(WriteStringClosure*,aClosure);
+ PRUnichar *cursor = closure->mWriteCursor;
+
+ // we're always going to consume the whole buffer no matter what
+ // happens, so take care of that right now.. that allows us to
+ // tweak aCount later. Do NOT move this!
+ *aWriteCount = aCount;
+
+ // if the last Write had an odd-number of bytes read, then
+ if (closure->mHasCarryoverByte) {
+ // re-create the two-byte sequence we want to work with
+ char bytes[2] = { closure->mCarryoverByte, *aFromSegment };
+ *cursor = *(PRUnichar*)bytes;
+ // Now the little endianness dance
+#ifdef IS_LITTLE_ENDIAN
+ *cursor = (PRUnichar) NS_SWAP16(*cursor);
+#endif
+ ++cursor;
+
+ // now skip past the first byte of the buffer.. code from here
+ // can assume normal operations, but should not assume aCount
+ // is relative to the ORIGINAL buffer
+ ++aFromSegment;
+ --aCount;
+
+ closure->mHasCarryoverByte = PR_FALSE;
+ }
+
+ // this array is possibly unaligned... be careful how we access it!
+ const PRUnichar *unicodeSegment =
+ NS_REINTERPRET_CAST(const PRUnichar*, aFromSegment);
+
+ // calculate number of full characters in segment (aCount could be odd!)
+ PRUint32 segmentLength = aCount / sizeof(PRUnichar);
+
+ // copy all data into our aligned buffer. byte swap if necessary.
+ memcpy(cursor, unicodeSegment, segmentLength * sizeof(PRUnichar));
+ PRUnichar *end = cursor + segmentLength;
+#ifdef IS_LITTLE_ENDIAN
+ for (; cursor < end; ++cursor)
+ *cursor = (PRUnichar) NS_SWAP16(*cursor);
+#endif
+ closure->mWriteCursor = end;
+
+ // remember this is the modifed aCount and aFromSegment,
+ // so that will take into account the fact that we might have
+ // skipped the first byte in the buffer
+ if (aCount % sizeof(PRUnichar) != 0) {
+ // we must have had a carryover byte, that we'll need the next
+ // time around
+ closure->mCarryoverByte = aFromSegment[aCount - 1];
+ closure->mHasCarryoverByte = PR_TRUE;
+ }
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsBinaryInputStream::ReadString(nsAString& aString)
+{
+ nsresult rv;
+ PRUint32 length, bytesRead;
+
+ rv = Read32(&length);
+ if (NS_FAILED(rv)) return rv;
+
+ // pre-allocate output buffer, and get direct access to buffer...
+ aString.SetLength(length);
+ nsAString::iterator start;
+ aString.BeginWriting(start);
+
+ WriteStringClosure closure;
+ closure.mWriteCursor = start.get();
+ closure.mHasCarryoverByte = PR_FALSE;
+
+ rv = ReadSegments(WriteSegmentToString, &closure,
+ length*sizeof(PRUnichar), &bytesRead);
+ if (NS_FAILED(rv)) return rv;
+
+ NS_ASSERTION(!closure.mHasCarryoverByte, "some strange stream corruption!");
+
+ if (bytesRead != length*sizeof(PRUnichar))
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::ReadBytes(PRUint32 aLength, char* *_rval)
+{
+ nsresult rv;
+ PRUint32 bytesRead;
+ char* s;
+
+ s = NS_REINTERPRET_CAST(char*, nsMemory::Alloc(aLength));
+ if (!s)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ rv = Read(s, aLength, &bytesRead);
+ if (NS_FAILED(rv)) {
+ nsMemory::Free(s);
+ return rv;
+ }
+ if (bytesRead != aLength) {
+ nsMemory::Free(s);
+ return NS_ERROR_FAILURE;
+ }
+
+ *_rval = s;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::ReadByteArray(PRUint32 aLength, PRUint8* *_rval)
+{
+ return ReadBytes(aLength, NS_REINTERPRET_CAST(char **, _rval));
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::ReadObject(PRBool aIsStrongRef, nsISupports* *aObject)
+{
+ NS_NOTREACHED("ReadObject");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsBinaryInputStream::ReadID(nsID *aResult)
+{
+ NS_NOTREACHED("ReadID");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP_(char*)
+nsBinaryInputStream::GetBuffer(PRUint32 aLength, PRUint32 aAlignMask)
+{
+ if (mBufferAccess)
+ return mBufferAccess->GetBuffer(aLength, aAlignMask);
+ return nsnull;
+}
+
+NS_IMETHODIMP_(void)
+nsBinaryInputStream::PutBuffer(char* aBuffer, PRUint32 aLength)
+{
+ if (mBufferAccess)
+ mBufferAccess->PutBuffer(aBuffer, aLength);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/io/nsBinaryStream.h b/src/libs/xpcom18a4/xpcom/io/nsBinaryStream.h
new file mode 100644
index 00000000..7be46dc7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsBinaryStream.h
@@ -0,0 +1,125 @@
+/* -*- 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-2001
+ * 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 nsBinaryStream_h___
+#define nsBinaryStream_h___
+
+#include "nsCOMPtr.h"
+#include "nsAString.h"
+#include "nsIObjectInputStream.h"
+#include "nsIObjectOutputStream.h"
+#include "nsIStreamBufferAccess.h"
+
+#define NS_BINARYOUTPUTSTREAM_CID \
+{ /* 86c37b9a-74e7-4672-844e-6e7dd83ba484 */ \
+ 0x86c37b9a, \
+ 0x74e7, \
+ 0x4672, \
+ {0x84, 0x4e, 0x6e, 0x7d, 0xd8, 0x3b, 0xa4, 0x84} \
+}
+
+#define NS_BINARYOUTPUTSTREAM_CONTRACTID "@mozilla.org/binaryoutputstream;1"
+#define NS_BINARYOUTPUTSTREAM_CLASSNAME "Binary Output Stream"
+
+// Derive from nsIObjectOutputStream so this class can be used as a superclass
+// by nsObjectOutputStream.
+class nsBinaryOutputStream : public nsIObjectOutputStream
+{
+public:
+ nsBinaryOutputStream() {};
+ // virtual dtor since subclasses call our Release()
+ virtual ~nsBinaryOutputStream() {};
+
+protected:
+ // nsISupports methods
+ NS_DECL_ISUPPORTS
+
+ // nsIOutputStream methods
+ NS_DECL_NSIOUTPUTSTREAM
+
+ // nsIBinaryOutputStream methods
+ NS_DECL_NSIBINARYOUTPUTSTREAM
+
+ // nsIObjectOutputStream methods
+ NS_DECL_NSIOBJECTOUTPUTSTREAM
+
+ // Call Write(), ensuring that all proffered data is written
+ nsresult WriteFully(const char *aBuf, PRUint32 aCount);
+
+ nsCOMPtr<nsIOutputStream> mOutputStream;
+ nsCOMPtr<nsIStreamBufferAccess> mBufferAccess;
+};
+
+#define NS_BINARYINPUTSTREAM_CID \
+{ /* c521a612-2aad-46db-b6ab-3b821fb150b1 */ \
+ 0xc521a612, \
+ 0x2aad, \
+ 0x46db, \
+ {0xb6, 0xab, 0x3b, 0x82, 0x1f, 0xb1, 0x50, 0xb1} \
+}
+
+#define NS_BINARYINPUTSTREAM_CONTRACTID "@mozilla.org/binaryinputstream;1"
+#define NS_BINARYINPUTSTREAM_CLASSNAME "Binary Input Stream"
+
+// Derive from nsIObjectInputStream so this class can be used as a superclass
+// by nsObjectInputStream.
+class nsBinaryInputStream : public nsIObjectInputStream
+{
+public:
+ nsBinaryInputStream() {};
+ // virtual dtor since subclasses call our Release()
+ virtual ~nsBinaryInputStream() {};
+
+protected:
+ // nsISupports methods
+ NS_DECL_ISUPPORTS
+
+ // nsIInputStream methods
+ NS_DECL_NSIINPUTSTREAM
+
+ // nsIBinaryInputStream methods
+ NS_DECL_NSIBINARYINPUTSTREAM
+
+ // nsIObjectInputStream methods
+ NS_DECL_NSIOBJECTINPUTSTREAM
+
+ nsCOMPtr<nsIInputStream> mInputStream;
+ nsCOMPtr<nsIStreamBufferAccess> mBufferAccess;
+};
+
+#endif // nsBinaryStream_h___
diff --git a/src/libs/xpcom18a4/xpcom/io/nsByteArrayInputStream.cpp b/src/libs/xpcom18a4/xpcom/io/nsByteArrayInputStream.cpp
new file mode 100644
index 00000000..364f71d5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsByteArrayInputStream.cpp
@@ -0,0 +1,164 @@
+/* -*- 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-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 "nsByteArrayInputStream.h"
+#include "nsMemory.h"
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsByteArrayInputStream, nsIInputStream, nsIByteArrayInputStream)
+
+nsByteArrayInputStream::nsByteArrayInputStream (char *buffer, PRUint32 bytes)
+ : _buffer (buffer), _nbytes (bytes), _pos (0)
+{
+}
+
+nsByteArrayInputStream::~nsByteArrayInputStream ()
+{
+ if (_buffer != NULL)
+ nsMemory::Free (_buffer);
+}
+
+NS_IMETHODIMP
+nsByteArrayInputStream::Available (PRUint32* aResult)
+{
+ if (aResult == NULL)
+ return NS_ERROR_NULL_POINTER;
+
+ if (_nbytes == 0 || _buffer == NULL)
+ *aResult = 0;
+ else
+ *aResult = _nbytes - _pos;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsByteArrayInputStream::Read (char* aBuffer, PRUint32 aCount, PRUint32 *aNumRead)
+{
+ if (aBuffer == NULL || aNumRead == NULL)
+ return NS_ERROR_NULL_POINTER;
+
+ if (_nbytes == 0)
+ return NS_ERROR_FAILURE;
+
+ if (aCount == 0 || _pos == _nbytes)
+ *aNumRead = 0;
+ else
+ {
+ NS_ASSERTION (_buffer != NULL, "Stream buffer has been released - there's an ownership problem somewhere!");
+ if (_buffer == NULL)
+ *aNumRead = 0;
+ else
+ if (aCount > _nbytes - _pos)
+ {
+ memcpy (aBuffer, &_buffer[_pos], *aNumRead = _nbytes - _pos);
+ _pos = _nbytes;
+ }
+ else
+ {
+ memcpy (aBuffer, &_buffer[_pos], *aNumRead = aCount);
+ _pos += aCount;
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsByteArrayInputStream::ReadSegments(nsWriteSegmentFun writer, void * aClosure, PRUint32 aCount, PRUint32 *aNumRead)
+{
+ if (aNumRead == NULL)
+ return NS_ERROR_NULL_POINTER;
+
+ if (_nbytes == 0)
+ return NS_ERROR_FAILURE;
+
+ if (aCount == 0 || _pos == _nbytes)
+ *aNumRead = 0;
+ else {
+ NS_ASSERTION (_buffer != NULL, "Stream buffer has been released - there's an ownership problem somewhere!");
+ PRUint32 readCount = PR_MIN(aCount, (_nbytes - _pos));
+ if (_buffer == NULL)
+ *aNumRead = 0;
+ else {
+ nsresult rv = writer (this, aClosure, &_buffer[_pos],
+ _pos, readCount, aNumRead);
+ if (NS_SUCCEEDED(rv))
+ _pos += *aNumRead;
+ }
+ }
+
+ // do not propogate errors returned from writer!
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsByteArrayInputStream::IsNonBlocking(PRBool *aNonBlocking)
+{
+ *aNonBlocking = PR_TRUE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsByteArrayInputStream::Close ()
+{
+ if (_buffer != NULL)
+ {
+ nsMemory::Free (_buffer);
+ _buffer = NULL;
+ _nbytes = 0;
+ }
+ else
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+NS_COM nsresult
+NS_NewByteArrayInputStream (nsIByteArrayInputStream* *aResult, char * buffer, unsigned long bytes)
+{
+ if (aResult == NULL)
+ return NS_ERROR_NULL_POINTER;
+
+ nsIByteArrayInputStream * stream = new nsByteArrayInputStream (buffer, bytes);
+
+ if (!stream)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF (stream);
+ *aResult = stream;
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsByteArrayInputStream.h b/src/libs/xpcom18a4/xpcom/io/nsByteArrayInputStream.h
new file mode 100644
index 00000000..2999eb5f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsByteArrayInputStream.h
@@ -0,0 +1,59 @@
+/* -*- 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-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 "nsIByteArrayInputStream.h"
+#include "nsCOMPtr.h"
+
+class nsByteArrayInputStream : public nsIByteArrayInputStream
+{
+ // nsISupports methods
+ NS_DECL_ISUPPORTS
+
+ // nsIInputStream methods
+ NS_DECL_NSIINPUTSTREAM
+
+public:
+ nsByteArrayInputStream (char *buffer, PRUint32 nbytes);
+
+private:
+ ~nsByteArrayInputStream ();
+
+ char *_buffer;
+ PRUint32 _nbytes;
+ PRUint32 _pos;
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsDirectoryService.cpp b/src/libs/xpcom18a4/xpcom/io/nsDirectoryService.cpp
new file mode 100644
index 00000000..60b16eda
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsDirectoryService.cpp
@@ -0,0 +1,1241 @@
+/* -*- 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):
+ * IBM Corp.
+ *
+ * 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 "nsCOMPtr.h"
+#include "nsDirectoryService.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsLocalFile.h"
+#include "nsDebug.h"
+#include "nsStaticAtom.h"
+
+#if defined(XP_MAC)
+#include <Folders.h>
+#include <Files.h>
+#include <Memory.h>
+#include <Processes.h>
+#include <Gestalt.h>
+#elif defined(XP_WIN)
+#include <windows.h>
+#include <shlobj.h>
+#include <stdlib.h>
+#include <stdio.h>
+#elif defined(XP_UNIX) || defined(XP_MACOSX)
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <dlfcn.h>
+#include "prenv.h"
+#ifdef XP_MACOSX
+#include <CoreServices/CoreServices.h>
+#include <Folders.h>
+#include <Files.h>
+# ifndef VBOX_WITH_NEWER_OSX_SDK
+# include <Memory.h>
+# endif
+#include <Processes.h>
+#include <Gestalt.h>
+#include <CFURL.h>
+#include <InternetConfig.h>
+#endif
+#elif defined(XP_OS2)
+#define MAX_PATH _MAX_PATH
+#elif defined(XP_BEOS)
+#include <FindDirectory.h>
+#include <Path.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <OS.h>
+#include <image.h>
+#include "prenv.h"
+#endif
+
+#include "SpecialSystemDirectory.h"
+#include "nsAppFileLocationProvider.h"
+
+#if defined(XP_MAC)
+#define COMPONENT_REGISTRY_NAME NS_LITERAL_CSTRING("Component Registry")
+#define COMPONENT_DIRECTORY NS_LITERAL_CSTRING("Components")
+#else
+#define COMPONENT_REGISTRY_NAME NS_LITERAL_CSTRING("compreg.dat")
+#define COMPONENT_DIRECTORY NS_LITERAL_CSTRING("components")
+#endif
+
+#define XPTI_REGISTRY_NAME NS_LITERAL_CSTRING("xpti.dat")
+
+// define home directory
+// For Windows platform, We are choosing Appdata folder as HOME
+#if defined (XP_WIN)
+#define HOME_DIR NS_WIN_APPDATA_DIR
+#elif defined (XP_MAC) || defined (XP_MACOSX)
+#define HOME_DIR NS_OSX_HOME_DIR
+#elif defined (XP_UNIX)
+#define HOME_DIR NS_UNIX_HOME_DIR
+#elif defined (XP_OS2)
+#define HOME_DIR NS_OS2_HOME_DIR
+#elif defined (XP_BEOS)
+#define HOME_DIR NS_BEOS_HOME_DIR
+#endif
+
+//----------------------------------------------------------------------------------------
+nsresult
+nsDirectoryService::GetCurrentProcessDirectory(nsILocalFile** aFile)
+//----------------------------------------------------------------------------------------
+{
+ NS_ENSURE_ARG_POINTER(aFile);
+ *aFile = nsnull;
+
+ // Set the component registry location:
+ if (!mService)
+ return NS_ERROR_FAILURE;
+
+ nsresult rv;
+
+ nsCOMPtr<nsIProperties> dirService;
+ rv = nsDirectoryService::Create(nsnull,
+ NS_GET_IID(nsIProperties),
+ getter_AddRefs(dirService)); // needs to be around for life of product
+
+ if (dirService)
+ {
+ nsCOMPtr <nsILocalFile> aLocalFile;
+ dirService->Get(NS_XPCOM_INIT_CURRENT_PROCESS_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(aLocalFile));
+ if (aLocalFile)
+ {
+ *aFile = aLocalFile;
+ NS_ADDREF(*aFile);
+ return NS_OK;
+ }
+ }
+
+ nsLocalFile* localFile = new nsLocalFile;
+
+ if (localFile == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(localFile);
+
+
+
+#ifdef XP_WIN
+ char buf[MAX_PATH];
+ if ( ::GetModuleFileName(0, buf, sizeof(buf)) ) {
+ // chop of the executable name by finding the rightmost backslash
+ char* lastSlash = PL_strrchr(buf, '\\');
+ if (lastSlash)
+ *(lastSlash + 1) = '\0';
+
+ localFile->InitWithNativePath(nsDependentCString(buf));
+ *aFile = localFile;
+ return NS_OK;
+ }
+
+#elif defined(XP_MAC)
+ // get info for the the current process to determine the directory
+ // its located in
+ OSErr err;
+ ProcessSerialNumber psn = {kNoProcess, kCurrentProcess};
+ ProcessInfoRec pInfo;
+ FSSpec tempSpec;
+
+ // initialize ProcessInfoRec before calling
+ // GetProcessInformation() or die horribly.
+ pInfo.processName = nil;
+ pInfo.processAppSpec = &tempSpec;
+ pInfo.processInfoLength = sizeof(ProcessInfoRec);
+
+ err = GetProcessInformation(&psn, &pInfo);
+ if (!err)
+ {
+ // create an FSSpec from the volume and dirid of the app.
+ FSSpec appFSSpec;
+ ::FSMakeFSSpec(pInfo.processAppSpec->vRefNum, pInfo.processAppSpec->parID, 0, &appFSSpec);
+
+ nsCOMPtr<nsILocalFileMac> localFileMac = do_QueryInterface((nsIFile*)localFile);
+ if (localFileMac)
+ {
+ localFileMac->InitWithFSSpec(&appFSSpec);
+ *aFile = localFile;
+ return NS_OK;
+ }
+ }
+#elif defined(XP_MACOSX)
+# ifdef MOZ_DEFAULT_VBOX_XPCOM_HOME
+ rv = localFile->InitWithNativePath(nsDependentCString(MOZ_DEFAULT_VBOX_XPCOM_HOME));
+ if (NS_SUCCEEDED(rv))
+ *aFile = localFile;
+# else
+ // Works even if we're not bundled.
+ CFBundleRef appBundle = CFBundleGetMainBundle();
+ if (appBundle != nsnull)
+ {
+ CFURLRef bundleURL = CFBundleCopyExecutableURL(appBundle);
+ if (bundleURL != nsnull)
+ {
+ CFURLRef parentURL = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, bundleURL);
+ if (parentURL)
+ {
+ // Pass PR_TRUE for the "resolveAgainstBase" arg to CFURLGetFileSystemRepresentation.
+ // This will resolve the relative portion of the CFURL against it base, giving a full
+ // path, which CFURLCopyFileSystemPath doesn't do.
+ char buffer[PATH_MAX];
+ if (CFURLGetFileSystemRepresentation(parentURL, PR_TRUE, (UInt8 *)buffer, sizeof(buffer)))
+ {
+#ifdef DEBUG_conrad
+ printf("nsDirectoryService - CurrentProcessDir is: %s\n", buffer);
+#endif
+ rv = localFile->InitWithNativePath(nsDependentCString(buffer));
+ if (NS_SUCCEEDED(rv))
+ *aFile = localFile;
+ }
+ CFRelease(parentURL);
+ }
+ CFRelease(bundleURL);
+ }
+ }
+#endif
+
+ NS_ASSERTION(*aFile, "nsDirectoryService - Could not determine CurrentProcessDir.\n");
+ if (*aFile)
+ return NS_OK;
+
+#elif defined(XP_UNIX)
+
+ // In the absence of a good way to get the executable directory let
+ // us try this for unix:
+ // - if VBOX_XPCOM_HOME is defined, that is it
+ // - else give the current directory
+ char buf[MAXPATHLEN];
+
+#if 0 /* we need .so location. */
+ // Actually we have a way on linux.
+ static volatile bool fPathSet = false;
+ static char szPath[MAXPATHLEN];
+ if (!fPathSet)
+ {
+ char buf2[MAXPATHLEN + 3];
+ buf2[0] = '\0';
+
+ /*
+ * Env.var. VBOX_XPCOM_HOME first.
+ */
+ char *psz = PR_GetEnv("VBOX_XPCOM_HOME");
+ if (psz)
+ {
+ if (strlen(psz) < MAXPATHLEN)
+ {
+ if (!realpath(psz, buf2))
+ strcpy(buf2, psz);
+ strcat(buf2, "/x"); /* for the filename stripping */
+ }
+ }
+
+ /*
+ * The dynamic loader.
+ */
+ if (!buf2[0])
+ {
+ Dl_info DlInfo = {0};
+ if ( !dladdr((void *)nsDirectoryService::mService, &DlInfo)
+ && DlInfo.dli_fname)
+ {
+ if (!realpath(DlInfo.dli_fname, buf2))
+ buf2[0] = '\0';
+ }
+ }
+
+ /*
+ * Executable location.
+ */
+ if (!buf2[0])
+ {
+ char buf[MAXPATHLEN];
+ int cchLink = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
+ if (cchLink > 0 || cchLink != sizeof(buf) - 1)
+ {
+ buf[cchLink] = '\0';
+ if (!realpath(buf, buf2))
+ buf2[0] = '\0';
+ }
+ }
+
+ /*
+ * Copy to static buffer on success.
+ */
+ if (buf2[0])
+ {
+ char *p = strrchr(buf2, '/');
+ if (p)
+ {
+ p[p == buf2] = '\0';
+ #ifdef DEBUG
+ printf("debug: (1) VBOX_XPCOM_HOME=%s\n", buf2);
+ #endif
+ strcpy(szPath, buf2);
+ fPathSet = true;
+ }
+ }
+ }
+ if (fPathSet)
+ {
+ localFile->InitWithNativePath(nsDependentCString(szPath));
+ *aFile = localFile;
+ return NS_OK;
+ }
+
+#endif
+
+
+ // The MOZ_DEFAULT_VBOX_XPCOM_HOME variable can be set at configure time with
+ // a --with-default-mozilla-five-home=foo autoconf flag.
+ //
+ // The idea here is to allow for builds that have a default VBOX_XPCOM_HOME
+ // regardless of the environment. This makes it easier to write apps that
+ // embed mozilla without having to worry about setting up the environment
+ //
+ // We do this py putenv()ing the default value into the environment. Note that
+ // we only do this if it is not already set.
+#ifdef MOZ_DEFAULT_VBOX_XPCOM_HOME
+ if (PR_GetEnv("VBOX_XPCOM_HOME") == nsnull)
+ PR_SetEnv("VBOX_XPCOM_HOME=" MOZ_DEFAULT_VBOX_XPCOM_HOME);
+#endif
+
+ char *moz5 = PR_GetEnv("VBOX_XPCOM_HOME");
+
+ if (moz5)
+ {
+ if (realpath(moz5, buf)) {
+ localFile->InitWithNativePath(nsDependentCString(buf));
+ *aFile = localFile;
+ return NS_OK;
+ }
+ }
+#if defined(DEBUG)
+ static PRBool firstWarning = PR_TRUE;
+
+ if(!moz5 && firstWarning) {
+ // Warn that VBOX_XPCOM_HOME not set, once.
+ printf("Warning: VBOX_XPCOM_HOME not set.\n");
+ firstWarning = PR_FALSE;
+ }
+#endif /* DEBUG */
+
+ // Fall back to current directory.
+ if (getcwd(buf, sizeof(buf)))
+ {
+ localFile->InitWithNativePath(nsDependentCString(buf));
+ *aFile = localFile;
+ return NS_OK;
+ }
+
+#elif defined(XP_OS2)
+ PPIB ppib;
+ PTIB ptib;
+ char buffer[CCHMAXPATH];
+ DosGetInfoBlocks( &ptib, &ppib);
+ DosQueryModuleName( ppib->pib_hmte, CCHMAXPATH, buffer);
+ *strrchr( buffer, '\\') = '\0'; // XXX DBCS misery
+ localFile->InitWithNativePath(nsDependentCString(buffer));
+ *aFile = localFile;
+ return NS_OK;
+
+#elif defined(XP_BEOS)
+
+ char *moz5 = getenv("VBOX_XPCOM_HOME");
+ if (moz5)
+ {
+ localFile->InitWithNativePath(nsDependentCString(moz5));
+ localFile->Normalize();
+ *aFile = localFile;
+ return NS_OK;
+ }
+ else
+ {
+ static char buf[MAXPATHLEN];
+ int32 cookie = 0;
+ image_info info;
+ char *p;
+ *buf = 0;
+ if(get_next_image_info(0, &cookie, &info) == B_OK)
+ {
+ strcpy(buf, info.name);
+ if((p = strrchr(buf, '/')) != 0)
+ {
+ *p = 0;
+ localFile->InitWithNativePath(nsDependentCString(buf));
+ *aFile = localFile;
+ return NS_OK;
+ }
+ }
+ }
+
+#endif
+
+ NS_RELEASE(localFile);
+
+ NS_ERROR("unable to get current process directory");
+ return NS_ERROR_FAILURE;
+} // GetCurrentProcessDirectory()
+
+
+nsIAtom* nsDirectoryService::sCurrentProcess = nsnull;
+nsIAtom* nsDirectoryService::sComponentRegistry = nsnull;
+nsIAtom* nsDirectoryService::sXPTIRegistry = nsnull;
+nsIAtom* nsDirectoryService::sComponentDirectory = nsnull;
+nsIAtom* nsDirectoryService::sGRE_Directory = nsnull;
+nsIAtom* nsDirectoryService::sGRE_ComponentDirectory = nsnull;
+nsIAtom* nsDirectoryService::sOS_DriveDirectory = nsnull;
+nsIAtom* nsDirectoryService::sOS_TemporaryDirectory = nsnull;
+nsIAtom* nsDirectoryService::sOS_CurrentProcessDirectory = nsnull;
+nsIAtom* nsDirectoryService::sOS_CurrentWorkingDirectory = nsnull;
+#if defined (XP_MACOSX)
+nsIAtom* nsDirectoryService::sDirectory = nsnull;
+nsIAtom* nsDirectoryService::sDesktopDirectory = nsnull;
+nsIAtom* nsDirectoryService::sTrashDirectory = nsnull;
+nsIAtom* nsDirectoryService::sStartupDirectory = nsnull;
+nsIAtom* nsDirectoryService::sShutdownDirectory = nsnull;
+nsIAtom* nsDirectoryService::sAppleMenuDirectory = nsnull;
+nsIAtom* nsDirectoryService::sControlPanelDirectory = nsnull;
+nsIAtom* nsDirectoryService::sExtensionDirectory = nsnull;
+nsIAtom* nsDirectoryService::sFontsDirectory = nsnull;
+nsIAtom* nsDirectoryService::sPreferencesDirectory = nsnull;
+nsIAtom* nsDirectoryService::sDocumentsDirectory = nsnull;
+nsIAtom* nsDirectoryService::sInternetSearchDirectory = nsnull;
+nsIAtom* nsDirectoryService::sUserLibDirectory = nsnull;
+nsIAtom* nsDirectoryService::sHomeDirectory = nsnull;
+nsIAtom* nsDirectoryService::sDefaultDownloadDirectory = nsnull;
+nsIAtom* nsDirectoryService::sUserDesktopDirectory = nsnull;
+nsIAtom* nsDirectoryService::sLocalDesktopDirectory = nsnull;
+nsIAtom* nsDirectoryService::sUserApplicationsDirectory = nsnull;
+nsIAtom* nsDirectoryService::sLocalApplicationsDirectory = nsnull;
+nsIAtom* nsDirectoryService::sUserDocumentsDirectory = nsnull;
+nsIAtom* nsDirectoryService::sLocalDocumentsDirectory = nsnull;
+nsIAtom* nsDirectoryService::sUserInternetPlugInDirectory = nsnull;
+nsIAtom* nsDirectoryService::sLocalInternetPlugInDirectory = nsnull;
+nsIAtom* nsDirectoryService::sUserFrameworksDirectory = nsnull;
+nsIAtom* nsDirectoryService::sLocalFrameworksDirectory = nsnull;
+nsIAtom* nsDirectoryService::sUserPreferencesDirectory = nsnull;
+nsIAtom* nsDirectoryService::sLocalPreferencesDirectory = nsnull;
+nsIAtom* nsDirectoryService::sPictureDocumentsDirectory = nsnull;
+nsIAtom* nsDirectoryService::sMovieDocumentsDirectory = nsnull;
+nsIAtom* nsDirectoryService::sMusicDocumentsDirectory = nsnull;
+nsIAtom* nsDirectoryService::sInternetSitesDirectory = nsnull;
+#elif defined (XP_WIN)
+nsIAtom* nsDirectoryService::sSystemDirectory = nsnull;
+nsIAtom* nsDirectoryService::sWindowsDirectory = nsnull;
+nsIAtom* nsDirectoryService::sHomeDirectory = nsnull;
+nsIAtom* nsDirectoryService::sDesktop = nsnull;
+nsIAtom* nsDirectoryService::sPrograms = nsnull;
+nsIAtom* nsDirectoryService::sControls = nsnull;
+nsIAtom* nsDirectoryService::sPrinters = nsnull;
+nsIAtom* nsDirectoryService::sPersonal = nsnull;
+nsIAtom* nsDirectoryService::sFavorites = nsnull;
+nsIAtom* nsDirectoryService::sStartup = nsnull;
+nsIAtom* nsDirectoryService::sRecent = nsnull;
+nsIAtom* nsDirectoryService::sSendto = nsnull;
+nsIAtom* nsDirectoryService::sBitbucket = nsnull;
+nsIAtom* nsDirectoryService::sStartmenu = nsnull;
+nsIAtom* nsDirectoryService::sDesktopdirectory = nsnull;
+nsIAtom* nsDirectoryService::sDrives = nsnull;
+nsIAtom* nsDirectoryService::sNetwork = nsnull;
+nsIAtom* nsDirectoryService::sNethood = nsnull;
+nsIAtom* nsDirectoryService::sFonts = nsnull;
+nsIAtom* nsDirectoryService::sTemplates = nsnull;
+nsIAtom* nsDirectoryService::sCommon_Startmenu = nsnull;
+nsIAtom* nsDirectoryService::sCommon_Programs = nsnull;
+nsIAtom* nsDirectoryService::sCommon_Startup = nsnull;
+nsIAtom* nsDirectoryService::sCommon_Desktopdirectory = nsnull;
+nsIAtom* nsDirectoryService::sAppdata = nsnull;
+nsIAtom* nsDirectoryService::sPrinthood = nsnull;
+nsIAtom* nsDirectoryService::sWinCookiesDirectory = nsnull;
+#elif defined (XP_UNIX)
+nsIAtom* nsDirectoryService::sLocalDirectory = nsnull;
+nsIAtom* nsDirectoryService::sLibDirectory = nsnull;
+nsIAtom* nsDirectoryService::sHomeDirectory = nsnull;
+#elif defined (XP_OS2)
+nsIAtom* nsDirectoryService::sSystemDirectory = nsnull;
+nsIAtom* nsDirectoryService::sOS2Directory = nsnull;
+nsIAtom* nsDirectoryService::sHomeDirectory = nsnull;
+nsIAtom* nsDirectoryService::sDesktopDirectory = nsnull;
+#elif defined (XP_BEOS)
+nsIAtom* nsDirectoryService::sSettingsDirectory = nsnull;
+nsIAtom* nsDirectoryService::sHomeDirectory = nsnull;
+nsIAtom* nsDirectoryService::sDesktopDirectory = nsnull;
+nsIAtom* nsDirectoryService::sSystemDirectory = nsnull;
+#endif
+
+
+nsDirectoryService* nsDirectoryService::mService = nsnull;
+
+nsDirectoryService::nsDirectoryService() :
+ mHashtable(256, PR_TRUE)
+{
+}
+
+NS_METHOD
+nsDirectoryService::Create(nsISupports *outer, REFNSIID aIID, void **aResult)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+ if (!mService)
+ {
+ mService = new nsDirectoryService();
+ if (!mService)
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ return mService->QueryInterface(aIID, aResult);
+}
+
+static const nsStaticAtom directory_atoms[] = {
+ { NS_XPCOM_CURRENT_PROCESS_DIR, &nsDirectoryService::sCurrentProcess },
+ { NS_XPCOM_COMPONENT_REGISTRY_FILE, &nsDirectoryService::sComponentRegistry },
+ { NS_XPCOM_COMPONENT_DIR, &nsDirectoryService::sComponentDirectory },
+ { NS_XPCOM_XPTI_REGISTRY_FILE, &nsDirectoryService::sXPTIRegistry },
+ { NS_GRE_DIR, &nsDirectoryService::sGRE_Directory },
+ { NS_GRE_COMPONENT_DIR, &nsDirectoryService::sGRE_ComponentDirectory },
+ { NS_OS_DRIVE_DIR, &nsDirectoryService::sOS_DriveDirectory },
+ { NS_OS_TEMP_DIR, &nsDirectoryService::sOS_TemporaryDirectory },
+ { NS_OS_CURRENT_PROCESS_DIR, &nsDirectoryService::sOS_CurrentProcessDirectory },
+ { NS_OS_CURRENT_WORKING_DIR, &nsDirectoryService::sOS_CurrentWorkingDirectory },
+ { NS_XPCOM_INIT_CURRENT_PROCESS_DIR, nsnull },
+#if defined (XP_MACOSX)
+ { NS_OS_SYSTEM_DIR, &nsDirectoryService::sDirectory },
+ { NS_MAC_DESKTOP_DIR, &nsDirectoryService::sDesktopDirectory },
+ { NS_MAC_TRASH_DIR, &nsDirectoryService::sTrashDirectory },
+ { NS_MAC_STARTUP_DIR, &nsDirectoryService::sStartupDirectory },
+ { NS_MAC_SHUTDOWN_DIR, &nsDirectoryService::sShutdownDirectory },
+ { NS_MAC_APPLE_MENU_DIR, &nsDirectoryService::sAppleMenuDirectory },
+ { NS_MAC_CONTROL_PANELS_DIR, &nsDirectoryService::sControlPanelDirectory },
+ { NS_MAC_EXTENSIONS_DIR, &nsDirectoryService::sExtensionDirectory },
+ { NS_MAC_FONTS_DIR, &nsDirectoryService::sFontsDirectory },
+ { NS_MAC_PREFS_DIR, &nsDirectoryService::sPreferencesDirectory },
+ { NS_MAC_DOCUMENTS_DIR, &nsDirectoryService::sDocumentsDirectory },
+ { NS_MAC_INTERNET_SEARCH_DIR, &nsDirectoryService::sInternetSearchDirectory },
+ { NS_MAC_USER_LIB_DIR, &nsDirectoryService::sUserLibDirectory },
+ { NS_OSX_HOME_DIR, &nsDirectoryService::sHomeDirectory },
+ { NS_OSX_DEFAULT_DOWNLOAD_DIR, &nsDirectoryService::sDefaultDownloadDirectory },
+ { NS_OSX_USER_DESKTOP_DIR, &nsDirectoryService::sUserDesktopDirectory },
+ { NS_OSX_LOCAL_DESKTOP_DIR, &nsDirectoryService::sLocalDesktopDirectory },
+ { NS_OSX_USER_APPLICATIONS_DIR, &nsDirectoryService::sUserApplicationsDirectory },
+ { NS_OSX_LOCAL_APPLICATIONS_DIR, &nsDirectoryService::sLocalApplicationsDirectory },
+ { NS_OSX_USER_DOCUMENTS_DIR, &nsDirectoryService::sUserDocumentsDirectory },
+ { NS_OSX_LOCAL_DOCUMENTS_DIR, &nsDirectoryService::sLocalDocumentsDirectory },
+ { NS_OSX_USER_INTERNET_PLUGIN_DIR, &nsDirectoryService::sUserInternetPlugInDirectory },
+ { NS_OSX_LOCAL_INTERNET_PLUGIN_DIR, &nsDirectoryService::sLocalInternetPlugInDirectory },
+ { NS_OSX_USER_FRAMEWORKS_DIR, &nsDirectoryService::sUserFrameworksDirectory },
+ { NS_OSX_LOCAL_FRAMEWORKS_DIR, &nsDirectoryService::sLocalFrameworksDirectory },
+ { NS_OSX_USER_PREFERENCES_DIR, &nsDirectoryService::sUserPreferencesDirectory },
+ { NS_OSX_LOCAL_PREFERENCES_DIR, &nsDirectoryService::sLocalPreferencesDirectory },
+ { NS_OSX_PICTURE_DOCUMENTS_DIR, &nsDirectoryService::sPictureDocumentsDirectory },
+ { NS_OSX_MOVIE_DOCUMENTS_DIR, &nsDirectoryService::sMovieDocumentsDirectory },
+ { NS_OSX_MUSIC_DOCUMENTS_DIR, &nsDirectoryService::sMusicDocumentsDirectory },
+ { NS_OSX_INTERNET_SITES_DIR, &nsDirectoryService::sInternetSitesDirectory },
+#elif defined (XP_WIN)
+ { NS_OS_SYSTEM_DIR, &nsDirectoryService::sSystemDirectory },
+ { NS_WIN_WINDOWS_DIR, &nsDirectoryService::sWindowsDirectory },
+ { NS_WIN_HOME_DIR, &nsDirectoryService::sHomeDirectory },
+ { NS_WIN_DESKTOP_DIR, &nsDirectoryService::sDesktop },
+ { NS_WIN_PROGRAMS_DIR, &nsDirectoryService::sPrograms },
+ { NS_WIN_CONTROLS_DIR, &nsDirectoryService::sControls },
+ { NS_WIN_PRINTERS_DIR, &nsDirectoryService::sPrinters },
+ { NS_WIN_PERSONAL_DIR, &nsDirectoryService::sPersonal },
+ { NS_WIN_FAVORITES_DIR, &nsDirectoryService::sFavorites },
+ { NS_WIN_STARTUP_DIR, &nsDirectoryService::sStartup },
+ { NS_WIN_RECENT_DIR, &nsDirectoryService::sRecent },
+ { NS_WIN_SEND_TO_DIR, &nsDirectoryService::sSendto },
+ { NS_WIN_BITBUCKET_DIR, &nsDirectoryService::sBitbucket },
+ { NS_WIN_STARTMENU_DIR, &nsDirectoryService::sStartmenu },
+ { NS_WIN_DESKTOP_DIRECTORY, &nsDirectoryService::sDesktopdirectory },
+ { NS_WIN_DRIVES_DIR, &nsDirectoryService::sDrives },
+ { NS_WIN_NETWORK_DIR, &nsDirectoryService::sNetwork },
+ { NS_WIN_NETHOOD_DIR, &nsDirectoryService::sNethood },
+ { NS_WIN_FONTS_DIR, &nsDirectoryService::sFonts },
+ { NS_WIN_TEMPLATES_DIR, &nsDirectoryService::sTemplates },
+ { NS_WIN_COMMON_STARTMENU_DIR, &nsDirectoryService::sCommon_Startmenu },
+ { NS_WIN_COMMON_PROGRAMS_DIR, &nsDirectoryService::sCommon_Programs },
+ { NS_WIN_COMMON_STARTUP_DIR, &nsDirectoryService::sCommon_Startup },
+ { NS_WIN_COMMON_DESKTOP_DIRECTORY, &nsDirectoryService::sCommon_Desktopdirectory },
+ { NS_WIN_APPDATA_DIR, &nsDirectoryService::sAppdata },
+ { NS_WIN_PRINTHOOD, &nsDirectoryService::sPrinthood },
+ { NS_WIN_COOKIES_DIR, &nsDirectoryService::sWinCookiesDirectory },
+#elif defined (XP_UNIX)
+ { NS_UNIX_LOCAL_DIR, &nsDirectoryService::sLocalDirectory },
+ { NS_UNIX_LIB_DIR, &nsDirectoryService::sLibDirectory },
+ { NS_UNIX_HOME_DIR, &nsDirectoryService::sHomeDirectory },
+#elif defined (XP_OS2)
+ { NS_OS_SYSTEM_DIR, &nsDirectoryService::sSystemDirectory },
+ { NS_OS2_DIR, &nsDirectoryService::sOS2Directory },
+ { NS_OS2_HOME_DIR, &nsDirectoryService::sHomeDirectory },
+ { NS_OS2_DESKTOP_DIR, &nsDirectoryService::sDesktopDirectory },
+#elif defined (XP_BEOS)
+ { NS_OS_SYSTEM_DIR, &nsDirectoryService::sSystemDirectory },
+ { NS_BEOS_SETTINGS_DIR, &nsDirectoryService::sSettingsDirectory },
+ { NS_BEOS_HOME_DIR, &nsDirectoryService::sHomeDirectory },
+ { NS_BEOS_DESKTOP_DIR, &nsDirectoryService::sDesktopDirectory },
+#endif
+};
+
+nsresult
+nsDirectoryService::Init()
+{
+ nsresult rv;
+
+ rv = NS_NewISupportsArray(getter_AddRefs(mProviders));
+ if (NS_FAILED(rv)) return rv;
+
+ NS_RegisterStaticAtoms(directory_atoms, NS_ARRAY_LENGTH(directory_atoms));
+
+ // Let the list hold the only reference to the provider.
+ nsAppFileLocationProvider *defaultProvider = new nsAppFileLocationProvider;
+ if (!defaultProvider)
+ return NS_ERROR_OUT_OF_MEMORY;
+ // AppendElement returns PR_TRUE for success.
+ rv = mProviders->AppendElement(defaultProvider) ? NS_OK : NS_ERROR_FAILURE;
+
+ return rv;
+}
+
+PRBool
+nsDirectoryService::ReleaseValues(nsHashKey* key, void* data, void* closure)
+{
+ nsISupports* value = (nsISupports*)data;
+ NS_IF_RELEASE(value);
+ return PR_TRUE;
+}
+
+nsDirectoryService::~nsDirectoryService()
+{
+ // clear the global
+ mService = nsnull;
+
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS4(nsDirectoryService, nsIProperties, nsIDirectoryService, nsIDirectoryServiceProvider, nsIDirectoryServiceProvider2)
+
+
+NS_IMETHODIMP
+nsDirectoryService::Undefine(const char* prop)
+{
+ nsCStringKey key(prop);
+ if (!mHashtable.Exists(&key))
+ return NS_ERROR_FAILURE;
+
+ mHashtable.Remove (&key);
+ return NS_OK;
+ }
+
+NS_IMETHODIMP
+nsDirectoryService::GetKeys(PRUint32 *count, char ***keys)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+struct FileData
+{
+ FileData(const char* aProperty,
+ const nsIID& aUUID) :
+ property(aProperty),
+ data(nsnull),
+ persistent(PR_TRUE),
+ uuid(aUUID) {}
+
+ const char* property;
+ nsISupports* data;
+ PRBool persistent;
+ const nsIID& uuid;
+};
+
+static PRBool FindProviderFile(nsISupports* aElement, void *aData)
+{
+ nsresult rv;
+ FileData* fileData = (FileData*)aData;
+ if (fileData->uuid.Equals(NS_GET_IID(nsISimpleEnumerator)))
+ {
+ // Not all providers implement this iface
+ nsCOMPtr<nsIDirectoryServiceProvider2> prov2 = do_QueryInterface(aElement);
+ if (prov2)
+ {
+ rv = prov2->GetFiles(fileData->property, (nsISimpleEnumerator **)&fileData->data);
+ if (NS_SUCCEEDED(rv) && fileData->data) {
+ fileData->persistent = PR_FALSE; // Enumerators can never be peristent
+ return PR_FALSE;
+ }
+ }
+ }
+ else
+ {
+ nsCOMPtr<nsIDirectoryServiceProvider> prov = do_QueryInterface(aElement);
+ if (!prov)
+ return PR_FALSE;
+ rv = prov->GetFile(fileData->property, &fileData->persistent, (nsIFile **)&fileData->data);
+ if (NS_SUCCEEDED(rv) && fileData->data)
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+}
+
+NS_IMETHODIMP
+nsDirectoryService::Get(const char* prop, const nsIID & uuid, void* *result)
+{
+ nsCStringKey key(prop);
+
+ nsCOMPtr<nsISupports> value = dont_AddRef(mHashtable.Get(&key));
+
+ if (value)
+ {
+ nsCOMPtr<nsIFile> cloneFile;
+ nsCOMPtr<nsIFile> cachedFile = do_QueryInterface(value);
+ NS_ASSERTION(cachedFile, "nsIFile expected");
+
+ cachedFile->Clone(getter_AddRefs(cloneFile));
+ return cloneFile->QueryInterface(uuid, result);
+ }
+
+ // it is not one of our defaults, lets check any providers
+ FileData fileData(prop, uuid);
+
+ mProviders->EnumerateBackwards(FindProviderFile, &fileData);
+ if (fileData.data)
+ {
+ if (fileData.persistent)
+ {
+ Set(prop, NS_STATIC_CAST(nsIFile*, fileData.data));
+ }
+ nsresult rv = (fileData.data)->QueryInterface(uuid, result);
+ NS_RELEASE(fileData.data); // addref occurs in FindProviderFile()
+ return rv;
+ }
+
+ FindProviderFile(NS_STATIC_CAST(nsIDirectoryServiceProvider*, this), &fileData);
+ if (fileData.data)
+ {
+ if (fileData.persistent)
+ {
+ Set(prop, NS_STATIC_CAST(nsIFile*, fileData.data));
+ }
+ nsresult rv = (fileData.data)->QueryInterface(uuid, result);
+ NS_RELEASE(fileData.data); // addref occurs in FindProviderFile()
+ return rv;
+ }
+
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsDirectoryService::Set(const char* prop, nsISupports* value)
+{
+ nsCStringKey key(prop);
+ if (mHashtable.Exists(&key) || value == nsnull)
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIFile> ourFile;
+ value->QueryInterface(NS_GET_IID(nsIFile), getter_AddRefs(ourFile));
+ if (ourFile)
+ {
+ nsCOMPtr<nsIFile> cloneFile;
+ ourFile->Clone (getter_AddRefs (cloneFile));
+ mHashtable.Put(&key, cloneFile);
+
+ return NS_OK;
+ }
+
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsDirectoryService::Has(const char *prop, PRBool *_retval)
+{
+ *_retval = PR_FALSE;
+ nsCOMPtr<nsIFile> value;
+ nsresult rv = Get(prop, NS_GET_IID(nsIFile), getter_AddRefs(value));
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (value)
+ {
+ *_retval = PR_TRUE;
+ }
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsDirectoryService::RegisterProvider(nsIDirectoryServiceProvider *prov)
+{
+ nsresult rv;
+ if (!prov)
+ return NS_ERROR_FAILURE;
+ if (!mProviders)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ nsCOMPtr<nsISupports> supports = do_QueryInterface(prov, &rv);
+ if (NS_FAILED(rv)) return rv;
+
+ // AppendElement returns PR_TRUE for success.
+ return mProviders->AppendElement(supports) ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsDirectoryService::UnregisterProvider(nsIDirectoryServiceProvider *prov)
+{
+ nsresult rv;
+ if (!prov)
+ return NS_ERROR_FAILURE;
+ if (!mProviders)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ nsCOMPtr<nsISupports> supports = do_QueryInterface(prov, &rv);
+ if (NS_FAILED(rv)) return rv;
+
+ // RemoveElement returns PR_TRUE for success.
+ return mProviders->RemoveElement(supports) ? NS_OK : NS_ERROR_FAILURE;
+}
+
+// DO NOT ADD ANY LOCATIONS TO THIS FUNCTION UNTIL YOU TALK TO: dougt@netscape.com.
+// This is meant to be a place of xpcom or system specific file locations, not
+// application specific locations. If you need the later, register a callback for
+// your application.
+
+NS_IMETHODIMP
+nsDirectoryService::GetFile(const char *prop, PRBool *persistent, nsIFile **_retval)
+{
+ nsCOMPtr<nsILocalFile> localFile;
+ nsresult rv = NS_ERROR_FAILURE;
+
+ *_retval = nsnull;
+ *persistent = PR_TRUE;
+
+ nsIAtom* inAtom = NS_NewAtom(prop);
+
+ // check to see if it is one of our defaults
+
+ if (inAtom == nsDirectoryService::sCurrentProcess ||
+ inAtom == nsDirectoryService::sOS_CurrentProcessDirectory )
+ {
+ rv = GetCurrentProcessDirectory(getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sComponentRegistry)
+ {
+ rv = GetCurrentProcessDirectory(getter_AddRefs(localFile));
+ if (!localFile)
+ return NS_ERROR_FAILURE;
+
+ localFile->AppendNative(COMPONENT_DIRECTORY);
+ localFile->AppendNative(COMPONENT_REGISTRY_NAME);
+ }
+ else if (inAtom == nsDirectoryService::sXPTIRegistry)
+ {
+ rv = GetCurrentProcessDirectory(getter_AddRefs(localFile));
+ if (!localFile)
+ return NS_ERROR_FAILURE;
+
+ localFile->AppendNative(COMPONENT_DIRECTORY);
+ localFile->AppendNative(XPTI_REGISTRY_NAME);
+ }
+
+ // Unless otherwise set, the core pieces of the GRE exist
+ // in the current process directory.
+ else if (inAtom == nsDirectoryService::sGRE_Directory)
+ {
+ rv = GetCurrentProcessDirectory(getter_AddRefs(localFile));
+ }
+ // the GRE components directory is relative to the GRE directory
+ // by default; applications may override this behavior in special
+ // cases
+ else if (inAtom == nsDirectoryService::sGRE_ComponentDirectory)
+ {
+ rv = Get(NS_GRE_DIR, nsILocalFile::GetIID(), getter_AddRefs(localFile));
+ if (localFile)
+ localFile->AppendNative(COMPONENT_DIRECTORY);
+ }
+ else if (inAtom == nsDirectoryService::sComponentDirectory)
+ {
+ rv = GetCurrentProcessDirectory(getter_AddRefs(localFile));
+ if (localFile)
+ localFile->AppendNative(COMPONENT_DIRECTORY);
+ }
+ else if (inAtom == nsDirectoryService::sOS_DriveDirectory)
+ {
+ rv = GetSpecialSystemDirectory(OS_DriveDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sOS_TemporaryDirectory)
+ {
+ rv = GetSpecialSystemDirectory(OS_TemporaryDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sOS_CurrentProcessDirectory)
+ {
+ rv = GetSpecialSystemDirectory(OS_CurrentProcessDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sOS_CurrentWorkingDirectory)
+ {
+ rv = GetSpecialSystemDirectory(OS_CurrentWorkingDirectory, getter_AddRefs(localFile));
+ }
+
+#if defined(XP_MACOSX)
+ else if (inAtom == nsDirectoryService::sDirectory)
+ {
+ rv = GetOSXFolderType(kClassicDomain, kSystemFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sDesktopDirectory)
+ {
+ rv = GetOSXFolderType(kClassicDomain, kDesktopFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sTrashDirectory)
+ {
+ rv = GetOSXFolderType(kClassicDomain, kTrashFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sStartupDirectory)
+ {
+ rv = GetOSXFolderType(kClassicDomain, kStartupFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sShutdownDirectory)
+ {
+ rv = GetOSXFolderType(kClassicDomain, kShutdownFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sAppleMenuDirectory)
+ {
+ rv = GetOSXFolderType(kClassicDomain, kAppleMenuFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sControlPanelDirectory)
+ {
+ rv = GetOSXFolderType(kClassicDomain, kControlPanelFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sExtensionDirectory)
+ {
+ rv = GetOSXFolderType(kClassicDomain, kExtensionFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sFontsDirectory)
+ {
+ rv = GetOSXFolderType(kClassicDomain, kFontsFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sPreferencesDirectory)
+ {
+ rv = GetOSXFolderType(kClassicDomain, kPreferencesFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sDocumentsDirectory)
+ {
+ rv = GetOSXFolderType(kClassicDomain, kDocumentsFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sInternetSearchDirectory)
+ {
+ rv = GetOSXFolderType(kClassicDomain, kInternetSearchSitesFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sUserLibDirectory)
+ {
+ rv = GetOSXFolderType(kUserDomain, kDomainLibraryFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sHomeDirectory)
+ {
+ rv = GetOSXFolderType(kUserDomain, kDomainTopLevelFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sDefaultDownloadDirectory)
+ {
+ NS_NewLocalFile(EmptyString(), PR_TRUE, getter_AddRefs(localFile));
+ nsCOMPtr<nsILocalFileMac> localMacFile(do_QueryInterface(localFile));
+
+ if (localMacFile)
+ {
+ OSErr err;
+ ICInstance icInstance;
+
+ err = ::ICStart(&icInstance, 'XPCM');
+ if (err == noErr)
+ {
+ ICAttr attrs;
+ ICFileSpec icFileSpec;
+ long size = kICFileSpecHeaderSize;
+ err = ::ICGetPref(icInstance, kICDownloadFolder, &attrs, &icFileSpec, &size);
+ if (err == noErr || (err == icTruncatedErr && size >= kICFileSpecHeaderSize))
+ {
+ rv = localMacFile->InitWithFSSpec(&icFileSpec.fss);
+ }
+ ::ICStop(icInstance);
+ }
+
+ if (NS_FAILED(rv))
+ {
+ // We got an error getting the DL folder from IC so try finding the user's Desktop folder
+ rv = GetOSXFolderType(kUserDomain, kDesktopFolderType, getter_AddRefs(localFile));
+ }
+ }
+
+ // Don't cache the DL directory as the user may change it while we're running.
+ // Negligible perf hit as this directory is only requested for downloads
+ *persistent = PR_FALSE;
+ }
+ else if (inAtom == nsDirectoryService::sUserDesktopDirectory)
+ {
+ rv = GetOSXFolderType(kUserDomain, kDesktopFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sLocalDesktopDirectory)
+ {
+ rv = GetOSXFolderType(kLocalDomain, kDesktopFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sUserApplicationsDirectory)
+ {
+ rv = GetOSXFolderType(kUserDomain, kApplicationsFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sLocalApplicationsDirectory)
+ {
+ rv = GetOSXFolderType(kLocalDomain, kApplicationsFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sUserDocumentsDirectory)
+ {
+ rv = GetOSXFolderType(kUserDomain, kDocumentsFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sLocalDocumentsDirectory)
+ {
+ rv = GetOSXFolderType(kLocalDomain, kDocumentsFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sUserInternetPlugInDirectory)
+ {
+ rv = GetOSXFolderType(kUserDomain, kInternetPlugInFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sLocalInternetPlugInDirectory)
+ {
+ rv = GetOSXFolderType(kLocalDomain, kInternetPlugInFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sUserFrameworksDirectory)
+ {
+ rv = GetOSXFolderType(kUserDomain, kFrameworksFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sLocalFrameworksDirectory)
+ {
+ rv = GetOSXFolderType(kLocalDomain, kFrameworksFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sUserPreferencesDirectory)
+ {
+ rv = GetOSXFolderType(kUserDomain, kPreferencesFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sLocalPreferencesDirectory)
+ {
+ rv = GetOSXFolderType(kLocalDomain, kPreferencesFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sPictureDocumentsDirectory)
+ {
+ rv = GetOSXFolderType(kUserDomain, kPictureDocumentsFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sMovieDocumentsDirectory)
+ {
+ rv = GetOSXFolderType(kUserDomain, kMovieDocumentsFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sMusicDocumentsDirectory)
+ {
+ rv = GetOSXFolderType(kUserDomain, kMusicDocumentsFolderType, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sInternetSitesDirectory)
+ {
+ rv = GetOSXFolderType(kUserDomain, kInternetSitesFolderType, getter_AddRefs(localFile));
+ }
+#elif defined (XP_WIN)
+ else if (inAtom == nsDirectoryService::sSystemDirectory)
+ {
+ rv = GetSpecialSystemDirectory(Win_SystemDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sWindowsDirectory)
+ {
+ rv = GetSpecialSystemDirectory(Win_WindowsDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sHomeDirectory)
+ {
+ rv = GetSpecialSystemDirectory(Win_HomeDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sDesktop)
+ {
+ rv = GetSpecialSystemDirectory(Win_Desktop, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sPrograms)
+ {
+ rv = GetSpecialSystemDirectory(Win_Programs, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sControls)
+ {
+ rv = GetSpecialSystemDirectory(Win_Controls, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sPrinters)
+ {
+ rv = GetSpecialSystemDirectory(Win_Printers, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sPersonal)
+ {
+ rv = GetSpecialSystemDirectory(Win_Personal, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sFavorites)
+ {
+ rv = GetSpecialSystemDirectory(Win_Favorites, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sStartup)
+ {
+ rv = GetSpecialSystemDirectory(Win_Startup, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sRecent)
+ {
+ rv = GetSpecialSystemDirectory(Win_Recent, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sSendto)
+ {
+ rv = GetSpecialSystemDirectory(Win_Sendto, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sBitbucket)
+ {
+ rv = GetSpecialSystemDirectory(Win_Bitbucket, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sStartmenu)
+ {
+ rv = GetSpecialSystemDirectory(Win_Startmenu, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sDesktopdirectory)
+ {
+ rv = GetSpecialSystemDirectory(Win_Desktopdirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sDrives)
+ {
+ rv = GetSpecialSystemDirectory(Win_Drives, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sNetwork)
+ {
+ rv = GetSpecialSystemDirectory(Win_Network, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sNethood)
+ {
+ rv = GetSpecialSystemDirectory(Win_Nethood, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sFonts)
+ {
+ rv = GetSpecialSystemDirectory(Win_Fonts, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sTemplates)
+ {
+ rv = GetSpecialSystemDirectory(Win_Templates, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sCommon_Startmenu)
+ {
+ rv = GetSpecialSystemDirectory(Win_Common_Startmenu, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sCommon_Programs)
+ {
+ rv = GetSpecialSystemDirectory(Win_Common_Programs, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sCommon_Startup)
+ {
+ rv = GetSpecialSystemDirectory(Win_Common_Startup, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sCommon_Desktopdirectory)
+ {
+ rv = GetSpecialSystemDirectory(Win_Common_Desktopdirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sAppdata)
+ {
+ rv = GetSpecialSystemDirectory(Win_Appdata, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sPrinthood)
+ {
+ rv = GetSpecialSystemDirectory(Win_Printhood, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sWinCookiesDirectory)
+ {
+ rv = GetSpecialSystemDirectory(Win_Cookies, getter_AddRefs(localFile));
+ }
+#elif defined (XP_UNIX)
+
+ else if (inAtom == nsDirectoryService::sLocalDirectory)
+ {
+ rv = GetSpecialSystemDirectory(Unix_LocalDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sLibDirectory)
+ {
+ rv = GetSpecialSystemDirectory(Unix_LibDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sHomeDirectory)
+ {
+ rv = GetSpecialSystemDirectory(Unix_HomeDirectory, getter_AddRefs(localFile));
+ }
+#elif defined (XP_OS2)
+ else if (inAtom == nsDirectoryService::sSystemDirectory)
+ {
+ rv = GetSpecialSystemDirectory(OS2_SystemDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sOS2Directory)
+ {
+ rv = GetSpecialSystemDirectory(OS2_OS2Directory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sHomeDirectory)
+ {
+ rv = GetSpecialSystemDirectory(OS2_HomeDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sDesktopDirectory)
+ {
+ rv = GetSpecialSystemDirectory(OS2_DesktopDirectory, getter_AddRefs(localFile));
+ }
+#elif defined (XP_BEOS)
+ else if (inAtom == nsDirectoryService::sSettingsDirectory)
+ {
+ rv = GetSpecialSystemDirectory(BeOS_SettingsDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sHomeDirectory)
+ {
+ rv = GetSpecialSystemDirectory(BeOS_HomeDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sDesktopDirectory)
+ {
+ rv = GetSpecialSystemDirectory(BeOS_DesktopDirectory, getter_AddRefs(localFile));
+ }
+ else if (inAtom == nsDirectoryService::sSystemDirectory)
+ {
+ rv = GetSpecialSystemDirectory(BeOS_SystemDirectory, getter_AddRefs(localFile));
+ }
+#endif
+
+
+ NS_RELEASE(inAtom);
+
+ if (localFile && NS_SUCCEEDED(rv))
+ return localFile->QueryInterface(NS_GET_IID(nsIFile), (void**)_retval);
+#ifdef DEBUG_dougt
+ printf("Failed to find directory for key: %s\n", prop);
+#endif
+ return rv;
+}
+
+NS_IMETHODIMP
+nsDirectoryService::GetFiles(const char *prop, nsISimpleEnumerator **_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = nsnull;
+
+ return NS_ERROR_FAILURE;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsDirectoryService.h b/src/libs/xpcom18a4/xpcom/io/nsDirectoryService.h
new file mode 100644
index 00000000..67e6e371
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsDirectoryService.h
@@ -0,0 +1,177 @@
+/* -*- 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):
+ * IBM Corp.
+ *
+ * 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 nsDirectoryService_h___
+#define nsDirectoryService_h___
+
+#include "nsIDirectoryService.h"
+#include "nsHashtable.h"
+#include "nsILocalFile.h"
+#include "nsISupportsArray.h"
+#include "nsIAtom.h"
+
+#define NS_XPCOM_INIT_CURRENT_PROCESS_DIR "MozBinD" // Can be used to set NS_XPCOM_CURRENT_PROCESS_DIR
+ // CANNOT be used to GET a location
+
+class nsDirectoryService : public nsIDirectoryService,
+ public nsIProperties,
+ public nsIDirectoryServiceProvider2
+{
+ public:
+
+ NS_DEFINE_STATIC_CID_ACCESSOR(NS_DIRECTORY_SERVICE_CID);
+
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+
+ NS_DECL_NSIPROPERTIES
+
+ NS_DECL_NSIDIRECTORYSERVICE
+
+ NS_DECL_NSIDIRECTORYSERVICEPROVIDER
+
+ NS_DECL_NSIDIRECTORYSERVICEPROVIDER2
+
+ nsDirectoryService();
+
+ static NS_METHOD
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+private:
+ ~nsDirectoryService();
+
+ nsresult GetCurrentProcessDirectory(nsILocalFile** aFile);
+
+ static nsDirectoryService* mService;
+ static PRBool PR_CALLBACK ReleaseValues(nsHashKey* key, void* data, void* closure);
+ nsSupportsHashtable mHashtable;
+ nsCOMPtr<nsISupportsArray> mProviders;
+
+public:
+ static nsIAtom *sCurrentProcess;
+ static nsIAtom *sComponentRegistry;
+ static nsIAtom *sComponentDirectory;
+ static nsIAtom *sXPTIRegistry;
+ static nsIAtom *sGRE_Directory;
+ static nsIAtom *sGRE_ComponentDirectory;
+ static nsIAtom *sOS_DriveDirectory;
+ static nsIAtom *sOS_TemporaryDirectory;
+ static nsIAtom *sOS_CurrentProcessDirectory;
+ static nsIAtom *sOS_CurrentWorkingDirectory;
+#if defined (XP_MACOSX)
+ static nsIAtom *sDirectory;
+ static nsIAtom *sDesktopDirectory;
+ static nsIAtom *sTrashDirectory;
+ static nsIAtom *sStartupDirectory;
+ static nsIAtom *sShutdownDirectory;
+ static nsIAtom *sAppleMenuDirectory;
+ static nsIAtom *sControlPanelDirectory;
+ static nsIAtom *sExtensionDirectory;
+ static nsIAtom *sFontsDirectory;
+ static nsIAtom *sPreferencesDirectory;
+ static nsIAtom *sDocumentsDirectory;
+ static nsIAtom *sInternetSearchDirectory;
+ static nsIAtom *sUserLibDirectory;
+ static nsIAtom *sHomeDirectory;
+ static nsIAtom *sDefaultDownloadDirectory;
+ static nsIAtom *sUserDesktopDirectory;
+ static nsIAtom *sLocalDesktopDirectory;
+ static nsIAtom *sUserApplicationsDirectory;
+ static nsIAtom *sLocalApplicationsDirectory;
+ static nsIAtom *sUserDocumentsDirectory;
+ static nsIAtom *sLocalDocumentsDirectory;
+ static nsIAtom *sUserInternetPlugInDirectory;
+ static nsIAtom *sLocalInternetPlugInDirectory;
+ static nsIAtom *sUserFrameworksDirectory;
+ static nsIAtom *sLocalFrameworksDirectory;
+ static nsIAtom *sUserPreferencesDirectory;
+ static nsIAtom *sLocalPreferencesDirectory;
+ static nsIAtom *sPictureDocumentsDirectory;
+ static nsIAtom *sMovieDocumentsDirectory;
+ static nsIAtom *sMusicDocumentsDirectory;
+ static nsIAtom *sInternetSitesDirectory;
+#elif defined (XP_WIN)
+ static nsIAtom *sSystemDirectory;
+ static nsIAtom *sWindowsDirectory;
+ static nsIAtom *sHomeDirectory;
+ static nsIAtom *sDesktop;
+ static nsIAtom *sPrograms;
+ static nsIAtom *sControls;
+ static nsIAtom *sPrinters;
+ static nsIAtom *sPersonal;
+ static nsIAtom *sFavorites;
+ static nsIAtom *sStartup;
+ static nsIAtom *sRecent;
+ static nsIAtom *sSendto;
+ static nsIAtom *sBitbucket;
+ static nsIAtom *sStartmenu;
+ static nsIAtom *sDesktopdirectory;
+ static nsIAtom *sDrives;
+ static nsIAtom *sNetwork;
+ static nsIAtom *sNethood;
+ static nsIAtom *sFonts;
+ static nsIAtom *sTemplates;
+ static nsIAtom *sCommon_Startmenu;
+ static nsIAtom *sCommon_Programs;
+ static nsIAtom *sCommon_Startup;
+ static nsIAtom *sCommon_Desktopdirectory;
+ static nsIAtom *sAppdata;
+ static nsIAtom *sPrinthood;
+ static nsIAtom *sWinCookiesDirectory;
+#elif defined (XP_UNIX)
+ static nsIAtom *sLocalDirectory;
+ static nsIAtom *sLibDirectory;
+ static nsIAtom *sHomeDirectory;
+#elif defined (XP_OS2)
+ static nsIAtom *sSystemDirectory;
+ static nsIAtom *sOS2Directory;
+ static nsIAtom *sHomeDirectory;
+ static nsIAtom *sDesktopDirectory;
+#elif defined (XP_BEOS)
+ static nsIAtom *sSettingsDirectory;
+ static nsIAtom *sHomeDirectory;
+ static nsIAtom *sDesktopDirectory;
+ static nsIAtom *sSystemDirectory;
+#endif
+
+
+};
+
+
+#endif
+
diff --git a/src/libs/xpcom18a4/xpcom/io/nsDirectoryServiceDefs.h b/src/libs/xpcom18a4/xpcom/io/nsDirectoryServiceDefs.h
new file mode 100644
index 00000000..6b3c8ba4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsDirectoryServiceDefs.h
@@ -0,0 +1,197 @@
+/* -*- 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) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Conrad Carlen conrad@ingress.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 ***** */
+
+/**
+ * Defines the property names for directories available from
+ * nsIDirectoryService. These dirs are always available even if no
+ * nsIDirectoryServiceProviders have been registered with the service.
+ * Application level keys are defined in nsAppDirectoryServiceDefs.h.
+ *
+ * Keys whose definition ends in "DIR" or "FILE" return a single nsIFile (or
+ * subclass). Keys whose definition ends in "LIST" return an nsISimpleEnumerator
+ * which enumerates a list of file objects.
+ *
+ * Defines listed in this file are FROZEN. This list may grow.
+ */
+
+#ifndef nsDirectoryServiceDefs_h___
+#define nsDirectoryServiceDefs_h___
+
+/* General OS specific locations */
+
+#define NS_OS_HOME_DIR "Home"
+#define NS_OS_TEMP_DIR "TmpD"
+#define NS_OS_CURRENT_WORKING_DIR "CurWorkD"
+
+/* Property returns the directory in which the procces was started from.
+ * On Unix this will be the path in the VBOX_XPCOM_HOME env var and if
+ * unset will be the current working directory.
+ */
+#define NS_OS_CURRENT_PROCESS_DIR "CurProcD"
+
+/* This location is similar to NS_OS_CURRENT_PROCESS_DIR, however,
+ * NS_XPCOM_CURRENT_PROCESS_DIR can be overriden by passing a "bin
+ * directory" to NS_InitXPCOM2().
+ */
+#define NS_XPCOM_CURRENT_PROCESS_DIR "XCurProcD"
+
+/* Property will return the location of the application components
+ * directory. By default, this directory will be contained in the
+ * NS_XPCOM_CURRENT_PROCESS_DIR.
+ */
+#define NS_XPCOM_COMPONENT_DIR "ComsD"
+
+/* Property will return a list of components directories that will
+ * will be registered after the application components directory.
+ */
+#define NS_XPCOM_COMPONENT_DIR_LIST "ComsDL"
+
+/* Property will return the location of the application components
+ * registry file.
+ */
+#define NS_XPCOM_COMPONENT_REGISTRY_FILE "ComRegF"
+
+/* Property will return the location of the application XPTI
+ * registry file.
+ */
+#define NS_XPCOM_XPTI_REGISTRY_FILE "XptiRegF"
+
+/* Property will return the location of the the XPCOM Shared Library.
+ */
+#define NS_XPCOM_LIBRARY_FILE "XpcomLib"
+
+/* Property will return the current location of the the GRE directory.
+ * If no GRE is used, this propery will behave like
+ * NS_XPCOM_CURRENT_PROCESS_DIR.
+ */
+#define NS_GRE_DIR "GreD"
+
+/* Property will return the current location of the the GRE component
+ * directory. If no GRE is used, this propery will behave like
+ * NS_XPCOM_COMPONENT_DIR.
+ */
+#define NS_GRE_COMPONENT_DIR "GreComsD"
+
+
+/* Platform Specific Locations */
+
+#if !defined (XP_UNIX) || defined(XP_MACOSX)
+ #define NS_OS_SYSTEM_DIR "SysD"
+#endif
+
+#if defined (XP_MACOSX)
+ #define NS_MAC_DESKTOP_DIR "Desk"
+ #define NS_MAC_TRASH_DIR "Trsh"
+ #define NS_MAC_STARTUP_DIR "Strt"
+ #define NS_MAC_SHUTDOWN_DIR "Shdwn"
+ #define NS_MAC_APPLE_MENU_DIR "ApplMenu"
+ #define NS_MAC_CONTROL_PANELS_DIR "CntlPnl"
+ #define NS_MAC_EXTENSIONS_DIR "Exts"
+ #define NS_MAC_FONTS_DIR "Fnts"
+ #define NS_MAC_PREFS_DIR "Prfs"
+ #define NS_MAC_DOCUMENTS_DIR "Docs"
+ #define NS_MAC_INTERNET_SEARCH_DIR "ISrch"
+ #define NS_OSX_HOME_DIR "Home"
+ #define NS_MAC_HOME_DIR NS_OSX_HOME_DIR
+ #define NS_MAC_DEFAULT_DOWNLOAD_DIR "DfltDwnld"
+ #define NS_MAC_USER_LIB_DIR "ULibDir" // Only available under OS X
+ #define NS_OSX_DEFAULT_DOWNLOAD_DIR NS_MAC_DEFAULT_DOWNLOAD_DIR
+ #define NS_OSX_USER_DESKTOP_DIR "UsrDsk"
+ #define NS_OSX_LOCAL_DESKTOP_DIR "LocDsk"
+ #define NS_OSX_USER_APPLICATIONS_DIR "UsrApp"
+ #define NS_OSX_LOCAL_APPLICATIONS_DIR "LocApp"
+ #define NS_OSX_USER_DOCUMENTS_DIR "UsrDocs"
+ #define NS_OSX_LOCAL_DOCUMENTS_DIR "LocDocs"
+ #define NS_OSX_USER_INTERNET_PLUGIN_DIR "UsrIntrntPlgn"
+ #define NS_OSX_LOCAL_INTERNET_PLUGIN_DIR "LoclIntrntPlgn"
+ #define NS_OSX_USER_FRAMEWORKS_DIR "UsrFrmwrks"
+ #define NS_OSX_LOCAL_FRAMEWORKS_DIR "LocFrmwrks"
+ #define NS_OSX_USER_PREFERENCES_DIR "UsrPrfs"
+ #define NS_OSX_LOCAL_PREFERENCES_DIR "LocPrfs"
+ #define NS_OSX_PICTURE_DOCUMENTS_DIR "Pct"
+ #define NS_OSX_MOVIE_DOCUMENTS_DIR "Mov"
+ #define NS_OSX_MUSIC_DOCUMENTS_DIR "Music"
+ #define NS_OSX_INTERNET_SITES_DIR "IntrntSts"
+#elif defined (XP_WIN)
+ #define NS_WIN_WINDOWS_DIR "WinD"
+ #define NS_WIN_HOME_DIR "Home"
+ #define NS_WIN_DESKTOP_DIR "DeskV" // virtual folder at the root of the namespace
+ #define NS_WIN_PROGRAMS_DIR "Progs"
+ #define NS_WIN_CONTROLS_DIR "Cntls"
+ #define NS_WIN_PRINTERS_DIR "Prnts"
+ #define NS_WIN_PERSONAL_DIR "Pers"
+ #define NS_WIN_FAVORITES_DIR "Favs"
+ #define NS_WIN_STARTUP_DIR "Strt"
+ #define NS_WIN_RECENT_DIR "Rcnt"
+ #define NS_WIN_SEND_TO_DIR "SndTo"
+ #define NS_WIN_BITBUCKET_DIR "Buckt"
+ #define NS_WIN_STARTMENU_DIR "Strt"
+ #define NS_WIN_DESKTOP_DIRECTORY "DeskP" // file sys dir which physically stores objects on desktop
+ #define NS_WIN_DRIVES_DIR "Drivs"
+ #define NS_WIN_NETWORK_DIR "NetW"
+ #define NS_WIN_NETHOOD_DIR "netH"
+ #define NS_WIN_FONTS_DIR "Fnts"
+ #define NS_WIN_TEMPLATES_DIR "Tmpls"
+ #define NS_WIN_COMMON_STARTMENU_DIR "CmStrt"
+ #define NS_WIN_COMMON_PROGRAMS_DIR "CmPrgs"
+ #define NS_WIN_COMMON_STARTUP_DIR "CmStrt"
+ #define NS_WIN_COMMON_DESKTOP_DIRECTORY "CmDeskP"
+ #define NS_WIN_APPDATA_DIR "AppData"
+ #define NS_WIN_PRINTHOOD "PrntHd"
+ #define NS_WIN_COOKIES_DIR "CookD"
+#elif defined (XP_UNIX)
+ #define NS_UNIX_LOCAL_DIR "Locl"
+ #define NS_UNIX_LIB_DIR "LibD"
+ #define NS_UNIX_HOME_DIR "Home"
+#elif defined (XP_OS2)
+ #define NS_OS2_DIR "OS2Dir"
+ #define NS_OS2_HOME_DIR "Home"
+ #define NS_OS2_DESKTOP_DIR "Desk"
+#elif defined (XP_BEOS)
+ #define NS_BEOS_SETTINGS_DIR "Setngs"
+ #define NS_BEOS_HOME_DIR "Home"
+ #define NS_BEOS_DESKTOP_DIR "Desk"
+#endif
+
+/* Deprecated */
+
+#define NS_OS_DRIVE_DIR "DrvD"
+
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/io/nsDirectoryServiceUtils.h b/src/libs/xpcom18a4/xpcom/io/nsDirectoryServiceUtils.h
new file mode 100644
index 00000000..f2482c76
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsDirectoryServiceUtils.h
@@ -0,0 +1,61 @@
+/* -*- 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-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 ***** */
+
+#ifndef nsDirectoryServiceUtils_h___
+#define nsDirectoryServiceUtils_h___
+
+#include "nsIServiceManager.h"
+#include "nsIProperties.h"
+#include "nsCOMPtr.h"
+
+#define NS_DIRECTORY_SERVICE_CID {0xf00152d0,0xb40b,0x11d3,{0x8c, 0x9c, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74}}
+
+inline nsresult
+NS_GetSpecialDirectory(const char* specialDirName, nsIFile* *result)
+{
+ nsresult rv;
+ static NS_DEFINE_CID(kDirectoryServiceCID, NS_DIRECTORY_SERVICE_CID);
+ nsCOMPtr<nsIProperties> serv(do_GetService(kDirectoryServiceCID, &rv));
+ if (NS_FAILED(rv))
+ return rv;
+
+ return serv->Get(specialDirName, NS_GET_IID(nsIFile),
+ NS_REINTERPRET_CAST(void**, result));
+}
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/io/nsEscape.cpp b/src/libs/xpcom18a4/xpcom/io/nsEscape.cpp
new file mode 100644
index 00000000..758339e4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsEscape.cpp
@@ -0,0 +1,491 @@
+/* -*- 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 ***** */
+
+// First checked in on 98/12/03 by John R. McMullen, derived from net.h/mkparse.c.
+
+#include "nsEscape.h"
+#include "nsMemory.h"
+#include "nsCRT.h"
+#include "nsReadableUtils.h"
+
+const int netCharType[256] =
+/* Bit 0 xalpha -- the alphas
+** Bit 1 xpalpha -- as xalpha but
+** converts spaces to plus and plus to %2B
+** Bit 3 ... path -- as xalphas but doesn't escape '/'
+*/
+ /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+ { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1x */
+ 0,0,0,0,0,0,0,0,0,0,7,4,0,7,7,4, /* 2x !"#$%&'()*+,-./ */
+ 7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0, /* 3x 0123456789:;<=>? */
+ 0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, /* 4x @ABCDEFGHIJKLMNO */
+ /* bits for '@' changed from 7 to 0 so '@' can be escaped */
+ /* in usernames and passwords in publishing. */
+ 7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,7, /* 5X PQRSTUVWXYZ[\]^_ */
+ 0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, /* 6x `abcdefghijklmno */
+ 7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0, /* 7X pqrstuvwxyz{\}~ DEL */
+ 0, };
+
+/* decode % escaped hex codes into character values
+ */
+#define UNHEX(C) \
+ ((C >= '0' && C <= '9') ? C - '0' : \
+ ((C >= 'A' && C <= 'F') ? C - 'A' + 10 : \
+ ((C >= 'a' && C <= 'f') ? C - 'a' + 10 : 0)))
+
+
+#define IS_OK(C) (netCharType[((unsigned int) (C))] & (mask))
+#define HEX_ESCAPE '%'
+
+//----------------------------------------------------------------------------------------
+static char* nsEscapeCount(
+ const char * str,
+ PRInt32 len,
+ nsEscapeMask mask,
+ PRInt32* out_len)
+//----------------------------------------------------------------------------------------
+{
+ if (!str)
+ return 0;
+
+ int i, extra = 0;
+ static const char hexChars[] = "0123456789ABCDEF";
+
+ register const unsigned char* src = (const unsigned char *) str;
+ for (i = 0; i < len; i++)
+ {
+ if (!IS_OK(*src++))
+ extra += 2; /* the escape, plus an extra byte for each nibble */
+ }
+
+ char* result = (char *)nsMemory::Alloc(len + extra + 1);
+ if (!result)
+ return 0;
+
+ register unsigned char* dst = (unsigned char *) result;
+ src = (const unsigned char *) str;
+ if (mask == url_XPAlphas)
+ {
+ for (i = 0; i < len; i++)
+ {
+ unsigned char c = *src++;
+ if (IS_OK(c))
+ *dst++ = c;
+ else if (c == ' ')
+ *dst++ = '+'; /* convert spaces to pluses */
+ else
+ {
+ *dst++ = HEX_ESCAPE;
+ *dst++ = hexChars[c >> 4]; /* high nibble */
+ *dst++ = hexChars[c & 0x0f]; /* low nibble */
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < len; i++)
+ {
+ unsigned char c = *src++;
+ if (IS_OK(c))
+ *dst++ = c;
+ else
+ {
+ *dst++ = HEX_ESCAPE;
+ *dst++ = hexChars[c >> 4]; /* high nibble */
+ *dst++ = hexChars[c & 0x0f]; /* low nibble */
+ }
+ }
+ }
+
+ *dst = '\0'; /* tack on eos */
+ if(out_len)
+ *out_len = dst - (unsigned char *) result;
+ return result;
+}
+
+//----------------------------------------------------------------------------------------
+NS_COM char* nsEscape(const char * str, nsEscapeMask mask)
+//----------------------------------------------------------------------------------------
+{
+ if(!str)
+ return NULL;
+ return nsEscapeCount(str, (PRInt32)strlen(str), mask, NULL);
+}
+
+//----------------------------------------------------------------------------------------
+NS_COM char* nsUnescape(char * str)
+//----------------------------------------------------------------------------------------
+{
+ nsUnescapeCount(str);
+ return str;
+}
+
+//----------------------------------------------------------------------------------------
+NS_COM PRInt32 nsUnescapeCount(char * str)
+//----------------------------------------------------------------------------------------
+{
+ register char *src = str;
+ register char *dst = str;
+ static const char hexChars[] = "0123456789ABCDEFabcdef";
+
+ char c1[] = " ";
+ char c2[] = " ";
+ char* const pc1 = c1;
+ char* const pc2 = c2;
+
+ while (*src)
+ {
+ c1[0] = *(src+1);
+ if (*(src+1) == '\0')
+ c2[0] = '\0';
+ else
+ c2[0] = *(src+2);
+
+ if (*src != HEX_ESCAPE || PL_strpbrk(pc1, hexChars) == 0 ||
+ PL_strpbrk(pc2, hexChars) == 0 )
+ *dst++ = *src++;
+ else
+ {
+ src++; /* walk over escape */
+ if (*src)
+ {
+ *dst = UNHEX(*src) << 4;
+ src++;
+ }
+ if (*src)
+ {
+ *dst = (*dst + UNHEX(*src));
+ src++;
+ }
+ dst++;
+ }
+ }
+
+ *dst = 0;
+ return (int)(dst - str);
+
+} /* NET_UnEscapeCnt */
+
+
+NS_COM char *
+nsEscapeHTML(const char * string)
+{
+ /* XXX Hardcoded max entity len. The +1 is for the trailing null. */
+ char *rv = (char *) nsMemory::Alloc(strlen(string) * 6 + 1);
+ char *ptr = rv;
+
+ if(rv)
+ {
+ for(; *string != '\0'; string++)
+ {
+ if(*string == '<')
+ {
+ *ptr++ = '&';
+ *ptr++ = 'l';
+ *ptr++ = 't';
+ *ptr++ = ';';
+ }
+ else if(*string == '>')
+ {
+ *ptr++ = '&';
+ *ptr++ = 'g';
+ *ptr++ = 't';
+ *ptr++ = ';';
+ }
+ else if(*string == '&')
+ {
+ *ptr++ = '&';
+ *ptr++ = 'a';
+ *ptr++ = 'm';
+ *ptr++ = 'p';
+ *ptr++ = ';';
+ }
+ else if (*string == '"')
+ {
+ *ptr++ = '&';
+ *ptr++ = 'q';
+ *ptr++ = 'u';
+ *ptr++ = 'o';
+ *ptr++ = 't';
+ *ptr++ = ';';
+ }
+ else if (*string == '\'')
+ {
+ *ptr++ = '&';
+ *ptr++ = '#';
+ *ptr++ = '3';
+ *ptr++ = '9';
+ *ptr++ = ';';
+ }
+ else
+ {
+ *ptr++ = *string;
+ }
+ }
+ *ptr = '\0';
+ }
+
+ return(rv);
+}
+
+NS_COM PRUnichar *
+nsEscapeHTML2(const PRUnichar *aSourceBuffer, PRInt32 aSourceBufferLen)
+{
+ // if the caller didn't calculate the length
+ if (aSourceBufferLen == -1) {
+ aSourceBufferLen = nsCRT::strlen(aSourceBuffer); // ...then I will
+ }
+
+ /* XXX Hardcoded max entity len. */
+ PRUnichar *resultBuffer = (PRUnichar *)nsMemory::Alloc(aSourceBufferLen *
+ 6 * sizeof(PRUnichar) + sizeof(PRUnichar('\0')));
+ PRUnichar *ptr = resultBuffer;
+
+ if (resultBuffer) {
+ PRInt32 i;
+
+ for(i = 0; i < aSourceBufferLen; i++) {
+ if(aSourceBuffer[i] == '<') {
+ *ptr++ = '&';
+ *ptr++ = 'l';
+ *ptr++ = 't';
+ *ptr++ = ';';
+ } else if(aSourceBuffer[i] == '>') {
+ *ptr++ = '&';
+ *ptr++ = 'g';
+ *ptr++ = 't';
+ *ptr++ = ';';
+ } else if(aSourceBuffer[i] == '&') {
+ *ptr++ = '&';
+ *ptr++ = 'a';
+ *ptr++ = 'm';
+ *ptr++ = 'p';
+ *ptr++ = ';';
+ } else if (aSourceBuffer[i] == '"') {
+ *ptr++ = '&';
+ *ptr++ = 'q';
+ *ptr++ = 'u';
+ *ptr++ = 'o';
+ *ptr++ = 't';
+ *ptr++ = ';';
+ } else if (aSourceBuffer[i] == '\'') {
+ *ptr++ = '&';
+ *ptr++ = '#';
+ *ptr++ = '3';
+ *ptr++ = '9';
+ *ptr++ = ';';
+ } else {
+ *ptr++ = aSourceBuffer[i];
+ }
+ }
+ *ptr = 0;
+ }
+
+ return resultBuffer;
+}
+
+//----------------------------------------------------------------------------------------
+
+const int EscapeChars[256] =
+/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
+ 0,1023, 0, 512,1023, 0,1023,1023,1023,1023,1023,1023,1023,1023, 953, 784, /* 2x !"#$%&'()*+,-./ */
+ 1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1008, 912, 0,1008, 0, 768, /* 3x 0123456789:;<=>? */
+ 1008,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023, /* 4x @ABCDEFGHIJKLMNO */
+ 1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023, 896, 896, 896, 896,1023, /* 5x PQRSTUVWXYZ[\]^_ */
+ 0,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023, /* 6x `abcdefghijklmno */
+ 1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023, 896,1012, 896,1023, 0, /* 7x pqrstuvwxyz{|}~ */
+ 0 /* 8x DEL */
+};
+
+#define NO_NEED_ESC(C) (EscapeChars[((unsigned int) (C))] & (mask))
+
+//----------------------------------------------------------------------------------------
+
+/* returns an escaped string */
+
+/* use the following masks to specify which
+ part of an URL you want to escape:
+
+ esc_Scheme = 1
+ esc_Username = 2
+ esc_Password = 4
+ esc_Host = 8
+ esc_Directory = 16
+ esc_FileBaseName = 32
+ esc_FileExtension = 64
+ esc_Param = 128
+ esc_Query = 256
+ esc_Ref = 512
+*/
+
+/* by default this function will not escape parts of a string
+ that already look escaped, which means it already includes
+ a valid hexcode. This is done to avoid multiple escapes of
+ a string. Use the following mask to force escaping of a
+ string:
+
+ esc_Forced = 1024
+*/
+
+NS_COM PRBool NS_EscapeURL(const char *part,
+ PRInt32 partLen,
+ PRInt16 mask,
+ nsACString &result)
+{
+ if (!part) {
+ NS_NOTREACHED("null pointer");
+ return PR_FALSE;
+ }
+
+ int i = 0;
+ static const char hexChars[] = "0123456789ABCDEF";
+ if (partLen < 0)
+ partLen = strlen(part);
+ PRBool forced = (mask & esc_Forced);
+ PRBool ignoreNonAscii = (mask & esc_OnlyASCII);
+ PRBool ignoreAscii = (mask & esc_OnlyNonASCII);
+ PRBool writing = (mask & esc_AlwaysCopy);
+ PRBool colon = (mask & esc_Colon);
+
+ register const unsigned char* src = (const unsigned char *) part;
+
+ char tempBuffer[100];
+ unsigned int tempBufferPos = 0;
+
+ for (i = 0; i < partLen; i++)
+ {
+ unsigned char c = *src++;
+
+ // if the char has not to be escaped or whatever follows % is
+ // a valid escaped string, just copy the char.
+ //
+ // Also the % will not be escaped until forced
+ // See bugzilla bug 61269 for details why we changed this
+ //
+ // And, we will not escape non-ascii characters if requested.
+ // On special request we will also escape the colon even when
+ // not covered by the matrix.
+ // ignoreAscii is not honored for control characters (C0 and DEL)
+ if ((NO_NEED_ESC(c) || (c == HEX_ESCAPE && !forced)
+ || (c > 0x7f && ignoreNonAscii)
+ || (c > 0x1f && c < 0x7f && ignoreAscii))
+ && !(c == ':' && colon))
+ {
+ if (writing)
+ tempBuffer[tempBufferPos++] = c;
+ }
+ else /* do the escape magic */
+ {
+ if (!writing)
+ {
+ result.Append(part, i);
+ writing = PR_TRUE;
+ }
+ tempBuffer[tempBufferPos++] = HEX_ESCAPE;
+ tempBuffer[tempBufferPos++] = hexChars[c >> 4]; /* high nibble */
+ tempBuffer[tempBufferPos++] = hexChars[c & 0x0f]; /* low nibble */
+ }
+
+ if (tempBufferPos >= sizeof(tempBuffer) - 4)
+ {
+ NS_ASSERTION(writing, "should be writing");
+ tempBuffer[tempBufferPos] = '\0';
+ result += tempBuffer;
+ tempBufferPos = 0;
+ }
+ }
+ if (writing) {
+ tempBuffer[tempBufferPos] = '\0';
+ result += tempBuffer;
+ }
+ return writing;
+}
+
+#define ISHEX(c) memchr(hexChars, c, sizeof(hexChars)-1)
+
+NS_COM PRBool NS_UnescapeURL(const char *str, PRInt32 len, PRInt16 flags, nsACString &result)
+{
+ if (!str) {
+ NS_NOTREACHED("null pointer");
+ return PR_FALSE;
+ }
+
+ if (len < 0)
+ len = strlen(str);
+
+ PRBool ignoreNonAscii = (flags & esc_OnlyASCII);
+ PRBool writing = (flags & esc_AlwaysCopy);
+ PRBool skipControl = (flags & esc_SkipControl);
+
+ static const char hexChars[] = "0123456789ABCDEFabcdef";
+
+ const char *last = str;
+ const char *p = str;
+
+ for (int i=0; i<len; ++i, ++p) {
+ //printf("%c [i=%d of len=%d]\n", *p, i, len);
+ if (*p == HEX_ESCAPE && i < len-2) {
+ unsigned char *p1 = ((unsigned char *) p) + 1;
+ unsigned char *p2 = ((unsigned char *) p) + 2;
+ if (ISHEX(*p1) && ISHEX(*p2) && !(ignoreNonAscii && *p1 >= '8') &&
+ !(skipControl &&
+ (*p1 < '2' || (*p1 == '7' && (*p2 == 'f' || *p2 == 'F'))))) {
+ //printf("- p1=%c p2=%c\n", *p1, *p2);
+ writing = PR_TRUE;
+ if (p > last) {
+ //printf("- p=%p, last=%p\n", p, last);
+ result.Append(last, p - last);
+ last = p;
+ }
+ char u = (UNHEX(*p1) << 4) + UNHEX(*p2);
+ //printf("- u=%c\n", u);
+ result.Append(u);
+ i += 2;
+ p += 2;
+ last += 3;
+ }
+ }
+ }
+ if (writing && last < str + len)
+ result.Append(last, str + len - last);
+
+ return writing;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsEscape.h b/src/libs/xpcom18a4/xpcom/io/nsEscape.h
new file mode 100644
index 00000000..aaf56738
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsEscape.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 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 ***** */
+
+/* First checked in on 98/12/03 by John R. McMullen, derived from net.h/mkparse.c. */
+
+#ifndef _ESCAPE_H_
+#define _ESCAPE_H_
+
+#include "prtypes.h"
+#include "nscore.h"
+#include "nsError.h"
+#include "nsString.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define nsEscape VBoxNsxpnsEscape
+#define nsUnescape VBoxNsxpnsUnescape
+#define nsUnescapeCount VBoxNsxpnsUnescapeCount
+#define nsEscapeHTML VBoxNsxpnsEscapeHTML
+#define nsEscapeHTML2 VBoxNsxpnsEscapeHTML2
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+/**
+ * Valid mask values for nsEscape
+ */
+typedef enum {
+ url_XAlphas = PR_BIT(0) /**< Normal escape - leave alphas intact, escape the rest */
+, url_XPAlphas = PR_BIT(1) /**< As url_XAlphas, but convert spaces (0x20) to '+' and plus to %2B */
+, url_Path = PR_BIT(2) /**< As url_XAlphas, but don't escape slash ('/') */
+} nsEscapeMask;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Escape the given string according to mask
+ * @param str The string to escape
+ * @param mask How to escape the string
+ * @return A newly allocated escaped string that must be free'd with
+ * nsCRT::free, or null on failure
+ */
+NS_COM char * nsEscape(const char * str, nsEscapeMask mask);
+
+NS_COM char * nsUnescape(char * str);
+ /* decode % escaped hex codes into character values,
+ * modifies the parameter, returns the same buffer
+ */
+
+NS_COM PRInt32 nsUnescapeCount (char * str);
+ /* decode % escaped hex codes into character values,
+ * modifies the parameter buffer, returns the length of the result
+ * (result may contain \0's).
+ */
+
+NS_COM char *
+nsEscapeHTML(const char * string);
+
+NS_COM PRUnichar *
+nsEscapeHTML2(const PRUnichar *aSourceBuffer,
+ PRInt32 aSourceBufferLen = -1);
+ /*
+ * Escape problem char's for HTML display
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/**
+ * NS_EscapeURL/NS_UnescapeURL constants for |flags| parameter:
+ */
+enum EscapeMask {
+ /** url components **/
+ esc_Scheme = PR_BIT(0),
+ esc_Username = PR_BIT(1),
+ esc_Password = PR_BIT(2),
+ esc_Host = PR_BIT(3),
+ esc_Directory = PR_BIT(4),
+ esc_FileBaseName = PR_BIT(5),
+ esc_FileExtension = PR_BIT(6),
+ esc_FilePath = esc_Directory | esc_FileBaseName | esc_FileExtension,
+ esc_Param = PR_BIT(7),
+ esc_Query = PR_BIT(8),
+ esc_Ref = PR_BIT(9),
+ /** special flags **/
+ esc_Minimal = esc_Scheme | esc_Username | esc_Password | esc_Host | esc_FilePath | esc_Param | esc_Query | esc_Ref,
+ esc_Forced = PR_BIT(10), /* forces escaping of existing escape sequences */
+ esc_OnlyASCII = PR_BIT(11), /* causes non-ascii octets to be skipped */
+ esc_OnlyNonASCII = PR_BIT(12), /* causes _graphic_ ascii octets (0x20-0x7E)
+ * to be skipped when escaping. causes all
+ * ascii octets to be skipped when unescaping */
+ esc_AlwaysCopy = PR_BIT(13), /* copy input to result buf even if escaping is unnecessary */
+ esc_Colon = PR_BIT(14), /* forces escape of colon */
+ esc_SkipControl = PR_BIT(15) /* skips C0 and DEL from unescaping */
+};
+
+/**
+ * NS_EscapeURL
+ *
+ * Escapes invalid char's in an URL segment. Has no side-effect if the URL
+ * segment is already escaped. Otherwise, the escaped URL segment is appended
+ * to |result|.
+ *
+ * @param str url segment string
+ * @param len url segment string length (-1 if unknown)
+ * @param flags url segment type flag
+ * @param result result buffer, untouched if part is already escaped
+ *
+ * @return TRUE if escaping was performed, FALSE otherwise.
+ */
+NS_COM PRBool NS_EscapeURL(const char *str,
+ PRInt32 len,
+ PRInt16 flags,
+ nsACString &result);
+
+/**
+ * Expands URL escape sequences... beware embedded null bytes!
+ *
+ * @param str url string to unescape
+ * @param len length of |str|
+ * @param flags only esc_OnlyNonASCII, esc_SkipControl and esc_AlwaysCopy
+ * are recognized
+ * @param result result buffer, untouched if |str| is already unescaped
+ *
+ * @return TRUE if unescaping was performed, FALSE otherwise.
+ */
+NS_COM PRBool NS_UnescapeURL(const char *str,
+ PRInt32 len,
+ PRInt16 flags,
+ nsACString &result);
+
+/** returns resultant string length **/
+inline PRInt32 NS_UnescapeURL(char *str) { return nsUnescapeCount(str); }
+
+/**
+ * string friendly versions...
+ */
+inline const nsACString &
+NS_EscapeURL(const nsASingleFragmentCString &part, PRInt16 partType, nsACString &result) {
+ const char *temp;
+ if (NS_EscapeURL(part.BeginReading(temp), part.Length(), partType, result))
+ return result;
+ return part;
+}
+inline const nsACString &
+NS_UnescapeURL(const nsASingleFragmentCString &str, PRInt16 flags, nsACString &result) {
+ const char *temp;
+ if (NS_UnescapeURL(str.BeginReading(temp), str.Length(), flags, result))
+ return result;
+ return str;
+}
+// inline unescape
+inline nsAFlatCString &
+NS_UnescapeURL(nsAFlatCString &str)
+{
+ str.SetLength(nsUnescapeCount(str.BeginWriting()));
+ return str;
+}
+
+#endif // _ESCAPE_H_
diff --git a/src/libs/xpcom18a4/xpcom/io/nsFastLoadFile.cpp b/src/libs/xpcom18a4/xpcom/io/nsFastLoadFile.cpp
new file mode 100644
index 00000000..56b09d22
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsFastLoadFile.cpp
@@ -0,0 +1,2581 @@
+/* -*- 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 <string.h>
+#include "prtypes.h"
+#include "nscore.h"
+#include "nsDebug.h"
+#include "nsEnumeratorUtils.h"
+#include "nsMemory.h"
+#include "nsXPIDLString.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+
+#include "nsIComponentManager.h"
+#include "nsIFile.h"
+#include "nsILocalFile.h"
+#include "nsISeekableStream.h"
+#include "nsISerializable.h"
+#include "nsIStreamBufferAccess.h"
+
+#include "nsBinaryStream.h"
+#include "nsFastLoadFile.h"
+#include "nsInt64.h"
+
+#ifdef DEBUG_brendan
+# define METERING
+# define DEBUG_MUX
+#endif
+
+#ifdef METERING
+# define METER(x) x
+#else
+# define METER(x) /* nothing */
+#endif
+
+#ifdef DEBUG_MUX
+# include <stdio.h>
+# include <stdarg.h>
+
+static void trace_mux(char mode, const char *format, ...)
+{
+ va_list ap;
+ static FILE *tfp;
+ if (!tfp) {
+ char tfn[16];
+ sprintf(tfn, "/tmp/mux.%ctrace", mode);
+ tfp = fopen(tfn, "w");
+ if (!tfp)
+ return;
+ setvbuf(tfp, NULL, _IOLBF, 0);
+ }
+ va_start(ap, format);
+ vfprintf(tfp, format, ap);
+ va_end(ap);
+}
+
+# define TRACE_MUX(args) trace_mux args
+#else
+# define TRACE_MUX(args) /* nothing */
+#endif
+
+/*
+ * Fletcher's 16-bit checksum, using 32-bit two's-complement arithmetic.
+ */
+#define FOLD_ONES_COMPLEMENT_CARRY(X) ((X) = ((X) & 0xffff) + ((X) >> 16))
+#define ONES_COMPLEMENT_ACCUMULATE(X,Y) (X) += (Y); if ((X) & 0x80000000) \
+ FOLD_ONES_COMPLEMENT_CARRY(X)
+#define FLETCHER_ACCUMULATE(A,B,U) ONES_COMPLEMENT_ACCUMULATE(A, U); \
+ ONES_COMPLEMENT_ACCUMULATE(B, A)
+
+PR_IMPLEMENT(PRUint32)
+NS_AccumulateFastLoadChecksum(PRUint32 *aChecksum,
+ const PRUint8* aBuffer,
+ PRUint32 aLength,
+ PRBool aLastBuffer)
+{
+ PRUint32 C = *aChecksum;
+ PRUint32 A = C & 0xffff;
+ PRUint32 B = C >> 16;
+
+ PRUint16 U = 0;
+ if (aLength >= 4) {
+ PRBool odd = PRWord(aBuffer) & 1;
+ switch (PRWord(aBuffer) & 3) {
+ case 3:
+ U = (aBuffer[0] << 8) | aBuffer[1];
+ FLETCHER_ACCUMULATE(A, B, U);
+ U = aBuffer[2];
+ aBuffer += 3;
+ aLength -= 3;
+ break;
+
+ case 2:
+ U = (aBuffer[0] << 8) | aBuffer[1];
+ FLETCHER_ACCUMULATE(A, B, U);
+ U = 0;
+ aBuffer += 2;
+ aLength -= 2;
+ break;
+
+ case 1:
+ U = *aBuffer++;
+ aLength--;
+ break;
+ }
+
+ PRUint32 W;
+ if (odd) {
+ while (aLength > 3) {
+ W = *NS_REINTERPRET_CAST(const PRUint32*, aBuffer);
+ U <<= 8;
+#ifdef IS_BIG_ENDIAN
+ U |= W >> 24;
+ FLETCHER_ACCUMULATE(A, B, U);
+ U = PRUint16(W >> 8);
+ FLETCHER_ACCUMULATE(A, B, U);
+ U = W & 0xff;
+#else
+ U |= W & 0xff;
+ FLETCHER_ACCUMULATE(A, B, U);
+ U = PRUint16(W >> 8);
+ U = NS_SWAP16(U);
+ FLETCHER_ACCUMULATE(A, B, U);
+ U = W >> 24;
+#endif
+ aBuffer += 4;
+ aLength -= 4;
+ }
+ aBuffer--; // we're odd, we didn't checksum the last byte
+ aLength++;
+ } else {
+ while (aLength > 3) {
+ W = *NS_REINTERPRET_CAST(const PRUint32*, aBuffer);
+#ifdef IS_BIG_ENDIAN
+ U = W >> 16;
+ FLETCHER_ACCUMULATE(A, B, U);
+ U = PRUint16(W);
+ FLETCHER_ACCUMULATE(A, B, U);
+#else
+ U = NS_SWAP16(W);
+ FLETCHER_ACCUMULATE(A, B, U);
+ U = W >> 16;
+ U = NS_SWAP16(W);
+ FLETCHER_ACCUMULATE(A, B, U);
+#endif
+ aBuffer += 4;
+ aLength -= 4;
+ }
+ }
+ }
+
+ if (aLastBuffer) {
+ NS_ASSERTION(aLength <= 4, "aLength botch");
+ switch (aLength) {
+ case 4:
+ U = (aBuffer[0] << 8) | aBuffer[1];
+ FLETCHER_ACCUMULATE(A, B, U);
+ U = (aBuffer[2] << 8) | aBuffer[3];
+ FLETCHER_ACCUMULATE(A, B, U);
+ break;
+
+ case 3:
+ U = (aBuffer[0] << 8) | aBuffer[1];
+ FLETCHER_ACCUMULATE(A, B, U);
+ U = aBuffer[2];
+ FLETCHER_ACCUMULATE(A, B, U);
+ break;
+
+ case 2:
+ U = (aBuffer[0] << 8) | aBuffer[1];
+ FLETCHER_ACCUMULATE(A, B, U);
+ break;
+
+ case 1:
+ U = aBuffer[0];
+ FLETCHER_ACCUMULATE(A, B, U);
+ break;
+ }
+
+ aLength = 0;
+ }
+
+ while (A >> 16)
+ FOLD_ONES_COMPLEMENT_CARRY(A);
+ while (B >> 16)
+ FOLD_ONES_COMPLEMENT_CARRY(B);
+
+ *aChecksum = (B << 16) | A;
+ return aLength;
+}
+
+PR_IMPLEMENT(PRUint32)
+NS_AddFastLoadChecksums(PRUint32 sum1, PRUint32 sum2, PRUint32 sum2ByteCount)
+{
+ PRUint32 A1 = sum1 & 0xffff;
+ PRUint32 B1 = sum1 >> 16;
+
+ PRUint32 A2 = sum2 & 0xffff;
+ PRUint32 B2 = sum2 >> 16;
+
+ PRUint32 A = A1 + A2;
+ while (A >> 16)
+ FOLD_ONES_COMPLEMENT_CARRY(A);
+
+ PRUint32 B = B2;
+ for (PRUint32 n = (sum2ByteCount + 1) / 2; n != 0; n--)
+ ONES_COMPLEMENT_ACCUMULATE(B, B1);
+ while (B >> 16)
+ FOLD_ONES_COMPLEMENT_CARRY(B);
+
+ return (B << 16) | A;
+}
+
+#undef FOLD_ONES_COMPLEMENT_CARRY
+#undef ONES_COMPLEMENT_ACCUMULATE
+#undef FLETCHER_ACCUMULATE
+
+static const char magic[] = MFL_FILE_MAGIC;
+
+// -------------------------- nsFastLoadFileReader --------------------------
+
+nsID nsFastLoadFileReader::nsFastLoadFooter::gDummyID;
+nsFastLoadFileReader::nsObjectMapEntry
+ nsFastLoadFileReader::nsFastLoadFooter::gDummySharpObjectEntry;
+
+NS_IMPL_ISUPPORTS_INHERITED5(nsFastLoadFileReader,
+ nsBinaryInputStream,
+ nsIObjectInputStream,
+ nsIFastLoadFileControl,
+ nsIFastLoadReadControl,
+ nsISeekableStream,
+ nsIFastLoadFileReader)
+
+MOZ_DECL_CTOR_COUNTER(nsFastLoadFileReader)
+
+nsresult
+nsFastLoadFileReader::ReadHeader(nsFastLoadHeader *aHeader)
+{
+ nsresult rv;
+ PRUint32 bytesRead;
+
+ rv = Read(NS_REINTERPRET_CAST(char*, aHeader), sizeof *aHeader, &bytesRead);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (bytesRead != sizeof *aHeader ||
+ memcmp(aHeader->mMagic, magic, MFL_FILE_MAGIC_SIZE)) {
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ aHeader->mChecksum = NS_SWAP32(aHeader->mChecksum);
+ aHeader->mVersion = NS_SWAP32(aHeader->mVersion);
+ aHeader->mFooterOffset = NS_SWAP32(aHeader->mFooterOffset);
+ aHeader->mFileSize = NS_SWAP32(aHeader->mFileSize);
+
+ return NS_OK;
+}
+
+// nsIFastLoadFileControl methods:
+
+NS_IMETHODIMP
+nsFastLoadFileReader::GetChecksum(PRUint32 *aChecksum)
+{
+ *aChecksum = mHeader.mChecksum;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileReader::SetChecksum(PRUint32 aChecksum)
+{
+ mHeader.mChecksum = aChecksum;
+ return NS_OK;
+}
+
+struct nsStringMapEntry : public PLDHashEntryHdr {
+ const char* mString; // key, must come first
+ nsISupports* mURI; // for SelectMuxedDocument return value
+};
+
+struct nsDocumentMapEntry : public nsStringMapEntry {
+ PRUint32 mInitialSegmentOffset; // offset of URI's first segment in file
+};
+
+struct nsDocumentMapReadEntry : public nsDocumentMapEntry {
+ PRUint32 mNextSegmentOffset; // offset of URI's next segment to read
+ PRUint32 mBytesLeft : 31, // bytes remaining in current segment
+ mNeedToSeek : 1; // flag to defer Seek from Select to
+ // Read, in case there is no Read before
+ // another entry is Selected (to improve
+ // input stream buffer utilization)
+ PRInt64 mSaveOffset; // in case demux schedule differs from
+ // mux schedule
+};
+
+PR_STATIC_CALLBACK(void)
+strmap_ClearEntry(PLDHashTable *aTable, PLDHashEntryHdr *aHdr)
+{
+ nsStringMapEntry* entry = NS_STATIC_CAST(nsStringMapEntry*, aHdr);
+
+ if (entry->mString)
+ nsMemory::Free((void*) entry->mString);
+ NS_IF_RELEASE(entry->mURI);
+ PL_DHashClearEntryStub(aTable, aHdr);
+}
+
+static const PLDHashTableOps strmap_DHashTableOps = {
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ PL_DHashGetKeyStub,
+ PL_DHashStringKey,
+ PL_DHashMatchStringKey,
+ PL_DHashMoveEntryStub,
+ strmap_ClearEntry,
+ PL_DHashFinalizeStub,
+ NULL
+};
+
+// An nsObjectMapEntry holds a strong reference to an XPCOM object, unless the
+// mObject member, when cast to NSFastLoadOID, has its MFL_OBJECT_DEF_TAG bit
+// set. NB: we rely on the fact that an nsISupports* is never an odd pointer.
+struct nsObjectMapEntry : public PLDHashEntryHdr {
+ nsISupports* mObject; // key, must come first
+};
+
+// Fast mapping from URI object pointer back to spec-indexed document info.
+struct nsURIMapReadEntry : public nsObjectMapEntry {
+ nsDocumentMapReadEntry* mDocMapEntry;
+};
+
+PR_STATIC_CALLBACK(void)
+objmap_ClearEntry(PLDHashTable *aTable, PLDHashEntryHdr *aHdr)
+{
+ nsObjectMapEntry* entry = NS_STATIC_CAST(nsObjectMapEntry*, aHdr);
+
+ // Ignore tagged object ids stored as object pointer keys (the updater
+ // code does this).
+ if ((NS_PTR_TO_INT32(entry->mObject) & MFL_OBJECT_DEF_TAG) == 0)
+ NS_IF_RELEASE(entry->mObject);
+ PL_DHashClearEntryStub(aTable, aHdr);
+}
+
+static const PLDHashTableOps objmap_DHashTableOps = {
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ PL_DHashGetKeyStub,
+ PL_DHashVoidPtrKeyStub,
+ PL_DHashMatchEntryStub,
+ PL_DHashMoveEntryStub,
+ objmap_ClearEntry,
+ PL_DHashFinalizeStub,
+ NULL
+};
+
+NS_IMETHODIMP
+nsFastLoadFileReader::HasMuxedDocument(const char* aURISpec, PRBool *aResult)
+{
+ nsDocumentMapReadEntry* docMapEntry =
+ NS_STATIC_CAST(nsDocumentMapReadEntry*,
+ PL_DHashTableOperate(&mFooter.mDocumentMap, aURISpec,
+ PL_DHASH_LOOKUP));
+
+ *aResult = PL_DHASH_ENTRY_IS_BUSY(docMapEntry);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileReader::StartMuxedDocument(nsISupports* aURI, const char* aURISpec)
+{
+ nsDocumentMapReadEntry* docMapEntry =
+ NS_STATIC_CAST(nsDocumentMapReadEntry*,
+ PL_DHashTableOperate(&mFooter.mDocumentMap, aURISpec,
+ PL_DHASH_LOOKUP));
+
+ // If the spec isn't in the map, return NS_ERROR_NOT_AVAILABLE so the
+ // FastLoad service can try for a file update.
+ if (PL_DHASH_ENTRY_IS_FREE(docMapEntry))
+ return NS_ERROR_NOT_AVAILABLE;
+
+ nsCOMPtr<nsISupports> key(do_QueryInterface(aURI));
+ nsURIMapReadEntry* uriMapEntry =
+ NS_STATIC_CAST(nsURIMapReadEntry*,
+ PL_DHashTableOperate(&mFooter.mURIMap, key,
+ PL_DHASH_ADD));
+ if (!uriMapEntry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ASSERTION(uriMapEntry->mDocMapEntry == nsnull,
+ "URI mapped to two different specs?");
+ if (uriMapEntry->mDocMapEntry)
+ return NS_ERROR_UNEXPECTED;
+
+ docMapEntry->mURI = aURI;
+ NS_ADDREF(docMapEntry->mURI);
+ uriMapEntry->mObject = key;
+ NS_ADDREF(uriMapEntry->mObject);
+ uriMapEntry->mDocMapEntry = docMapEntry;
+ TRACE_MUX(('r', "start %p (%p) %s\n", aURI, key.get(), aURISpec));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileReader::SelectMuxedDocument(nsISupports* aURI,
+ nsISupports** aResult)
+{
+ nsresult rv;
+
+ // Find the given URI's entry and select it for more reading.
+ nsCOMPtr<nsISupports> key(do_QueryInterface(aURI));
+ nsURIMapReadEntry* uriMapEntry =
+ NS_STATIC_CAST(nsURIMapReadEntry*,
+ PL_DHashTableOperate(&mFooter.mURIMap, key,
+ PL_DHASH_LOOKUP));
+
+ // If the URI isn't in the map, return NS_ERROR_NOT_AVAILABLE so the
+ // FastLoad service can try selecting the file updater.
+ if (PL_DHASH_ENTRY_IS_FREE(uriMapEntry))
+ return NS_ERROR_NOT_AVAILABLE;
+
+ // If we're interrupting another document's segment, save its offset so
+ // we can seek back when it's reselected. If prevDocMapEntry->mNeedToSeek
+ // is set, that means the stream is not positioned for prevDocMapEntry, to
+ // avoid buffer thrashing. See below in this function for more.
+ nsDocumentMapReadEntry* prevDocMapEntry = mCurrentDocumentMapEntry;
+ if (prevDocMapEntry &&
+ prevDocMapEntry->mBytesLeft &&
+ !prevDocMapEntry->mNeedToSeek) {
+ rv = Tell(&prevDocMapEntry->mSaveOffset);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ // It turns out we get a fair amount of redundant select calls, thanks to
+ // non-blocking hunks of data from the parser that are devoid of scripts.
+ // As more data gets FastLoaded, the number of these useless selects will
+ // decline.
+ nsDocumentMapReadEntry* docMapEntry = uriMapEntry->mDocMapEntry;
+ if (docMapEntry == prevDocMapEntry) {
+ TRACE_MUX(('r', "select prev %s same as current!\n",
+ docMapEntry->mString));
+ }
+
+ // Invariant: docMapEntry->mBytesLeft implies docMapEntry->mSaveOffset has
+ // been set non-zero by the Tell call above.
+ else if (docMapEntry->mBytesLeft) {
+ NS_ASSERTION(docMapEntry->mSaveOffset != 0,
+ "reselecting from multiplex at unsaved offset?");
+
+ // Defer Seek till Read, in case of "ping-pong" Selects without any
+ // intervening Reads, to avoid dumping the underlying mInputStream's
+ // input buffer for cases where alternate "pongs" fall in the same
+ // buffer.
+ docMapEntry->mNeedToSeek = PR_TRUE;
+ }
+
+ *aResult = prevDocMapEntry ? prevDocMapEntry->mURI : nsnull;
+ NS_IF_ADDREF(*aResult);
+
+ mCurrentDocumentMapEntry = docMapEntry;
+#ifdef DEBUG_MUX
+ PRInt64 currentSegmentOffset;
+ Tell(&currentSegmentOffset);
+ trace_mux('r', "select %p (%p) offset %ld\n",
+ aURI, key.get(), (long) currentSegmentOffset);
+#endif
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileReader::EndMuxedDocument(nsISupports* aURI)
+{
+ nsCOMPtr<nsISupports> key(do_QueryInterface(aURI));
+ nsURIMapReadEntry* uriMapEntry =
+ NS_STATIC_CAST(nsURIMapReadEntry*,
+ PL_DHashTableOperate(&mFooter.mURIMap, key,
+ PL_DHASH_LOOKUP));
+
+ // If the URI isn't in the map, return NS_ERROR_NOT_AVAILABLE so the
+ // FastLoad service can try to end a select on its file updater.
+ if (PL_DHASH_ENTRY_IS_FREE(uriMapEntry))
+ return NS_ERROR_NOT_AVAILABLE;
+
+ // Drop our ref to the URI object that was passed to StartMuxedDocument,
+ // we no longer need it, and we do not want to extend its lifetime.
+ if (uriMapEntry->mDocMapEntry)
+ NS_RELEASE(uriMapEntry->mDocMapEntry->mURI);
+
+ // Shrink the table if half the entries are removed sentinels.
+ PRUint32 size = PL_DHASH_TABLE_SIZE(&mFooter.mURIMap);
+ if (mFooter.mURIMap.removedCount >= (size >> 2))
+ PL_DHashTableOperate(&mFooter.mURIMap, key, PL_DHASH_REMOVE);
+ else
+ PL_DHashTableRawRemove(&mFooter.mURIMap, uriMapEntry);
+
+ TRACE_MUX(('r', "end %p (%p)\n", aURI, key.get()));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileReader::Read(char* aBuffer, PRUint32 aCount, PRUint32 *aBytesRead)
+{
+ nsresult rv;
+
+ nsDocumentMapReadEntry* entry = mCurrentDocumentMapEntry;
+ if (entry) {
+ // Don't call our Seek wrapper, as it clears mCurrentDocumentMapEntry.
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mInputStream));
+ if (entry->mNeedToSeek) {
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ entry->mSaveOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ entry->mNeedToSeek = PR_FALSE;
+ }
+
+ // Loop to handle empty segments, which may be generated by the
+ // writer, given Start A; Start B; Select A; Select B; write B data;
+ // multiplexing schedules, which do tend to occur given non-blocking
+ // i/o with LIFO scheduling. XXXbe investigate LIFO issues
+ while (entry->mBytesLeft == 0) {
+ // Check for unexpected end of multiplexed stream.
+ NS_ASSERTION(entry->mNextSegmentOffset != 0,
+ "document demuxed from FastLoad file more than once?");
+ if (entry->mNextSegmentOffset == 0)
+ return NS_ERROR_UNEXPECTED;
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ entry->mNextSegmentOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Clear mCurrentDocumentMapEntry temporarily to avoid recursion.
+ mCurrentDocumentMapEntry = nsnull;
+
+ rv = Read32(&entry->mNextSegmentOffset);
+ if (NS_SUCCEEDED(rv)) {
+ PRUint32 bytesLeft = 0;
+ rv = Read32(&bytesLeft);
+ entry->mBytesLeft = bytesLeft;
+ }
+
+ mCurrentDocumentMapEntry = entry;
+ if (NS_FAILED(rv))
+ return rv;
+
+ NS_ASSERTION(entry->mBytesLeft >= 8, "demux segment length botch!");
+ entry->mBytesLeft -= 8;
+ }
+ }
+
+ rv = mInputStream->Read(aBuffer, aCount, aBytesRead);
+
+ if (NS_SUCCEEDED(rv) && entry) {
+ NS_ASSERTION(entry->mBytesLeft >= *aBytesRead, "demux Read underflow!");
+ entry->mBytesLeft -= *aBytesRead;
+
+#ifdef NS_DEBUG
+ // Invariant: !entry->mBytesLeft implies entry->mSaveOffset == 0.
+ if (entry->mBytesLeft == 0)
+ entry->mSaveOffset = 0;
+#endif
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileReader::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
+ PRUint32 aCount, PRUint32 *aResult)
+{
+ nsDocumentMapReadEntry* entry = mCurrentDocumentMapEntry;
+
+ NS_ASSERTION(!entry || (!entry->mNeedToSeek && entry->mBytesLeft != 0),
+ "ReadSegments called from above nsFastLoadFileReader layer?!");
+
+ nsresult rv = nsBinaryInputStream::ReadSegments(aWriter, aClosure, aCount,
+ aResult);
+ if (NS_SUCCEEDED(rv) && entry) {
+ NS_ASSERTION(entry->mBytesLeft >= *aResult,
+ "demux ReadSegments underflow!");
+ entry->mBytesLeft -= *aResult;
+
+#ifdef NS_DEBUG
+ // Invariant: !entry->mBytesLeft implies entry->mSaveOffset == 0.
+ if (entry->mBytesLeft == 0)
+ entry->mSaveOffset = 0;
+#endif
+ }
+ return rv;
+}
+
+/**
+ * XXX tuneme
+ */
+#define MFL_CHECKSUM_BUFSIZE 8192
+
+NS_IMETHODIMP
+nsFastLoadFileReader::ComputeChecksum(PRUint32 *aResult)
+{
+ nsCOMPtr<nsIInputStream> stream = mInputStream;
+
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(stream));
+ PRInt64 saveOffset;
+ nsresult rv = seekable->Tell(&saveOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCOMPtr<nsIStreamBufferAccess> bufferAccess(do_QueryInterface(stream));
+ if (bufferAccess) {
+ rv = bufferAccess->GetUnbufferedStream(getter_AddRefs(stream));
+ if (NS_FAILED(rv))
+ return rv;
+
+ seekable = do_QueryInterface(stream);
+ if (!seekable)
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
+ if (NS_FAILED(rv))
+ return rv;
+
+ char buf[MFL_CHECKSUM_BUFSIZE];
+ PRUint32 len, rem;
+
+ rem = offsetof(nsFastLoadHeader, mChecksum);
+ rv = stream->Read(buf, rem, &len);
+ if (NS_FAILED(rv))
+ return rv;
+ if (len != rem)
+ return NS_ERROR_UNEXPECTED;
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_CUR, 4);
+ if (NS_FAILED(rv))
+ return rv;
+ memset(buf + rem, 0, 4);
+ rem += 4;
+
+ PRUint32 checksum = 0;
+ while (NS_SUCCEEDED(rv = stream->Read(buf + rem, sizeof buf - rem, &len)) &&
+ len) {
+ len += rem;
+ rem = NS_AccumulateFastLoadChecksum(&checksum,
+ NS_REINTERPRET_CAST(PRUint8*, buf),
+ len,
+ PR_FALSE);
+ if (rem)
+ memcpy(buf, buf + len - rem, rem);
+ }
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (rem) {
+ NS_AccumulateFastLoadChecksum(&checksum,
+ NS_REINTERPRET_CAST(PRUint8*, buf),
+ rem,
+ PR_TRUE);
+ }
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, saveOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aResult = checksum;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileReader::GetDependencies(nsISimpleEnumerator* *aDependencies)
+{
+ return NS_NewArrayEnumerator(aDependencies, mFooter.mDependencies);
+}
+
+nsresult
+nsFastLoadFileReader::ReadFooter(nsFastLoadFooter *aFooter)
+{
+ nsresult rv;
+
+ rv = ReadFooterPrefix(aFooter);
+ if (NS_FAILED(rv))
+ return rv;
+
+ aFooter->mIDMap = new nsID[aFooter->mNumIDs];
+ if (!aFooter->mIDMap)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PRUint32 i, n;
+ for (i = 0, n = aFooter->mNumIDs; i < n; i++) {
+ rv = ReadSlowID(&aFooter->mIDMap[i]);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ aFooter->mObjectMap = new nsObjectMapEntry[aFooter->mNumSharpObjects];
+ if (!aFooter->mObjectMap)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ for (i = 0, n = aFooter->mNumSharpObjects; i < n; i++) {
+ nsObjectMapEntry* entry = &aFooter->mObjectMap[i];
+
+ rv = ReadSharpObjectInfo(entry);
+ if (NS_FAILED(rv))
+ return rv;
+
+ entry->mReadObject = nsnull;
+ entry->mSkipOffset = 0;
+ entry->mSaveStrongRefCnt = entry->mStrongRefCnt;
+ entry->mSaveWeakRefCnt = entry->mWeakRefCnt;
+ }
+
+ if (!PL_DHashTableInit(&aFooter->mDocumentMap, &strmap_DHashTableOps,
+ (void *)this, sizeof(nsDocumentMapReadEntry),
+ aFooter->mNumMuxedDocuments)) {
+ aFooter->mDocumentMap.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (!PL_DHashTableInit(&aFooter->mURIMap, &objmap_DHashTableOps,
+ (void *)this, sizeof(nsURIMapReadEntry),
+ aFooter->mNumMuxedDocuments)) {
+ aFooter->mURIMap.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ for (i = 0, n = aFooter->mNumMuxedDocuments; i < n; i++) {
+ nsFastLoadMuxedDocumentInfo info;
+
+ rv = ReadMuxedDocumentInfo(&info);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsDocumentMapReadEntry* entry =
+ NS_STATIC_CAST(nsDocumentMapReadEntry*,
+ PL_DHashTableOperate(&aFooter->mDocumentMap,
+ info.mURISpec,
+ PL_DHASH_ADD));
+ if (!entry) {
+ nsMemory::Free((void*) info.mURISpec);
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ NS_ASSERTION(!entry->mString, "duplicate URISpec in MuxedDocumentMap");
+ entry->mString = info.mURISpec;
+ entry->mURI = nsnull;
+ entry->mInitialSegmentOffset = info.mInitialSegmentOffset;
+ entry->mNextSegmentOffset = info.mInitialSegmentOffset;
+ entry->mBytesLeft = 0;
+ entry->mNeedToSeek = PR_FALSE;
+ entry->mSaveOffset = 0;
+ }
+
+ nsCOMPtr<nsISupportsArray> readDeps;
+ rv = NS_NewISupportsArray(getter_AddRefs(readDeps));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCAutoString filename;
+ for (i = 0, n = aFooter->mNumDependencies; i < n; i++) {
+ rv = ReadCString(filename);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRInt64 fastLoadMtime;
+ rv = Read64(NS_REINTERPRET_CAST(PRUint64*, &fastLoadMtime));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCOMPtr<nsILocalFile> file;
+ rv = NS_NewNativeLocalFile(filename, PR_TRUE, getter_AddRefs(file));
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRInt64 currentMtime;
+ rv = file->GetLastModifiedTime(&currentMtime);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (LL_NE(fastLoadMtime, currentMtime)) {
+#ifdef DEBUG
+ nsCAutoString path;
+ file->GetNativePath(path);
+ printf("%s mtime changed, invalidating FastLoad file\n",
+ path.get());
+#endif
+ return NS_ERROR_FAILURE;
+ }
+
+ rv = readDeps->AppendElement(file);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ aFooter->mDependencies = readDeps;
+ return NS_OK;
+}
+
+nsresult
+nsFastLoadFileReader::ReadFooterPrefix(nsFastLoadFooterPrefix *aFooterPrefix)
+{
+ nsresult rv;
+
+ rv = Read32(&aFooterPrefix->mNumIDs);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Read32(&aFooterPrefix->mNumSharpObjects);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Read32(&aFooterPrefix->mNumMuxedDocuments);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Read32(&aFooterPrefix->mNumDependencies);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return NS_OK;
+}
+
+nsresult
+nsFastLoadFileReader::ReadSlowID(nsID *aID)
+{
+ nsresult rv;
+
+ rv = Read32(&aID->m0);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Read16(&aID->m1);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Read16(&aID->m2);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRUint32 bytesRead;
+ rv = Read(NS_REINTERPRET_CAST(char*, aID->m3), sizeof aID->m3, &bytesRead);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (bytesRead != sizeof aID->m3)
+ return NS_ERROR_FAILURE;
+ return NS_OK;
+}
+
+nsresult
+nsFastLoadFileReader::ReadFastID(NSFastLoadID *aID)
+{
+ nsresult rv = Read32(aID);
+ if (NS_SUCCEEDED(rv))
+ *aID ^= MFL_ID_XOR_KEY;
+ return rv;
+}
+
+nsresult
+nsFastLoadFileReader::ReadSharpObjectInfo(nsFastLoadSharpObjectInfo *aInfo)
+{
+ nsresult rv;
+
+ rv = Read32(&aInfo->mCIDOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ NS_ASSERTION(aInfo->mCIDOffset != 0,
+ "fastload reader: mCIDOffset cannot be zero!");
+
+ rv = Read16(&aInfo->mStrongRefCnt);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Read16(&aInfo->mWeakRefCnt);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return NS_OK;
+}
+
+nsresult
+nsFastLoadFileReader::ReadMuxedDocumentInfo(nsFastLoadMuxedDocumentInfo *aInfo)
+{
+ nsresult rv;
+
+ nsCAutoString spec;
+ rv = ReadCString(spec);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Read32(&aInfo->mInitialSegmentOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ aInfo->mURISpec = ToNewCString(spec);
+ return NS_OK;
+}
+
+nsresult
+nsFastLoadFileReader::Open()
+{
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mInputStream));
+ if (!seekable)
+ return NS_ERROR_UNEXPECTED;
+
+ nsresult rv;
+
+ // Don't bother buffering the header, as we immediately seek to EOF.
+ nsCOMPtr<nsIStreamBufferAccess>
+ bufferAccess(do_QueryInterface(mInputStream));
+ if (bufferAccess)
+ bufferAccess->DisableBuffering();
+
+ rv = ReadHeader(&mHeader);
+
+ if (bufferAccess)
+ bufferAccess->EnableBuffering();
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (mHeader.mVersion != MFL_FILE_VERSION)
+ return NS_ERROR_UNEXPECTED;
+ if (mHeader.mFooterOffset == 0)
+ return NS_ERROR_UNEXPECTED;
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_END, 0);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRInt64 fileSize;
+ rv = seekable->Tell(&fileSize);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsInt64 fileSize64 = fileSize;
+ const nsInt64 maxUint32 = PR_UINT32_MAX;
+ NS_ASSERTION(fileSize64 <= maxUint32, "fileSize must fit in 32 bits");
+ if ((PRUint32) fileSize64 != mHeader.mFileSize)
+ return NS_ERROR_UNEXPECTED;
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ PRInt32(mHeader.mFooterOffset));
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = ReadFooter(&mFooter);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ sizeof(nsFastLoadHeader));
+}
+
+NS_IMETHODIMP
+nsFastLoadFileReader::Close()
+{
+ // Give up our strong "keepalive" references, in case not all objects that
+ // were deserialized were fully re-connected.
+ //
+ // This happens for sure when an nsFastLoadFileUpdater is created and wraps
+ // an nsFastLoadFileReader whose data was already deserialized by an earlier
+ // FastLoad episode. The reader is useful in the second such episode during
+ // a session not so much for reading objects as for its footer information,
+ // which primes the updater's tables so that after the update completes, the
+ // FastLoad file has a superset footer.
+
+ for (PRUint32 i = 0, n = mFooter.mNumSharpObjects; i < n; i++) {
+ nsObjectMapEntry* entry = &mFooter.mObjectMap[i];
+ entry->mReadObject = nsnull;
+ }
+
+ return mInputStream->Close();
+}
+
+nsresult
+nsFastLoadFileReader::DeserializeObject(nsISupports* *aObject)
+{
+ nsresult rv;
+ NSFastLoadID fastCID;
+
+ rv = ReadFastID(&fastCID);
+ if (NS_FAILED(rv))
+ return rv;
+
+ const nsID& slowCID = mFooter.GetID(fastCID);
+ nsCOMPtr<nsISupports> object(do_CreateInstance(slowCID, &rv));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCOMPtr<nsISerializable> serializable(do_QueryInterface(object));
+ if (!serializable)
+ return NS_ERROR_FAILURE;
+
+ rv = serializable->Read(this);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aObject = object;
+ NS_ADDREF(*aObject);
+ return NS_OK;
+}
+
+nsresult
+nsFastLoadFileReader::ReadObject(PRBool aIsStrongRef, nsISupports* *aObject)
+{
+ nsresult rv;
+ NSFastLoadOID oid;
+
+ rv = Read32(&oid);
+ if (NS_FAILED(rv))
+ return rv;
+ oid ^= MFL_OID_XOR_KEY;
+
+ nsCOMPtr<nsISupports> object;
+
+ if (oid == MFL_DULL_OBJECT_OID) {
+ // A very dull object, defined at point of single (strong) reference.
+ NS_ASSERTION(aIsStrongRef, "dull object read via weak ref!");
+
+ rv = DeserializeObject(getter_AddRefs(object));
+ if (NS_FAILED(rv))
+ return rv;
+ } else {
+ NS_ASSERTION((oid & MFL_WEAK_REF_TAG) ==
+ (aIsStrongRef ? 0 : MFL_WEAK_REF_TAG),
+ "strong vs. weak ref deserialization mismatch!");
+
+ nsObjectMapEntry* entry = &mFooter.GetSharpObjectEntry(oid);
+
+ // Check whether we've already deserialized the object for this OID.
+ object = entry->mReadObject;
+ if (!object) {
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mInputStream));
+ PRInt64 saveOffset;
+ nsDocumentMapReadEntry* saveDocMapEntry = nsnull;
+
+ rv = seekable->Tell(&saveOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRUint32 saveOffset32 = saveOffset;
+ if (entry->mCIDOffset != saveOffset32) {
+ // We skipped deserialization of this object from its position
+ // earlier in the input stream, presumably due to the reference
+ // there being an nsFastLoadPtr, or (more likely) because the
+ // object was muxed in another document, and deserialization
+ // order does not match serialization order. So we must seek
+ // back and read it now.
+ NS_ASSERTION(entry->mCIDOffset < saveOffset32,
+ "out of order object?!");
+
+ // Ape our Seek wrapper by clearing mCurrentDocumentMapEntry.
+ // This allows for a skipped object to be referenced from two
+ // or more multiplexed documents in the FastLoad file.
+ saveDocMapEntry = mCurrentDocumentMapEntry;
+ mCurrentDocumentMapEntry = nsnull;
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ entry->mCIDOffset);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ rv = DeserializeObject(getter_AddRefs(object));
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (entry->mCIDOffset != saveOffset32) {
+ // Save the "skip offset" in case we need to skip this object
+ // definition when reading forward, later on.
+ rv = seekable->Tell(&entry->mSkipOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Restore stream offset and mCurrentDocumentMapEntry in case
+ // we're still reading forward through a part of the multiplex
+ // to get object definitions eagerly.
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, saveOffset);
+ if (NS_FAILED(rv))
+ return rv;
+ mCurrentDocumentMapEntry = saveDocMapEntry;
+ }
+
+ // Save object until all refs have been deserialized.
+ entry->mReadObject = object;
+ } else {
+ // What if we are at a definition that's already been read? This
+ // case arises when a sharp object's def is serialized before its
+ // refs, while a non-defining ref is deserialized before the def.
+ // We must skip over the object definition.
+ if (oid & MFL_OBJECT_DEF_TAG) {
+ NS_ASSERTION(entry->mSkipOffset != 0, "impossible! see above");
+ nsCOMPtr<nsISeekableStream>
+ seekable(do_QueryInterface(mInputStream));
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ entry->mSkipOffset);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ }
+
+ if (aIsStrongRef) {
+ NS_ASSERTION(entry->mStrongRefCnt != 0,
+ "mStrongRefCnt underflow!");
+ --entry->mStrongRefCnt;
+ } else {
+ NS_ASSERTION(MFL_GET_WEAK_REFCNT(entry) != 0,
+ "mWeakRefCnt underflow!");
+ MFL_DROP_WEAK_REFCNT(entry);
+ }
+
+ if (entry->mStrongRefCnt == 0 && MFL_GET_WEAK_REFCNT(entry) == 0)
+ entry->mReadObject = nsnull;
+ }
+
+ if (oid & MFL_QUERY_INTERFACE_TAG) {
+ NSFastLoadID iid;
+ rv = ReadFastID(&iid);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = object->QueryInterface(mFooter.GetID(iid),
+ NS_REINTERPRET_CAST(void**, aObject));
+ if (NS_FAILED(rv))
+ return rv;
+ } else {
+ *aObject = object;
+ NS_ADDREF(*aObject);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileReader::ReadID(nsID *aResult)
+{
+ nsresult rv;
+ NSFastLoadID fastID;
+
+ rv = ReadFastID(&fastID);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aResult = mFooter.GetID(fastID);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileReader::Seek(PRInt32 aWhence, PRInt64 aOffset)
+{
+ mCurrentDocumentMapEntry = nsnull;
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mInputStream));
+ return seekable->Seek(aWhence, aOffset);
+}
+
+NS_IMETHODIMP
+nsFastLoadFileReader::Tell(PRInt64 *aResult)
+{
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mInputStream));
+ return seekable->Tell(aResult);
+}
+
+NS_IMETHODIMP
+nsFastLoadFileReader::SetEOF()
+{
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mInputStream));
+ return seekable->SetEOF();
+}
+
+NS_COM nsresult
+NS_NewFastLoadFileReader(nsIObjectInputStream* *aResult,
+ nsIInputStream* aSrcStream)
+{
+ nsFastLoadFileReader* reader = new nsFastLoadFileReader(aSrcStream);
+ if (!reader)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Stabilize reader's refcnt.
+ nsCOMPtr<nsIObjectInputStream> stream(reader);
+
+ nsresult rv = reader->Open();
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aResult = stream;
+ NS_ADDREF(*aResult);
+ return NS_OK;
+}
+
+// -------------------------- nsFastLoadFileWriter --------------------------
+
+NS_IMPL_ISUPPORTS_INHERITED4(nsFastLoadFileWriter,
+ nsBinaryOutputStream,
+ nsIObjectOutputStream,
+ nsIFastLoadFileControl,
+ nsIFastLoadWriteControl,
+ nsISeekableStream)
+
+MOZ_DECL_CTOR_COUNTER(nsFastLoadFileWriter)
+
+struct nsIDMapEntry : public PLDHashEntryHdr {
+ NSFastLoadID mFastID; // 1 + nsFastLoadFooter::mIDMap index
+ nsID mSlowID; // key, used by PLDHashTableOps below
+};
+
+PR_STATIC_CALLBACK(const void *)
+idmap_GetKey(PLDHashTable *aTable, PLDHashEntryHdr *aHdr)
+{
+ nsIDMapEntry* entry = NS_STATIC_CAST(nsIDMapEntry*, aHdr);
+
+ return &entry->mSlowID;
+}
+
+PR_STATIC_CALLBACK(PLDHashNumber)
+idmap_HashKey(PLDHashTable *aTable, const void *aKey)
+{
+ const nsID *idp = NS_REINTERPRET_CAST(const nsID*, aKey);
+
+ return idp->m0;
+}
+
+PR_STATIC_CALLBACK(PRBool)
+idmap_MatchEntry(PLDHashTable *aTable,
+ const PLDHashEntryHdr *aHdr,
+ const void *aKey)
+{
+ const nsIDMapEntry* entry = NS_STATIC_CAST(const nsIDMapEntry*, aHdr);
+ const nsID *idp = NS_REINTERPRET_CAST(const nsID*, aKey);
+
+ return memcmp(&entry->mSlowID, idp, sizeof(nsID)) == 0;
+}
+
+static const PLDHashTableOps idmap_DHashTableOps = {
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ idmap_GetKey,
+ idmap_HashKey,
+ idmap_MatchEntry,
+ PL_DHashMoveEntryStub,
+ PL_DHashClearEntryStub,
+ PL_DHashFinalizeStub,
+ NULL
+};
+
+nsresult
+nsFastLoadFileWriter::MapID(const nsID& aSlowID, NSFastLoadID *aResult)
+{
+ nsIDMapEntry* entry =
+ NS_STATIC_CAST(nsIDMapEntry*,
+ PL_DHashTableOperate(&mIDMap, &aSlowID, PL_DHASH_ADD));
+ if (!entry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (entry->mFastID == 0) {
+ entry->mFastID = mIDMap.entryCount;
+ entry->mSlowID = aSlowID;
+ }
+
+ *aResult = entry->mFastID;
+ return NS_OK;
+}
+
+nsresult
+nsFastLoadFileWriter::WriteHeader(nsFastLoadHeader *aHeader)
+{
+ nsresult rv;
+ PRUint32 bytesWritten;
+
+ rv = Write(aHeader->mMagic, MFL_FILE_MAGIC_SIZE, &bytesWritten);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (bytesWritten != MFL_FILE_MAGIC_SIZE)
+ return NS_ERROR_FAILURE;
+
+ rv = Write32(aHeader->mChecksum);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write32(aHeader->mVersion);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write32(aHeader->mFooterOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write32(aHeader->mFileSize);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return NS_OK;
+}
+
+// nsIFastLoadFileControl methods:
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::GetChecksum(PRUint32 *aChecksum)
+{
+ if (mHeader.mChecksum == 0)
+ return NS_ERROR_NOT_AVAILABLE;
+ *aChecksum = mHeader.mChecksum;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::SetChecksum(PRUint32 aChecksum)
+{
+ mHeader.mChecksum = aChecksum;
+ return NS_OK;
+}
+
+struct nsDocumentMapWriteEntry : public nsDocumentMapEntry {
+ PRUint32 mCurrentSegmentOffset; // last written segment's offset
+};
+
+// Fast mapping from URI object pointer back to spec-indexed document info.
+// We also may need the slow mapping from mURISpec to nsDocumentMapWriteEntry,
+// because the writer's mDocumentMap double hash table may grow "behind the
+// back of" each mURIMap entry's mDocMapEntry member.
+struct nsURIMapWriteEntry : public nsObjectMapEntry {
+ nsDocumentMapWriteEntry* mDocMapEntry;
+ PRUint32 mGeneration;
+ const char* mURISpec;
+};
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::HasMuxedDocument(const char* aURISpec, PRBool *aResult)
+{
+ nsDocumentMapWriteEntry* docMapEntry =
+ NS_STATIC_CAST(nsDocumentMapWriteEntry*,
+ PL_DHashTableOperate(&mDocumentMap, aURISpec,
+ PL_DHASH_LOOKUP));
+
+ *aResult = PL_DHASH_ENTRY_IS_BUSY(docMapEntry);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::StartMuxedDocument(nsISupports* aURI,
+ const char* aURISpec)
+{
+ // Save mDocumentMap table generation and mCurrentDocumentMapEntry key in
+ // case the hash table grows during the PL_DHASH_ADD operation.
+ PRUint32 saveGeneration = mDocumentMap.generation;
+ const char* saveURISpec = mCurrentDocumentMapEntry
+ ? mCurrentDocumentMapEntry->mString
+ : nsnull;
+
+ nsDocumentMapWriteEntry* docMapEntry =
+ NS_STATIC_CAST(nsDocumentMapWriteEntry*,
+ PL_DHashTableOperate(&mDocumentMap, aURISpec,
+ PL_DHASH_ADD));
+ if (!docMapEntry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // If the generation number changed, refresh mCurrentDocumentMapEntry.
+ if (mCurrentDocumentMapEntry && mDocumentMap.generation != saveGeneration) {
+ mCurrentDocumentMapEntry =
+ NS_STATIC_CAST(nsDocumentMapWriteEntry*,
+ PL_DHashTableOperate(&mDocumentMap, saveURISpec,
+ PL_DHASH_LOOKUP));
+ NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(mCurrentDocumentMapEntry),
+ "mCurrentDocumentMapEntry lost during table growth?!");
+
+ // Refresh saveGeneration for use below when initializing uriMapEntry.
+ saveGeneration = mDocumentMap.generation;
+ }
+
+ NS_ASSERTION(docMapEntry->mString == nsnull,
+ "redundant multiplexed document?");
+ if (docMapEntry->mString)
+ return NS_ERROR_UNEXPECTED;
+
+ void* spec = nsMemory::Clone(aURISpec, strlen(aURISpec) + 1);
+ if (!spec)
+ return NS_ERROR_OUT_OF_MEMORY;
+ docMapEntry->mString = NS_REINTERPRET_CAST(const char*, spec);
+ docMapEntry->mURI = aURI;
+ NS_ADDREF(docMapEntry->mURI);
+
+ nsCOMPtr<nsISupports> key(do_QueryInterface(aURI));
+ nsURIMapWriteEntry* uriMapEntry =
+ NS_STATIC_CAST(nsURIMapWriteEntry*,
+ PL_DHashTableOperate(&mURIMap, key, PL_DHASH_ADD));
+ if (!uriMapEntry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ASSERTION(uriMapEntry->mDocMapEntry == nsnull,
+ "URI mapped to two different specs?");
+ if (uriMapEntry->mDocMapEntry)
+ return NS_ERROR_UNEXPECTED;
+
+ uriMapEntry->mObject = key;
+ NS_ADDREF(uriMapEntry->mObject);
+ uriMapEntry->mDocMapEntry = docMapEntry;
+ uriMapEntry->mGeneration = saveGeneration;
+ uriMapEntry->mURISpec = NS_REINTERPRET_CAST(const char*, spec);
+ TRACE_MUX(('w', "start %p (%p) %s\n", aURI, key.get(), aURISpec));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::SelectMuxedDocument(nsISupports* aURI,
+ nsISupports** aResult)
+{
+ // Avoid repeatedly QI'ing to nsISeekableStream as we tell and seek.
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mOutputStream));
+
+ // Capture the current file offset (XXXbe maintain our own via Write?)
+ nsresult rv;
+ PRInt64 currentSegmentOffset;
+ rv = seekable->Tell(&currentSegmentOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRUint32 currentSegmentOffset32 = currentSegmentOffset;
+ // Look for an existing entry keyed by aURI, added by StartMuxedDocument.
+ nsCOMPtr<nsISupports> key(do_QueryInterface(aURI));
+ nsURIMapWriteEntry* uriMapEntry =
+ NS_STATIC_CAST(nsURIMapWriteEntry*,
+ PL_DHashTableOperate(&mURIMap, key, PL_DHASH_LOOKUP));
+ NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(uriMapEntry),
+ "SelectMuxedDocument without prior StartMuxedDocument?");
+ if (PL_DHASH_ENTRY_IS_FREE(uriMapEntry))
+ return NS_ERROR_UNEXPECTED;
+
+ // Beware that uriMapEntry->mDocMapEntry may be stale, if an mDocumentMap
+ // addition caused that table to grow. We save the mDocumentMap generation
+ // in each uriMapEntry and compare it to the current generation, rehashing
+ // uriMapEntry->mURISpec if necessary.
+
+ nsDocumentMapWriteEntry* docMapEntry = uriMapEntry->mDocMapEntry;
+ if (uriMapEntry->mGeneration != mDocumentMap.generation) {
+ docMapEntry =
+ NS_STATIC_CAST(nsDocumentMapWriteEntry*,
+ PL_DHashTableOperate(&mDocumentMap,
+ uriMapEntry->mURISpec,
+ PL_DHASH_LOOKUP));
+ NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(docMapEntry), "lost mDocMapEntry!?");
+ uriMapEntry->mDocMapEntry = docMapEntry;
+ uriMapEntry->mGeneration = mDocumentMap.generation;
+ }
+ docMapEntry = uriMapEntry->mDocMapEntry;
+
+ // If there is a muxed document segment open, close it now by setting its
+ // length, stored in the second PRUint32 of the segment.
+ nsDocumentMapWriteEntry* prevDocMapEntry = mCurrentDocumentMapEntry;
+ if (prevDocMapEntry) {
+ if (prevDocMapEntry == docMapEntry) {
+ TRACE_MUX(('w', "select prev %s same as current!\n",
+ prevDocMapEntry->mString));
+ *aResult = docMapEntry->mURI;
+ NS_ADDREF(*aResult);
+ return NS_OK;
+ }
+
+ PRUint32 prevSegmentOffset = prevDocMapEntry->mCurrentSegmentOffset;
+ TRACE_MUX(('w', "select prev %s offset %lu\n",
+ prevDocMapEntry->mString, prevSegmentOffset));
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ prevSegmentOffset + 4);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // The length counts all bytes in the segment, including the header
+ // that contains [nextSegmentOffset, length].
+ rv = Write32(currentSegmentOffset32 - prevSegmentOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Seek back to the current offset only if we are not going to seek
+ // back to *this* entry's last "current" segment offset and write its
+ // next segment offset at the first PRUint32 of the segment.
+ if (!docMapEntry->mInitialSegmentOffset) {
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ currentSegmentOffset);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ }
+
+ // If this entry was newly added, set its key and initial segment offset.
+ // Otherwise, seek back to write the next segment offset of the previous
+ // segment for this document in the multiplex.
+ if (!docMapEntry->mInitialSegmentOffset) {
+ docMapEntry->mInitialSegmentOffset = currentSegmentOffset32;
+ } else {
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ docMapEntry->mCurrentSegmentOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write32(currentSegmentOffset32);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ currentSegmentOffset);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ // Update this document's current segment offset so we can later fix its
+ // next segment offset (unless it is last, in which case we leave the zero
+ // placeholder as a terminator).
+ docMapEntry->mCurrentSegmentOffset = currentSegmentOffset32;
+
+ rv = Write32(0); // nextSegmentOffset placeholder
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write32(0); // length placeholder
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aResult = prevDocMapEntry ? prevDocMapEntry->mURI : nsnull;
+ NS_IF_ADDREF(*aResult);
+
+ mCurrentDocumentMapEntry = docMapEntry;
+ TRACE_MUX(('w', "select %p (%p) offset %lu\n",
+ aURI, key.get(), currentSegmentOffset));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::EndMuxedDocument(nsISupports* aURI)
+{
+ nsCOMPtr<nsISupports> key(do_QueryInterface(aURI));
+ nsURIMapWriteEntry* uriMapEntry =
+ NS_STATIC_CAST(nsURIMapWriteEntry*,
+ PL_DHashTableOperate(&mURIMap, key, PL_DHASH_LOOKUP));
+
+ // If the URI isn't in the map, nsFastLoadFileWriter::StartMuxedDocument
+ // must have been called with a redundant URI, *and* its caller must have
+ // ignored the NS_ERROR_UNEXPECTED it returned in that case.
+ if (PL_DHASH_ENTRY_IS_FREE(uriMapEntry)) {
+ TRACE_MUX(('w', "bad end %p (%p)\n", aURI, key.get()));
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ // Drop our ref to the URI object that was passed to StartMuxedDocument,
+ // we no longer need it, and we do not want to extend its lifetime.
+ if (uriMapEntry->mDocMapEntry)
+ NS_RELEASE(uriMapEntry->mDocMapEntry->mURI);
+
+ // Shrink the table if half the entries are removed sentinels.
+ PRUint32 size = PL_DHASH_TABLE_SIZE(&mURIMap);
+ if (mURIMap.removedCount >= (size >> 2))
+ PL_DHashTableOperate(&mURIMap, key, PL_DHASH_REMOVE);
+ else
+ PL_DHashTableRawRemove(&mURIMap, uriMapEntry);
+
+ TRACE_MUX(('w', "end %p (%p)\n", aURI, key.get()));
+ return NS_OK;
+}
+
+struct nsDependencyMapEntry : public nsStringMapEntry {
+ PRInt64 mLastModified;
+};
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::AddDependency(nsIFile* aFile)
+{
+ nsCAutoString path;
+ nsresult rv = aFile->GetNativePath(path);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsDependencyMapEntry* entry =
+ NS_STATIC_CAST(nsDependencyMapEntry*,
+ PL_DHashTableOperate(&mDependencyMap, path.get(),
+ PL_DHASH_ADD));
+ if (!entry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (!entry->mString) {
+ const char *tmp = ToNewCString(path);
+ if (!tmp)
+ return NS_ERROR_OUT_OF_MEMORY;
+ entry->mString = tmp;
+
+ // If we can't get the last modified time from aFile, assume it does
+ // not exist, or is otherwise inaccessible to us (due to permissions),
+ // remove the dependency, and suppress the failure.
+ //
+ // Otherwise, we would end up aborting the fastload process due to a
+ // missing .js or .xul or other file on every startup.
+
+ rv = aFile->GetLastModifiedTime(&entry->mLastModified);
+ if (NS_FAILED(rv)) {
+ PL_DHashTableOperate(&mDependencyMap, path.get(), PL_DHASH_REMOVE);
+ rv = NS_OK;
+ }
+ }
+ return rv;
+}
+
+nsresult
+nsFastLoadFileWriter::WriteFooterPrefix(const nsFastLoadFooterPrefix& aFooterPrefix)
+{
+ nsresult rv;
+
+ rv = Write32(aFooterPrefix.mNumIDs);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write32(aFooterPrefix.mNumSharpObjects);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write32(aFooterPrefix.mNumMuxedDocuments);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write32(aFooterPrefix.mNumDependencies);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return NS_OK;
+}
+
+nsresult
+nsFastLoadFileWriter::WriteSlowID(const nsID& aID)
+{
+ nsresult rv;
+
+ rv = Write32(aID.m0);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write16(aID.m1);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write16(aID.m2);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRUint32 bytesWritten;
+ rv = Write(NS_REINTERPRET_CAST(const char*, aID.m3), sizeof aID.m3,
+ &bytesWritten);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (bytesWritten != sizeof aID.m3)
+ return NS_ERROR_FAILURE;
+ return NS_OK;
+}
+
+nsresult
+nsFastLoadFileWriter::WriteFastID(NSFastLoadID aID)
+{
+ return Write32(aID ^ MFL_ID_XOR_KEY);
+}
+
+nsresult
+nsFastLoadFileWriter::WriteSharpObjectInfo(const nsFastLoadSharpObjectInfo& aInfo)
+{
+ nsresult rv;
+
+ NS_ASSERTION(aInfo.mCIDOffset != 0,
+ "fastload writer: mCIDOffset cannot be zero!");
+
+ rv = Write32(aInfo.mCIDOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write16(aInfo.mStrongRefCnt);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write16(aInfo.mWeakRefCnt);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return NS_OK;
+}
+
+nsresult
+nsFastLoadFileWriter::WriteMuxedDocumentInfo(const nsFastLoadMuxedDocumentInfo& aInfo)
+{
+ nsresult rv;
+
+ rv = WriteStringZ(aInfo.mURISpec);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write32(aInfo.mInitialSegmentOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return NS_OK;
+}
+
+PLDHashOperator PR_CALLBACK
+nsFastLoadFileWriter::IDMapEnumerate(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData)
+{
+ nsIDMapEntry* entry = NS_STATIC_CAST(nsIDMapEntry*, aHdr);
+ PRUint32 index = entry->mFastID - 1;
+ nsID* vector = NS_REINTERPRET_CAST(nsID*, aData);
+
+ NS_ASSERTION(index < aTable->entryCount, "bad nsIDMap index!");
+ vector[index] = entry->mSlowID;
+ return PL_DHASH_NEXT;
+}
+
+struct nsSharpObjectMapEntry : public nsObjectMapEntry {
+ NSFastLoadOID mOID;
+ nsFastLoadSharpObjectInfo mInfo;
+};
+
+PLDHashOperator PR_CALLBACK
+nsFastLoadFileWriter::ObjectMapEnumerate(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData)
+{
+ nsSharpObjectMapEntry* entry = NS_STATIC_CAST(nsSharpObjectMapEntry*, aHdr);
+ PRUint32 index = MFL_OID_TO_SHARP_INDEX(entry->mOID);
+ nsFastLoadSharpObjectInfo* vector =
+ NS_REINTERPRET_CAST(nsFastLoadSharpObjectInfo*, aData);
+
+ NS_ASSERTION(index < aTable->entryCount, "bad nsObjectMap index!");
+ vector[index] = entry->mInfo;
+
+ NS_ASSERTION(entry->mInfo.mStrongRefCnt, "no strong ref in serialization!");
+
+ // Ignore tagged object ids stored as object pointer keys (the updater
+ // code does this).
+ if ((NS_PTR_TO_INT32(entry->mObject) & MFL_OBJECT_DEF_TAG) == 0)
+ NS_RELEASE(entry->mObject);
+
+ return PL_DHASH_NEXT;
+}
+
+PLDHashOperator PR_CALLBACK
+nsFastLoadFileWriter::DocumentMapEnumerate(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData)
+{
+ nsFastLoadFileWriter* writer =
+ NS_REINTERPRET_CAST(nsFastLoadFileWriter*, aTable->data);
+ nsDocumentMapWriteEntry* entry =
+ NS_STATIC_CAST(nsDocumentMapWriteEntry*, aHdr);
+ nsresult* rvp = NS_REINTERPRET_CAST(nsresult*, aData);
+
+ nsFastLoadMuxedDocumentInfo info;
+ info.mURISpec = entry->mString;
+ info.mInitialSegmentOffset = entry->mInitialSegmentOffset;
+ *rvp = writer->WriteMuxedDocumentInfo(info);
+
+ return NS_FAILED(*rvp) ? PL_DHASH_STOP : PL_DHASH_NEXT;
+}
+
+PLDHashOperator PR_CALLBACK
+nsFastLoadFileWriter::DependencyMapEnumerate(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData)
+{
+ nsFastLoadFileWriter* writer =
+ NS_REINTERPRET_CAST(nsFastLoadFileWriter*, aTable->data);
+ nsDependencyMapEntry* entry = NS_STATIC_CAST(nsDependencyMapEntry*, aHdr);
+ nsresult* rvp = NS_REINTERPRET_CAST(nsresult*, aData);
+
+ *rvp = writer->WriteStringZ(entry->mString);
+ if (NS_SUCCEEDED(*rvp))
+ *rvp = writer->Write64(entry->mLastModified);
+
+ return NS_FAILED(*rvp) ? PL_DHASH_STOP :PL_DHASH_NEXT;
+}
+
+nsresult
+nsFastLoadFileWriter::WriteFooter()
+{
+ nsresult rv;
+ PRUint32 i, count;
+
+ nsFastLoadFooterPrefix footerPrefix;
+ footerPrefix.mNumIDs = mIDMap.entryCount;
+ footerPrefix.mNumSharpObjects = mObjectMap.entryCount;
+ footerPrefix.mNumMuxedDocuments = mDocumentMap.entryCount;
+ footerPrefix.mNumDependencies = mDependencyMap.entryCount;
+
+ rv = WriteFooterPrefix(footerPrefix);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Enumerate mIDMap into a vector indexed by mFastID and write it.
+ nsID* idvec = new nsID[footerPrefix.mNumIDs];
+ if (!idvec)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ count = PL_DHashTableEnumerate(&mIDMap, IDMapEnumerate, idvec);
+ NS_ASSERTION(count == footerPrefix.mNumIDs, "bad mIDMap enumeration!");
+ for (i = 0; i < count; i++) {
+ rv = WriteSlowID(idvec[i]);
+ if (NS_FAILED(rv)) break;
+ }
+
+ delete[] idvec;
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Enumerate mObjectMap into a vector indexed by mOID and write it.
+ nsFastLoadSharpObjectInfo* objvec =
+ new nsFastLoadSharpObjectInfo[footerPrefix.mNumSharpObjects];
+ if (!objvec)
+ return NS_ERROR_OUT_OF_MEMORY;
+#ifdef NS_DEBUG
+ memset(objvec, 0, footerPrefix.mNumSharpObjects *
+ sizeof(nsFastLoadSharpObjectInfo));
+#endif
+
+ count = PL_DHashTableEnumerate(&mObjectMap, ObjectMapEnumerate, objvec);
+ NS_ASSERTION(count == footerPrefix.mNumSharpObjects,
+ "bad mObjectMap enumeration!");
+ for (i = 0; i < count; i++) {
+ rv = WriteSharpObjectInfo(objvec[i]);
+ if (NS_FAILED(rv)) break;
+ }
+
+ delete[] objvec;
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Enumerate mDocumentMap, writing nsFastLoadMuxedDocumentInfo records
+ count = PL_DHashTableEnumerate(&mDocumentMap, DocumentMapEnumerate, &rv);
+ if (NS_FAILED(rv))
+ return rv;
+
+ NS_ASSERTION(count == footerPrefix.mNumMuxedDocuments,
+ "bad mDocumentMap enumeration!");
+
+ // Write out make-like file dependencies.
+ count = PL_DHashTableEnumerate(&mDependencyMap, DependencyMapEnumerate, &rv);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return NS_OK;
+}
+
+nsresult
+nsFastLoadFileWriter::Init()
+{
+ if (!PL_DHashTableInit(&mIDMap, &idmap_DHashTableOps, (void *)this,
+ sizeof(nsIDMapEntry), PL_DHASH_MIN_SIZE)) {
+ mIDMap.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (!PL_DHashTableInit(&mObjectMap, &objmap_DHashTableOps, (void *)this,
+ sizeof(nsSharpObjectMapEntry), PL_DHASH_MIN_SIZE)) {
+ mObjectMap.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (!PL_DHashTableInit(&mDocumentMap, &strmap_DHashTableOps, (void *)this,
+ sizeof(nsDocumentMapWriteEntry),
+ PL_DHASH_MIN_SIZE)) {
+ mDocumentMap.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (!PL_DHashTableInit(&mURIMap, &objmap_DHashTableOps, (void *)this,
+ sizeof(nsURIMapWriteEntry), PL_DHASH_MIN_SIZE)) {
+ mURIMap.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (!PL_DHashTableInit(&mDependencyMap, &strmap_DHashTableOps, (void *)this,
+ sizeof(nsDependencyMapEntry), PL_DHASH_MIN_SIZE)) {
+ mDependencyMap.ops = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ return NS_OK;
+}
+
+nsresult
+nsFastLoadFileWriter::Open()
+{
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mOutputStream));
+ if (!seekable)
+ return NS_ERROR_UNEXPECTED;
+
+ nsresult rv;
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ sizeof(nsFastLoadHeader));
+ if (NS_FAILED(rv))
+ return rv;
+
+ return Init();
+}
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::Close()
+{
+ nsresult rv;
+
+ memcpy(mHeader.mMagic, magic, MFL_FILE_MAGIC_SIZE);
+ mHeader.mChecksum = 0;
+ mHeader.mVersion = MFL_FILE_VERSION;
+
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mOutputStream));
+
+ PRInt64 footerOffset;
+ rv = seekable->Tell(&footerOffset);
+
+ LL_L2UI(mHeader.mFooterOffset, footerOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // If there is a muxed document segment open, close it now by setting its
+ // length, stored in the second PRUint32 of the segment.
+ if (mCurrentDocumentMapEntry) {
+ PRUint32 currentSegmentOffset =
+ mCurrentDocumentMapEntry->mCurrentSegmentOffset;
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ currentSegmentOffset + 4);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write32(mHeader.mFooterOffset - currentSegmentOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Seek back to the current offset to write the footer.
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ mHeader.mFooterOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ mCurrentDocumentMapEntry = nsnull;
+ }
+
+ rv = WriteFooter();
+ if (NS_FAILED(rv))
+ return rv;
+ PRInt64 fileSize;
+ rv = seekable->Tell(&fileSize);
+ LL_L2UI(mHeader.mFileSize, fileSize);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = WriteHeader(&mHeader);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Now compute the checksum, using mFileIO to get an input stream on the
+ // underlying FastLoad file.
+ if (mFileIO) {
+ // Get the unbuffered output stream, which flushes the buffered header
+ // so we can read and checksum it along with the rest of the file, and
+ // which allows us to write the checksum directly.
+ nsCOMPtr<nsIStreamBufferAccess>
+ bufferAccess(do_QueryInterface(mOutputStream));
+ nsCOMPtr<nsIOutputStream> output;
+ rv = bufferAccess->GetUnbufferedStream(getter_AddRefs(output));
+ if (NS_FAILED(rv) || !output)
+ return NS_ERROR_UNEXPECTED;
+
+ nsCOMPtr<nsIInputStream> input;
+ rv = mFileIO->GetInputStream(getter_AddRefs(input));
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Get the unbuffered input stream, to avoid copying overhead and to
+ // keep our view of the file coherent with the writer -- we don't want
+ // to hit a stale buffer in the reader's underlying stream.
+ bufferAccess = do_QueryInterface(input);
+ rv = bufferAccess->GetUnbufferedStream(getter_AddRefs(input));
+ if (NS_FAILED(rv) || !input)
+ return NS_ERROR_UNEXPECTED;
+
+ // Seek the input stream to offset 0, in case it's a reader who has
+ // already been used to consume some of the FastLoad file.
+ seekable = do_QueryInterface(input);
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
+ if (NS_FAILED(rv))
+ return rv;
+
+ char buf[MFL_CHECKSUM_BUFSIZE];
+ PRUint32 len, rem = 0;
+ PRUint32 checksum = 0;
+
+ // Ok, we're finally ready to checksum the FastLoad file we just wrote!
+ while (NS_SUCCEEDED(rv =
+ input->Read(buf + rem, sizeof buf - rem, &len)) &&
+ len) {
+ len += rem;
+ rem = NS_AccumulateFastLoadChecksum(&checksum,
+ NS_REINTERPRET_CAST(PRUint8*,
+ buf),
+ len,
+ PR_FALSE);
+ if (rem)
+ memcpy(buf, buf + len - rem, rem);
+ }
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (rem) {
+ NS_AccumulateFastLoadChecksum(&checksum,
+ NS_REINTERPRET_CAST(PRUint8*, buf),
+ rem,
+ PR_TRUE);
+ }
+
+ // Store the checksum in the FastLoad file header and remember it via
+ // mHeader.mChecksum, for GetChecksum.
+ seekable = do_QueryInterface(output);
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ offsetof(nsFastLoadHeader, mChecksum));
+ if (NS_FAILED(rv))
+ return rv;
+
+ mHeader.mChecksum = checksum;
+ checksum = NS_SWAP32(checksum);
+ PRUint32 bytesWritten;
+ rv = output->Write(NS_REINTERPRET_CAST(char*, &checksum),
+ sizeof checksum,
+ &bytesWritten);
+ if (NS_FAILED(rv))
+ return rv;
+ if (bytesWritten != sizeof checksum)
+ return NS_ERROR_FAILURE;
+ }
+
+ return mOutputStream->Close();
+}
+
+// Psuedo-tag used as flag between WriteSingleRefObject and WriteObjectCommon.
+#define MFL_SINGLE_REF_PSEUDO_TAG PR_BIT(MFL_OBJECT_TAG_BITS)
+
+nsresult
+nsFastLoadFileWriter::WriteObjectCommon(nsISupports* aObject,
+ PRBool aIsStrongRef,
+ PRUint32 aTags)
+{
+ nsrefcnt rc;
+ nsresult rv;
+
+ NS_ASSERTION((NS_PTR_TO_INT32(aObject) & MFL_OBJECT_DEF_TAG) == 0,
+ "odd nsISupports*, oh no!");
+
+ // Here be manual refcounting dragons!
+ rc = aObject->AddRef();
+ NS_ASSERTION(rc != 0, "bad refcnt when writing aObject!");
+
+ NSFastLoadOID oid;
+ nsCOMPtr<nsIClassInfo> classInfo;
+
+ if (rc == 2 && (aTags & MFL_SINGLE_REF_PSEUDO_TAG)) {
+ // Dull object: only one strong ref and no weak refs in serialization.
+ // Conservative: we don't trust the caller if there are more than two
+ // refs (one from the AddRef above, one from the data structure that's
+ // being serialized).
+ oid = MFL_DULL_OBJECT_OID;
+ aObject->Release();
+ } else {
+ // Object is presumed to be multiply connected through some combo of
+ // strong and weak refs. Hold onto it via mObjectMap.
+ nsSharpObjectMapEntry* entry =
+ NS_STATIC_CAST(nsSharpObjectMapEntry*,
+ PL_DHashTableOperate(&mObjectMap, aObject,
+ PL_DHASH_ADD));
+ if (!entry) {
+ aObject->Release();
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (!entry->mObject) {
+ // First time we've seen this object address: add it to mObjectMap
+ // and serialize the object at the current stream offset.
+ PRInt64 thisOffset;
+ rv = Tell(&thisOffset);
+ if (NS_FAILED(rv)) {
+ aObject->Release();
+ return rv;
+ }
+
+ // NB: aObject was already held, and mObject is a raw nsISupports*.
+ entry->mObject = aObject;
+
+ oid = (mObjectMap.entryCount << MFL_OBJECT_TAG_BITS);
+ entry->mOID = oid;
+
+ // NB: the (32-bit, fast) CID and object data follow the OID.
+ entry->mInfo.mCIDOffset = thisOffset + sizeof(oid);
+ entry->mInfo.mStrongRefCnt = aIsStrongRef ? 1 : 0;
+ entry->mInfo.mWeakRefCnt = aIsStrongRef ? 0 : 1;
+
+ // Record in oid the fact that we're defining this object in the
+ // stream, and get the object's class info here, so we can take
+ // note of singletons in order to avoid reserializing them when
+ // updating after reading.
+ oid |= MFL_OBJECT_DEF_TAG;
+ classInfo = do_QueryInterface(aObject);
+ if (!classInfo)
+ return NS_ERROR_FAILURE;
+
+ PRUint32 flags;
+ if (NS_SUCCEEDED(classInfo->GetFlags(&flags)) &&
+ (flags & nsIClassInfo::SINGLETON)) {
+ MFL_SET_SINGLETON_FLAG(&entry->mInfo);
+ }
+ } else {
+ // Already serialized, recover oid and update the desired refcnt.
+ oid = entry->mOID;
+ if (aIsStrongRef) {
+ ++entry->mInfo.mStrongRefCnt;
+ NS_ASSERTION(entry->mInfo.mStrongRefCnt != 0,
+ "mStrongRefCnt overflow");
+ } else {
+ MFL_BUMP_WEAK_REFCNT(&entry->mInfo);
+ NS_ASSERTION(MFL_GET_WEAK_REFCNT(&entry->mInfo) != 0,
+ "mWeakRefCnt overflow");
+ }
+
+ aObject->Release();
+ }
+ }
+
+ if (!aIsStrongRef)
+ oid |= MFL_WEAK_REF_TAG;
+ oid |= (aTags & MFL_QUERY_INTERFACE_TAG);
+
+ rv = Write32(oid ^ MFL_OID_XOR_KEY);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (oid & MFL_OBJECT_DEF_TAG) {
+ nsCOMPtr<nsISerializable> serializable(do_QueryInterface(aObject));
+ if (!serializable)
+ return NS_ERROR_FAILURE;
+
+ nsCID slowCID;
+ rv = classInfo->GetClassIDNoAlloc(&slowCID);
+ if (NS_FAILED(rv))
+ return rv;
+
+ NSFastLoadID fastCID;
+ rv = MapID(slowCID, &fastCID);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = WriteFastID(fastCID);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = serializable->Write(this);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::WriteObject(nsISupports* aObject, PRBool aIsStrongRef)
+{
+#ifdef NS_DEBUG
+ nsCOMPtr<nsISupports> rootObject(do_QueryInterface(aObject));
+
+ NS_ASSERTION(rootObject.get() == aObject,
+ "bad call to WriteObject -- call WriteCompoundObject!");
+#endif
+
+ return WriteObjectCommon(aObject, aIsStrongRef, 0);
+}
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::WriteSingleRefObject(nsISupports* aObject)
+{
+#ifdef NS_DEBUG
+ nsCOMPtr<nsISupports> rootObject(do_QueryInterface(aObject));
+
+ NS_ASSERTION(rootObject.get() == aObject,
+ "bad call to WriteSingleRefObject -- call WriteCompoundObject!");
+#endif
+
+ return WriteObjectCommon(aObject, PR_TRUE, MFL_SINGLE_REF_PSEUDO_TAG);
+}
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::WriteCompoundObject(nsISupports* aObject,
+ const nsIID& aIID,
+ PRBool aIsStrongRef)
+{
+ nsresult rv;
+ nsCOMPtr<nsISupports> rootObject(do_QueryInterface(aObject));
+
+#ifdef NS_DEBUG
+ nsCOMPtr<nsISupports> roundtrip;
+ rootObject->QueryInterface(aIID, getter_AddRefs(roundtrip));
+
+ NS_ASSERTION(rootObject.get() != aObject,
+ "wasteful call to WriteCompoundObject -- call WriteObject!");
+ NS_ASSERTION(roundtrip.get() == aObject,
+ "bad aggregation or multiple inheritance detected by call to "
+ "WriteCompoundObject!");
+#endif
+
+ rv = WriteObjectCommon(rootObject, aIsStrongRef, MFL_QUERY_INTERFACE_TAG);
+ if (NS_FAILED(rv))
+ return rv;
+
+ NSFastLoadID iid;
+ rv = MapID(aIID, &iid);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return WriteFastID(iid);
+}
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::WriteID(const nsID& aID)
+{
+ nsresult rv;
+ NSFastLoadID fastID;
+
+ rv = MapID(aID, &fastID);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return WriteFastID(fastID);
+}
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::Seek(PRInt32 aWhence, PRInt64 aOffset)
+{
+ mCurrentDocumentMapEntry = nsnull;
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mOutputStream));
+ return seekable->Seek(aWhence, aOffset);
+}
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::Tell(PRInt64 *aResult)
+{
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mOutputStream));
+ return seekable->Tell(aResult);
+}
+
+NS_IMETHODIMP
+nsFastLoadFileWriter::SetEOF()
+{
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mOutputStream));
+ return seekable->SetEOF();
+}
+
+NS_COM nsresult
+NS_NewFastLoadFileWriter(nsIObjectOutputStream* *aResult,
+ nsIOutputStream* aDestStream,
+ nsIFastLoadFileIO* aFileIO)
+{
+ nsFastLoadFileWriter* writer =
+ new nsFastLoadFileWriter(aDestStream, aFileIO);
+ if (!writer)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Stabilize writer's refcnt.
+ nsCOMPtr<nsIObjectOutputStream> stream(writer);
+
+ nsresult rv = writer->Open();
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aResult = stream;
+ NS_ADDREF(*aResult);
+ return NS_OK;
+}
+
+// -------------------------- nsFastLoadFileUpdater --------------------------
+
+NS_IMPL_ISUPPORTS_INHERITED1(nsFastLoadFileUpdater,
+ nsFastLoadFileWriter,
+ nsIFastLoadFileIO)
+
+NS_IMETHODIMP
+nsFastLoadFileUpdater::GetInputStream(nsIInputStream** aResult)
+{
+ *aResult = mInputStream;
+ NS_IF_ADDREF(*aResult);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileUpdater::GetOutputStream(nsIOutputStream** aResult)
+{
+ *aResult = nsnull;
+ return NS_OK;
+}
+
+PLDHashOperator PR_CALLBACK
+nsFastLoadFileUpdater::CopyReadDocumentMapEntryToUpdater(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData)
+{
+ nsDocumentMapReadEntry* readEntry =
+ NS_STATIC_CAST(nsDocumentMapReadEntry*, aHdr);
+ nsFastLoadFileUpdater* updater =
+ NS_REINTERPRET_CAST(nsFastLoadFileUpdater*, aData);
+
+ void* spec = nsMemory::Clone(readEntry->mString,
+ strlen(readEntry->mString) + 1);
+ if (!spec)
+ return PL_DHASH_STOP;
+
+ nsDocumentMapWriteEntry* writeEntry =
+ NS_STATIC_CAST(nsDocumentMapWriteEntry*,
+ PL_DHashTableOperate(&updater->mDocumentMap, spec,
+ PL_DHASH_ADD));
+ if (!writeEntry) {
+ nsMemory::Free(spec);
+ return PL_DHASH_STOP;
+ }
+
+ writeEntry->mString = NS_REINTERPRET_CAST(const char*, spec);
+ writeEntry->mURI = nsnull;
+ writeEntry->mInitialSegmentOffset = readEntry->mInitialSegmentOffset;
+ writeEntry->mCurrentSegmentOffset = 0;
+ return PL_DHASH_NEXT;
+}
+
+nsresult
+nsFastLoadFileUpdater::Open(nsFastLoadFileReader* aReader)
+{
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mOutputStream));
+ if (!seekable)
+ return NS_ERROR_UNEXPECTED;
+
+ nsresult rv;
+ rv = nsFastLoadFileWriter::Init();
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRUint32 i, n;
+
+ // Map from dense, zero-based, uint32 NSFastLoadID in reader to 16-byte
+ // nsID in updater.
+ nsID* readIDMap = aReader->mFooter.mIDMap;
+ for (i = 0, n = aReader->mFooter.mNumIDs; i < n; i++) {
+ NSFastLoadID fastID;
+ rv = MapID(readIDMap[i], &fastID);
+ NS_ASSERTION(fastID == i + 1, "huh?");
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ // Map from reader dense, zero-based MFL_OID_TO_SHARP_INDEX(oid) to sharp
+ // object offset and refcnt information in updater.
+ nsFastLoadFileReader::nsObjectMapEntry* readObjectMap =
+ aReader->mFooter.mObjectMap;
+
+ // Prepare to save aReader state in case we need to seek back and read a
+ // singleton object that might otherwise get written by this updater.
+ nsDocumentMapReadEntry* saveDocMapEntry = nsnull;
+ nsCOMPtr<nsISeekableStream> inputSeekable;
+ PRInt64 saveOffset = 0;
+
+ for (i = 0, n = aReader->mFooter.mNumSharpObjects; i < n; i++) {
+ nsFastLoadFileReader::nsObjectMapEntry* readEntry = &readObjectMap[i];
+
+ NS_ASSERTION(readEntry->mCIDOffset != 0,
+ "fastload updater: mCIDOffset cannot be zero!");
+
+ // If the reader didn't read this object but it's a singleton, we must
+ // "deserialize" it now, to discover its one and only root nsISupports
+ // address. The object already exists in memory if it was created at
+ // startup without resort to the FastLoad file. The canonical example
+ // is the system principal object held by all XUL JS scripts.
+
+ nsISupports* obj = readEntry->mReadObject;
+ if (!obj && MFL_GET_SINGLETON_FLAG(readEntry)) {
+ if (!saveDocMapEntry) {
+ inputSeekable = do_QueryInterface(aReader->mInputStream);
+ rv = inputSeekable->Tell(&saveOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ saveDocMapEntry = aReader->mCurrentDocumentMapEntry;
+ aReader->mCurrentDocumentMapEntry = nsnull;
+ }
+
+ rv = inputSeekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ readEntry->mCIDOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = aReader
+ ->DeserializeObject(getter_AddRefs(readEntry->mReadObject));
+ if (NS_FAILED(rv))
+ return rv;
+ obj = readEntry->mReadObject;
+
+ // Don't forget to set mSkipOffset in case someone calls the reader
+ // to "deserialize" (yet again) the object we just read.
+ //
+ // Say the singleton is the system principal, and the FastLoad file
+ // contains data for navigator.xul including scripts and functions.
+ // If we update the FastLoad file to contain data for messenger.xul
+ // in a separate session started via mozilla -mail, *and during the
+ // same FastLoad episode in this session* race to open a navigator
+ // window, we will attempt to read all objects serialized in the
+ // navigator.xul portion of the FastLoad file.
+ //
+ // mSkipOffset must be set in such a case so the reader can skip
+ // the system principal's serialized data, because the updater for
+ // messenger.xul being opened here has already read it.
+
+ rv = inputSeekable->Tell(&readEntry->mSkipOffset);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ NSFastLoadOID oid = MFL_SHARP_INDEX_TO_OID(i);
+ void* key = obj
+ ? NS_REINTERPRET_CAST(void*, obj)
+ : NS_REINTERPRET_CAST(void*, (oid | MFL_OBJECT_DEF_TAG));
+
+ nsSharpObjectMapEntry* writeEntry =
+ NS_STATIC_CAST(nsSharpObjectMapEntry*,
+ PL_DHashTableOperate(&mObjectMap, key,
+ PL_DHASH_ADD));
+ if (!writeEntry)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Hold the object if there is one, so that objmap_ClearEntry can
+ // release the reference.
+ NS_IF_ADDREF(obj);
+ writeEntry->mObject = NS_REINTERPRET_CAST(nsISupports*, key);
+ writeEntry->mOID = oid;
+ writeEntry->mInfo.mCIDOffset = readEntry->mCIDOffset;
+ writeEntry->mInfo.mStrongRefCnt = readEntry->mSaveStrongRefCnt;
+ writeEntry->mInfo.mWeakRefCnt = readEntry->mSaveWeakRefCnt;
+ }
+
+ // If we had to read any singletons, restore aReader's saved state.
+ if (saveDocMapEntry) {
+ rv = inputSeekable->Seek(nsISeekableStream::NS_SEEK_SET, saveOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ aReader->mCurrentDocumentMapEntry = saveDocMapEntry;
+ }
+
+ // Copy URI spec string and initial segment offset in FastLoad file from
+ // nsDocumentMapReadEntry in reader to nsDocumentMapWriteEntry in updater.
+ // If we didn't enumerate all entries, we ran out of memory.
+ n = PL_DHashTableEnumerate(&aReader->mFooter.mDocumentMap,
+ CopyReadDocumentMapEntryToUpdater,
+ this);
+ if (n != aReader->mFooter.mDocumentMap.entryCount)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Copy source filename dependencies from reader to updater.
+ nsISupportsArray* readDeps = aReader->mFooter.mDependencies;
+ rv = readDeps->Count(&n);
+ if (NS_FAILED(rv))
+ return rv;
+
+ for (i = 0; i < n; i++) {
+ nsCOMPtr<nsIFile> file;
+ rv = readDeps->GetElementAt(i, getter_AddRefs(file));
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = AddDependency(file);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ // Seek to the reader's footer offset so we overwrite the footer. First,
+ // update the header to have a zero mFooterOffset, which will invalidate
+ // the FastLoad file on next startup read attempt, should we crash before
+ // completing this update.
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ offsetof(nsFastLoadHeader, mFooterOffset));
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = Write32(0);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET,
+ aReader->mHeader.mFooterOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Avoid creating yet another object by implementing nsIFastLoadFileIO on
+ // this updater, and save aReader's input stream so it can be returned by
+ // GetInputStream called from nsFastLoadFileWriter::Close. This requires
+ // that we override Close to break the resulting zero-length cycle.
+ mFileIO = this;
+ mInputStream = aReader->mInputStream;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadFileUpdater::Close()
+{
+ // Call base-class Close implementation, which uses mFileIO.
+ nsresult rv = nsFastLoadFileWriter::Close();
+
+ // Break degenerate cycle from this->mFileIO to this.
+ mFileIO = nsnull;
+ return rv;
+}
+
+NS_COM nsresult
+NS_NewFastLoadFileUpdater(nsIObjectOutputStream* *aResult,
+ nsIOutputStream* aOutputStream,
+ nsIObjectInputStream* aReaderAsStream)
+{
+ // Make sure that aReaderAsStream is an nsFastLoadFileReader.
+ nsCOMPtr<nsIFastLoadFileReader> reader(do_QueryInterface(aReaderAsStream));
+ if (!reader)
+ return NS_ERROR_UNEXPECTED;
+
+ nsFastLoadFileUpdater* updater = new nsFastLoadFileUpdater(aOutputStream);
+ if (!updater)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Stabilize updater's refcnt.
+ nsCOMPtr<nsIObjectOutputStream> stream(updater);
+
+ nsresult rv = updater->Open(NS_STATIC_CAST(nsFastLoadFileReader*,
+ aReaderAsStream));
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aResult = stream;
+ NS_ADDREF(*aResult);
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsFastLoadFile.h b/src/libs/xpcom18a4/xpcom/io/nsFastLoadFile.h
new file mode 100644
index 00000000..9f6f061a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsFastLoadFile.h
@@ -0,0 +1,566 @@
+/* -*- 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 ***** */
+
+#ifndef nsFastLoadFile_h___
+#define nsFastLoadFile_h___
+
+/**
+ * Mozilla FastLoad file format and helper types.
+ */
+
+#include "prtypes.h"
+#include "pldhash.h"
+
+#include "nsBinaryStream.h"
+#include "nsCOMPtr.h"
+#include "nsDebug.h"
+#include "nsID.h"
+#include "nsMemory.h"
+#include "nsVoidArray.h"
+
+#include "nsIFastLoadFileControl.h"
+#include "nsIFastLoadService.h"
+#include "nsISeekableStream.h"
+#include "nsISupportsArray.h"
+
+/**
+ * FastLoad file Object ID (OID) is an identifier for multiply and cyclicly
+ * connected objects in the serialized graph of all reachable objects.
+ *
+ * Holy Mixed Metaphors: JS, after Common Lisp, uses #n= to define a "sharp
+ * variable" naming an object that's multiply or cyclicly connected, and #n#
+ * to stand for a connection to an already-defined object. We too call any
+ * object with multiple references "sharp", and (here it comes) any object
+ * with only one reference "dull".
+ *
+ * Note that only sharp objects require a mapping from OID to FastLoad file
+ * offset and other information. Dull objects can be serialized _in situ_
+ * (where they are referenced) and deserialized when their (singular, shared)
+ * OID is scanned.
+ *
+ * We also compress 16-byte XPCOM IDs into 32-bit dense identifiers to save
+ * space. See nsFastLoadFooter, below, for the mapping data structure used to
+ * compute an nsID given an NSFastLoadID.
+ */
+typedef PRUint32 NSFastLoadID; // nsFastLoadFooter::mIDMap index
+typedef PRUint32 NSFastLoadOID; // nsFastLoadFooter::mObjectMap index
+
+/**
+ * A Mozilla FastLoad file is an untagged (in general) stream of objects and
+ * primitive-type data. Small integers are fairly common, and could easily be
+ * confused for NSFastLoadIDs and NSFastLoadOIDs. To help catch bugs where
+ * reader and writer code fail to match, we XOR unlikely 32-bit numbers with
+ * NSFastLoad*IDs when storing and fetching. The following unlikely values are
+ * irrational numbers ((sqrt(5)-1)/2, sqrt(2)-1) represented in fixed point.
+ *
+ * The reader XORs, converts the ID to an index, and bounds-checks all array
+ * accesses that use the index. Array access code asserts that the index is in
+ * bounds, and returns a dummy array element if it isn't.
+ */
+#define MFL_ID_XOR_KEY 0x9E3779B9 // key XOR'd with ID when serialized
+#define MFL_OID_XOR_KEY 0x6A09E667 // key XOR'd with OID when serialized
+
+/**
+ * An OID can be tagged to introduce the serialized definition of the object,
+ * or to stand for a strong or weak reference to that object. Thus the high
+ * 29 bits actually identify the object, and the low three bits tell whether
+ * the object is being defined or just referenced -- and via what inheritance
+ * chain or inner object, if necessary.
+ *
+ * The MFL_QUERY_INTERFACE_TAG bit helps us cope with aggregation and multiple
+ * inheritance: object identity follows the XPCOM rule, but a deserializer may
+ * need to query for an interface not on the primary inheritance chain ending
+ * in the nsISupports whose address uniquely identifies the XPCOM object being
+ * referenced or defined.
+ */
+#define MFL_OBJECT_TAG_BITS 3
+#define MFL_OBJECT_TAG_MASK PR_BITMASK(MFL_OBJECT_TAG_BITS)
+
+#define MFL_OBJECT_DEF_TAG 1U // object definition follows this OID
+#define MFL_WEAK_REF_TAG 2U // OID weakly refers to a prior object
+ // NB: do not confuse with nsWeakPtr!
+#define MFL_QUERY_INTERFACE_TAG 4U // QI object to the ID follows this OID
+ // NB: an NSFastLoadID, not an nsIID!
+
+/**
+ * The dull object identifier introduces the definition of all objects that
+ * have only one (necessarily strong) ref in the serialization. The definition
+ * appears at the point of reference.
+ */
+#define MFL_DULL_OBJECT_OID MFL_OBJECT_DEF_TAG
+
+/**
+ * Convert an OID to an index into nsFastLoadFooter::mObjectMap.
+ */
+#define MFL_OID_TO_SHARP_INDEX(oid) (((oid) >> MFL_OBJECT_TAG_BITS) - 1)
+#define MFL_SHARP_INDEX_TO_OID(index) (((index) + 1) << MFL_OBJECT_TAG_BITS)
+
+/**
+ * Magic "number" at start of a FastLoad file. Inspired by the PNG "magic"
+ * string, which inspired XPCOM's typelib (.xpt) file magic. Guaranteed to be
+ * corrupted by FTP-as-ASCII and other likely errors, meaningful to clued-in
+ * humans, and ending in ^Z to terminate erroneous text input on Windows.
+ */
+#define MFL_FILE_MAGIC "XPCOM\nMozFASL\r\n\032"
+#define MFL_FILE_MAGIC_SIZE 16
+
+#define MFL_FILE_VERSION_0 0
+#define MFL_FILE_VERSION_1 1000
+#define MFL_FILE_VERSION 4 // fix to note singletons in object map
+
+/**
+ * Compute Fletcher's 16-bit checksum over aLength bytes starting at aBuffer,
+ * with the initial accumulators seeded from *aChecksum, and final checksum
+ * returned in *aChecksum. The return value is the number of unchecked bytes,
+ * which may be non-zero if aBuffer is misaligned or aLength is odd. Callers
+ * should copy any remaining bytes to the front of the next buffer.
+ *
+ * If aLastBuffer is false, do not check any bytes remaining due to misaligned
+ * aBuffer or odd aLength, instead returning the remaining byte count. But if
+ * aLastBuffer is true, treat aBuffer as the last buffer in the file and check
+ * every byte, returning 0. Here's a read-loop checksumming sketch:
+ *
+ * char buf[BUFSIZE];
+ * PRUint32 len, rem = 0;
+ * PRUint32 checksum = 0;
+ *
+ * while (NS_SUCCEEDED(rv = Read(buf + rem, sizeof buf - rem, &len)) && len) {
+ * len += rem;
+ * rem = NS_AccumulateFastLoadChecksum(&checksum,
+ * NS_REINTERPRET_CAST(PRUint8*, buf),
+ * len,
+ * PR_FALSE);
+ * if (rem)
+ * memcpy(buf, buf + len - rem, rem);
+ * }
+ *
+ * if (rem) {
+ * NS_AccumulateFastLoadChecksum(&checksum,
+ * NS_REINTERPRET_CAST(PRUint8*, buf),
+ * rem,
+ * PR_TRUE);
+ * }
+ *
+ * After this, if NS_SUCCEEDED(rv), checksum contains a valid FastLoad sum.
+ */
+PR_EXTERN(PRUint32)
+NS_AccumulateFastLoadChecksum(PRUint32 *aChecksum,
+ const PRUint8* aBuffer,
+ PRUint32 aLength,
+ PRBool aLastBuffer);
+
+PR_EXTERN(PRUint32)
+NS_AddFastLoadChecksums(PRUint32 sum1, PRUint32 sum2, PRUint32 sum2ByteCount);
+
+/**
+ * Header at the start of a FastLoad file.
+ */
+struct nsFastLoadHeader {
+ char mMagic[MFL_FILE_MAGIC_SIZE];
+ PRUint32 mChecksum;
+ PRUint32 mVersion;
+ PRUint32 mFooterOffset;
+ PRUint32 mFileSize;
+};
+
+/**
+ * Footer prefix structure (footer header, ugh), after which come arrays of
+ * structures or strings counted by these members.
+ */
+struct nsFastLoadFooterPrefix {
+ PRUint32 mNumIDs;
+ PRUint32 mNumSharpObjects;
+ PRUint32 mNumMuxedDocuments;
+ PRUint32 mNumDependencies;
+};
+
+struct nsFastLoadSharpObjectInfo {
+ PRUint32 mCIDOffset; // offset of object's NSFastLoadID and data
+ PRUint16 mStrongRefCnt;
+ PRUint16 mWeakRefCnt; // high bit is singleton flag, see below
+};
+
+#define MFL_SINGLETON_FLAG 0x8000
+#define MFL_WEAK_REFCNT_MASK 0x7fff
+
+#define MFL_GET_SINGLETON_FLAG(ip) ((ip)->mWeakRefCnt & MFL_SINGLETON_FLAG)
+#define MFL_GET_WEAK_REFCNT(ip) ((ip)->mWeakRefCnt & MFL_WEAK_REFCNT_MASK)
+
+#define MFL_SET_SINGLETON_FLAG(ip) \
+ ((ip)->mWeakRefCnt |= MFL_SINGLETON_FLAG)
+#define MFL_SET_WEAK_REFCNT(ip,rc) \
+ ((ip)->mWeakRefCnt = (((ip)->mWeakRefCnt & MFL_SINGLETON_FLAG) | (rc)))
+
+#define MFL_BUMP_WEAK_REFCNT(ip) (++(ip)->mWeakRefCnt)
+#define MFL_DROP_WEAK_REFCNT(ip) (--(ip)->mWeakRefCnt)
+
+struct nsFastLoadMuxedDocumentInfo {
+ const char* mURISpec;
+ PRUint32 mInitialSegmentOffset;
+};
+
+// forward declarations of opaque types defined in nsFastLoadFile.cpp
+struct nsDocumentMapReadEntry;
+struct nsDocumentMapWriteEntry;
+
+// So nsFastLoadFileUpdater can verify that its nsIObjectInputStream parameter
+// is an nsFastLoadFileReader.
+#define NS_FASTLOADFILEREADER_IID \
+ {0x7d37d1bb,0xcef3,0x4c5f,{0x97,0x68,0x0f,0x89,0x7f,0x1a,0xe1,0x40}}
+
+struct nsIFastLoadFileReader : public nsISupports {
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_FASTLOADFILEREADER_IID)
+};
+
+/**
+ * Inherit from the concrete class nsBinaryInputStream, which inherits from
+ * abstract nsIObjectInputStream but does not implement its direct methods.
+ * Though the names are not as clear as I'd like, this seems to be the best
+ * way to share nsBinaryStream.cpp code.
+ */
+class nsFastLoadFileReader
+ : public nsBinaryInputStream,
+ public nsIFastLoadReadControl,
+ public nsISeekableStream,
+ public nsIFastLoadFileReader
+{
+ public:
+ nsFastLoadFileReader(nsIInputStream *aStream)
+ : mCurrentDocumentMapEntry(nsnull) {
+ SetInputStream(aStream);
+ MOZ_COUNT_CTOR(nsFastLoadFileReader);
+ }
+
+ virtual ~nsFastLoadFileReader() {
+ MOZ_COUNT_DTOR(nsFastLoadFileReader);
+ }
+
+ private:
+ // nsISupports methods
+ NS_DECL_ISUPPORTS_INHERITED
+
+ // overridden nsIObjectInputStream methods
+ NS_IMETHOD ReadObject(PRBool aIsStrongRef, nsISupports* *_retval);
+ NS_IMETHOD ReadID(nsID *aResult);
+
+ // nsIFastLoadFileControl methods
+ NS_DECL_NSIFASTLOADFILECONTROL
+
+ // nsIFastLoadReadControl methods
+ NS_DECL_NSIFASTLOADREADCONTROL
+
+ // nsISeekableStream methods
+ NS_DECL_NSISEEKABLESTREAM
+
+ // Override Read so we can demultiplex a document interleaved with others.
+ NS_IMETHOD Read(char* aBuffer, PRUint32 aCount, PRUint32 *aBytesRead);
+
+ // Override ReadSegments too, as nsBinaryInputStream::ReadSegments does
+ // not call through our overridden Read method -- it calls directly into
+ // the underlying input stream.
+ NS_IMETHODIMP ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
+ PRUint32 aCount, PRUint32 *aResult);
+
+ nsresult ReadHeader(nsFastLoadHeader *aHeader);
+
+ /**
+ * In-memory representation of an indexed nsFastLoadSharpObjectInfo record.
+ */
+ struct nsObjectMapEntry : public nsFastLoadSharpObjectInfo {
+ nsCOMPtr<nsISupports> mReadObject;
+ PRInt64 mSkipOffset;
+ PRUint16 mSaveStrongRefCnt; // saved for an Update
+ PRUint16 mSaveWeakRefCnt; // after a Read
+ };
+
+ /**
+ * In-memory representation of the FastLoad file footer.
+ */
+ struct nsFastLoadFooter : public nsFastLoadFooterPrefix {
+ nsFastLoadFooter()
+ : mIDMap(nsnull),
+ mObjectMap(nsnull) {
+ mDocumentMap.ops = mURIMap.ops = nsnull;
+ }
+
+ ~nsFastLoadFooter() {
+ delete[] mIDMap;
+ delete[] mObjectMap;
+ if (mDocumentMap.ops)
+ PL_DHashTableFinish(&mDocumentMap);
+ if (mURIMap.ops)
+ PL_DHashTableFinish(&mURIMap);
+ }
+
+ // These can't be static within GetID and GetSharpObjectEntry or the
+ // toolchains on HP-UX 10.20's, RH 7.0, and Mac OS X all barf at link
+ // time ("common symbols not allowed with MY_DHLIB output format", to
+ // quote the OS X rev of gcc).
+ static nsID gDummyID;
+ static nsObjectMapEntry gDummySharpObjectEntry;
+
+ const nsID& GetID(NSFastLoadID aFastId) const {
+ PRUint32 index = aFastId - 1;
+ NS_ASSERTION(index < mNumIDs, "aFastId out of range");
+ if (index >= mNumIDs)
+ return gDummyID;
+ return mIDMap[index];
+ }
+
+ nsObjectMapEntry&
+ GetSharpObjectEntry(NSFastLoadOID aOID) const {
+ PRUint32 index = MFL_OID_TO_SHARP_INDEX(aOID);
+ NS_ASSERTION(index < mNumSharpObjects, "aOID out of range");
+ if (index >= mNumSharpObjects)
+ return gDummySharpObjectEntry;
+ return mObjectMap[index];
+ }
+
+ // Map from dense, zero-based, uint32 NSFastLoadID to 16-byte nsID.
+ nsID* mIDMap;
+
+ // Map from dense, zero-based MFL_OID_TO_SHARP_INDEX(oid) to sharp
+ // object offset and refcnt information.
+ nsObjectMapEntry* mObjectMap;
+
+ // Map from URI spec string to nsDocumentMapReadEntry, which helps us
+ // demultiplex a document's objects from among the interleaved object
+ // stream segments in the FastLoad file.
+ PLDHashTable mDocumentMap;
+
+ // Fast mapping from URI object pointer to mDocumentMap entry, valid
+ // only while the muxed document is loading.
+ PLDHashTable mURIMap;
+
+ // List of source filename dependencies that should trigger regeneration
+ // of the FastLoad file.
+ nsCOMPtr<nsISupportsArray> mDependencies;
+ };
+
+ nsresult ReadFooter(nsFastLoadFooter *aFooter);
+ nsresult ReadFooterPrefix(nsFastLoadFooterPrefix *aFooterPrefix);
+ nsresult ReadSlowID(nsID *aID);
+ nsresult ReadFastID(NSFastLoadID *aID);
+ nsresult ReadSharpObjectInfo(nsFastLoadSharpObjectInfo *aInfo);
+ nsresult ReadMuxedDocumentInfo(nsFastLoadMuxedDocumentInfo *aInfo);
+ nsresult DeserializeObject(nsISupports* *aObject);
+
+ nsresult Open();
+ NS_IMETHOD Close();
+
+ protected:
+ nsFastLoadHeader mHeader;
+ nsFastLoadFooter mFooter;
+
+ nsDocumentMapReadEntry* mCurrentDocumentMapEntry;
+
+ friend class nsFastLoadFileUpdater;
+};
+
+NS_COM nsresult
+NS_NewFastLoadFileReader(nsIObjectInputStream* *aResult,
+ nsIInputStream* aSrcStream);
+
+/**
+ * Inherit from the concrete class nsBinaryInputStream, which inherits from
+ * abstract nsIObjectInputStream but does not implement its direct methods.
+ * Though the names are not as clear as I'd like, this seems to be the best
+ * way to share nsBinaryStream.cpp code.
+ */
+class nsFastLoadFileWriter
+ : public nsBinaryOutputStream,
+ public nsIFastLoadWriteControl,
+ public nsISeekableStream
+{
+ public:
+ nsFastLoadFileWriter(nsIOutputStream *aStream, nsIFastLoadFileIO* aFileIO)
+ : mCurrentDocumentMapEntry(nsnull),
+ mFileIO(aFileIO)
+ {
+ SetOutputStream(aStream);
+ mHeader.mChecksum = 0;
+ mIDMap.ops = mObjectMap.ops = mDocumentMap.ops = mURIMap.ops = nsnull;
+ mDependencyMap.ops = nsnull;
+ MOZ_COUNT_CTOR(nsFastLoadFileWriter);
+ }
+
+ virtual ~nsFastLoadFileWriter()
+ {
+ if (mIDMap.ops)
+ PL_DHashTableFinish(&mIDMap);
+ if (mObjectMap.ops)
+ PL_DHashTableFinish(&mObjectMap);
+ if (mDocumentMap.ops)
+ PL_DHashTableFinish(&mDocumentMap);
+ if (mURIMap.ops)
+ PL_DHashTableFinish(&mURIMap);
+ if (mDependencyMap.ops)
+ PL_DHashTableFinish(&mDependencyMap);
+ MOZ_COUNT_DTOR(nsFastLoadFileWriter);
+ }
+
+ private:
+ // nsISupports methods
+ NS_DECL_ISUPPORTS_INHERITED
+
+ // overridden nsIObjectOutputStream methods
+ NS_IMETHOD WriteObject(nsISupports* aObject, PRBool aIsStrongRef);
+ NS_IMETHOD WriteSingleRefObject(nsISupports* aObject);
+ NS_IMETHOD WriteCompoundObject(nsISupports* aObject,
+ const nsIID& aIID,
+ PRBool aIsStrongRef);
+ NS_IMETHOD WriteID(const nsID& aID);
+
+ // nsIFastLoadFileControl methods
+ NS_DECL_NSIFASTLOADFILECONTROL
+
+ // nsIFastLoadWriteControl methods
+ NS_DECL_NSIFASTLOADWRITECONTROL
+
+ // nsISeekableStream methods
+ NS_DECL_NSISEEKABLESTREAM
+
+ nsresult MapID(const nsID& aSlowID, NSFastLoadID *aResult);
+
+ nsresult WriteHeader(nsFastLoadHeader *aHeader);
+ nsresult WriteFooter();
+ nsresult WriteFooterPrefix(const nsFastLoadFooterPrefix& aFooterPrefix);
+ nsresult WriteSlowID(const nsID& aID);
+ nsresult WriteFastID(NSFastLoadID aID);
+ nsresult WriteSharpObjectInfo(const nsFastLoadSharpObjectInfo& aInfo);
+ nsresult WriteMuxedDocumentInfo(const nsFastLoadMuxedDocumentInfo& aInfo);
+
+ nsresult Init();
+ nsresult Open();
+ NS_IMETHOD Close();
+
+ nsresult WriteObjectCommon(nsISupports* aObject,
+ PRBool aIsStrongRef,
+ PRUint32 aQITag);
+
+ static PLDHashOperator PR_CALLBACK
+ IDMapEnumerate(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData);
+
+ static PLDHashOperator PR_CALLBACK
+ ObjectMapEnumerate(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData);
+
+ static PLDHashOperator PR_CALLBACK
+ DocumentMapEnumerate(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData);
+
+ static PLDHashOperator PR_CALLBACK
+ DependencyMapEnumerate(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData);
+
+ protected:
+ nsFastLoadHeader mHeader;
+
+ PLDHashTable mIDMap;
+ PLDHashTable mObjectMap;
+ PLDHashTable mDocumentMap;
+ PLDHashTable mURIMap;
+ PLDHashTable mDependencyMap;
+
+ nsDocumentMapWriteEntry* mCurrentDocumentMapEntry;
+ nsCOMPtr<nsIFastLoadFileIO> mFileIO;
+};
+
+NS_COM nsresult
+NS_NewFastLoadFileWriter(nsIObjectOutputStream* *aResult,
+ nsIOutputStream* aDestStream,
+ nsIFastLoadFileIO* aFileIO);
+
+/**
+ * Subclass of nsFastLoadFileWriter, friend of nsFastLoadFileReader which it
+ * wraps when a FastLoad file needs to be updated. The wrapped reader can be
+ * used to demulitplex data for documents already in the FastLoad file, while
+ * the updater writes new data over the old footer, then writes a new footer
+ * that maps all data on Close.
+ */
+class nsFastLoadFileUpdater
+ : public nsFastLoadFileWriter,
+ nsIFastLoadFileIO
+{
+ public:
+ nsFastLoadFileUpdater(nsIOutputStream* aOutputStream)
+ : nsFastLoadFileWriter(aOutputStream, nsnull) {
+ MOZ_COUNT_CTOR(nsFastLoadFileUpdater);
+ }
+
+ virtual ~nsFastLoadFileUpdater() {
+ MOZ_COUNT_DTOR(nsFastLoadFileUpdater);
+ }
+
+ private:
+ // nsISupports methods
+ NS_DECL_ISUPPORTS_INHERITED
+
+ // nsIFastLoadFileIO methods
+ NS_DECL_NSIFASTLOADFILEIO
+
+ nsresult Open(nsFastLoadFileReader* aReader);
+ NS_IMETHOD Close();
+
+ static PLDHashOperator PR_CALLBACK
+ CopyReadDocumentMapEntryToUpdater(PLDHashTable *aTable,
+ PLDHashEntryHdr *aHdr,
+ PRUint32 aNumber,
+ void *aData);
+
+ friend class nsFastLoadFileReader;
+
+ protected:
+ nsCOMPtr<nsIInputStream> mInputStream;
+};
+
+NS_COM nsresult
+NS_NewFastLoadFileUpdater(nsIObjectOutputStream* *aResult,
+ nsIOutputStream* aOutputStream,
+ nsIObjectInputStream* aReaderAsStream);
+
+#endif // nsFastLoadFile_h___
diff --git a/src/libs/xpcom18a4/xpcom/io/nsFastLoadPtr.h b/src/libs/xpcom18a4/xpcom/io/nsFastLoadPtr.h
new file mode 100644
index 00000000..0c832357
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsFastLoadPtr.h
@@ -0,0 +1,112 @@
+/* -*- 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 ***** */
+
+#ifndef nsFastLoadPtr_h___
+#define nsFastLoadPtr_h___
+
+/**
+ * Mozilla FastLoad file object pointer template type.
+ *
+ * Use nsFastLoadPtr<T> rather than nsCOMPtr<T> when declaring a strong XPCOM
+ * ref member of a data structure that's conditionally loaded at application
+ * startup. You must be willing to tolerate the null mRawPtr test on every
+ * dereference of this member pointer, or else copy it to a local to optimize
+ * away the cost.
+ */
+
+#ifndef nsCOMPtr_h___
+#include "nsCOMPtr.h"
+#endif
+
+#ifndef nsIFastLoadService_h___
+#include "nsIFastLoadService.h"
+#endif
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define gFastLoadService_ VBoxNsxpgFastLoadService_
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+/**
+ * nsFastLoadPtr is a template class, so we don't want a class static service
+ * pointer member declared in nsFastLoadPtr, above. Plus, we need special
+ * declaration magic to export data across DLL/DSO boundaries. So we use an
+ * old-fashioned global variable that refers weakly to the one true FastLoad
+ * service. This pointer is maintained by that singleton's ctor and dtor.
+ */
+PR_EXPORT_DATA(nsIFastLoadService*) gFastLoadService_;
+
+template <class T>
+class nsFastLoadPtr : public nsCOMPtr<T> {
+ public:
+ nsDerivedSafe<T>* get() const {
+ if (!this->mRawPtr) {
+ gFastLoadService_->GetFastLoadReferent(
+ NS_REINTERPRET_CAST(nsISupports**,
+ &this->mRawPtr));
+ }
+ return NS_REINTERPRET_CAST(nsDerivedSafe<T>*, this->mRawPtr);
+ }
+
+ /**
+ * Deserialize an nsFastLoadPtr from aInputStream, skipping the referent
+ * object, but saving the object's offset for later deserialization.
+ *
+ * Lowercase name _a la_ get, because it's called the same way -- not via
+ * operator->().
+ */
+ nsresult read(nsIObjectInputStream* aInputStream) {
+ return gFastLoadService_->ReadFastLoadPtr(aInputStream,
+ NS_REINTERPRET_CAST(nsISupports**,
+ &this->mRawPtr));
+ }
+
+ /**
+ * Serialize an nsFastLoadPtr reference and possibly the referent object,
+ * if that object has not yet been serialized.
+ *
+ * Lowercase name _a la_ get, because it's called the same way -- not via
+ * operator->().
+ */
+ nsresult write(nsIObjectOutputStream* aOutputStream) {
+ return gFastLoadService_->WriteFastLoadPtr(aOutputStream,
+ NS_REINTERPRET_CAST(nsISupports*,
+ this->mRawPtr));
+ }
+};
+
+#endif // nsFastLoadPtr_h___
diff --git a/src/libs/xpcom18a4/xpcom/io/nsFastLoadService.cpp b/src/libs/xpcom18a4/xpcom/io/nsFastLoadService.cpp
new file mode 100644
index 00000000..4df187c1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsFastLoadService.cpp
@@ -0,0 +1,571 @@
+/* -*- 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 "prtypes.h"
+#include "prio.h"
+#include "prtime.h"
+#include "pldhash.h"
+
+#include "nsAppDirectoryServiceDefs.h"
+#include "nsAutoLock.h"
+#include "nsCOMPtr.h"
+#include "nsFastLoadFile.h"
+#include "nsFastLoadPtr.h"
+#include "nsFastLoadService.h"
+#include "nsString.h"
+
+#include "nsIComponentManager.h"
+#include "nsIEnumerator.h"
+#include "nsIFastLoadFileControl.h"
+#include "nsIFile.h"
+#include "nsIObjectInputStream.h"
+#include "nsIObjectOutputStream.h"
+#include "nsISeekableStream.h"
+#include "nsISupports.h"
+
+PR_IMPLEMENT_DATA(nsIFastLoadService*) gFastLoadService_ = nsnull;
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsFastLoadService, nsIFastLoadService)
+
+nsFastLoadService::nsFastLoadService()
+ : mLock(nsnull),
+ mFastLoadPtrMap(nsnull),
+ mDirection(0)
+{
+ NS_ASSERTION(gFastLoadService_ == nsnull, "double FastLoadService init?");
+ gFastLoadService_ = this;
+}
+
+nsFastLoadService::~nsFastLoadService()
+{
+ gFastLoadService_ = nsnull;
+
+ if (mInputStream)
+ mInputStream->Close();
+ if (mOutputStream)
+ mOutputStream->Close();
+
+ if (mFastLoadPtrMap)
+ PL_DHashTableDestroy(mFastLoadPtrMap);
+ if (mLock)
+ PR_DestroyLock(mLock);
+}
+
+NS_IMETHODIMP
+nsFastLoadService::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
+{
+ *aResult = nsnull;
+ if (aOuter)
+ return NS_ERROR_NO_AGGREGATION;
+
+ nsFastLoadService* fastLoadService = new nsFastLoadService();
+ if (!fastLoadService)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ fastLoadService->mLock = PR_NewLock();
+ if (!fastLoadService->mLock) {
+ delete fastLoadService;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ NS_ADDREF(fastLoadService);
+ nsresult rv = fastLoadService->QueryInterface(aIID, aResult);
+ NS_RELEASE(fastLoadService);
+ return rv;
+}
+
+#if defined XP_MAC
+
+// Mac format: "<Basename> FastLoad File" with <basename> capitalized.
+# include "nsCRT.h"
+
+# define MASSAGE_BASENAME(bn) (bn.SetCharAt(nsCRT::ToUpper(bn.CharAt(0)), 0))
+# define PLATFORM_FASL_SUFFIX " FastLoad File"
+
+#elif defined(XP_UNIX) || defined(XP_BEOS)
+
+// Unix format: "<basename>.mfasl".
+# define MASSAGE_BASENAME(bn) /* nothing */
+# define PLATFORM_FASL_SUFFIX ".mfasl"
+
+#elif defined(XP_WIN) || defined(XP_OS2)
+
+// Windows format: "<basename>.mfl".
+# define MASSAGE_BASENAME(bn) /* nothing */
+# define PLATFORM_FASL_SUFFIX ".mfl"
+
+#endif
+
+nsresult
+nsFastLoadService::NewFastLoadFile(const char* aBaseName, nsIFile* *aResult)
+{
+ nsresult rv;
+ nsCOMPtr<nsIFile> file;
+
+ rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
+ getter_AddRefs(file));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCAutoString name(aBaseName);
+ MASSAGE_BASENAME(name);
+ name += PLATFORM_FASL_SUFFIX;
+ rv = file->AppendNative(name);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aResult = file;
+ NS_ADDREF(*aResult);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::NewInputStream(nsIInputStream* aSrcStream,
+ nsIObjectInputStream* *aResult)
+{
+ nsAutoLock lock(mLock);
+
+ nsCOMPtr<nsIObjectInputStream> stream;
+ nsresult rv = NS_NewFastLoadFileReader(getter_AddRefs(stream), aSrcStream);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aResult = stream;
+ NS_ADDREF(*aResult);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::NewOutputStream(nsIOutputStream* aDestStream,
+ nsIObjectOutputStream* *aResult)
+{
+ nsAutoLock lock(mLock);
+
+ return NS_NewFastLoadFileWriter(aResult, aDestStream, mFileIO);
+}
+
+NS_IMETHODIMP
+nsFastLoadService::GetInputStream(nsIObjectInputStream* *aResult)
+{
+ NS_IF_ADDREF(*aResult = mInputStream);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::SetInputStream(nsIObjectInputStream* aStream)
+{
+ nsAutoLock lock(mLock);
+ mInputStream = aStream;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::GetOutputStream(nsIObjectOutputStream* *aResult)
+{
+ NS_IF_ADDREF(*aResult = mOutputStream);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::SetOutputStream(nsIObjectOutputStream* aStream)
+{
+ nsAutoLock lock(mLock);
+ mOutputStream = aStream;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::GetFileIO(nsIFastLoadFileIO* *aResult)
+{
+ NS_IF_ADDREF(*aResult = mFileIO);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::SetFileIO(nsIFastLoadFileIO* aFileIO)
+{
+ nsAutoLock lock(mLock);
+ mFileIO = aFileIO;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::GetDirection(PRInt32 *aResult)
+{
+ *aResult = mDirection;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::HasMuxedDocument(const char* aURISpec, PRBool *aResult)
+{
+ nsresult rv = NS_ERROR_NOT_AVAILABLE;
+ nsCOMPtr<nsIFastLoadFileControl> control;
+
+ *aResult = PR_FALSE;
+ nsAutoLock lock(mLock);
+
+ if (mInputStream) {
+ control = do_QueryInterface(mInputStream);
+ if (control)
+ rv = control->HasMuxedDocument(aURISpec, aResult);
+ }
+
+ if (! *aResult && mOutputStream) {
+ control = do_QueryInterface(mOutputStream);
+ if (control)
+ rv = control->HasMuxedDocument(aURISpec, aResult);
+ }
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::StartMuxedDocument(nsISupports* aURI, const char* aURISpec,
+ PRInt32 aDirectionFlags)
+{
+ nsresult rv = NS_ERROR_NOT_AVAILABLE;
+ nsCOMPtr<nsIFastLoadFileControl> control;
+ nsAutoLock lock(mLock);
+
+ // Try for an input stream first, in case aURISpec's data is multiplexed
+ // in the current FastLoad file.
+ if ((aDirectionFlags & NS_FASTLOAD_READ) && mInputStream) {
+ control = do_QueryInterface(mInputStream);
+ if (control) {
+ // If aURISpec is not in the multiplex, control->StartMuxedDocument
+ // will return NS_ERROR_NOT_AVAILABLE.
+ rv = control->StartMuxedDocument(aURI, aURISpec);
+ if (NS_SUCCEEDED(rv) || rv != NS_ERROR_NOT_AVAILABLE)
+ return rv;
+
+ // Ok, aURISpec is not in the existing mux. If we have no output
+ // stream yet, wrap the reader with a FastLoad file updater.
+ if (!mOutputStream && mFileIO) {
+ nsCOMPtr<nsIOutputStream> output;
+ rv = mFileIO->GetOutputStream(getter_AddRefs(output));
+ if (NS_FAILED(rv))
+ return rv;
+
+ // NB: mInputStream must be an nsFastLoadFileReader!
+ rv = NS_NewFastLoadFileUpdater(getter_AddRefs(mOutputStream),
+ output,
+ mInputStream);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ if (aDirectionFlags == NS_FASTLOAD_READ) {
+ // Tell our caller to re-start multiplexing, rather than attempt
+ // to select and deserialize now.
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+ }
+ }
+
+ if ((aDirectionFlags & NS_FASTLOAD_WRITE) && mOutputStream) {
+ control = do_QueryInterface(mOutputStream);
+ if (control)
+ rv = control->StartMuxedDocument(aURI, aURISpec);
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::SelectMuxedDocument(nsISupports* aURI, nsISupports** aResult)
+{
+ nsresult rv = NS_ERROR_NOT_AVAILABLE;
+ nsCOMPtr<nsIFastLoadFileControl> control;
+ nsAutoLock lock(mLock);
+
+ // Try to select the reader, if any; then only if the URI was not in the
+ // file already, select the writer/updater.
+ if (mInputStream) {
+ control = do_QueryInterface(mInputStream);
+ if (control) {
+ rv = control->SelectMuxedDocument(aURI, aResult);
+ if (NS_SUCCEEDED(rv))
+ mDirection = NS_FASTLOAD_READ;
+ }
+ }
+
+ if (rv == NS_ERROR_NOT_AVAILABLE && mOutputStream) {
+ control = do_QueryInterface(mOutputStream);
+ if (control) {
+ rv = control->SelectMuxedDocument(aURI, aResult);
+ if (NS_SUCCEEDED(rv))
+ mDirection = NS_FASTLOAD_WRITE;
+ }
+ }
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::EndMuxedDocument(nsISupports* aURI)
+{
+ nsresult rv = NS_ERROR_NOT_AVAILABLE;
+ nsCOMPtr<nsIFastLoadFileControl> control;
+ nsAutoLock lock(mLock);
+
+ // Try to end the document identified by aURI in the reader, if any; then
+ // only if the URI was not in the file already, end the writer/updater.
+ if (mInputStream) {
+ control = do_QueryInterface(mInputStream);
+ if (control)
+ rv = control->EndMuxedDocument(aURI);
+ }
+
+ if (rv == NS_ERROR_NOT_AVAILABLE && mOutputStream) {
+ control = do_QueryInterface(mOutputStream);
+ if (control)
+ rv = control->EndMuxedDocument(aURI);
+ }
+
+ mDirection = 0;
+ return rv;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::AddDependency(nsIFile* aFile)
+{
+ nsAutoLock lock(mLock);
+
+ nsCOMPtr<nsIFastLoadWriteControl> control(do_QueryInterface(mOutputStream));
+ if (!control)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ return control->AddDependency(aFile);
+}
+
+NS_IMETHODIMP
+nsFastLoadService::ComputeChecksum(nsIFile* aFile,
+ nsIFastLoadReadControl* aControl,
+ PRUint32 *aChecksum)
+{
+ nsCAutoString path;
+ nsresult rv = aFile->GetNativePath(path);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCStringKey key(path);
+ PRUint32 checksum = NS_PTR_TO_INT32(mChecksumTable.Get(&key));
+ if (checksum) {
+ *aChecksum = checksum;
+ return NS_OK;
+ }
+
+ rv = aControl->ComputeChecksum(&checksum);
+ if (NS_FAILED(rv))
+ return rv;
+
+#ifndef VBOX
+ mChecksumTable.Put(&key, NS_INT32_TO_PTR(checksum));
+#else /* VBOX */
+ mChecksumTable.Put(&key, (void *)(uintptr_t)checksum);
+#endif /* VBOX */
+ *aChecksum = checksum;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::CacheChecksum(nsIFile* aFile, nsIObjectOutputStream *aStream)
+{
+ nsCOMPtr<nsIFastLoadFileControl> control(do_QueryInterface(aStream));
+ if (!control)
+ return NS_ERROR_FAILURE;
+
+ PRUint32 checksum;
+ nsresult rv = control->GetChecksum(&checksum);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCAutoString path;
+ rv = aFile->GetNativePath(path);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCStringKey key(path);
+#ifndef VBOX
+ mChecksumTable.Put(&key, NS_INT32_TO_PTR(checksum));
+#else /* VBOX */
+ mChecksumTable.Put(&key, (void *)(uintptr_t)checksum);
+#endif /* VBOX */
+ return NS_OK;
+}
+
+struct nsFastLoadPtrEntry : public PLDHashEntryHdr {
+ nsISupports** mPtrAddr; // key, must come first for PL_DHashGetStubOps
+ PRUint32 mOffset;
+};
+
+NS_IMETHODIMP
+nsFastLoadService::GetFastLoadReferent(nsISupports* *aPtrAddr)
+{
+ NS_ASSERTION(*aPtrAddr == nsnull,
+ "aPtrAddr doesn't point to null nsFastLoadPtr<T>::mRawAddr?");
+
+ nsAutoLock lock(mLock);
+ if (!mFastLoadPtrMap || !mInputStream)
+ return NS_OK;
+
+ nsFastLoadPtrEntry* entry =
+ NS_STATIC_CAST(nsFastLoadPtrEntry*,
+ PL_DHashTableOperate(mFastLoadPtrMap, aPtrAddr,
+ PL_DHASH_LOOKUP));
+ if (PL_DHASH_ENTRY_IS_FREE(entry))
+ return NS_OK;
+
+ nsresult rv;
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(mInputStream));
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, entry->mOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = mInputStream->ReadObject(PR_TRUE, aPtrAddr);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Shrink the table if half the entries are removed sentinels.
+ PRUint32 size = PL_DHASH_TABLE_SIZE(mFastLoadPtrMap);
+ if (mFastLoadPtrMap->removedCount >= (size >> 2))
+ PL_DHashTableOperate(mFastLoadPtrMap, entry, PL_DHASH_REMOVE);
+ else
+ PL_DHashTableRawRemove(mFastLoadPtrMap, entry);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::ReadFastLoadPtr(nsIObjectInputStream* aInputStream,
+ nsISupports* *aPtrAddr)
+{
+ // nsFastLoadPtrs self-construct to null, so if we have a non-null value
+ // in our inout parameter, we must have been read already, alright!
+ if (*aPtrAddr)
+ return NS_OK;
+
+ nsresult rv;
+ PRUint32 nextOffset;
+ nsAutoLock lock(mLock);
+
+ rv = aInputStream->Read32(&nextOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(aInputStream));
+ if (!seekable)
+ return NS_ERROR_FAILURE;
+
+ PRInt64 thisOffset;
+ rv = seekable->Tell(&thisOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, nextOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (!mFastLoadPtrMap) {
+ mFastLoadPtrMap = PL_NewDHashTable(PL_DHashGetStubOps(), this,
+ sizeof(nsFastLoadPtrEntry),
+ PL_DHASH_MIN_SIZE);
+ if (!mFastLoadPtrMap)
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ nsFastLoadPtrEntry* entry =
+ NS_STATIC_CAST(nsFastLoadPtrEntry*,
+ PL_DHashTableOperate(mFastLoadPtrMap, aPtrAddr,
+ PL_DHASH_ADD));
+ NS_ASSERTION(entry->mPtrAddr == nsnull, "duplicate nsFastLoadPtr?!");
+
+ entry->mPtrAddr = aPtrAddr;
+
+ LL_L2UI(entry->mOffset, thisOffset);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFastLoadService::WriteFastLoadPtr(nsIObjectOutputStream* aOutputStream,
+ nsISupports* aObject)
+{
+ NS_ASSERTION(aObject != nsnull, "writing an unread nsFastLoadPtr?!");
+ if (!aObject)
+ return NS_ERROR_UNEXPECTED;
+
+ nsresult rv;
+ nsAutoLock lock(mLock); // serialize writes to aOutputStream
+
+ nsCOMPtr<nsISeekableStream> seekable(do_QueryInterface(aOutputStream));
+ if (!seekable)
+ return NS_ERROR_FAILURE;
+
+ PRInt64 saveOffset;
+ rv = seekable->Tell(&saveOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = aOutputStream->Write32(0); // nextOffset placeholder
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = aOutputStream->WriteObject(aObject, PR_TRUE);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRInt64 nextOffset;
+ rv = seekable->Tell(&nextOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, saveOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = aOutputStream->Write32(nextOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, nextOffset);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsFastLoadService.h b/src/libs/xpcom18a4/xpcom/io/nsFastLoadService.h
new file mode 100644
index 00000000..8f1aa6ae
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsFastLoadService.h
@@ -0,0 +1,71 @@
+/* -*- 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 "prtypes.h"
+#include "pldhash.h"
+#include "nsCOMPtr.h"
+#include "nsHashtable.h"
+#include "nsIFastLoadService.h"
+#include "nsIObjectInputStream.h"
+#include "nsIObjectOutputStream.h"
+
+class nsFastLoadFileReader;
+class nsFastLoadFileWriter;
+
+class nsFastLoadService : public nsIFastLoadService
+{
+ public:
+ nsFastLoadService();
+ private:
+ ~nsFastLoadService();
+
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIFASTLOADSERVICE
+
+ static NS_METHOD
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+ private:
+ PRLock* mLock;
+ PLDHashTable* mFastLoadPtrMap;
+ nsCOMPtr<nsIObjectInputStream> mInputStream;
+ nsCOMPtr<nsIObjectOutputStream> mOutputStream;
+ nsCOMPtr<nsIFastLoadFileIO> mFileIO;
+ PRInt32 mDirection;
+ nsHashtable mChecksumTable;
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIAsyncInputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIAsyncInputStream.idl
new file mode 100644
index 00000000..6ce0bb30
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIAsyncInputStream.idl
@@ -0,0 +1,136 @@
+/* ***** 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.
+ *
+ * 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):
+ * Darin Fisher <darin@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 "nsIInputStream.idl"
+
+interface nsIInputStreamCallback;
+interface nsIEventTarget;
+
+/**
+ * If an input stream is non-blocking, it may return NS_BASE_STREAM_WOULD_BLOCK
+ * when read. The caller must then wait for the stream to have some data to
+ * read. If the stream implements nsIAsyncInputStream, then the caller can use
+ * this interface to request an asynchronous notification when the stream
+ * becomes readable or closed (via the AsyncWait method).
+ *
+ * While this interface is almost exclusively used with non-blocking streams, it
+ * is not necessary that nsIInputStream::isNonBlocking return true. Nor is it
+ * necessary that a non-blocking nsIInputStream implementation also implement
+ * nsIAsyncInputStream.
+ */
+[scriptable, uuid(15a15329-00de-44e8-ab06-0d0b0d43dc5b)]
+interface nsIAsyncInputStream : nsIInputStream
+{
+ /**
+ * This method closes the stream and sets its internal status. If the
+ * stream is already closed, then this method is ignored. Once the stream
+ * is closed, the stream's status cannot be changed. Any successful status
+ * code passed to this method is treated as NS_BASE_STREAM_CLOSED, which
+ * has an effect equivalent to nsIInputStream::close.
+ *
+ * NOTE: this method exists in part to support pipes, which have both an
+ * input end and an output end. If the input end of a pipe is closed, then
+ * writes to the output end of the pipe will fail. The error code returned
+ * when an attempt is made to write to a "broken" pipe corresponds to the
+ * status code passed in when the input end of the pipe was closed, which
+ * greatly simplifies working with pipes in some cases.
+ *
+ * @param aStatus
+ * The error that will be reported if this stream is accessed after
+ * it has been closed.
+ */
+ void closeWithStatus(in nsresult aStatus);
+
+ /**
+ * Asynchronously wait for the stream to be readable or closed. The
+ * notification is one-shot, meaning that each asyncWait call will result
+ * in exactly one notification callback. After the OnInputStreamReady event
+ * is dispatched, the stream releases its reference to the
+ * nsIInputStreamCallback object. It is safe to call asyncWait again from the
+ * notification handler.
+ *
+ * This method may be called at any time (even if read has not been called).
+ * In other words, this method may be called when the stream already has
+ * data to read. It may also be called when the stream is closed. If the
+ * stream is already readable or closed when AsyncWait is called, then the
+ * OnInputStreamReady event will be dispatched immediately. Otherwise, the
+ * event will be dispatched when the stream becomes readable or closed.
+ *
+ * @param aCallback
+ * This object is notified when the stream becomes ready.
+ * @param aFlags
+ * This parameter specifies optional flags passed in to configure
+ * the behavior of this method. Pass zero to specify no flags.
+ * @param aRequestedCount
+ * Wait until at least this many bytes can be read. This is only
+ * a suggestion to the underlying stream; it may be ignored. The
+ * caller may pass zero to indicate no preference.
+ * @param aEventTarget
+ * Specify NULL to receive notification on ANY thread (possibly even
+ * recursively on the calling thread -- i.e., synchronously), or
+ * specify that the notification be delivered to a specific event
+ * target.
+ */
+ void asyncWait(in nsIInputStreamCallback aCallback,
+ in unsigned long aFlags,
+ in unsigned long aRequestedCount,
+ in nsIEventTarget aEventTarget);
+
+ /**
+ * If passed to asyncWait, this flag overrides the default behavior,
+ * causing the OnInputStreamReady notification to be suppressed until the
+ * stream becomes closed (either as a result of closeWithStatus/close being
+ * called on the stream or possibly due to some error in the underlying
+ * stream).
+ */
+ const unsigned long WAIT_CLOSURE_ONLY = (1<<0);
+};
+
+/**
+ * This is a companion interface for nsIAsyncInputStream::asyncWait.
+ */
+[scriptable, uuid(d1f28e94-3a6e-4050-a5f5-2e81b1fc2a43)]
+interface nsIInputStreamCallback : nsISupports
+{
+ /**
+ * Called to indicate that the stream is either readable or closed.
+ *
+ * @param aStream
+ * The stream whose asyncWait method was called.
+ */
+ void onInputStreamReady(in nsIAsyncInputStream aStream);
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIAsyncOutputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIAsyncOutputStream.idl
new file mode 100644
index 00000000..b0dd9ec0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIAsyncOutputStream.idl
@@ -0,0 +1,136 @@
+/* ***** 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.
+ *
+ * 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):
+ * Darin Fisher <darin@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 "nsIOutputStream.idl"
+
+interface nsIOutputStreamCallback;
+interface nsIEventTarget;
+
+/**
+ * If an output stream is non-blocking, it may return NS_BASE_STREAM_WOULD_BLOCK
+ * when written to. The caller must then wait for the stream to become
+ * writable. If the stream implements nsIAsyncOutputStream, then the caller can
+ * use this interface to request an asynchronous notification when the stream
+ * becomes writable or closed (via the AsyncWait method).
+ *
+ * While this interface is almost exclusively used with non-blocking streams, it
+ * is not necessary that nsIOutputStream::isNonBlocking return true. Nor is it
+ * necessary that a non-blocking nsIOutputStream implementation also implement
+ * nsIAsyncOutputStream.
+ */
+[scriptable, uuid(10dc9c94-8aff-49c6-8af9-d7fdb7339dae)]
+interface nsIAsyncOutputStream : nsIOutputStream
+{
+ /**
+ * This method closes the stream and sets its internal status. If the
+ * stream is already closed, then this method is ignored. Once the stream
+ * is closed, the stream's status cannot be changed. Any successful status
+ * code passed to this method is treated as NS_BASE_STREAM_CLOSED, which
+ * is equivalent to nsIInputStream::close.
+ *
+ * NOTE: this method exists in part to support pipes, which have both an
+ * input end and an output end. If the output end of a pipe is closed, then
+ * reads from the input end of the pipe will fail. The error code returned
+ * when an attempt is made to read from a "closed" pipe corresponds to the
+ * status code passed in when the output end of the pipe is closed, which
+ * greatly simplifies working with pipes in some cases.
+ *
+ * @param aStatus
+ * The error that will be reported if this stream is accessed after
+ * it has been closed.
+ */
+ void closeWithStatus(in nsresult reason);
+
+ /**
+ * Asynchronously wait for the stream to be writable or closed. The
+ * notification is one-shot, meaning that each asyncWait call will result
+ * in exactly one notification callback. After the OnOutputStreamReady event
+ * is dispatched, the stream releases its reference to the
+ * nsIOutputStreamCallback object. It is safe to call asyncWait again from the
+ * notification handler.
+ *
+ * This method may be called at any time (even if write has not been called).
+ * In other words, this method may be called when the stream already has
+ * room for more data. It may also be called when the stream is closed. If
+ * the stream is already writable or closed when AsyncWait is called, then the
+ * OnOutputStreamReady event will be dispatched immediately. Otherwise, the
+ * event will be dispatched when the stream becomes writable or closed.
+ *
+ * @param aCallback
+ * This object is notified when the stream becomes ready.
+ * @param aFlags
+ * This parameter specifies optional flags passed in to configure
+ * the behavior of this method. Pass zero to specify no flags.
+ * @param aRequestedCount
+ * Wait until at least this many bytes can be written. This is only
+ * a suggestion to the underlying stream; it may be ignored. The
+ * caller may pass zero to indicate no preference.
+ * @param aEventTarget
+ * Specify NULL to receive notification on ANY thread (possibly even
+ * recursively on the calling thread -- i.e., synchronously), or
+ * specify that the notification be delivered to a specific event
+ * target.
+ */
+ void asyncWait(in nsIOutputStreamCallback aCallback,
+ in unsigned long aFlags,
+ in unsigned long aRequestedCount,
+ in nsIEventTarget aEventTarget);
+
+ /**
+ * If passed to asyncWait, this flag overrides the default behavior,
+ * causing the OnOutputStreamReady notification to be suppressed until the
+ * stream becomes closed (either as a result of closeWithStatus/close being
+ * called on the stream or possibly due to some error in the underlying
+ * stream).
+ */
+ const unsigned long WAIT_CLOSURE_ONLY = (1<<0);
+};
+
+/**
+ * This is a companion interface for nsIAsyncOutputStream::asyncWait.
+ */
+[scriptable, uuid(40dbcdff-9053-42c5-a57c-3ec910d0f148)]
+interface nsIOutputStreamCallback : nsISupports
+{
+ /**
+ * Called to indicate that the stream is either writable or closed.
+ *
+ * @param aStream
+ * The stream whose asyncWait method was called.
+ */
+ void onOutputStreamReady(in nsIAsyncOutputStream aStream);
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIBaseStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIBaseStream.idl
new file mode 100644
index 00000000..12e4c5f0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIBaseStream.idl
@@ -0,0 +1,45 @@
+/* -*- 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"
+
+[scriptable, uuid(6ccb17a0-e95e-11d1-beae-00805f8a66dc)]
+interface nsIBaseStream : nsISupports
+{
+ /** Close the stream. */
+ void close();
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIBinaryInputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIBinaryInputStream.idl
new file mode 100644
index 00000000..bc9ea0b5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIBinaryInputStream.idl
@@ -0,0 +1,121 @@
+/* -*- 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-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 "nsIInputStream.idl"
+#include "nsrootidl.idl"
+
+/**
+ * This interface allows consumption of primitive data types from a "binary
+ * stream" containing untagged, big-endian binary data, i.e. as produced by an
+ * implementation of nsIBinaryOutputStream. This might be used, for example,
+ * to implement network protocols or to read from architecture-neutral disk
+ * files, i.e. ones that can be read and written by both big-endian and
+ * little-endian platforms.
+ *
+ * @See nsIBinaryOutputStream
+ */
+
+[scriptable, uuid(7b456cb0-8772-11d3-90cf-0040056a906e)]
+interface nsIBinaryInputStream : nsIInputStream {
+ void setInputStream(in nsIInputStream aInputStream);
+
+ PRBool readBoolean();
+
+ PRUint8 read8();
+ PRUint16 read16();
+ PRUint32 read32();
+ PRUint64 read64();
+
+ float readFloat();
+ double readDouble();
+
+ /**
+ * Read a NUL-terminated 8-bit char* string from a binary stream.
+ */
+ ACString readCString();
+
+ /**
+ * Read a NUL-terminated 16-bit PRUnichar* string from a binary stream.
+ */
+ AString readString();
+
+ /**
+ * Read an opaque byte array from a binary stream.
+ */
+ void readBytes(in PRUint32 aLength,
+ [size_is(aLength), retval] out string aString);
+
+ /**
+ * Read an opaque byte array from a binary stream, storing the results
+ * as an array of PRUint8s.
+ */
+ void readByteArray(in PRUint32 aLength,
+ [array, size_is(aLength), retval] out PRUint8 aBytes);
+};
+
+%{C++
+
+inline nsresult
+NS_ReadOptionalCString(nsIBinaryInputStream* aStream, nsACString& aResult)
+{
+ PRBool nonnull;
+ nsresult rv = aStream->ReadBoolean(&nonnull);
+ if (NS_SUCCEEDED(rv)) {
+ if (nonnull)
+ rv = aStream->ReadCString(aResult);
+ else
+ aResult.Truncate();
+ }
+ return rv;
+}
+
+inline nsresult
+NS_ReadOptionalString(nsIBinaryInputStream* aStream, nsAString& aResult)
+{
+ PRBool nonnull;
+ nsresult rv = aStream->ReadBoolean(&nonnull);
+ if (NS_SUCCEEDED(rv)) {
+ if (nonnull)
+ rv = aStream->ReadString(aResult);
+ else
+ aResult.Truncate();
+ }
+ return rv;
+}
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIBinaryOutputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIBinaryOutputStream.idl
new file mode 100644
index 00000000..16a100b7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIBinaryOutputStream.idl
@@ -0,0 +1,119 @@
+/* -*- 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-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 "nsIOutputStream.idl"
+#include "nsrootidl.idl"
+
+/**
+ * This interface allows writing of primitive data types (integers,
+ * floating-point values, booleans, etc.) to a stream in a binary, untagged,
+ * fixed-endianness format. This might be used, for example, to implement
+ * network protocols or to produce architecture-neutral binary disk files,
+ * i.e. ones that can be read and written by both big-endian and little-endian
+ * platforms. Output is written in big-endian order (high-order byte first),
+ * as this is traditional network order.
+ *
+ * @See nsIBinaryInputStream
+ */
+
+[scriptable, uuid(204ee610-8765-11d3-90cf-0040056a906e)]
+interface nsIBinaryOutputStream : nsIOutputStream {
+ void setOutputStream(in nsIOutputStream aOutputStream);
+
+ void writeBoolean(in PRBool aBoolean);
+
+ void write8(in PRUint8 aByte);
+ void write16(in PRUint16 a16);
+ void write32(in PRUint32 a32);
+ void write64(in PRUint64 a64);
+
+ void writeFloat(in float aFloat);
+ void writeDouble(in double aDouble);
+
+ /**
+ * Write a NUL-terminated 8-bit char* string to a binary stream.
+ */
+ void writeStringZ(in string aString);
+
+ /**
+ * Write a NUL-terminated 16-bit PRUnichar* string to a binary stream.
+ */
+ void writeWStringZ(in wstring aString);
+
+ /**
+ * Write a NUL-terminated UTF8-encoded string to a binary stream, produced
+ * from a NUL-terminated 16-bit PRUnichar* string argument.
+ */
+ void writeUtf8Z(in wstring aString);
+
+ /**
+ * Write an opaque byte array to a binary stream.
+ */
+ void writeBytes([size_is(aLength)] in string aString, in PRUint32 aLength);
+
+ /**
+ * Write an opaque byte array to a binary stream.
+ */
+ void writeByteArray([array, size_is(aLength)] in PRUint8 aBytes,
+ in PRUint32 aLength);
+
+};
+
+%{C++
+
+inline nsresult
+NS_WriteOptionalStringZ(nsIBinaryOutputStream* aStream, const char* aString)
+{
+ PRBool nonnull = (aString != nsnull);
+ nsresult rv = aStream->WriteBoolean(nonnull);
+ if (NS_SUCCEEDED(rv) && nonnull)
+ rv = aStream->WriteStringZ(aString);
+ return rv;
+}
+
+inline nsresult
+NS_WriteOptionalWStringZ(nsIBinaryOutputStream* aStream, const PRUnichar* aString)
+{
+ PRBool nonnull = (aString != nsnull);
+ nsresult rv = aStream->WriteBoolean(nonnull);
+ if (NS_SUCCEEDED(rv) && nonnull)
+ rv = aStream->WriteWStringZ(aString);
+ return rv;
+}
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIByteArrayInputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIByteArrayInputStream.idl
new file mode 100644
index 00000000..a124e923
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIByteArrayInputStream.idl
@@ -0,0 +1,48 @@
+/* -*- 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 "nsIInputStream.idl"
+
+[scriptable, uuid(b5a21556-35fc-4815-aff1-f9142639686e)]
+interface nsIByteArrayInputStream : nsIInputStream
+{
+};
+
+%{C++
+extern NS_COM nsresult
+NS_NewByteArrayInputStream (nsIByteArrayInputStream ** aResult, char * buffer, unsigned long size);
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIDirectoryEnumerator.idl b/src/libs/xpcom18a4/xpcom/io/nsIDirectoryEnumerator.idl
new file mode 100644
index 00000000..b32a7f62
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIDirectoryEnumerator.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 the Directory Enumerator Interface.
+ *
+ * The Initial Developer of the Original Code is Google Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Ben Goodger <ben@mozilla.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 ***** */
+
+#include "nsISupports.idl"
+
+interface nsIFile;
+
+/**
+ * This interface provides a means for enumerating the contents of a directory.
+ * It is similar to nsISimpleEnumerator except the retrieved entries are QI'ed
+ * to nsIFile, and there is a mechanism for closing the directory when the
+ * enumeration is complete.
+ *
+ * @status UNDER_REVIEW
+ */
+[scriptable, uuid(31f7f4ae-6916-4f2d-a81e-926a4e3022ee)]
+interface nsIDirectoryEnumerator : nsISupports
+{
+ /**
+ * Retrieves the next file in the sequence. The "nextFile" element is the
+ * first element upon the first call. This attribute is null if there is no
+ * next element.
+ */
+ readonly attribute nsIFile nextFile;
+
+ /**
+ * Closes the directory being enumerated, releasing the system resource.
+ * @throws NS_OK if the call succeeded and the directory was closed.
+ * NS_ERROR_FAILURE if the directory close failed.
+ * It is safe to call this function many times.
+ */
+ void close();
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIDirectoryService.idl b/src/libs/xpcom18a4/xpcom/io/nsIDirectoryService.idl
new file mode 100644
index 00000000..c34b7aa9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIDirectoryService.idl
@@ -0,0 +1,138 @@
+/* -*- 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 "nsISupports.idl"
+#include "nsIFile.idl"
+
+/**
+ * nsIDirectoryServiceProvider
+ *
+ * Used by Directory Service to get file locations.
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(bbf8cab0-d43a-11d3-8cc2-00609792278c)]
+interface nsIDirectoryServiceProvider: nsISupports
+{
+ /**
+ * getFile
+ *
+ * Directory Service calls this when it gets the first request for
+ * a prop or on every request if the prop is not persistent.
+ *
+ * @param prop The symbolic name of the file.
+ * @param persistent TRUE - The returned file will be cached by Directory
+ * Service. Subsequent requests for this prop will
+ * bypass the provider and use the cache.
+ * FALSE - The provider will be asked for this prop
+ * each time it is requested.
+ *
+ * @return The file represented by the property.
+ *
+ */
+ nsIFile getFile(in string prop, out PRBool persistent);
+};
+
+/**
+ * nsIDirectoryServiceProvider2
+ *
+ * An extension of nsIDirectoryServiceProvider which allows
+ * multiple files to be returned for the given key.
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(2f977d4b-5485-11d4-87e2-0010a4e75ef2)]
+interface nsIDirectoryServiceProvider2: nsIDirectoryServiceProvider
+{
+ /**
+ * getFiles
+ *
+ * Directory Service calls this when it gets a request for
+ * a prop and the requested type is nsISimpleEnumerator.
+ *
+ * @param prop The symbolic name of the file list.
+ *
+ * @return An enumerator for a list of file locations.
+ * The elements in the enumeration are nsIFile
+ *
+ */
+ nsISimpleEnumerator getFiles(in string prop);
+};
+
+/**
+ * nsIDirectoryService
+ *
+ * @status FROZEN
+ */
+
+[scriptable, uuid(57a66a60-d43a-11d3-8cc2-00609792278c)]
+interface nsIDirectoryService: nsISupports
+{
+ /**
+ * init
+ *
+ * Must be called. Used internally by XPCOM initialization.
+ *
+ */
+ void init();
+
+ /**
+ * registerProvider
+ *
+ * Register a provider with the service.
+ *
+ * @param prov The service will keep a strong reference
+ * to this object. It will be released when
+ * the service is released.
+ *
+ */
+ void registerProvider(in nsIDirectoryServiceProvider prov);
+
+ /**
+ * unregisterProvider
+ *
+ * Unregister a provider with the service.
+ *
+ * @param prov
+ *
+ */
+ void unregisterProvider(in nsIDirectoryServiceProvider prov);
+};
+
+
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIFastLoadFileControl.idl b/src/libs/xpcom18a4/xpcom/io/nsIFastLoadFileControl.idl
new file mode 100644
index 00000000..99f5a287
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIFastLoadFileControl.idl
@@ -0,0 +1,123 @@
+/* -*- 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"
+#include "nsrootidl.idl"
+
+interface nsIFile;
+interface nsISimpleEnumerator;
+
+/**
+ * The nsIFastLoadFileControl interface and its subinterfaces are mix-ins for
+ * classes implementing nsIObjectInputStream and nsIObjectOutputStream, so that
+ * those stream types can be used with nsIFastLoadService to access and compute
+ * FastLoad file checksums, update and check FastLoad file dependencies, and
+ * multiplex documents loaded via non-blocking i/o.
+ *
+ * If an nsIObjectInputStream class doesn't support nsIFastLoadReadControl, or
+ * an nsIObjectOutputStream class doesn't support nsIFastLoadWriteControl, that
+ * implementation may still be useful for object serialization, but it can't be
+ * used to read or write a Mozilla FastLoad file.
+ */
+[scriptable, uuid(8a1e2c63-af50-4147-af7e-26289dc180dd)]
+interface nsIFastLoadFileControl : nsISupports
+{
+ /**
+ * Get and set the recorded checksum value from the FastLoad file header.
+ */
+ attribute PRUint32 checksum;
+
+ /**
+ * Multiplexed document control methods. A FastLoad file may contain
+ * multiple interleaved documents identified by a URI specifier string,
+ * and indexed for fast multiplexor select by an opaque URI object key.
+ * You StartMuxedDocument when initiating a document load, then Select
+ * before every batch of calls to (de)serialize document data, and End
+ * when the load completes.
+ *
+ * Document multiplexing is necessary to support incremental FastLoad
+ * development in a non-blocking i/o architecture such as Mozilla, where
+ * some (but not all, at first, or for a while during development) of the
+ * results of parsing and compiling various inputs can be multiplexed to
+ * or from a FastLoad file.
+ *
+ * Note: Select returns the previously selected URI object in case the
+ * caller is synchronously selecting and writing data to the FastLoad
+ * file, so the caller can reselect the previous URI and return to code
+ * the continues to write FastLoad data for the previous URI, unaware of
+ * the nested select/write/reselect.
+ */
+ void startMuxedDocument(in nsISupports aURI, in string aURISpec);
+ nsISupports selectMuxedDocument(in nsISupports aURI);
+ void endMuxedDocument(in nsISupports aURI);
+
+ /**
+ * Return true if aURISpec identifies a muxed document in the FastLoad
+ * file, false otherwise.
+ */
+ boolean hasMuxedDocument(in string aURISpec);
+};
+
+[scriptable, uuid(652ecec6-d40b-45b6-afef-641d6c63a35b)]
+interface nsIFastLoadReadControl : nsIFastLoadFileControl
+{
+ /**
+ * Computes the correct checksum of the FastLoad file, independent of the
+ * header's checksum value. The header checksum field is treated as zero
+ * when computing the checksum.
+ */
+ PRUint32 computeChecksum();
+
+ /**
+ * Get the collection of dependency nsIFile instances recorded during the
+ * FastLoad file write or read/update process, and checked during the read
+ * process to invalidate the FastLoad file if any dependencies are newer.
+ */
+ readonly attribute nsISimpleEnumerator dependencies;
+};
+
+[scriptable, uuid(2ad6e9e6-1379-4e45-a899-a54b27ff915c)]
+interface nsIFastLoadWriteControl : nsIFastLoadFileControl
+{
+ /**
+ * Add a file dependency of the FastLoad file (e.g., a .jar file) to the
+ * set of dependencies that trigger regeneration if any dependency has a
+ * last-modified-time greater than the FastLoad file's mtime.
+ */
+ void addDependency(in nsIFile aFile);
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIFastLoadService.idl b/src/libs/xpcom18a4/xpcom/io/nsIFastLoadService.idl
new file mode 100644
index 00000000..0b177463
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIFastLoadService.idl
@@ -0,0 +1,155 @@
+/* -*- 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"
+#include "nsrootidl.idl"
+
+interface nsIFastLoadReadControl;
+interface nsIFile;
+interface nsIInputStream;
+interface nsIOutputStream;
+interface nsIObjectInputStream;
+interface nsIObjectOutputStream;
+
+[scriptable, uuid(715577db-d9c5-464a-a32e-0a40c29b22d4)]
+interface nsIFastLoadFileIO : nsISupports
+{
+ readonly attribute nsIInputStream inputStream;
+ readonly attribute nsIOutputStream outputStream;
+};
+
+[scriptable, uuid(759e475e-0c23-4dbf-b1b8-78c9369e3072)]
+interface nsIFastLoadService : nsISupports
+{
+ nsIFile newFastLoadFile(in string aBaseName);
+
+ nsIObjectInputStream newInputStream(in nsIInputStream aSrcStream);
+ nsIObjectOutputStream newOutputStream(in nsIOutputStream aDestStream);
+
+ // Flag values for the direction attribute and the aDirectionFlags
+ // parameter to startMuxedDocument.
+ const PRInt32 NS_FASTLOAD_READ = 1;
+ const PRInt32 NS_FASTLOAD_WRITE = 2;
+
+ attribute nsIObjectInputStream inputStream;
+ attribute nsIObjectOutputStream outputStream;
+ attribute nsIFastLoadFileIO fileIO;
+ readonly attribute PRInt32 direction;
+
+ /**
+ * These methods associate a URI object with its spec, for faster select
+ * using the object pointer as a key, rather than the spec string. The
+ * selectMuxedDocument method returns the previously selected URI object,
+ * in case a caller needs to reselect the previous after muxing data for
+ * a given URI synchronously. For the non-blocking or "asynchronous" i/o
+ * case, the caller must select the source URI from the FastLoad multiplex
+ * before writing a new burst of data parsed from the slow-loaded source.
+ *
+ * Clients of inputStream and outputStream should try to demultiplex data
+ * from the input stream only if fastLoadService->StartMuxedDocument(uri,
+ * urispec, NS_FASTLOAD_READ) succeeds. If StartMuxedDocument fails with
+ * NS_ERROR_NOT_AVAILABLE, callers should slow-load the documents, muxing
+ * their data to the current output stream.
+ */
+ void startMuxedDocument(in nsISupports aURI,
+ in string aURISpec,
+ in PRInt32 aDirectionFlags);
+ nsISupports selectMuxedDocument(in nsISupports aURI);
+ void endMuxedDocument(in nsISupports aURI);
+
+ void addDependency(in nsIFile aFile);
+
+ PRUint32 computeChecksum(in nsIFile aFile,
+ in nsIFastLoadReadControl aControl);
+ void cacheChecksum(in nsIFile aFile,
+ in nsIObjectOutputStream aStream);
+
+ [noscript] void getFastLoadReferent(inout nsISupports aPtr);
+
+ [noscript] void readFastLoadPtr(in nsIObjectInputStream aInputStream,
+ inout nsISupports aPtr);
+
+ [noscript] void writeFastLoadPtr(in nsIObjectOutputStream aOutputStream,
+ in nsISupports aPtr);
+
+ /**
+ * Return true if aURISpec identifies a muxed document in the FastLoad
+ * file, false otherwise.
+ */
+ boolean hasMuxedDocument(in string aURISpec);
+};
+
+%{C++
+#define NS_FASTLOADSERVICE_CLASSNAME "Mozilla FastLoad Service"
+
+#define NS_FASTLOADSERVICE_CID \
+ {0xc943093c,0xac94,0x4bee,{0x84,0x0b,0x8b,0x5a,0x6e,0x31,0x4f,0xa7}}
+
+#define NS_FASTLOADSERVICE_CONTRACTID \
+ "@mozilla.org/fast-load-service;1"
+
+#ifndef nsCOMPtr_h___
+# include "nsCOMPtr.h"
+#endif
+#ifndef __gen_nsIFile_h__
+# include "nsIFile.h"
+#endif
+#ifndef nsIServiceManager_h___
+# include "nsIServiceManager.h"
+#endif
+
+inline const nsGetServiceByCID
+do_GetFastLoadService(nsresult *aResultCode = 0)
+{
+ static NS_DEFINE_CID(kFastLoadServiceCID, NS_FASTLOADSERVICE_CID);
+ return nsGetServiceByCID(kFastLoadServiceCID, nsnull, aResultCode);
+}
+
+inline nsresult
+NS_AddFastLoadDependency(nsIFile* aFile)
+{
+ nsCOMPtr<nsIFastLoadService> fastLoadService(do_GetFastLoadService());
+ if (fastLoadService) {
+ nsresult rv = fastLoadService->AddDependency(aFile);
+ if (NS_FAILED(rv) && rv != NS_ERROR_NOT_AVAILABLE)
+ return rv;
+ }
+ return NS_OK;
+}
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIFile.idl b/src/libs/xpcom18a4/xpcom/io/nsIFile.idl
new file mode 100644
index 00000000..1d70858e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIFile.idl
@@ -0,0 +1,343 @@
+/* -*- 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-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Doug Turner <dougt@netscape.com>
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * Darin Fisher <darin@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 "nsISupports.idl"
+
+interface nsISimpleEnumerator;
+
+/**
+ * This is the only correct cross-platform way to specify a file.
+ * Strings are not such a way. If you grew up on windows or unix, you
+ * may think they are. Welcome to reality.
+ *
+ * All methods with string parameters have two forms. The preferred
+ * form operates on UCS-2 encoded characters strings. An alternate
+ * form operates on characters strings encoded in the "native" charset.
+ *
+ * A string containing characters encoded in the native charset cannot
+ * be safely passed to javascript via xpconnect. Therefore, the "native
+ * methods" are not scriptable.
+ *
+ * @status FROZEN
+ */
+[scriptable, uuid(c8c0a080-0868-11d3-915f-d9d889d48e3c)]
+interface nsIFile : nsISupports
+{
+ /**
+ * Create Types
+ *
+ * NORMAL_FILE_TYPE - A normal file.
+ * DIRECTORY_TYPE - A directory/folder.
+ */
+ const unsigned long NORMAL_FILE_TYPE = 0;
+ const unsigned long DIRECTORY_TYPE = 1;
+
+ /**
+ * append[Native]
+ *
+ * This function is used for constructing a descendent of the
+ * current nsIFile.
+ *
+ * @param node
+ * A string which is intended to be a child node of the nsIFile.
+ * For the |appendNative| method, the node must be in the native
+ * filesystem charset.
+ */
+ void append(in AString node);
+ [noscript] void appendNative(in ACString node);
+
+ /**
+ * Normalize the pathName (e.g. removing .. and . components on Unix).
+ */
+ void normalize();
+
+ /**
+ * create
+ *
+ * This function will create a new file or directory in the
+ * file system. Any nodes that have not been created or
+ * resolved, will be. If the file or directory already
+ * exists create() will return NS_ERROR_FILE_ALREADY_EXISTS.
+ *
+ * @param type
+ * This specifies the type of file system object
+ * to be made. The only two types at this time
+ * are file and directory which are defined above.
+ * If the type is unrecongnized, we will return an
+ * error (NS_ERROR_FILE_UNKNOWN_TYPE).
+ *
+ * @param permissions
+ * The unix style octal permissions. This may
+ * be ignored on systems that do not need to do
+ * permissions.
+ */
+ void create(in unsigned long type, in unsigned long permissions);
+
+ /**
+ * Accessor to the leaf name of the file itself.
+ * For the |nativeLeafName| method, the nativeLeafName must
+ * be in the native filesystem charset.
+ */
+ attribute AString leafName;
+ [noscript] attribute ACString nativeLeafName;
+
+ /**
+ * copyTo[Native]
+ *
+ * This will copy this file to the specified newParentDir.
+ * If a newName is specified, the file will be renamed.
+ * If 'this' is not created we will return an error
+ * (NS_ERROR_FILE_TARGET_DOES_NOT_EXIST).
+ *
+ * copyTo may fail if the file already exists in the destination
+ * directory.
+ *
+ * copyTo will NOT resolve aliases/shortcuts during the copy.
+ *
+ * @param newParentDir
+ * This param is the destination directory. If the
+ * newParentDir is null, copyTo() will use the parent
+ * directory of this file. If the newParentDir is not
+ * empty and is not a directory, an error will be
+ * returned (NS_ERROR_FILE_DESTINATION_NOT_DIR). For the
+ * |CopyToNative| method, the newName must be in the
+ * native filesystem charset.
+ *
+ * @param newName
+ * This param allows you to specify a new name for
+ * the file to be copied. This param may be empty, in
+ * which case the current leaf name will be used.
+ */
+ void copyTo(in nsIFile newParentDir, in AString newName);
+ [noscript] void CopyToNative(in nsIFile newParentDir, in ACString newName);
+
+ /**
+ * copyToFollowingLinks[Native]
+ *
+ * This function is identical to copyTo with the exception that,
+ * as the name implies, it follows symbolic links. The XP_UNIX
+ * implementation always follow symbolic links when copying. For
+ * the |CopyToFollowingLinks| method, the newName must be in the
+ * native filesystem charset.
+ */
+ void copyToFollowingLinks(in nsIFile newParentDir, in AString newName);
+ [noscript] void copyToFollowingLinksNative(in nsIFile newParentDir, in ACString newName);
+
+ /**
+ * moveTo[Native]
+ *
+ * A method to move this file or directory to newParentDir.
+ * If a newName is specified, the file or directory will be renamed.
+ * If 'this' is not created we will return an error
+ * (NS_ERROR_FILE_TARGET_DOES_NOT_EXIST).
+ * If 'this' is a file, and the destination file already exists, moveTo
+ * will replace the old file.
+ *
+ * moveTo will NOT resolve aliases/shortcuts during the copy.
+ * moveTo will do the right thing and allow copies across volumes.
+ * moveTo will return an error (NS_ERROR_FILE_DIR_NOT_EMPTY) if 'this' is
+ * a directory and the destination directory is not empty.
+ * moveTo will return an error (NS_ERROR_FILE_ACCESS_DENIED) if 'this' is
+ * a directory and the destination directory is not writable.
+ *
+ * @param newParentDir
+ * This param is the destination directory. If the
+ * newParentDir is empty, moveTo() will rename the file
+ * within its current directory. If the newParentDir is
+ * not empty and does not name a directory, an error will
+ * be returned (NS_ERROR_FILE_DESTINATION_NOT_DIR). For
+ * the |moveToNative| method, the newName must be in the
+ * native filesystem charset.
+ *
+ * @param newName
+ * This param allows you to specify a new name for
+ * the file to be moved. This param may be empty, in
+ * which case the current leaf name will be used.
+ */
+ void moveTo(in nsIFile newParentDir, in AString newName);
+ [noscript] void moveToNative(in nsIFile newParentDir, in ACString newName);
+
+ /**
+ * This will try to delete this file. The 'recursive' flag
+ * must be PR_TRUE to delete directories which are not empty.
+ *
+ * This will not resolve any symlinks.
+ */
+ void remove(in boolean recursive);
+
+ /**
+ * Attributes of nsIFile.
+ */
+
+ attribute unsigned long permissions;
+ attribute unsigned long permissionsOfLink;
+
+ /**
+ * File Times are to be in milliseconds from
+ * midnight (00:00:00), January 1, 1970 Greenwich Mean
+ * Time (GMT).
+ */
+ attribute PRInt64 lastModifiedTime;
+ attribute PRInt64 lastModifiedTimeOfLink;
+
+ /**
+ * WARNING! On the Mac, getting/setting the file size with nsIFile
+ * only deals with the size of the data fork. If you need to
+ * know the size of the combined data and resource forks use the
+ * GetFileSizeWithResFork() method defined on nsILocalFileMac.
+ */
+ attribute PRInt64 fileSize;
+ readonly attribute PRInt64 fileSizeOfLink;
+
+ /**
+ * target & path
+ *
+ * Accessor to the string path. The native version of these
+ * strings are not guaranteed to be a usable path to pass to
+ * NSPR or the C stdlib. There are problems that affect
+ * platforms on which a path does not fully specify a file
+ * because two volumes can have the same name (e.g., XP_MAC).
+ * This is solved by holding "private", native data in the
+ * nsIFile implementation. This native data is lost when
+ * you convert to a string.
+ *
+ * DO NOT PASS TO USE WITH NSPR OR STDLIB!
+ *
+ * target
+ * Find out what the symlink points at. Will give error
+ * (NS_ERROR_FILE_INVALID_PATH) if not a symlink.
+ *
+ * path
+ * Find out what the nsIFile points at.
+ *
+ * Note that the ACString attributes are returned in the
+ * native filesystem charset.
+ *
+ */
+ readonly attribute AString target;
+ [noscript] readonly attribute ACString nativeTarget;
+ readonly attribute AString path;
+ [noscript] readonly attribute ACString nativePath;
+
+ boolean exists();
+ boolean isWritable();
+ boolean isReadable();
+ boolean isExecutable();
+ boolean isHidden();
+ boolean isDirectory();
+ boolean isFile();
+ boolean isSymlink();
+ /**
+ * Not a regular file, not a directory, not a symlink.
+ */
+ boolean isSpecial();
+
+ /**
+ * createUnique
+ *
+ * This function will create a new file or directory in the
+ * file system. Any nodes that have not been created or
+ * resolved, will be. If this file already exists, we try
+ * variations on the leaf name "suggestedName" until we find
+ * one that did not already exist.
+ *
+ * If the search for nonexistent files takes too long
+ * (thousands of the variants already exist), we give up and
+ * return NS_ERROR_FILE_TOO_BIG.
+ *
+ * @param type
+ * This specifies the type of file system object
+ * to be made. The only two types at this time
+ * are file and directory which are defined above.
+ * If the type is unrecongnized, we will return an
+ * error (NS_ERROR_FILE_UNKNOWN_TYPE).
+ *
+ * @param permissions
+ * The unix style octal permissions. This may
+ * be ignored on systems that do not need to do
+ * permissions.
+ */
+ void createUnique(in unsigned long type, in unsigned long permissions);
+
+ /**
+ * clone()
+ *
+ * This function will allocate and initialize a nsIFile object to the
+ * exact location of the |this| nsIFile.
+ *
+ * @param file
+ * A nsIFile which this object will be initialize
+ * with.
+ *
+ */
+ nsIFile clone();
+
+ /**
+ * Will determine if the inFile equals this.
+ */
+ boolean equals(in nsIFile inFile);
+
+ /**
+ * Will determine if inFile is a descendant of this file
+ * If |recur| is true, look in subdirectories too
+ */
+ boolean contains(in nsIFile inFile, in boolean recur);
+
+ /**
+ * Parent will be null when this is at the top of the volume.
+ */
+ readonly attribute nsIFile parent;
+
+ /**
+ * Returns an enumeration of the elements in a directory. Each
+ * element in the enumeration is an nsIFile.
+ *
+ * @return NS_ERROR_FILE_NOT_DIRECTORY if the current nsIFile does
+ * not specify a directory.
+ */
+ readonly attribute nsISimpleEnumerator directoryEntries;
+};
+
+%{C++
+#ifndef MOZILLA_STRICT_API
+#include "nsDirectoryServiceUtils.h"
+#endif
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIInputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIInputStream.idl
new file mode 100644
index 00000000..827f6363
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIInputStream.idl
@@ -0,0 +1,139 @@
+/* -*- 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):
+ * Warren Harris <warren@netscape.com>
+ * Darin Fisher <darin@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 "nsISupports.idl"
+
+interface nsIInputStream;
+
+%{C++
+/**
+ * The signature of the writer function passed to ReadSegments. This
+ * is the "consumer" of data that gets read from the stream's buffer.
+ *
+ * @param aInStream stream being read
+ * @param aClosure opaque parameter passed to ReadSegments
+ * @param aFromSegment pointer to memory owned by the input stream
+ * @param aToOffset amount already read (since ReadSegments was called)
+ * @param aCount length of fromSegment
+ * @param aWriteCount number of bytes read
+ *
+ * Implementers should return the following:
+ *
+ * @return NS_OK and (*aWriteCount > 0) if consumed some data
+ * @return <any-error> if not interested in consuming any data
+ *
+ * Errors are never passed to the caller of ReadSegments.
+ *
+ * NOTE: returning NS_OK and (*aWriteCount = 0) has undefined behavior.
+ *
+ * @status FROZEN
+ */
+typedef NS_CALLBACK(nsWriteSegmentFun)(nsIInputStream *aInStream,
+ void *aClosure,
+ const char *aFromSegment,
+ PRUint32 aToOffset,
+ PRUint32 aCount,
+ PRUint32 *aWriteCount);
+%}
+
+native nsWriteSegmentFun(nsWriteSegmentFun);
+
+/**
+ * nsIInputStream
+ *
+ * @status FROZEN
+ */
+[scriptable, uuid(fa9c7f6c-61b3-11d4-9877-00c04fa0cf4a)]
+interface nsIInputStream : nsISupports
+{
+ /**
+ * Close the stream.
+ */
+ void close();
+
+ /**
+ * @return number of bytes currently available in the stream
+ */
+ unsigned long available();
+
+ /**
+ * Read data from the stream.
+ *
+ * @param aBuf the buffer into which the data is to be read
+ * @param aCount the maximum number of bytes to be read
+ *
+ * @return number of bytes read (may be less than aCount).
+ * @return 0 if reached end of file
+ *
+ * @throws NS_BASE_STREAM_WOULD_BLOCK if reading from the input stream would
+ * block the calling thread (non-blocking mode only)
+ * @throws <other-error> on failure
+ */
+ [noscript] unsigned long read(in charPtr aBuf, in unsigned long aCount);
+
+ /**
+ * Low-level read method that has access to the stream's underlying buffer.
+ * The writer function may be called multiple times for segmented buffers.
+ * ReadSegments is expected to keep calling the writer until either there is
+ * nothing left to read or the writer returns an error. ReadSegments should
+ * not call the writer with zero bytes to consume.
+ *
+ * @param aWriter the "consumer" of the data to be read
+ * @param aClosure opaque parameter passed to writer
+ * @param aCount the maximum number of bytes to be read
+ *
+ * @return number of bytes read (may be less than aCount)
+ * @return 0 if reached end of file (or if aWriter refused to consume data)
+ *
+ * @throws NS_BASE_STREAM_WOULD_BLOCK if reading from the input stream would
+ * block the calling thread (non-blocking mode only)
+ * @throws <other-error> on failure
+ *
+ * NOTE: this function may be unimplemented if a stream has no underlying
+ * buffer (e.g., socket input stream).
+ */
+ [noscript] unsigned long readSegments(in nsWriteSegmentFun aWriter,
+ in voidPtr aClosure,
+ in unsigned long aCount);
+
+ /**
+ * @return true if stream is non-blocking
+ */
+ boolean isNonBlocking();
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIInputStreamTee.idl b/src/libs/xpcom18a4/xpcom/io/nsIInputStreamTee.idl
new file mode 100644
index 00000000..524e7ee2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIInputStreamTee.idl
@@ -0,0 +1,61 @@
+/* -*- 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
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.com> (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 "nsIInputStream.idl"
+
+interface nsIOutputStream;
+
+/**
+ * A nsIInputStreamTee is a wrapper for an input stream, that when read
+ * reads the specified amount of data from its |source| and copies that
+ * data to its |sink|. |sink| must be a blocking output stream.
+ */
+[scriptable, uuid(44e8b2c8-1ecb-4a63-8b23-3e3500c34f32)]
+interface nsIInputStreamTee : nsIInputStream
+{
+ attribute nsIInputStream source;
+ attribute nsIOutputStream sink;
+};
+
+%{C++
+// factory method
+extern NS_COM nsresult
+NS_NewInputStreamTee(nsIInputStream **tee, // read from this input stream
+ nsIInputStream *source,
+ nsIOutputStream *sink);
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsILineInputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsILineInputStream.idl
new file mode 100644
index 00000000..23781dc4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsILineInputStream.idl
@@ -0,0 +1,54 @@
+/* -*- 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
+ * Boris Zbarsky <bzbarsky@mit.edu>.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * 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 nsILineInputStream;
+
+[scriptable, uuid(c97b466c-1e6e-4773-a4ab-2b2b3190a7a6)]
+interface nsILineInputStream : nsISupports
+{
+ /**
+ * Read a single line from the stream, where a line is a
+ * possibly zero length sequence of 8bit chars terminated by a
+ * CR, LF, CRLF, LFCR, or eof.
+ * The line terminator is not returned.
+ * Return false for end of file, true otherwise
+ */
+ boolean readLine(out ACString aLine);
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsILocalFile.idl b/src/libs/xpcom18a4/xpcom/io/nsILocalFile.idl
new file mode 100644
index 00000000..8d7a1dda
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsILocalFile.idl
@@ -0,0 +1,180 @@
+/* -*- 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 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):
+ * Doug Turner <dougt@netscape.com>
+ * Darin Fisher <darin@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 "nsIFile.idl"
+
+%{C++
+#include "prio.h"
+#include "prlink.h"
+#include <stdio.h>
+%}
+
+[ptr] native PRFileDescStar(PRFileDesc);
+[ptr] native PRLibraryStar(PRLibrary);
+[ptr] native FILE(FILE);
+
+/**
+ * This interface adds methods to nsIFile that are particular to a file
+ * that is accessible via the local file system.
+ *
+ * It follows the same string conventions as nsIFile.
+ *
+ * @status FROZEN
+ */
+[scriptable, uuid(aa610f20-a889-11d3-8c81-000064657374)]
+interface nsILocalFile : nsIFile
+{
+ /**
+ * initWith[Native]Path
+ *
+ * This function will initialize the nsILocalFile object. Any
+ * internal state information will be reset.
+ *
+ * NOTE: This function has a known bug on the macintosh and
+ * other OSes which do not represent file locations as paths.
+ * If you do use this function, be very aware of this problem!
+ *
+ * @param filePath
+ * A string which specifies a full file path to a
+ * location. Relative paths will be treated as an
+ * error (NS_ERROR_FILE_UNRECOGNIZED_PATH). For
+ * initWithNativePath, the filePath must be in the native
+ * filesystem charset.
+ */
+ void initWithPath(in AString filePath);
+ [noscript] void initWithNativePath(in ACString filePath);
+
+ /**
+ * initWithFile
+ *
+ * Initialize this object with another file
+ *
+ * @param aFile
+ * the file this becomes equivalent to
+ */
+ void initWithFile(in nsILocalFile aFile);
+
+ /**
+ * followLinks
+ *
+ * This attribute will determine if the nsLocalFile will auto
+ * resolve symbolic links. By default, this value will be false
+ * on all non unix systems. On unix, this attribute is effectively
+ * a noop.
+ */
+ attribute PRBool followLinks;
+
+ [noscript] PRFileDescStar openNSPRFileDesc(in long flags, in long mode);
+ [noscript] FILE openANSIFileDesc(in string mode);
+
+ [noscript] PRLibraryStar load();
+
+ readonly attribute PRInt64 diskSpaceAvailable;
+
+ /**
+ * appendRelative[Native]Path
+ *
+ * Append a relative path to the current path of the nsILocalFile object.
+ *
+ * @param relativeFilePath
+ * relativeFilePath is a native relative path. For security reasons,
+ * this cannot contain .. or cannot start with a directory separator.
+ * For the |appendRelativeNativePath| method, the relativeFilePath
+ * must be in the native filesystem charset.
+ */
+ void appendRelativePath(in AString relativeFilePath);
+ [noscript] void appendRelativeNativePath(in ACString relativeFilePath);
+
+ /**
+ * Accessor to a null terminated string which will specify
+ * the file in a persistent manner for disk storage.
+ *
+ * The character set of this attribute is undefined. DO NOT TRY TO
+ * INTERPRET IT AS HUMAN READABLE TEXT!
+ */
+ attribute ACString persistentDescriptor;
+
+ /**
+ * reveal
+ *
+ * Ask the operating system to open the folder which contains
+ * this file or folder. This routine only works on platforms which
+ * support the ability to open a folder...
+ */
+ void reveal();
+
+ /**
+ * launch
+ *
+ * Ask the operating system to attempt to open the file.
+ * this really just simulates "double clicking" the file on your platform.
+ * This routine only works on platforms which support this functionality.
+ */
+ void launch();
+
+ /**
+ * getRelativeDescriptor
+ *
+ * Returns a relative file path in an opaque, XP format. It is therefore
+ * not a native path.
+ *
+ * The character set of the string returned from this function is
+ * undefined. DO NOT TRY TO INTERPRET IT AS HUMAN READABLE TEXT!
+ *
+ * @param fromFile
+ * the file from which the descriptor is relative.
+ * There is no defined result if this param is null.
+ */
+ ACString getRelativeDescriptor(in nsILocalFile fromFile);
+
+ /**
+ * setRelativeDescriptor
+ *
+ * Initializes the file to the location relative to fromFile using
+ * a string returned by getRelativeDescriptor.
+ *
+ * @param fromFile
+ * the file to which the descriptor is relative
+ * @param relative
+ * the relative descriptor obtained from getRelativeDescriptor
+ */
+ void setRelativeDescriptor(in nsILocalFile fromFile, in ACString relativeDesc);
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/io/nsILocalFileMac.idl b/src/libs/xpcom18a4/xpcom/io/nsILocalFileMac.idl
new file mode 100644
index 00000000..e04ea7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsILocalFileMac.idl
@@ -0,0 +1,262 @@
+/* -*- 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
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Conrad Carlen <ccarlen@netscape.com>
+ * Mark Mentovai <mark@moxienet.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 "nsILocalFile.idl"
+
+%{C++
+#include <Files.h>
+#include <CFURL.h>
+%}
+
+ native OSType(OSType);
+ native FSSpec(FSSpec);
+[ptr] native FSSpecPtr(FSSpec);
+ native FSRef(FSRef);
+[ptr] native FSRefPtr(FSRef);
+ native CFURLRef(CFURLRef);
+
+[scriptable, uuid(748f3ffe-27d9-4402-9de9-494badbeebf4)]
+interface nsILocalFileMac : nsILocalFile
+{
+ /**
+ * initWithCFURL
+ *
+ * Init this object with a CFURLRef
+ *
+ * NOTE: Supported only for XP_MACOSX or TARGET_CARBON
+ * NOTE: If the path of the CFURL is /a/b/c, at least a/b must exist beforehand.
+ *
+ * @param aCFURL the CoreFoundation URL
+ *
+ */
+ [noscript] void initWithCFURL(in CFURLRef aCFURL);
+
+ /**
+ * initWithFSRef
+ *
+ * Init this object with an FSRef
+ *
+ * NOTE: Supported only for XP_MACOSX or TARGET_CARBON
+ *
+ * @param aFSRef the native file spec
+ *
+ */
+ [noscript] void initWithFSRef([const] in FSRefPtr aFSRef);
+
+ /**
+ * initWithFSSpec
+ *
+ * Init this object with an FSSpec
+ * Legacy method - leaving in place for now
+ *
+ * @param aFileSpec the native file spec
+ *
+ */
+ [noscript] void initWithFSSpec([const] in FSSpecPtr aFileSpec);
+
+ /**
+ * initToAppWithCreatorCode
+ *
+ * Init this object to point to an application having the given
+ * creator code. If this app is missing, this will fail. It will first
+ * look for running application with the given creator.
+ *
+ * @param aAppCreator the signature of the app
+ *
+ */
+ [noscript] void initToAppWithCreatorCode(in OSType aAppCreator);
+
+ /**
+ * getCFURL
+ *
+ * Returns the CFURLRef of the file object. The caller is
+ * responsible for calling CFRelease() on it.
+ *
+ * NOTE: Observes the state of the followLinks attribute.
+ * If the file object is an alias and followLinks is TRUE, returns
+ * the target of the alias. If followLinks is FALSE, returns
+ * the unresolved alias file.
+ *
+ * NOTE: Supported only for XP_MACOSX or TARGET_CARBON
+ *
+ * @return
+ *
+ */
+ [noscript] CFURLRef getCFURL();
+
+ /**
+ * getFSRef
+ *
+ * Returns the FSRef of the file object.
+ *
+ * NOTE: Observes the state of the followLinks attribute.
+ * If the file object is an alias and followLinks is TRUE, returns
+ * the target of the alias. If followLinks is FALSE, returns
+ * the unresolved alias file.
+ *
+ * NOTE: Supported only for XP_MACOSX or TARGET_CARBON
+ *
+ * @return
+ *
+ */
+ [noscript] FSRef getFSRef();
+
+ /**
+ * getFSSpec
+ *
+ * Returns the FSSpec of the file object.
+ *
+ * NOTE: Observes the state of the followLinks attribute.
+ * If the file object is an alias and followLinks is TRUE, returns
+ * the target of the alias. If followLinks is FALSE, returns
+ * the unresolved alias file.
+ *
+ * @return
+ *
+ */
+ [noscript] FSSpec getFSSpec();
+
+ /**
+ * fileSizeWithResFork
+ *
+ * Returns the combined size of both the data fork and the resource
+ * fork (if present) rather than just the size of the data fork
+ * as returned by GetFileSize()
+ *
+ */
+ readonly attribute PRInt64 fileSizeWithResFork;
+
+ /**
+ * Use with SetFileType() to specify the signature of current process
+ */
+ const unsigned long CURRENT_PROCESS_CREATOR = 0x8000000;
+
+ /**
+ * fileType, creator
+ *
+ * File type and creator attributes
+ *
+ */
+ [noscript] attribute OSType fileType;
+ [noscript] attribute OSType fileCreator;
+
+ /**
+ * setFileTypeAndCreatorFromMIMEType
+ *
+ * Sets the file type and creator code from a MIME type.
+ * Internet Config is used to determine the mapping.
+ *
+ * @param aMIMEType
+ *
+ */
+ void setFileTypeAndCreatorFromMIMEType(in string aMIMEType);
+
+ /**
+ * setFileTypeAndCreatorFromExtension
+ *
+ * Sets the file type and creator code from a file extension
+ * Internet Config is used to determine the mapping.
+ *
+ * @param aExtension
+ *
+ */
+ void setFileTypeAndCreatorFromExtension(in string aExtension);
+
+ /**
+ * launchWithDoc
+ *
+ * Launch the application that this file points to with a document.
+ *
+ * @param aDocToLoad Must not be NULL. If no document, use nsILocalFile::launch
+ * @param aLaunchInBackground TRUE if the application should not come to the front.
+ *
+ */
+ void launchWithDoc(in nsILocalFile aDocToLoad, in boolean aLaunchInBackground);
+
+ /**
+ * openDocWithApp
+ *
+ * Open the document that this file points to with the given application.
+ *
+ * @param aAppToOpenWith The application with which to open the document.
+ * If NULL, the creator code of the document is used
+ * to determine the application.
+ * @param aLaunchInBackground TRUE if the application should not come to the front.
+ *
+ */
+ void openDocWithApp(in nsILocalFile aAppToOpenWith, in boolean aLaunchInBackground);
+
+ /**
+ * isPackage
+ *
+ * returns true if a directory is determined to be a package under Mac OS 9/X
+ *
+ */
+ boolean isPackage();
+
+ /**
+ * bundleDisplayName
+ *
+ * returns the display name of the application bundle (usually the human
+ * readable name of the application)
+ */
+ readonly attribute AString bundleDisplayName;
+
+ /**
+ * bundleIdentifier
+ *
+ * returns the identifier of the bundle
+ */
+ readonly attribute AUTF8String bundleIdentifier;
+};
+
+%{C++
+extern "C"
+{
+
+#ifndef XP_MACOSX
+NS_EXPORT const char* NS_TruncNodeName(const char *aNode, char *outBuf);
+#endif
+
+NS_EXPORT nsresult NS_NewLocalFileWithFSSpec(const FSSpec* inSpec, PRBool followSymlinks, nsILocalFileMac* *result);
+
+// NS_NewLocalFileWithFSRef is available since Mozilla 1.8.1.
+NS_EXPORT nsresult NS_NewLocalFileWithFSRef(const FSRef* aFSRef, PRBool aFollowSymlinks, nsILocalFileMac** result);
+}
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsILocalFileOS2.idl b/src/libs/xpcom18a4/xpcom/io/nsILocalFileOS2.idl
new file mode 100644
index 00000000..95b4177b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsILocalFileOS2.idl
@@ -0,0 +1,90 @@
+/* -*- 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
+ * Richard L. Walsh.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Rich Walsh <dragtext@e-vertise.com> (Original Author)
+ *
+ * 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 "nsILocalFile.idl"
+
+interface nsIArray;
+
+[scriptable, uuid(26de2089-239d-4697-818b-bae1fe8e8e0d)]
+interface nsILocalFileOS2 : nsILocalFile
+{
+ /**
+ * getFileTypes
+ *
+ * Returns the file's .TYPE extended attribute as an array of
+ * nsISupportsCStrings.
+ *
+ */
+ nsIArray getFileTypes( );
+
+ /**
+ * setFileTypes
+ *
+ * Sets the file's .TYPE extended attribute from a comma-separated
+ * list of types (this format is used because clients are unlikely
+ * to write more than a single type).
+ * @param fileTypes
+ * a string in the filesystem's native character set
+ *
+ */
+ void setFileTypes( in ACString fileTypes );
+
+ /**
+ * isFileType
+ *
+ * Returns TRUE if the file has a .TYPE extended attribute that
+ * matches the string passed in. The comparison is case-sensitive.
+ * @param fileType
+ * a string in the filesystem's native character set
+ *
+ */
+ PRBool isFileType( in ACString fileType );
+
+ /**
+ * setFileSource
+ *
+ * Identifies the origin of a downloaded file by writing the
+ * source URI's spec to the .SUBJECT extended attribute.
+ *
+ * @param aURI
+ * the source URI
+ *
+ */
+ void setFileSource( in AUTF8String aURI );
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIMultiplexInputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIMultiplexInputStream.idl
new file mode 100644
index 00000000..ec309ecd
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIMultiplexInputStream.idl
@@ -0,0 +1,88 @@
+/* -*- 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 frightening to behold.
+ *
+ * The Initial Developer of the Original Code is
+ * Jonas Sicking.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Jonas Sicking <sicking@bigfoot.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 "nsIInputStream.idl"
+
+/**
+ * The multiplex stream concatinates a list of input streams into a single
+ * stream.
+ */
+
+[scriptable, uuid(a076fd12-1dd1-11b2-b19a-d53b5dffaade)]
+interface nsIMultiplexInputStream : nsIInputStream
+{
+ /**
+ * Number of streams in this multiplex-stream
+ */
+ readonly attribute unsigned long count;
+
+ /**
+ * Appends a stream to the end of the streams. The cursor of the stream
+ * should be located at the beginning of the stream if the implementation
+ * of this nsIMultiplexInputStream also is used as an nsISeekableStream.
+ * @param stream stream to append
+ */
+ void appendStream(in nsIInputStream stream);
+
+ /**
+ * Insert a stream at specified index. If the cursor of this stream is at
+ * the beginning of the stream at index, the cursor will be placed at the
+ * beginning of the inserted stream instead.
+ * The cursor of the new stream should be located at the beginning of the
+ * stream if the implementation of this nsIMultiplexInputStream also is
+ * used as an nsISeekableStream.
+ * @param stream stream to insert
+ * @param index index to insert stream at, must be <= count
+ */
+ void insertStream(in nsIInputStream stream, in unsigned long index);
+
+ /**
+ * Remove stream at specified index. If this stream is the one currently
+ * being read the readcursor is moved to the beginning of the next
+ * stream
+ * @param index remove stream at this index, must be < count
+ */
+ void removeStream(in unsigned long index);
+
+ /**
+ * Get stream at specified index.
+ * @param index return stream at this index, must be < count
+ * @return stream at specified index
+ */
+ nsIInputStream getStream(in unsigned long index);
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIObjectInputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIObjectInputStream.idl
new file mode 100644
index 00000000..97c0ca6e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIObjectInputStream.idl
@@ -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 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 "nsIBinaryInputStream.idl"
+#include "nsrootidl.idl"
+
+/**
+ * @see nsIObjectOutputStream
+ * @see nsIBinaryInputStream
+ */
+
+[scriptable, uuid(6c248606-4eae-46fa-9df0-ba58502368eb)]
+interface nsIObjectInputStream : nsIBinaryInputStream
+{
+ /**
+ * Read an object from this stream to satisfy a strong or weak reference
+ * to one of its interfaces. If the interface was not along the primary
+ * inheritance chain ending in the "root" or XPCOM-identity nsISupports,
+ * readObject will QueryInterface from the deserialized object root to the
+ * correct interface, which was specified when the object was serialized.
+ *
+ * @see nsIObjectOutputStream
+ */
+ nsISupports readObject(in PRBool aIsStrongRef);
+
+ [notxpcom] nsresult readID(out nsID aID);
+
+ /**
+ * Optimized deserialization support -- see nsIStreamBufferAccess.idl.
+ */
+ [notxpcom] charPtr getBuffer(in PRUint32 aLength, in PRUint32 aAlignMask);
+ [notxpcom] void putBuffer(in charPtr aBuffer, in PRUint32 aLength);
+};
+
+%{C++
+
+inline nsresult
+NS_ReadOptionalObject(nsIObjectInputStream* aStream, PRBool aIsStrongRef,
+ nsISupports* *aResult)
+{
+ PRBool nonnull;
+ nsresult rv = aStream->ReadBoolean(&nonnull);
+ if (NS_SUCCEEDED(rv)) {
+ if (nonnull)
+ rv = aStream->ReadObject(aIsStrongRef, aResult);
+ else
+ *aResult = nsnull;
+ }
+ return rv;
+}
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIObjectOutputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIObjectOutputStream.idl
new file mode 100644
index 00000000..b8072127
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIObjectOutputStream.idl
@@ -0,0 +1,131 @@
+/* -*- 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 "nsIBinaryOutputStream.idl"
+#include "nsrootidl.idl"
+
+/**
+ * @See nsIObjectInputStream
+ * @See nsIBinaryOutputStream
+ */
+
+[scriptable, uuid(92c898ac-5fde-4b99-87b3-5d486422094b)]
+interface nsIObjectOutputStream : nsIBinaryOutputStream
+{
+ /**
+ * Write the object whose "root" or XPCOM-identity nsISupports is aObject.
+ * The cause for writing this object is a strong or weak reference, so the
+ * aIsStrongRef argument must tell which kind of pointer is being followed
+ * here during serialization.
+ *
+ * If the object has only one strong reference in the serialization and no
+ * weak refs, use writeSingleRefObject. This is a valuable optimization:
+ * it saves space in the stream, and cycles on both ends of the process.
+ *
+ * If the reference being serialized is a pointer to an interface not on
+ * the primary inheritance chain ending in the root nsISupports, you must
+ * call writeCompoundObject instead of this method.
+ */
+ void writeObject(in nsISupports aObject, in PRBool aIsStrongRef);
+
+ /**
+ * Write an object referenced singly and strongly via its root nsISupports
+ * or a subclass of its root nsISupports. There must not be other refs to
+ * aObject in memory, or in the serialization.
+ */
+ void writeSingleRefObject(in nsISupports aObject);
+
+ /**
+ * Write the object referenced by an interface pointer at aObject that
+ * inherits from a non-primary nsISupports, i.e., a reference to one of
+ * the multiply inherited interfaces derived from an nsISupports other
+ * than the root or XPCOM-identity nsISupports; or a reference to an
+ * inner object in the case of true XPCOM aggregation. aIID identifies
+ * this interface.
+ */
+ void writeCompoundObject(in nsISupports aObject,
+ in nsIIDRef aIID,
+ in PRBool aIsStrongRef);
+
+ void writeID(in nsIDRef aID);
+
+ /**
+ * Optimized serialization support -- see nsIStreamBufferAccess.idl.
+ */
+ [notxpcom] charPtr getBuffer(in PRUint32 aLength, in PRUint32 aAlignMask);
+ [notxpcom] void putBuffer(in charPtr aBuffer, in PRUint32 aLength);
+};
+
+%{C++
+
+inline nsresult
+NS_WriteOptionalObject(nsIObjectOutputStream* aStream, nsISupports* aObject,
+ PRBool aIsStrongRef)
+{
+ PRBool nonnull = (aObject != nsnull);
+ nsresult rv = aStream->WriteBoolean(nonnull);
+ if (NS_SUCCEEDED(rv) && nonnull)
+ rv = aStream->WriteObject(aObject, aIsStrongRef);
+ return rv;
+}
+
+inline nsresult
+NS_WriteOptionalSingleRefObject(nsIObjectOutputStream* aStream,
+ nsISupports* aObject)
+{
+ PRBool nonnull = (aObject != nsnull);
+ nsresult rv = aStream->WriteBoolean(nonnull);
+ if (NS_SUCCEEDED(rv) && nonnull)
+ rv = aStream->WriteSingleRefObject(aObject);
+ return rv;
+}
+
+inline nsresult
+NS_WriteOptionalCompoundObject(nsIObjectOutputStream* aStream,
+ nsISupports* aObject,
+ const nsIID& aIID,
+ PRBool aIsStrongRef)
+{
+ PRBool nonnull = (aObject != nsnull);
+ nsresult rv = aStream->WriteBoolean(nonnull);
+ if (NS_SUCCEEDED(rv) && nonnull)
+ rv = aStream->WriteCompoundObject(aObject, aIID, aIsStrongRef);
+ return rv;
+}
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIObservableInputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIObservableInputStream.idl
new file mode 100644
index 00000000..66b2d6e6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIObservableInputStream.idl
@@ -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.
+ *
+ * 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): Darin Fisher <darin@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 nsIInputStream;
+interface nsIInputStreamObserver;
+
+[scriptable, uuid(6f489efe-1dd2-11b2-af78-fb84ae21591b)]
+interface nsIObservableInputStream : nsISupports
+{
+ /**
+ * Allows users to set an observer on an input stream to receive notifications
+ * about the consumer emptying the input stream's underlying buffer, or closing the
+ * stream. This is necessary for non-blocking streams so that the producer can suspend
+ * itself until more data can be written.
+ */
+ attribute nsIInputStreamObserver observer;
+};
+
+[scriptable, uuid(019d67cc-61b4-11d4-9877-00c04fa0cf4a)]
+interface nsIInputStreamObserver : nsISupports
+{
+ /**
+ * Called when the input stream's consumer has read all the existing data from the stream.
+ */
+ void onEmpty(in nsIInputStream inStr);
+
+ /**
+ * Called when the consumer closes its end of the stream.
+ */
+ void onClose(in nsIInputStream inStr);
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIObservableOutputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIObservableOutputStream.idl
new file mode 100644
index 00000000..4cdab3c1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIObservableOutputStream.idl
@@ -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.
+ *
+ * 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): Darin Fisher <darin@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 nsIOutputStream;
+interface nsIOutputStreamObserver;
+
+[scriptable, uuid(15b374f8-1dd2-11b2-87ab-c3299d704fd3)]
+interface nsIObservableOutputStream : nsISupports
+{
+ /**
+ * Allows users to set an observer on an input stream to receive notifications
+ * about the consumer emptying the input stream's underlying buffer, or closing the
+ * stream. This is necessary for non-blocking streams so that the producer can suspend
+ * itself until more data can be written.
+ */
+ attribute nsIOutputStreamObserver observer;
+};
+
+[scriptable, uuid(12314194-61b4-11d4-9877-00c04fa0cf4a)]
+interface nsIOutputStreamObserver : nsISupports
+{
+ /**
+ * Called when the output stream's producer has written more data into the stream.
+ */
+ void onWrite(in nsIOutputStream outStr, in unsigned long amount);
+
+ /**
+ * Called when the stream's underlying buffer becomes full.
+ */
+ void onFull(in nsIOutputStream outStr);
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIOutputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIOutputStream.idl
new file mode 100644
index 00000000..ec5035c6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIOutputStream.idl
@@ -0,0 +1,167 @@
+/* -*- 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):
+ * Warren Harris <warren@netscape.com>
+ * Darin Fisher <darin@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 "nsISupports.idl"
+
+interface nsIOutputStream;
+interface nsIInputStream;
+
+%{C++
+/**
+ * The signature for the reader function passed to WriteSegments. This
+ * is the "provider" of data that gets written into the stream's buffer.
+ *
+ * @param aOutStream stream being written to
+ * @param aClosure opaque parameter passed to WriteSegments
+ * @param aToSegment pointer to memory owned by the output stream
+ * @param aFromOffset amount already written (since WriteSegments was called)
+ * @param aCount length of toSegment
+ * @param aReadCount number of bytes written
+ *
+ * Implementers should return the following:
+ *
+ * @return NS_OK and (*aReadCount > 0) if successfully provided some data
+ * @return NS_OK and (*aReadCount = 0) or
+ * @return <any-error> if not interested in providing any data
+ *
+ * Errors are never passed to the caller of WriteSegments.
+ *
+ * @status FROZEN
+ */
+typedef NS_CALLBACK(nsReadSegmentFun)(nsIOutputStream *aOutStream,
+ void *aClosure,
+ char *aToSegment,
+ PRUint32 aFromOffset,
+ PRUint32 aCount,
+ PRUint32 *aReadCount);
+%}
+
+native nsReadSegmentFun(nsReadSegmentFun);
+
+/**
+ * nsIOutputStream
+ *
+ * @status FROZEN
+ */
+[scriptable, uuid(0d0acd2a-61b4-11d4-9877-00c04fa0cf4a)]
+interface nsIOutputStream : nsISupports
+{
+ /**
+ * Close the stream. Forces the output stream to flush any buffered data.
+ *
+ * @throws NS_BASE_STREAM_WOULD_BLOCK if unable to flush without blocking
+ * the calling thread (non-blocking mode only)
+ */
+ void close();
+
+ /**
+ * Flush the stream.
+ *
+ * @throws NS_BASE_STREAM_WOULD_BLOCK if unable to flush without blocking
+ * the calling thread (non-blocking mode only)
+ */
+ void flush();
+
+ /**
+ * Write data into the stream.
+ *
+ * @param aBuf the buffer containing the data to be written
+ * @param aCount the maximum number of bytes to be written
+ *
+ * @return number of bytes written (may be less than aCount)
+ *
+ * @throws NS_BASE_STREAM_WOULD_BLOCK if writing to the output stream would
+ * block the calling thread (non-blocking mode only)
+ * @throws <other-error> on failure
+ */
+ unsigned long write(in string aBuf, in unsigned long aCount);
+
+ /**
+ * Writes data into the stream from an input stream.
+ *
+ * @param aFromStream the stream containing the data to be written
+ * @param aCount the maximum number of bytes to be written
+ *
+ * @return number of bytes written (may be less than aCount)
+ *
+ * @throws NS_BASE_STREAM_WOULD_BLOCK if writing to the output stream would
+ * block the calling thread (non-blocking mode only)
+ * @throws <other-error> on failure
+ *
+ * NOTE: This method is defined by this interface in order to allow the
+ * output stream to efficiently copy the data from the input stream into
+ * its internal buffer (if any). If this method was provided as an external
+ * facility, a separate char* buffer would need to be used in order to call
+ * the output stream's other Write method.
+ */
+ unsigned long writeFrom(in nsIInputStream aFromStream,
+ in unsigned long aCount);
+
+ /**
+ * Low-level write method that has access to the stream's underlying buffer.
+ * The reader function may be called multiple times for segmented buffers.
+ * WriteSegments is expected to keep calling the reader until either there
+ * is nothing left to write or the reader returns an error. WriteSegments
+ * should not call the reader with zero bytes to provide.
+ *
+ * @param aReader the "provider" of the data to be written
+ * @param aClosure opaque parameter passed to reader
+ * @param aCount the maximum number of bytes to be written
+ *
+ * @return number of bytes written (may be less than aCount)
+ *
+ * @throws NS_BASE_STREAM_WOULD_BLOCK if writing to the output stream would
+ * block the calling thread (non-blocking mode only)
+ * @throws <other-error> on failure
+ *
+ * NOTE: this function may be unimplemented if a stream has no underlying
+ * buffer (e.g., socket output stream).
+ */
+ [noscript] unsigned long writeSegments(in nsReadSegmentFun aReader,
+ in voidPtr aClosure,
+ in unsigned long aCount);
+
+ /**
+ * @return true if stream is non-blocking
+ *
+ * NOTE: writing to a blocking output stream will block the calling thread
+ * until all given data can be consumed by the stream.
+ */
+ boolean isNonBlocking();
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIPipe.idl b/src/libs/xpcom18a4/xpcom/io/nsIPipe.idl
new file mode 100644
index 00000000..bbe3d978
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIPipe.idl
@@ -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 ***** */
+
+#include "nsIAsyncInputStream.idl"
+#include "nsIAsyncOutputStream.idl"
+
+interface nsIMemory;
+
+/**
+ * nsIPipe represents an in-process buffer that can be read using nsIInputStream
+ * and written using nsIOutputStream. The reader and writer of a pipe do not
+ * have to be on the same thread. As a result, the pipe is an ideal mechanism
+ * to bridge data exchange between two threads. For example, a worker thread
+ * might write data to a pipe from which the main thread will read.
+ *
+ * Each end of the pipe can be either blocking or non-blocking. Recall that a
+ * non-blocking stream will return NS_BASE_STREAM_WOULD_BLOCK if it cannot be
+ * read or written to without blocking the calling thread. For example, if you
+ * try to read from an empty pipe that has not yet been closed, then if that
+ * pipe's input end is non-blocking, then the read call will fail immediately
+ * with NS_BASE_STREAM_WOULD_BLOCK as the error condition. However, if that
+ * pipe's input end is blocking, then the read call will not return until the
+ * pipe has data or until the pipe is closed. This example presumes that the
+ * pipe is being filled asynchronously on some background thread.
+ *
+ * The pipe supports nsIAsyncInputStream and nsIAsyncOutputStream, which give
+ * the user of a non-blocking pipe the ability to wait for the pipe to become
+ * ready again. For example, in the case of an empty non-blocking pipe, the
+ * user can call AsyncWait on the input end of the pipe to be notified when
+ * the pipe has data to read (or when the pipe becomes closed).
+ *
+ * NS_NewPipe2 and NS_NewPipe provide convenient pipe constructors. In most
+ * cases nsIPipe is not actually used. It is usually enough to just get
+ * references to the pipe's input and output end. In which case, the pipe is
+ * automatically closed when the respective pipe ends are released.
+ */
+[scriptable, uuid(f4211abc-61b3-11d4-9877-00c04fa0cf4a)]
+interface nsIPipe : nsISupports
+{
+ /**
+ * initialize this pipe
+ */
+ void init(in boolean nonBlockingInput,
+ in boolean nonBlockingOutput,
+ in unsigned long segmentSize,
+ in unsigned long segmentCount,
+ in nsIMemory segmentAllocator);
+
+ /**
+ * The pipe's input end, which also implements nsISearchableInputStream.
+ */
+ readonly attribute nsIAsyncInputStream inputStream;
+
+ /**
+ * The pipe's output end.
+ */
+ readonly attribute nsIAsyncOutputStream outputStream;
+};
+
+/**
+ * XXX this interface doesn't really belong in here. It is here because
+ * currently nsPipeInputStream is the only implementation of this interface.
+ */
+[scriptable, uuid(8C39EF62-F7C9-11d4-98F5-001083010E9B)]
+interface nsISearchableInputStream : nsISupports
+{
+ /**
+ * Searches for a string in the input stream. Since the stream has a notion
+ * of EOF, it is possible that the string may at some time be in the
+ * buffer, but is is not currently found up to some offset. Consequently,
+ * both the found and not found cases return an offset:
+ * if found, return offset where it was found
+ * if not found, return offset of the first byte not searched
+ * In the case the stream is at EOF and the string is not found, the first
+ * byte not searched will correspond to the length of the buffer.
+ */
+ void search(in string forString,
+ in boolean ignoreCase,
+ out boolean found,
+ out unsigned long offsetSearchedTo);
+};
+
+%{C++
+
+/**
+ * NS_NewPipe2
+ *
+ * This function supercedes NS_NewPipe. It differs from NS_NewPipe in two
+ * major ways:
+ * (1) returns nsIAsyncInputStream and nsIAsyncOutputStream, so it is
+ * not necessary to QI in order to access these interfaces.
+ * (2) the size of the pipe is determined by the number of segments
+ * times the size of each segment.
+ *
+ * @param pipeIn
+ * resulting input end of the pipe
+ * @param pipeOut
+ * resulting output end of the pipe
+ * @param nonBlockingInput
+ * true specifies non-blocking input stream behavior
+ * @param nonBlockingOutput
+ * true specifies non-blocking output stream behavior
+ * @param segmentSize
+ * specifies the segment size in bytes (pass 0 to use default value)
+ * @param segmentCount
+ * specifies the max number of segments (pass 0 to use default value)
+ * passing PR_UINT32_MAX here causes the pipe to have "infinite" space.
+ * this mode can be useful in some cases, but should always be used with
+ * caution. the default value for this parameter is a finite value.
+ * @param segmentAlloc
+ * pass reference to nsIMemory to have all pipe allocations use this
+ * allocator (pass null to use the default allocator)
+ */
+extern NS_COM nsresult
+NS_NewPipe2(nsIAsyncInputStream **pipeIn,
+ nsIAsyncOutputStream **pipeOut,
+ PRBool nonBlockingInput = PR_FALSE,
+ PRBool nonBlockingOutput = PR_FALSE,
+ PRUint32 segmentSize = 0,
+ PRUint32 segmentCount = 0,
+ nsIMemory *segmentAlloc = nsnull);
+
+/**
+ * NS_NewPipe
+ *
+ * Preserved for backwards compatibility. Plus, this interface is more
+ * amiable in certain contexts (e.g., when you don't need the pipe's async
+ * capabilities).
+ *
+ * @param pipeIn
+ * resulting input end of the pipe
+ * @param pipeOut
+ * resulting output end of the pipe
+ * @param segmentSize
+ * specifies the segment size in bytes (pass 0 to use default value)
+ * @param maxSize
+ * specifies the max size of the pipe (pass 0 to use default value)
+ * number of segments is maxSize / segmentSize, and maxSize must be a
+ * multiple of segmentSize. passing PR_UINT32_MAX here causes the
+ * pipe to have "infinite" space. this mode can be useful in some
+ * cases, but should always be used with caution. the default value
+ * for this parameter is a finite value.
+ * @param nonBlockingInput
+ * true specifies non-blocking input stream behavior
+ * @param nonBlockingOutput
+ * true specifies non-blocking output stream behavior
+ * @param segmentAlloc
+ * pass reference to nsIMemory to have all pipe allocations use this
+ * allocator (pass null to use the default allocator)
+ */
+inline nsresult
+NS_NewPipe(nsIInputStream **pipeIn,
+ nsIOutputStream **pipeOut,
+ PRUint32 segmentSize = 0,
+ PRUint32 maxSize = 0,
+ PRBool nonBlockingInput = PR_FALSE,
+ PRBool nonBlockingOutput = PR_FALSE,
+ nsIMemory *segmentAlloc = nsnull)
+{
+ PRUint32 segmentCount;
+ if (segmentSize == 0)
+ segmentCount = 0; // use default
+ else
+ segmentCount = maxSize / segmentSize;
+
+ nsIAsyncInputStream *in;
+ nsIAsyncOutputStream *out;
+ nsresult rv = NS_NewPipe2(&in, &out, nonBlockingInput, nonBlockingOutput,
+ segmentSize, segmentCount, segmentAlloc);
+ if (NS_FAILED(rv)) return rv;
+
+ *pipeIn = in;
+ *pipeOut = out;
+ return NS_OK;
+}
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIScriptableInputStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIScriptableInputStream.idl
new file mode 100644
index 00000000..9a21b1d0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIScriptableInputStream.idl
@@ -0,0 +1,73 @@
+/* -*- 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 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"
+
+interface nsIInputStream;
+
+/**
+ * nsIScriptableInputStream provides scriptable access to the nsIInputStream.
+ *
+ * @status FROZEN
+ */
+[scriptable, uuid(a2a32f90-9b90-11d3-a189-0050041caf44)]
+interface nsIScriptableInputStream : nsISupports
+{
+ /**
+ * Closes the stream.
+ */
+ void close();
+
+ /** Wrap the given nsIInputStream with this nsIScriptableInputStream.
+ * @param aInputStream [in] parameter providing the stream to wrap
+ */
+ void init(in nsIInputStream aInputStream);
+
+ /** Return the number of bytes currently available in the stream
+ * @param _retval [out] parameter to hold the number of bytes
+ * if an error occurs, the parameter will be undefined
+ * @return error status
+ */
+ unsigned long available();
+
+ /** Read data from the stream.
+ * @param aCount [in] the maximum number of bytes to read
+ * @param _retval [out] the data
+ */
+ string read(in unsigned long aCount);
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsISeekableStream.idl b/src/libs/xpcom18a4/xpcom/io/nsISeekableStream.idl
new file mode 100644
index 00000000..b2827c12
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsISeekableStream.idl
@@ -0,0 +1,102 @@
+/* -*- 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):
+ *
+ * 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 ***** */
+
+
+/*
+ * nsISeekableStream
+ *
+ * Note that a stream might not implement all methods (e.g., a readonly stream
+ * won't implement setEOF)
+ *
+ * @status UNDER_REVIEW
+ */
+
+#include "nsISupports.idl"
+
+[scriptable, uuid(8429d350-1040-4661-8b71-f2a6ba455980)]
+interface nsISeekableStream : nsISupports
+{
+ /*
+ * Sets the stream pointer to the value of the 'offset' parameter
+ */
+ const PRInt32 NS_SEEK_SET = 0;
+
+ /*
+ * Sets the stream pointer to its current location plus the value
+ * of the offset parameter.
+ */
+ const PRInt32 NS_SEEK_CUR = 1;
+
+ /*
+ * Sets the stream pointer to the size of the stream plus the value
+ * of the offset parameter.
+ */
+ const PRInt32 NS_SEEK_END = 2;
+
+ /**
+ * seek
+ *
+ * This method moves the stream offset of the steam implementing this
+ * interface.
+ *
+ * @param whence specifies how to interpret the 'offset' parameter in
+ * setting the stream offset associated with the implementing
+ * stream.
+ *
+ * @param offset specifies a value, in bytes, that is used in conjunction
+ * with the 'whence' parameter to set the stream offset of the
+ * implementing stream. A negative value causes seeking in
+ * the reverse direction.
+ */
+ void seek(in long whence, in long long offset);
+
+ /**
+ * tell
+ *
+ * This method reports the current offset, in bytes, from the start of the
+ * stream.
+ */
+ long long tell();
+
+
+ /**
+ * setEOF
+ *
+ * This method truncates the stream at the current offset.
+ */
+ void setEOF();
+};
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIStorageStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIStorageStream.idl
new file mode 100644
index 00000000..148136b9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIStorageStream.idl
@@ -0,0 +1,107 @@
+/* -*- 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-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"
+#include "nsrootidl.idl"
+
+interface nsIMemory;
+interface nsIInputStream;
+interface nsIOutputStream;
+
+/**
+ * The nsIStorageStream interface maintains an internal data buffer that can be
+ * filled using a single output stream. One or more independent input streams
+ * can be created to read the data from the buffer non-destructively.
+ */
+
+[scriptable, uuid(604ad9d0-753e-11d3-90ca-34278643278f)]
+interface nsIStorageStream : nsISupports
+{
+ /**
+ *
+ * Initialize the stream, setting up the amount of space that will be
+ * allocated for the stream's backing-store.
+ *
+ * @param segmentSize
+ * Size of each segment. Must be a power of two.
+ * @param maxSize
+ * Maximum total size of this stream. length will always be less
+ * than or equal to this value. Passing PR_UINT32_MAX is safe.
+ * @param segmentAllocator
+ * Which allocator to use for the segments. May be null, in which
+ * case a default allocator will be used.
+ */
+ void init(in PRUint32 segmentSize, in PRUint32 maxSize, in nsIMemory segmentAllocator);
+
+ /**
+ * Get a reference to the one and only output stream for this instance.
+ * The zero-based startPosition argument is used is used to set the initial
+ * write cursor position. The startPosition cannot be set larger than the
+ * current buffer length. Calling this method has the side-effect of
+ * truncating the internal buffer to startPosition bytes.
+ */
+ nsIOutputStream getOutputStream(in PRInt32 startPosition);
+
+ /**
+ * Create a new input stream to read data (written by the singleton output
+ * stream) from the internal buffer. Multiple, independent input streams
+ * can be created.
+ */
+ nsIInputStream newInputStream(in PRInt32 startPosition);
+
+ /**
+ * The length attribute indicates the total number of bytes stored in the
+ * nsIStorageStream internal buffer, regardless of any consumption by input
+ * streams. Assigning to the length field can be used to truncate the
+ * buffer data, but can not be used when either the instance's output
+ * stream is in use.
+ *
+ * @See #writeInProgress */
+ attribute PRUint32 length;
+
+ /**
+ * True, when output stream has not yet been Close'ed
+ */
+ readonly attribute boolean writeInProgress;
+};
+
+%{C++
+// Factory method
+NS_COM nsresult
+NS_NewStorageStream(PRUint32 segmentSize, PRUint32 maxSize, nsIStorageStream **result);
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIStreamBufferAccess.idl b/src/libs/xpcom18a4/xpcom/io/nsIStreamBufferAccess.idl
new file mode 100644
index 00000000..dc41585f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIStreamBufferAccess.idl
@@ -0,0 +1,191 @@
+/* -*- 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"
+#include "nsrootidl.idl"
+
+/**
+ * An interface for access to a buffering stream implementation's underlying
+ * memory buffer.
+ *
+ * Stream implementations that QueryInterface to nsIStreamBufferAccess must
+ * ensure that all buffers are aligned on the most restrictive type size for
+ * the current architecture (e.g., sizeof(double) for RISCy CPUs). malloc(3)
+ * satisfies this requirement.
+ */
+[uuid(ac923b72-ac87-4892-ac7a-ca385d429435)]
+interface nsIStreamBufferAccess : nsISupports
+{
+ /**
+ * Get access to a contiguous, aligned run of bytes in the stream's buffer.
+ * Exactly one successful getBuffer call must occur before a putBuffer call
+ * taking the non-null pointer returned by the successful getBuffer.
+ *
+ * The run of bytes are the next bytes (modulo alignment padding) to read
+ * for an input stream, and the next bytes (modulo alignment padding) to
+ * store before (eventually) writing buffered data to an output stream.
+ * There can be space beyond this run of bytes in the buffer for further
+ * accesses before the fill or flush point is reached.
+ *
+ * @param aLength
+ * Count of contiguous bytes requested at the address A that satisfies
+ * (A & aAlignMask) == 0 in the buffer, starting from the current stream
+ * position, mapped to a buffer address B. The stream implementation
+ * must pad from B to A by skipping bytes (if input stream) or storing
+ * zero bytes (if output stream).
+ *
+ * @param aAlignMask
+ * Bit-mask computed by subtracting 1 from the power-of-two alignment
+ * modulus (e.g., 3 or sizeof(PRUint32)-1 for PRUint32 alignment).
+ *
+ * @return
+ * The aligned pointer to aLength bytes in the buffer, or null if the
+ * buffer has no room for aLength bytes starting at the next address A
+ * after the current position that satisfies (A & aAlignMask) == 0.
+ */
+ [notxpcom] charPtr getBuffer(in PRUint32 aLength, in PRUint32 aAlignMask);
+
+ /**
+ * Relinquish access to the stream's buffer, filling if at end of an input
+ * buffer, flushing if completing an output buffer. After a getBuffer call
+ * that returns non-null, putBuffer must be called.
+ *
+ * @param aBuffer
+ * A non-null pointer returned by getBuffer on the same stream buffer
+ * access object.
+ *
+ * @param aLength
+ * The same count of contiguous bytes passed to the getBuffer call that
+ * returned aBuffer.
+ */
+ [notxpcom] void putBuffer(in charPtr aBuffer, in PRUint32 aLength);
+
+ /**
+ * Disable and enable buffering on the stream implementing this interface.
+ * DisableBuffering flushes an output stream's buffer, and invalidates an
+ * input stream's buffer.
+ */
+ void disableBuffering();
+ void enableBuffering();
+
+ /**
+ * The underlying, unbuffered input or output stream.
+ */
+ readonly attribute nsISupports unbufferedStream;
+};
+
+%{C++
+
+// Swap macros, used to convert to/from canonical (big-endian) format
+#if defined IS_LITTLE_ENDIAN
+
+# define NS_SWAP16(x) ((((x) & 0xff) << 8) | (((x) >> 8) & 0xff))
+# define NS_SWAP32(x) ((NS_SWAP16((x) & 0xffff) << 16) | (NS_SWAP16((x) >> 16)))
+
+// We want to avoid casting to 32-bit types if possible, since that violates
+// aliasing rules (a standard compiler may assume that pointers of two types
+// do not address overlapping storage).
+//
+// XXX What if we have a compiler that follows aliasing rules strictly but
+// doesn't have a 64-bit int type?
+//
+// XXXbe shouldn't NSPR's LL_INIT work for non-constant arguments in all cases?
+
+# if defined HAVE_LONG_LONG
+# if PR_BYTES_PER_LONG == 8
+# define ULL_(x) x ## UL
+# elif (defined WIN32 || defined WIN16) && !defined __GNUC__
+# define ULL_(x) ((uint64) x ## i64)
+# else
+# define ULL_(x) x ## ULL
+# endif
+
+# define NS_SWAP64(x) ((((x) & ULL_(0xff00000000000000)) >> 56) | \
+ (((x) & ULL_(0x00ff000000000000)) >> 40) | \
+ (((x) & ULL_(0x0000ff0000000000)) >> 24) | \
+ (((x) & ULL_(0x000000ff00000000)) >> 8) | \
+ (((x) & ULL_(0x00000000ff000000)) << 8) | \
+ (((x) & ULL_(0x0000000000ff0000)) << 24) | \
+ (((x) & ULL_(0x000000000000ff00)) << 40) | \
+ (((x) /* & ULL_(0x00000000000000ff) */) << 56))
+# else
+# define NS_SWAP64(x) LL_INIT((((x).lo /* & 0xff000000ul */) >> 24) | \
+ (((x).lo & 0x00ff0000ul) >> 8) | \
+ (((x).lo & 0x0000ff00ul) << 8) | \
+ (((x).lo /* & 0x000000fful */) << 24), \
+ (((x).hi /* & 0xff000000ul */) >> 24) | \
+ (((x).hi & 0x00ff0000ul) >> 8) | \
+ (((x).hi & 0x0000ff00ul) << 8) | \
+ (((x).hi /* & 0x000000fful */) << 24))
+# endif
+
+#elif defined IS_BIG_ENDIAN
+
+# define NS_SWAP16(x) (x)
+# define NS_SWAP32(x) (x)
+# define NS_SWAP64(x) (x)
+
+#else
+
+# error "Unknown byte order"
+
+#endif
+
+/**
+ * These macros get and put a buffer given either an sba parameter that may
+ * point to an object implementing nsIStreamBufferAccess, nsIObjectInputStream,
+ * or nsIObjectOutputStream.
+ */
+#define NS_GET_BUFFER(sba,n,a) ((sba)->GetBuffer(n, a))
+#define NS_PUT_BUFFER(sba,p,n) ((sba)->PutBuffer(p, n))
+
+#define NS_GET8(p) (*(PRUint8*)(p))
+#define NS_GET16(p) NS_SWAP16(*(PRUint16*)(p))
+#define NS_GET32(p) NS_SWAP32(*(PRUint32*)(p))
+#define NS_GET64(p) NS_SWAP64(*(PRUint64*)(p))
+#define NS_GET_FLOAT(p) ((float)NS_SWAP32(*(PRUint32*)(p)))
+#define NS_GET_DOUBLE(p) ((double)NS_SWAP64(*(PRUint64*)(p)))
+
+#define NS_PUT8(p,x) (*(PRUint8*)(p) = (x))
+#define NS_PUT16(p,x) (*(PRUint16*)(p) = NS_SWAP16(x))
+#define NS_PUT32(p,x) (*(PRUint32*)(p) = NS_SWAP32(x))
+#define NS_PUT64(p,x) (*(PRUint64*)(p) = NS_SWAP64(x))
+#define NS_PUT_FLOAT(p,x) (*(PRUint32*)(p) = NS_SWAP32(*(PRUint32*)&(x)))
+#define NS_PUT_DOUBLE(p,x) (*(PRUint64*)(p) = NS_SWAP64(*(PRUint64*)&(x)))
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIStringStream.idl b/src/libs/xpcom18a4/xpcom/io/nsIStringStream.idl
new file mode 100644
index 00000000..09a90548
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIStringStream.idl
@@ -0,0 +1,138 @@
+/* -*- 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):
+ * mcmullen@netscape.com (original author)
+ * scc@mozilla.org
+ * davidm@netscape.com
+ * darin@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 ***** */
+
+/**
+ * Based on original code from nsIStringStream.h
+ */
+
+#include "nsIInputStream.idl"
+
+/**
+ * nsIStringInputStream
+ *
+ * Provides scriptable and specialized C++ only methods for initializing a
+ * nsIInputStream implementation with a simple character array.
+ */
+[scriptable, uuid(450cd2d4-f0fd-424d-b365-b1251f80fd53)]
+interface nsIStringInputStream : nsIInputStream
+{
+ /**
+ * SetData - assign data to the input stream (copied on assignment).
+ *
+ * @param data - stream data
+ * @param dataLen - stream data length (-1 if length should be computed)
+ *
+ * NOTE: C++ code should consider using AdoptData or ShareData to avoid
+ * making an extra copy of the stream data.
+ */
+ void setData(in string data, in long dataLen);
+
+ /**
+ * NOTE: the following methods are designed to give C++ code added control
+ * over the ownership and lifetime of the stream data. Use with care :-)
+ */
+
+ /**
+ * AdoptData - assign data to the input stream. the input stream takes
+ * ownership of the given data buffer and will nsMemory::Free it when
+ * the input stream is destroyed.
+ *
+ * @param data - stream data
+ * @param dataLen - stream data length (-1 if length should be computed)
+ */
+ [noscript] void adoptData(in charPtr data, in long dataLen);
+
+ /**
+ * ShareData - assign data to the input stream. the input stream references
+ * the given data buffer until the input stream is destroyed. the given
+ * data buffer must outlive the input stream.
+ *
+ * @param data - stream data
+ * @param dataLen - stream data length (-1 if length should be computed)
+ */
+ [noscript] void shareData(in string data, in long dataLen);
+};
+
+%{C++
+
+//-----------------------------------------------------------------------------
+// C++ factory methods
+//-----------------------------------------------------------------------------
+
+#include "nsIInputStream.h"
+#include "nsString.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define NS_NewByteInputStream VBoxNsxpNS_NewByteInputStream
+#define NS_NewCStringInputStream VBoxNsxpNS_NewCStringInputStream
+#define NS_NewCharInputStream VBoxNsxpNS_NewCharInputStream
+#define NS_NewStringInputStream VBoxNsxpNS_NewStringInputStream
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+//-----------------------------------------------------------------------------
+// Factory method to get an nsInputStream from an nsAString. Result will
+// implement nsIStringInputStream and nsIRandomAccessStore
+extern "C" NS_COM nsresult
+NS_NewStringInputStream(nsIInputStream** aStreamResult,
+ const nsAString& aStringToRead);
+
+//-----------------------------------------------------------------------------
+// Factory method to get an nsInputStream from an nsACString. Result will
+// implement nsIStringInputStream and nsIRandomAccessStore
+extern "C" NS_COM nsresult
+NS_NewCStringInputStream(nsIInputStream** aStreamResult,
+ const nsACString& aStringToRead);
+
+//-----------------------------------------------------------------------------
+// Factory method to get an nsInputStream from a string. Result will
+// implement nsIStringInputStream and nsIRandomAccessStore
+extern "C" NS_COM nsresult
+NS_NewCharInputStream(nsIInputStream** aStreamResult,
+ const char* aStringToRead);
+
+//-----------------------------------------------------------------------------
+// Factory method to get an nsInputStream from a byte buffer. Result will
+// implement nsIStringInputStream and nsIRandomAccessStore
+extern "C" NS_COM nsresult
+NS_NewByteInputStream(nsIInputStream** aStreamResult,
+ const char* aStringToRead,
+ PRInt32 aLength);
+%}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsIUnicharInputStream.h b/src/libs/xpcom18a4/xpcom/io/nsIUnicharInputStream.h
new file mode 100644
index 00000000..7232249d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsIUnicharInputStream.h
@@ -0,0 +1,94 @@
+/* -*- 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 nsIUnicharInputStream_h___
+#define nsIUnicharInputStream_h___
+
+#include "nsIInputStream.h"
+#include "nsString.h"
+#include "nscore.h"
+
+class nsIUnicharInputStream;
+
+typedef NS_CALLBACK(nsWriteUnicharSegmentFun)(nsIUnicharInputStream *aInStream,
+ void *aClosure,
+ const PRUnichar *aFromSegment,
+ PRUint32 aToOffset,
+ PRUint32 aCount,
+ PRUint32 *aWriteCount);
+/* c4bcf6ee-3a79-4d77-8d48-f17be3199b3b */
+#define NS_IUNICHAR_INPUT_STREAM_IID \
+{ 0xc4bcf6ee, 0x3a79, 0x4d77, \
+ {0x8d, 0x48, 0xf1, 0x7b, 0xe3, 0x19, 0x9b, 0x3b} }
+
+/** Abstract unicode character input stream
+ * @see nsIInputStream
+ */
+class NS_NO_VTABLE nsIUnicharInputStream : public nsISupports {
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IUNICHAR_INPUT_STREAM_IID)
+
+ NS_IMETHOD Read(PRUnichar* aBuf,
+ PRUint32 aCount,
+ PRUint32 *aReadCount) = 0;
+ NS_IMETHOD Close() = 0;
+ NS_IMETHOD ReadSegments(nsWriteUnicharSegmentFun aWriter,
+ void* aClosure,
+ PRUint32 aCount,
+ PRUint32 *aReadCount) = 0;
+};
+
+/**
+ * Create a nsIUnicharInputStream that wraps up a string. Data is fed
+ * from the string out until the done. When this object is destroyed
+ * it destroyes the string (so make a copy if you don't want it doing
+ * that)
+ */
+extern NS_COM nsresult
+ NS_NewStringUnicharInputStream(nsIUnicharInputStream** aInstancePtrResult,
+ nsString* aString);
+
+/** Create a new nsUnicharInputStream that provides a converter for the
+ * byte input stream aStreamToWrap. If no converter can be found then
+ * nsnull is returned and the error code is set to
+ * NS_INPUTSTREAM_NO_CONVERTER.
+ */
+extern NS_COM nsresult
+ NS_NewUTF8ConverterStream(nsIUnicharInputStream** aInstancePtrResult,
+ nsIInputStream* aStreamToWrap,
+ PRInt32 aBufferSize = 0);
+
+#endif /* nsUnicharInputStream_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/io/nsInputStreamTee.cpp b/src/libs/xpcom18a4/xpcom/io/nsInputStreamTee.cpp
new file mode 100644
index 00000000..b0651ad1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsInputStreamTee.cpp
@@ -0,0 +1,224 @@
+/* -*- 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) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@netscape.com> (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 "nsIInputStreamTee.h"
+#include "nsIInputStream.h"
+#include "nsIOutputStream.h"
+#include "nsCOMPtr.h"
+
+class nsInputStreamTee : public nsIInputStreamTee
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIINPUTSTREAM
+ NS_DECL_NSIINPUTSTREAMTEE
+
+ nsInputStreamTee();
+
+private:
+ ~nsInputStreamTee() {}
+
+ nsresult TeeSegment(const char *buf, PRUint32 count);
+
+ static NS_METHOD WriteSegmentFun(nsIInputStream *, void *, const char *,
+ PRUint32, PRUint32, PRUint32 *);
+
+private:
+ nsCOMPtr<nsIInputStream> mSource;
+ nsCOMPtr<nsIOutputStream> mSink;
+ nsWriteSegmentFun mWriter; // for implementing ReadSegments
+ void *mClosure; // for implementing ReadSegments
+};
+
+nsInputStreamTee::nsInputStreamTee()
+{
+}
+
+nsresult
+nsInputStreamTee::TeeSegment(const char *buf, PRUint32 count)
+{
+ if (!mSink)
+ return NS_OK; // nothing to do
+ nsresult rv;
+ PRUint32 bytesWritten = 0;
+ while (count) {
+ rv = mSink->Write(buf + bytesWritten, count, &bytesWritten);
+ if (NS_FAILED(rv)) {
+ // ok, this is not a fatal error... just drop our reference to mSink
+ // and continue on as if nothing happened.
+ NS_WARNING("Write failed (non-fatal)");
+ // catch possible misuse of the input stream tee
+ NS_ASSERTION(rv != NS_BASE_STREAM_WOULD_BLOCK, "sink must be a blocking stream");
+ mSink = 0;
+ break;
+ }
+ NS_ASSERTION(bytesWritten <= count, "wrote too much");
+ count -= bytesWritten;
+ }
+ return NS_OK;
+}
+
+NS_METHOD
+nsInputStreamTee::WriteSegmentFun(nsIInputStream *in, void *closure, const char *fromSegment,
+ PRUint32 offset, PRUint32 count, PRUint32 *writeCount)
+{
+ nsInputStreamTee *tee = NS_REINTERPRET_CAST(nsInputStreamTee *, closure);
+
+ nsresult rv = tee->mWriter(in, tee->mClosure, fromSegment, offset, count, writeCount);
+ if (NS_FAILED(rv) || (*writeCount == 0)) {
+ NS_ASSERTION((NS_FAILED(rv) ? (*writeCount == 0) : PR_TRUE),
+ "writer returned an error with non-zero writeCount");
+ return rv;
+ }
+
+ return tee->TeeSegment(fromSegment, *writeCount);
+}
+
+NS_IMPL_ISUPPORTS2(nsInputStreamTee,
+ nsIInputStreamTee,
+ nsIInputStream)
+
+NS_IMETHODIMP
+nsInputStreamTee::Close()
+{
+ NS_ENSURE_TRUE(mSource, NS_ERROR_NOT_INITIALIZED);
+ nsresult rv = mSource->Close();
+ mSource = 0;
+ mSink = 0;
+ return rv;
+}
+
+NS_IMETHODIMP
+nsInputStreamTee::Available(PRUint32 *avail)
+{
+ NS_ENSURE_TRUE(mSource, NS_ERROR_NOT_INITIALIZED);
+ return mSource->Available(avail);
+}
+
+NS_IMETHODIMP
+nsInputStreamTee::Read(char *buf, PRUint32 count, PRUint32 *bytesRead)
+{
+ NS_ENSURE_TRUE(mSource, NS_ERROR_NOT_INITIALIZED);
+
+ nsresult rv = mSource->Read(buf, count, bytesRead);
+ if (NS_FAILED(rv) || (*bytesRead == 0))
+ return rv;
+
+ return TeeSegment(buf, *bytesRead);
+}
+
+NS_IMETHODIMP
+nsInputStreamTee::ReadSegments(nsWriteSegmentFun writer,
+ void *closure,
+ PRUint32 count,
+ PRUint32 *bytesRead)
+{
+ NS_ENSURE_TRUE(mSource, NS_ERROR_NOT_INITIALIZED);
+
+ mWriter = writer;
+ mClosure = closure;
+
+ return mSource->ReadSegments(WriteSegmentFun, this, count, bytesRead);
+}
+
+NS_IMETHODIMP
+nsInputStreamTee::IsNonBlocking(PRBool *result)
+{
+ NS_ENSURE_TRUE(mSource, NS_ERROR_NOT_INITIALIZED);
+ return mSource->IsNonBlocking(result);
+}
+
+NS_IMETHODIMP
+nsInputStreamTee::SetSource(nsIInputStream *source)
+{
+ mSource = source;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsInputStreamTee::GetSource(nsIInputStream **source)
+{
+ NS_IF_ADDREF(*source = mSource);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsInputStreamTee::SetSink(nsIOutputStream *sink)
+{
+#ifdef DEBUG
+ if (sink) {
+ PRBool nonBlocking;
+ nsresult rv = sink->IsNonBlocking(&nonBlocking);
+ if (NS_FAILED(rv) || nonBlocking)
+ NS_ERROR("sink should be a blocking stream");
+ }
+#endif
+ mSink = sink;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsInputStreamTee::GetSink(nsIOutputStream **sink)
+{
+ NS_IF_ADDREF(*sink = mSink);
+ return NS_OK;
+}
+
+// factory method
+
+NS_COM nsresult
+NS_NewInputStreamTee(nsIInputStream **result,
+ nsIInputStream *source,
+ nsIOutputStream *sink)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIInputStreamTee> tee;
+ NS_NEWXPCOM(tee, nsInputStreamTee);
+ if (!tee)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ rv = tee->SetSource(source);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = tee->SetSink(sink);
+ if (NS_FAILED(rv)) return rv;
+
+ NS_ADDREF(*result = tee);
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLinebreakConverter.cpp b/src/libs/xpcom18a4/xpcom/io/nsLinebreakConverter.cpp
new file mode 100644
index 00000000..88905f97
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLinebreakConverter.cpp
@@ -0,0 +1,495 @@
+/* -*- 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 "nsLinebreakConverter.h"
+
+#include "nsMemory.h"
+#include "nsCRT.h"
+
+
+#if defined(XP_WIN) && defined(_MSC_VER) && (_MSC_VER <= 1100)
+#define LOSER_CHAR_CAST(t) (char *)(t)
+#define LOSER_UNICHAR_CAST(t) (PRUnichar *)(t)
+#else
+#define LOSER_CHAR_CAST(t) (t)
+#define LOSER_UNICHAR_CAST(t) (t)
+#endif
+
+/*----------------------------------------------------------------------------
+ GetLinebreakString
+
+ Could make this inline
+----------------------------------------------------------------------------*/
+static const char* GetLinebreakString(nsLinebreakConverter::ELinebreakType aBreakType)
+{
+ static const char* const sLinebreaks[] = {
+ "", // any
+ NS_LINEBREAK, // platform
+ LFSTR, // content
+ CRLF, // net
+ CRSTR, // Mac
+ LFSTR, // Unix
+ CRLF, // Windows
+ nsnull
+ };
+
+ return sLinebreaks[aBreakType];
+}
+
+
+/*----------------------------------------------------------------------------
+ AppendLinebreak
+
+ Wee inline method to append a line break. Modifies ioDest.
+----------------------------------------------------------------------------*/
+template<class T>
+void AppendLinebreak(T*& ioDest, const char* lineBreakStr)
+{
+ *ioDest++ = *lineBreakStr;
+
+ if (lineBreakStr[1])
+ *ioDest++ = lineBreakStr[1];
+}
+
+/*----------------------------------------------------------------------------
+ CountChars
+
+ Counts occurrences of breakStr in aSrc
+----------------------------------------------------------------------------*/
+template<class T>
+PRInt32 CountLinebreaks(const T* aSrc, PRInt32 inLen, const char* breakStr)
+{
+ const T* src = aSrc;
+ const T* srcEnd = aSrc + inLen;
+ PRInt32 theCount = 0;
+
+ while (src < srcEnd)
+ {
+ if (*src == *breakStr)
+ {
+ src ++;
+ if (src < srcEnd && breakStr[1] && *src == breakStr[1])
+ src ++;
+
+ theCount ++;
+ }
+ else
+ {
+ src ++;
+ }
+ }
+
+ return theCount;
+}
+
+
+/*----------------------------------------------------------------------------
+ ConvertBreaks
+
+ ioLen *includes* a terminating null, if any
+----------------------------------------------------------------------------*/
+template<class T>
+static T* ConvertBreaks(const T* inSrc, PRInt32& ioLen, const char* srcBreak, const char* destBreak)
+{
+ NS_ASSERTION(inSrc && srcBreak && destBreak, "Got a null string");
+
+ T* resultString = nsnull;
+
+ // handle the no conversion case
+ if (nsCRT::strcmp(srcBreak, destBreak) == 0)
+ {
+ resultString = (T *)nsMemory::Alloc(sizeof(T) * ioLen);
+ if (!resultString) return nsnull;
+ memcpy(resultString, inSrc, sizeof(T) * ioLen); // includes the null, if any
+ return resultString;
+ }
+
+ PRInt32 srcBreakLen = strlen(srcBreak);
+ PRInt32 destBreakLen = strlen(destBreak);
+
+ // handle the easy case, where the string length does not change, and the
+ // breaks are only 1 char long, i.e. CR <-> LF
+ if (srcBreakLen == destBreakLen && srcBreakLen == 1)
+ {
+ resultString = (T *)nsMemory::Alloc(sizeof(T) * ioLen);
+ if (!resultString) return nsnull;
+
+ const T* src = inSrc;
+ const T* srcEnd = inSrc + ioLen; // includes null, if any
+ T* dst = resultString;
+
+ char srcBreakChar = *srcBreak; // we know it's one char long already
+ char dstBreakChar = *destBreak;
+
+ while (src < srcEnd)
+ {
+ if (*src == srcBreakChar)
+ {
+ *dst++ = dstBreakChar;
+ src++;
+ }
+ else
+ {
+ *dst++ = *src++;
+ }
+ }
+
+ // ioLen does not change
+ }
+ else
+ {
+ // src and dest termination is different length. Do it a slower way.
+
+ // count linebreaks in src. Assumes that chars in 2-char linebreaks are unique.
+ PRInt32 numLinebreaks = CountLinebreaks(inSrc, ioLen, srcBreak);
+
+ PRInt32 newBufLen = ioLen - (numLinebreaks * srcBreakLen) + (numLinebreaks * destBreakLen);
+ resultString = (T *)nsMemory::Alloc(sizeof(T) * newBufLen);
+ if (!resultString) return nsnull;
+
+ const T* src = inSrc;
+ const T* srcEnd = inSrc + ioLen; // includes null, if any
+ T* dst = resultString;
+
+ while (src < srcEnd)
+ {
+ if (*src == *srcBreak)
+ {
+ *dst++ = *destBreak;
+ if (destBreak[1])
+ *dst++ = destBreak[1];
+
+ src ++;
+ if (src < srcEnd && srcBreak[1] && *src == srcBreak[1])
+ src ++;
+ }
+ else
+ {
+ *dst++ = *src++;
+ }
+ }
+
+ ioLen = newBufLen;
+ }
+
+ return resultString;
+}
+
+
+/*----------------------------------------------------------------------------
+ ConvertBreaksInSitu
+
+ Convert breaks in situ. Can only do this if the linebreak length
+ does not change.
+----------------------------------------------------------------------------*/
+template<class T>
+static void ConvertBreaksInSitu(T* inSrc, PRInt32 inLen, char srcBreak, char destBreak)
+{
+ T* src = inSrc;
+ T* srcEnd = inSrc + inLen;
+
+ while (src < srcEnd)
+ {
+ if (*src == srcBreak)
+ *src = destBreak;
+
+ src ++;
+ }
+}
+
+
+/*----------------------------------------------------------------------------
+ ConvertUnknownBreaks
+
+ Convert unknown line breaks to the specified break.
+
+ This will convert CRLF pairs to one break, and single CR or LF to a break.
+----------------------------------------------------------------------------*/
+template<class T>
+static T* ConvertUnknownBreaks(const T* inSrc, PRInt32& ioLen, const char* destBreak)
+{
+ const T* src = inSrc;
+ const T* srcEnd = inSrc + ioLen; // includes null, if any
+
+ PRInt32 destBreakLen = strlen(destBreak);
+ PRInt32 finalLen = 0;
+
+ while (src < srcEnd)
+ {
+ if (*src == nsCRT::CR)
+ {
+ if (src < srcEnd && src[1] == nsCRT::LF)
+ {
+ // CRLF
+ finalLen += destBreakLen;
+ src ++;
+ }
+ else
+ {
+ // Lone CR
+ finalLen += destBreakLen;
+ }
+ }
+ else if (*src == nsCRT::LF)
+ {
+ // Lone LF
+ finalLen += destBreakLen;
+ }
+ else
+ {
+ finalLen ++;
+ }
+ src ++;
+ }
+
+ T* resultString = (T *)nsMemory::Alloc(sizeof(T) * finalLen);
+ if (!resultString) return nsnull;
+
+ src = inSrc;
+ srcEnd = inSrc + ioLen; // includes null, if any
+
+ T* dst = resultString;
+
+ while (src < srcEnd)
+ {
+ if (*src == nsCRT::CR)
+ {
+ if (src < srcEnd && src[1] == nsCRT::LF)
+ {
+ // CRLF
+ AppendLinebreak(dst, destBreak);
+ src ++;
+ }
+ else
+ {
+ // Lone CR
+ AppendLinebreak(dst, destBreak);
+ }
+ }
+ else if (*src == nsCRT::LF)
+ {
+ // Lone LF
+ AppendLinebreak(dst, destBreak);
+ }
+ else
+ {
+ *dst++ = *src;
+ }
+ src ++;
+ }
+
+ ioLen = finalLen;
+ return resultString;
+}
+
+
+#ifdef XP_MAC
+#pragma mark -
+#endif
+
+
+/*----------------------------------------------------------------------------
+ ConvertLineBreaks
+
+----------------------------------------------------------------------------*/
+char* nsLinebreakConverter::ConvertLineBreaks(const char* aSrc,
+ ELinebreakType aSrcBreaks, ELinebreakType aDestBreaks, PRInt32 aSrcLen, PRInt32* outLen)
+{
+ NS_ASSERTION(aDestBreaks != eLinebreakAny, "Invalid parameter");
+ if (!aSrc) return nsnull;
+
+ PRInt32 sourceLen = (aSrcLen == kIgnoreLen) ? strlen(aSrc) + 1 : aSrcLen;
+
+ char* resultString;
+ if (aSrcBreaks == eLinebreakAny)
+ resultString = ConvertUnknownBreaks(LOSER_CHAR_CAST(aSrc), sourceLen, GetLinebreakString(aDestBreaks));
+ else
+ resultString = ConvertBreaks(LOSER_CHAR_CAST(aSrc), sourceLen, GetLinebreakString(aSrcBreaks), GetLinebreakString(aDestBreaks));
+
+ if (outLen)
+ *outLen = sourceLen;
+ return resultString;
+}
+
+
+/*----------------------------------------------------------------------------
+ ConvertLineBreaksInSitu
+
+----------------------------------------------------------------------------*/
+nsresult nsLinebreakConverter::ConvertLineBreaksInSitu(char **ioBuffer, ELinebreakType aSrcBreaks,
+ ELinebreakType aDestBreaks, PRInt32 aSrcLen, PRInt32* outLen)
+{
+ NS_ASSERTION(ioBuffer && *ioBuffer, "Null pointer passed");
+ if (!ioBuffer || !*ioBuffer) return NS_ERROR_NULL_POINTER;
+
+ NS_ASSERTION(aDestBreaks != eLinebreakAny, "Invalid parameter");
+
+ PRInt32 sourceLen = (aSrcLen == kIgnoreLen) ? strlen(*ioBuffer) + 1 : aSrcLen;
+
+ // can we convert in-place?
+ const char* srcBreaks = GetLinebreakString(aSrcBreaks);
+ const char* dstBreaks = GetLinebreakString(aDestBreaks);
+
+ if ( (aSrcBreaks != eLinebreakAny) &&
+ (strlen(srcBreaks) == 1) &&
+ (strlen(dstBreaks) == 1) )
+ {
+ ConvertBreaksInSitu(*ioBuffer, sourceLen, *srcBreaks, *dstBreaks);
+ if (outLen)
+ *outLen = sourceLen;
+ }
+ else
+ {
+ char* destBuffer;
+
+ if (aSrcBreaks == eLinebreakAny)
+ destBuffer = ConvertUnknownBreaks(*ioBuffer, sourceLen, dstBreaks);
+ else
+ destBuffer = ConvertBreaks(*ioBuffer, sourceLen, srcBreaks, dstBreaks);
+
+ if (!destBuffer) return NS_ERROR_OUT_OF_MEMORY;
+ *ioBuffer = destBuffer;
+ if (outLen)
+ *outLen = sourceLen;
+ }
+
+ return NS_OK;
+}
+
+
+/*----------------------------------------------------------------------------
+ ConvertUnicharLineBreaks
+
+----------------------------------------------------------------------------*/
+PRUnichar* nsLinebreakConverter::ConvertUnicharLineBreaks(const PRUnichar* aSrc,
+ ELinebreakType aSrcBreaks, ELinebreakType aDestBreaks, PRInt32 aSrcLen, PRInt32* outLen)
+{
+ NS_ASSERTION(aDestBreaks != eLinebreakAny, "Invalid parameter");
+ if (!aSrc) return nsnull;
+
+ PRInt32 bufLen = (aSrcLen == kIgnoreLen) ? nsCRT::strlen(aSrc) + 1 : aSrcLen;
+
+ PRUnichar* resultString;
+ if (aSrcBreaks == eLinebreakAny)
+ resultString = ConvertUnknownBreaks(LOSER_UNICHAR_CAST(aSrc), bufLen, GetLinebreakString(aDestBreaks));
+ else
+ resultString = ConvertBreaks(LOSER_UNICHAR_CAST(aSrc), bufLen, GetLinebreakString(aSrcBreaks), GetLinebreakString(aDestBreaks));
+
+ if (outLen)
+ *outLen = bufLen;
+ return resultString;
+}
+
+
+/*----------------------------------------------------------------------------
+ ConvertStringLineBreaks
+
+----------------------------------------------------------------------------*/
+nsresult nsLinebreakConverter::ConvertUnicharLineBreaksInSitu(PRUnichar **ioBuffer,
+ ELinebreakType aSrcBreaks, ELinebreakType aDestBreaks, PRInt32 aSrcLen, PRInt32* outLen)
+{
+ NS_ASSERTION(ioBuffer && *ioBuffer, "Null pointer passed");
+ if (!ioBuffer || !*ioBuffer) return NS_ERROR_NULL_POINTER;
+ NS_ASSERTION(aDestBreaks != eLinebreakAny, "Invalid parameter");
+
+ PRInt32 sourceLen = (aSrcLen == kIgnoreLen) ? nsCRT::strlen(*ioBuffer) + 1 : aSrcLen;
+
+ // can we convert in-place?
+ const char* srcBreaks = GetLinebreakString(aSrcBreaks);
+ const char* dstBreaks = GetLinebreakString(aDestBreaks);
+
+ if ( (aSrcBreaks != eLinebreakAny) &&
+ (strlen(srcBreaks) == 1) &&
+ (strlen(dstBreaks) == 1) )
+ {
+ ConvertBreaksInSitu(*ioBuffer, sourceLen, *srcBreaks, *dstBreaks);
+ if (outLen)
+ *outLen = sourceLen;
+ }
+ else
+ {
+ PRUnichar* destBuffer;
+
+ if (aSrcBreaks == eLinebreakAny)
+ destBuffer = ConvertUnknownBreaks(*ioBuffer, sourceLen, dstBreaks);
+ else
+ destBuffer = ConvertBreaks(*ioBuffer, sourceLen, srcBreaks, dstBreaks);
+
+ if (!destBuffer) return NS_ERROR_OUT_OF_MEMORY;
+ *ioBuffer = destBuffer;
+ if (outLen)
+ *outLen = sourceLen;
+ }
+
+ return NS_OK;
+}
+
+/*----------------------------------------------------------------------------
+ ConvertStringLineBreaks
+
+----------------------------------------------------------------------------*/
+nsresult nsLinebreakConverter::ConvertStringLineBreaks(nsString& ioString,
+ ELinebreakType aSrcBreaks, ELinebreakType aDestBreaks)
+{
+
+ NS_ASSERTION(aDestBreaks != eLinebreakAny, "Invalid parameter");
+
+ // nothing to do
+ if (ioString.IsEmpty()) return NS_OK;
+
+ nsresult rv;
+
+ // remember the old buffer in case
+ // we blow it away later
+ nsString::char_iterator stringBuf;
+ ioString.BeginWriting(stringBuf);
+
+ PRInt32 newLen;
+
+ rv = ConvertUnicharLineBreaksInSitu(&stringBuf,
+ aSrcBreaks, aDestBreaks,
+ ioString.Length() + 1, &newLen);
+ if (NS_FAILED(rv)) return rv;
+
+ if (stringBuf != ioString.get())
+ ioString.Adopt(stringBuf);
+
+ return NS_OK;
+}
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLinebreakConverter.h b/src/libs/xpcom18a4/xpcom/io/nsLinebreakConverter.h
new file mode 100644
index 00000000..ec4bce57
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLinebreakConverter.h
@@ -0,0 +1,156 @@
+/* -*- 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 nsLinebreakConverter_h_
+#define nsLinebreakConverter_h_
+
+
+#include "nscore.h"
+#include "nsString.h"
+
+// utility class for converting between different line breaks.
+
+class NS_COM nsLinebreakConverter
+{
+public:
+
+ // Note: enum must match char* array in GetLinebreakString
+ typedef enum {
+ eLinebreakAny, // any kind of linebreak (i.e. "don't care" source)
+
+ eLinebreakPlatform, // platform linebreak
+ eLinebreakContent, // Content model linebreak (LF)
+ eLinebreakNet, // Form submission linebreak (CRLF)
+
+ eLinebreakMac, // CR
+ eLinebreakUnix, // LF
+ eLinebreakWindows // CRLF
+
+ } ELinebreakType;
+
+ enum {
+ kIgnoreLen = -1
+ };
+
+ /* ConvertLineBreaks
+ * Convert line breaks in the supplied string, allocating and returning
+ * a new buffer. Returns nsnull on failure.
+ * @param aSrc: the source string. if aSrcLen == kIgnoreLen this string is assumed
+ * to be null terminated, otherwise it must be at least aSrcLen long.
+ * @param aSrcBreaks: the line breaks in the source. If unknown, pass eLinebreakAny.
+ * If known, pass the known value, as this may be more efficient.
+ * @param aDestBreaks: the line breaks you want in the output.
+ * @param aSrcLen: length of the source. If -1, the source is assumed to be a null-
+ * terminated string.
+ * @param aOutLen: used to return character length of returned buffer, if not null.
+ */
+ static char* ConvertLineBreaks(const char* aSrc,
+ ELinebreakType aSrcBreaks, ELinebreakType aDestBreaks,
+ PRInt32 aSrcLen = kIgnoreLen, PRInt32* aOutLen = nsnull);
+
+
+ /* ConvertUnicharLineBreaks
+ * Convert line breaks in the supplied string, allocating and returning
+ * a new buffer. Returns nsnull on failure.
+ * @param aSrc: the source string. if aSrcLen == kIgnoreLen this string is assumed
+ * to be null terminated, otherwise it must be at least aSrcLen long.
+ * @param aSrcBreaks: the line breaks in the source. If unknown, pass eLinebreakAny.
+ * If known, pass the known value, as this may be more efficient.
+ * @param aDestBreaks: the line breaks you want in the output.
+ * @param aSrcLen: length of the source, in characters. If -1, the source is assumed to be a null-
+ * terminated string.
+ * @param aOutLen: used to return character length of returned buffer, if not null.
+ */
+ static PRUnichar* ConvertUnicharLineBreaks(const PRUnichar* aSrc,
+ ELinebreakType aSrcBreaks, ELinebreakType aDestBreaks,
+ PRInt32 aSrcLen = kIgnoreLen, PRInt32* aOutLen = nsnull);
+
+
+ /* ConvertStringLineBreaks
+ * Convert line breaks in the supplied string, changing the string buffer (i.e. in-place conversion)
+ * @param ioString: the string to be converted.
+ * @param aSrcBreaks: the line breaks in the source. If unknown, pass eLinebreakAny.
+ * If known, pass the known value, as this may be more efficient.
+ * @param aDestBreaks: the line breaks you want in the output.
+ * @param aSrcLen: length of the source, in characters. If -1, the source is assumed to be a null-
+ * terminated string.
+ */
+ static nsresult ConvertStringLineBreaks(nsString& ioString, ELinebreakType aSrcBreaks, ELinebreakType aDestBreaks);
+
+
+ /* ConvertLineBreaksInSitu
+ * Convert line breaks in place if possible. NOTE: THIS MAY REALLOCATE THE BUFFER,
+ * BUT IT WON'T FREE THE OLD BUFFER (because it doesn't know how). So be prepared
+ * to keep a copy of the old pointer, and free it if this passes back a new pointer.
+ * ALSO NOTE: DON'T PASS A STATIC STRING POINTER TO THIS FUNCTION.
+ *
+ * @param ioBuffer: the source buffer. if aSrcLen == kIgnoreLen this string is assumed
+ * to be null terminated, otherwise it must be at least aSrcLen long.
+ * @param aSrcBreaks: the line breaks in the source. If unknown, pass eLinebreakAny.
+ * If known, pass the known value, as this may be more efficient.
+ * @param aDestBreaks: the line breaks you want in the output.
+ * @param aSrcLen: length of the source. If -1, the source is assumed to be a null-
+ * terminated string.
+ * @param aOutLen: used to return character length of returned buffer, if not null.
+ */
+ static nsresult ConvertLineBreaksInSitu(char **ioBuffer, ELinebreakType aSrcBreaks, ELinebreakType aDestBreaks,
+ PRInt32 aSrcLen = kIgnoreLen, PRInt32* aOutLen = nsnull);
+
+
+ /* ConvertUnicharLineBreaksInSitu
+ * Convert line breaks in place if possible. NOTE: THIS MAY REALLOCATE THE BUFFER,
+ * BUT IT WON'T FREE THE OLD BUFFER (because it doesn't know how). So be prepared
+ * to keep a copy of the old pointer, and free it if this passes back a new pointer.
+ *
+ * @param ioBuffer: the source buffer. if aSrcLen == kIgnoreLen this string is assumed
+ * to be null terminated, otherwise it must be at least aSrcLen long.
+ * @param aSrcBreaks: the line breaks in the source. If unknown, pass eLinebreakAny.
+ * If known, pass the known value, as this may be more efficient.
+ * @param aDestBreaks: the line breaks you want in the output.
+ * @param aSrcLen: length of the source in characters. If -1, the source is assumed to be a null-
+ * terminated string.
+ * @param aOutLen: used to return character length of returned buffer, if not null.
+ */
+ static nsresult ConvertUnicharLineBreaksInSitu(PRUnichar **ioBuffer, ELinebreakType aSrcBreaks, ELinebreakType aDestBreaks,
+ PRInt32 aSrcLen = kIgnoreLen, PRInt32* aOutLen = nsnull);
+
+};
+
+
+
+
+#endif // nsLinebreakConverter_h_
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFile.h b/src/libs/xpcom18a4/xpcom/io/nsLocalFile.h
new file mode 100644
index 00000000..8201affb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFile.h
@@ -0,0 +1,118 @@
+/* -*- 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 *****
+ *
+ * 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. OS/2 build.
+ */
+
+#ifndef _NS_LOCAL_FILE_H_
+#define _NS_LOCAL_FILE_H_
+
+#define NS_LOCAL_FILE_CID {0x2e23e220, 0x60be, 0x11d3, {0x8c, 0x4a, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74}}
+
+#define NS_DECL_NSLOCALFILE_UNICODE_METHODS \
+ nsresult AppendUnicode(const PRUnichar *aNode); \
+ nsresult GetUnicodeLeafName(PRUnichar **aLeafName); \
+ nsresult SetUnicodeLeafName(const PRUnichar *aLeafName); \
+ nsresult CopyToUnicode(nsIFile *aNewParentDir, const PRUnichar *aNewLeafName); \
+ nsresult CopyToFollowingLinksUnicode(nsIFile *aNewParentDir, const PRUnichar *aNewLeafName); \
+ nsresult MoveToUnicode(nsIFile *aNewParentDir, const PRUnichar *aNewLeafName); \
+ nsresult GetUnicodeTarget(PRUnichar **aTarget); \
+ nsresult GetUnicodePath(PRUnichar **aPath); \
+ nsresult InitWithUnicodePath(const PRUnichar *aPath); \
+ nsresult AppendRelativeUnicodePath(const PRUnichar *aRelativePath);
+
+// nsXPComInit needs to know about how we are implemented,
+// so here we will export it. Other users should not depend
+// on this.
+
+#include <errno.h>
+#include "nsILocalFile.h"
+
+#ifdef XP_WIN
+#include "nsLocalFileWin.h"
+#elif defined(XP_MACOSX) && !defined(VBOX_MACOSX_FOLLOWS_UNIX_IO)
+#include "nsLocalFileOSX.h"
+#elif defined(XP_MAC)
+#include "nsLocalFileMac.h"
+#elif defined(XP_UNIX) || defined(XP_BEOS)
+#include "nsLocalFileUnix.h"
+#elif defined(XP_OS2)
+#include "nsLocalFileOS2.h"
+#else
+#error NOT_IMPLEMENTED
+#endif
+
+#define NSRESULT_FOR_RETURN(ret) (((ret) < 0) ? NSRESULT_FOR_ERRNO() : NS_OK)
+
+inline nsresult
+nsresultForErrno(int err)
+{
+ switch (err) {
+ case 0:
+ return NS_OK;
+ case ENOENT:
+ return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST;
+ case ENOTDIR:
+ return NS_ERROR_FILE_DESTINATION_NOT_DIR;
+#ifdef ENOLINK
+ case ENOLINK:
+ return NS_ERROR_FILE_UNRESOLVABLE_SYMLINK;
+#endif /* ENOLINK */
+ case EEXIST:
+ return NS_ERROR_FILE_ALREADY_EXISTS;
+#ifdef EPERM
+ case EPERM:
+#endif /* EPERM */
+ case EACCES:
+ return NS_ERROR_FILE_ACCESS_DENIED;
+ default:
+ return NS_ERROR_FAILURE;
+ }
+}
+
+#define NSRESULT_FOR_ERRNO() nsresultForErrno(errno)
+
+void NS_StartupLocalFile();
+void NS_ShutdownLocalFile();
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFileCommon.cpp b/src/libs/xpcom18a4/xpcom/io/nsLocalFileCommon.cpp
new file mode 100644
index 00000000..664c5304
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFileCommon.cpp
@@ -0,0 +1,278 @@
+/* -*- 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) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Doug Turner <dougt@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 "nsIServiceManager.h"
+
+#include "nsLocalFile.h" // includes platform-specific headers
+#include "nsLocalFileUnicode.h"
+
+#include "nsString.h"
+#include "nsCOMPtr.h"
+#include "nsReadableUtils.h"
+#include "nsPrintfCString.h"
+#include "nsCRT.h"
+
+#ifdef XP_WIN
+#include <string.h>
+#endif
+
+
+void NS_StartupLocalFile()
+{
+ nsLocalFile::GlobalInit();
+}
+
+void NS_ShutdownLocalFile()
+{
+ nsLocalFile::GlobalShutdown();
+}
+
+#if (!defined(XP_MAC) && !defined(XP_MACOSX)) || defined(VBOX_MACOSX_FOLLOWS_UNIX_IO)
+NS_IMETHODIMP
+nsLocalFile::InitWithFile(nsILocalFile *aFile)
+{
+ NS_ENSURE_ARG(aFile);
+
+ nsCAutoString path;
+ aFile->GetNativePath(path);
+ if (path.IsEmpty())
+ return NS_ERROR_INVALID_ARG;
+ return InitWithNativePath(path);
+}
+#endif
+
+#if defined(XP_MAC)
+#define kMaxFilenameLength 31
+#else
+#define kMaxFilenameLength 255
+#endif
+
+NS_IMETHODIMP
+nsLocalFile::CreateUnique(PRUint32 type, PRUint32 attributes)
+{
+ nsresult rv = Create(type, attributes);
+
+ if (NS_SUCCEEDED(rv)) return NS_OK;
+ if (rv != NS_ERROR_FILE_ALREADY_EXISTS) return rv;
+
+ nsCAutoString leafName;
+ rv = GetNativeLeafName(leafName);
+
+ if (NS_FAILED(rv)) return rv;
+
+ const char* lastDot = strrchr(leafName.get(), '.');
+ char suffix[kMaxFilenameLength + 1] = "";
+ if (lastDot)
+ {
+ strncpy(suffix, lastDot, kMaxFilenameLength); // include '.'
+ suffix[kMaxFilenameLength] = 0; // make sure it's null terminated
+ leafName.SetLength(lastDot - leafName.get()); // strip suffix and dot.
+ }
+
+ const int maxRootLength = (kMaxFilenameLength - 4) - strlen(suffix) - 1;
+
+ if ((int)leafName.Length() > (int)maxRootLength)
+ leafName.SetLength(maxRootLength);
+
+ for (short indx = 1; indx < 10000; indx++)
+ {
+ // start with "Picture-1.jpg" after "Picture.jpg" exists
+ SetNativeLeafName(leafName +
+ nsPrintfCString("-%d", indx) +
+ nsDependentCString(suffix));
+
+ rv = Create(type, attributes);
+
+ if (NS_SUCCEEDED(rv) || rv != NS_ERROR_FILE_ALREADY_EXISTS)
+ {
+ return rv;
+ }
+ }
+
+ // The disk is full, sort of
+ return NS_ERROR_FILE_TOO_BIG;
+}
+
+#if defined(XP_MAC)
+static const PRUnichar kPathSeparatorChar = ':';
+#elif defined(XP_WIN) || defined(XP_OS2)
+static const PRUnichar kPathSeparatorChar = '\\';
+#elif defined(XP_UNIX) || defined(XP_BEOS)
+static const PRUnichar kPathSeparatorChar = '/';
+#else
+#error Need to define file path separator for your platform
+#endif
+
+#if defined(XP_MAC)
+static const char kSlashStr[] = "/";
+static const char kESCSlashStr[] = "%2F";
+#endif
+
+static PRInt32 SplitPath(PRUnichar *path, PRUnichar **nodeArray, PRInt32 arrayLen)
+{
+ if (*path == 0)
+ return 0;
+
+ PRUnichar **nodePtr = nodeArray;
+ if (*path == kPathSeparatorChar)
+ path++;
+ *nodePtr++ = path;
+
+ for (PRUnichar *cp = path; *cp != 0; cp++) {
+ if (*cp == kPathSeparatorChar) {
+ *cp++ = 0;
+ if (*cp == 0)
+ break;
+ if (nodePtr - nodeArray >= arrayLen)
+ return -1;
+ *nodePtr++ = cp;
+ }
+ }
+ return nodePtr - nodeArray;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::GetRelativeDescriptor(nsILocalFile *fromFile, nsACString& _retval)
+{
+ NS_ENSURE_ARG_POINTER(fromFile);
+ const PRInt32 kMaxNodesInPath = 32;
+
+ //
+ // _retval will be UTF-8 encoded
+ //
+
+ nsresult rv;
+ _retval.Truncate(0);
+
+ nsAutoString thisPath, fromPath;
+ PRUnichar *thisNodes[kMaxNodesInPath], *fromNodes[kMaxNodesInPath];
+ PRInt32 thisNodeCnt, fromNodeCnt, nodeIndex;
+
+ rv = GetPath(thisPath);
+ if (NS_FAILED(rv))
+ return rv;
+ rv = fromFile->GetPath(fromPath);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // get raw pointer to mutable string buffer
+ PRUnichar *thisPathPtr; thisPath.BeginWriting(thisPathPtr);
+ PRUnichar *fromPathPtr; fromPath.BeginWriting(fromPathPtr);
+
+ thisNodeCnt = SplitPath(thisPathPtr, thisNodes, kMaxNodesInPath);
+ fromNodeCnt = SplitPath(fromPathPtr, fromNodes, kMaxNodesInPath);
+ if (thisNodeCnt < 0 || fromNodeCnt < 0)
+ return NS_ERROR_FAILURE;
+
+ for (nodeIndex = 0; nodeIndex < thisNodeCnt && nodeIndex < fromNodeCnt; ++nodeIndex) {
+#ifdef XP_WIN
+ if (_wcsicmp(thisNodes[nodeIndex], fromNodes[nodeIndex]))
+ break;
+#else
+ if (nsCRT::strcmp(thisNodes[nodeIndex], fromNodes[nodeIndex]))
+ break;
+#endif
+ }
+
+ PRInt32 branchIndex = nodeIndex;
+ for (nodeIndex = branchIndex; nodeIndex < fromNodeCnt; nodeIndex++)
+ _retval.AppendLiteral("../");
+ for (nodeIndex = branchIndex; nodeIndex < thisNodeCnt; nodeIndex++) {
+ NS_ConvertUCS2toUTF8 nodeStr(thisNodes[nodeIndex]);
+#ifdef XP_MAC
+ nodeStr.ReplaceSubstring(kSlashStr, kESCSlashStr);
+#endif
+ _retval.Append(nodeStr);
+ if (nodeIndex + 1 < thisNodeCnt)
+ _retval.Append('/');
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetRelativeDescriptor(nsILocalFile *fromFile, const nsACString& relativeDesc)
+{
+ NS_NAMED_LITERAL_CSTRING(kParentDirStr, "../");
+
+ nsCOMPtr<nsIFile> targetFile;
+ nsresult rv = fromFile->Clone(getter_AddRefs(targetFile));
+ if (NS_FAILED(rv))
+ return rv;
+
+ //
+ // relativeDesc is UTF-8 encoded
+ //
+
+ nsCString::const_iterator strBegin, strEnd;
+ relativeDesc.BeginReading(strBegin);
+ relativeDesc.EndReading(strEnd);
+
+ nsCString::const_iterator nodeBegin(strBegin), nodeEnd(strEnd);
+ nsCString::const_iterator pos(strBegin);
+
+ nsCOMPtr<nsIFile> parentDir;
+ while (FindInReadable(kParentDirStr, nodeBegin, nodeEnd)) {
+ rv = targetFile->GetParent(getter_AddRefs(parentDir));
+ if (NS_FAILED(rv))
+ return rv;
+ targetFile = parentDir;
+
+ nodeBegin = nodeEnd;
+ pos = nodeEnd;
+ nodeEnd = strEnd;
+ }
+
+ nodeBegin = nodeEnd = pos;
+ while (nodeEnd != strEnd) {
+ FindCharInReadable('/', nodeEnd, strEnd);
+#ifdef XP_MAC
+ nsCAutoString nodeString(Substring(nodeBegin, nodeEnd));
+ nodeString.ReplaceSubstring(kESCSlashStr, kSlashStr);
+ targetFile->Append(NS_ConvertUTF8toUCS2(nodeString));
+#else
+ targetFile->Append(NS_ConvertUTF8toUCS2(Substring(nodeBegin, nodeEnd)));
+#endif
+ if (nodeEnd != strEnd) // If there's more left in the string, inc over the '/' nodeEnd is on.
+ ++nodeEnd;
+ nodeBegin = nodeEnd;
+ }
+
+ nsCOMPtr<nsILocalFile> targetLocalFile(do_QueryInterface(targetFile));
+ return InitWithFile(targetLocalFile);
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFileMac.cpp b/src/libs/xpcom18a4/xpcom/io/nsLocalFileMac.cpp
new file mode 100644
index 00000000..bebc76c1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFileMac.cpp
@@ -0,0 +1,3554 @@
+/* -*- 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 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):
+ * Steve Dagley <sdagley@netscape.com>
+ * John R. McMullen
+ *
+ * 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 "nsCOMPtr.h"
+#include "nsMemory.h"
+#include "nsXPIDLString.h"
+
+#include "nsLocalFile.h"
+#include "nsNativeCharsetUtils.h"
+#include "nsISimpleEnumerator.h"
+#include "nsIComponentManager.h"
+#include "nsIInternetConfigService.h"
+#include "nsIMIMEInfo.h"
+#include "prtypes.h"
+#include "prerror.h"
+
+#include "nsReadableUtils.h"
+#include "nsITimelineService.h"
+
+#ifdef XP_MACOSX
+#include "nsXPIDLString.h"
+
+#include "private/pprio.h"
+#else
+#include "pprio.h" // Include this rather than prio.h so we get def of PR_ImportFile
+#endif
+#include "prmem.h"
+#include "plbase64.h"
+
+#include "FullPath.h"
+#include "FileCopy.h"
+#include "MoreFilesExtras.h"
+#include "DirectoryCopy.h"
+#include <Script.h>
+#include <Processes.h>
+#include <StringCompare.h>
+#include <Resources.h>
+
+#include <AppleEvents.h>
+#include <AEDataModel.h>
+#include <AERegistry.h>
+#include <Gestalt.h>
+
+#include <Math64.h>
+#include <Aliases.h>
+#include <Folders.h>
+#include <Gestalt.h>
+#include "macDirectoryCopy.h"
+
+#include <limits.h>
+
+// Stupid @#$% header looks like its got extern mojo but it doesn't really
+extern "C"
+{
+#ifndef XP_MACOSX
+// BADPINK - this MSL header doesn't exist under macosx :-(
+#include <FSp_fopen.h>
+#endif
+}
+
+#if TARGET_CARBON
+#include <CodeFragments.h> // Needed for definition of kUnresolvedCFragSymbolAddress
+#include <LaunchServices.h>
+#endif
+
+#pragma mark [Constants]
+
+const OSType kDefaultCreator = 'MOSS';
+
+#pragma mark -
+#pragma mark [nsPathParser]
+
+class nsPathParser
+{
+public:
+ nsPathParser(const nsACString &path);
+
+ ~nsPathParser()
+ {
+ if (mAllocatedBuffer)
+ nsMemory::Free(mAllocatedBuffer);
+ }
+
+ const char* First()
+ {
+ return nsCRT::strtok(mBuffer, ":", &mNewString);
+ }
+ const char* Next()
+ {
+ return nsCRT::strtok(mNewString, ":", &mNewString);
+ }
+ const char* Remainder()
+ {
+ return mNewString;
+ }
+
+private:
+ char mAutoBuffer[512];
+ char *mAllocatedBuffer;
+ char *mBuffer, *mNewString;
+};
+
+nsPathParser::nsPathParser(const nsACString &inPath) :
+ mAllocatedBuffer(nsnull), mNewString(nsnull)
+{
+ PRUint32 inPathLen = inPath.Length();
+ if (inPathLen >= sizeof(mAutoBuffer)) {
+ mAllocatedBuffer = (char *)nsMemory::Alloc(inPathLen + 1);
+ mBuffer = mAllocatedBuffer;
+ }
+ else
+ mBuffer = mAutoBuffer;
+
+ // copy inPath into mBuffer
+ nsACString::const_iterator start, end;
+ inPath.BeginReading(start);
+ inPath.EndReading(end);
+
+ PRUint32 size, offset = 0;
+ for ( ; start != end; start.advance(size)) {
+ const char* buf = start.get();
+ size = start.size_forward();
+ memcpy(mBuffer + offset, buf, size);
+ offset += size;
+ }
+ mBuffer[offset] = '\0';
+}
+
+#pragma mark -
+#pragma mark [static util funcs]
+
+static inline void ClearFSSpec(FSSpec& aSpec)
+{
+ aSpec.vRefNum = 0;
+ aSpec.parID = 0;
+ aSpec.name[0] = 0;
+}
+
+
+// Simple func to map Mac OS errors into nsresults
+static nsresult MacErrorMapper(OSErr inErr)
+{
+ nsresult outErr;
+
+ switch (inErr)
+ {
+ case noErr:
+ outErr = NS_OK;
+ break;
+
+ case fnfErr:
+ outErr = NS_ERROR_FILE_NOT_FOUND;
+ break;
+
+ case dupFNErr:
+ outErr = NS_ERROR_FILE_ALREADY_EXISTS;
+ break;
+
+ case dskFulErr:
+ outErr = NS_ERROR_FILE_DISK_FULL;
+ break;
+
+ case fLckdErr:
+ outErr = NS_ERROR_FILE_IS_LOCKED;
+ break;
+
+ // Can't find good map for some
+ case bdNamErr:
+ outErr = NS_ERROR_FAILURE;
+ break;
+
+ default:
+ outErr = NS_ERROR_FAILURE;
+ break;
+ }
+ return outErr;
+}
+
+
+
+/*----------------------------------------------------------------------------
+ IsEqualFSSpec
+
+ Compare two canonical FSSpec records.
+
+ Entry: file1 = pointer to first FSSpec record.
+ file2 = pointer to second FSSpec record.
+
+ Exit: function result = true if the FSSpec records are equal.
+----------------------------------------------------------------------------*/
+
+static PRBool IsEqualFSSpec(const FSSpec& file1, const FSSpec& file2)
+{
+ return
+ file1.vRefNum == file2.vRefNum &&
+ file1.parID == file2.parID &&
+ EqualString(file1.name, file2.name, false, true);
+}
+
+
+/*----------------------------------------------------------------------------
+ GetParentFolderSpec
+
+ Given an FSSpec to a (possibly non-existent) file, get an FSSpec for its
+ parent directory.
+
+----------------------------------------------------------------------------*/
+
+static OSErr GetParentFolderSpec(const FSSpec& fileSpec, FSSpec& parentDirSpec)
+{
+ CInfoPBRec pBlock = {0};
+ OSErr err = noErr;
+
+ parentDirSpec.name[0] = 0;
+
+ pBlock.dirInfo.ioVRefNum = fileSpec.vRefNum;
+ pBlock.dirInfo.ioDrDirID = fileSpec.parID;
+ pBlock.dirInfo.ioNamePtr = (StringPtr)parentDirSpec.name;
+ pBlock.dirInfo.ioFDirIndex = -1; //get info on parID
+ err = PBGetCatInfoSync(&pBlock);
+ if (err != noErr) return err;
+
+ parentDirSpec.vRefNum = fileSpec.vRefNum;
+ parentDirSpec.parID = pBlock.dirInfo.ioDrParID;
+
+ return err;
+}
+
+
+/*----------------------------------------------------------------------------
+ VolHasDesktopDB
+
+ Check to see if a volume supports the new desktop database.
+
+ Entry: vRefNum = vol ref num of volumn
+
+ Exit: function result = error code.
+ *hasDesktop = true if volume has the new desktop database.
+----------------------------------------------------------------------------*/
+
+static OSErr VolHasDesktopDB (short vRefNum, Boolean *hasDesktop)
+{
+ HParamBlockRec pb;
+ GetVolParmsInfoBuffer info;
+ OSErr err = noErr;
+
+ pb.ioParam.ioCompletion = nil;
+ pb.ioParam.ioNamePtr = nil;
+ pb.ioParam.ioVRefNum = vRefNum;
+ pb.ioParam.ioBuffer = (Ptr)&info;
+ pb.ioParam.ioReqCount = sizeof(info);
+ err = PBHGetVolParmsSync(&pb);
+ *hasDesktop = err == noErr && (info.vMAttrib & (1L << bHasDesktopMgr)) != 0;
+ return err;
+}
+
+
+/*----------------------------------------------------------------------------
+ GetLastModDateTime
+
+ Get the last mod date and time of a file.
+
+ Entry: fSpec = pointer to file spec.
+
+ Exit: function result = error code.
+ *lastModDateTime = last mod date and time.
+----------------------------------------------------------------------------*/
+
+static OSErr GetLastModDateTime(const FSSpec *fSpec, unsigned long *lastModDateTime)
+{
+ CInfoPBRec pBlock;
+ OSErr err = noErr;
+
+ pBlock.hFileInfo.ioNamePtr = (StringPtr)fSpec->name;
+ pBlock.hFileInfo.ioVRefNum = fSpec->vRefNum;
+ pBlock.hFileInfo.ioFDirIndex = 0;
+ pBlock.hFileInfo.ioDirID = fSpec->parID;
+ err = PBGetCatInfoSync(&pBlock);
+ if (err != noErr) return err;
+ *lastModDateTime = pBlock.hFileInfo.ioFlMdDat;
+ return noErr;
+}
+
+
+/*----------------------------------------------------------------------------
+ FindAppOnVolume
+
+ Find an application on a volume.
+
+ Entry: sig = application signature.
+ vRefNum = vol ref num
+
+ Exit: function result = error code
+ = afpItemNotFound if app not found on vol.
+ *file = file spec for application on volume.
+----------------------------------------------------------------------------*/
+
+static OSErr FindAppOnVolume (OSType sig, short vRefNum, FSSpec *file)
+{
+ DTPBRec pb;
+ OSErr err = noErr;
+ short ioDTRefNum, i;
+ FInfo fInfo;
+ FSSpec candidate;
+ unsigned long lastModDateTime, maxLastModDateTime;
+
+ memset(&pb, 0, sizeof(DTPBRec));
+ pb.ioCompletion = nil;
+ pb.ioVRefNum = vRefNum;
+ pb.ioNamePtr = nil;
+ err = PBDTGetPath(&pb);
+ if (err != noErr) return err;
+ ioDTRefNum = pb.ioDTRefNum;
+
+ memset(&pb, 0, sizeof(DTPBRec));
+ pb.ioCompletion = nil;
+ pb.ioIndex = 0;
+ pb.ioFileCreator = sig;
+ pb.ioNamePtr = file->name;
+ pb.ioDTRefNum = ioDTRefNum;
+ err = PBDTGetAPPLSync(&pb);
+
+ if (err == fnfErr || err == paramErr) return afpItemNotFound;
+ if (err != noErr) return err;
+
+ file->vRefNum = vRefNum;
+ file->parID = pb.ioAPPLParID;
+
+ err = FSpGetFInfo(file, &fInfo);
+ if (err == noErr) return noErr;
+
+ i = 1;
+ maxLastModDateTime = 0;
+ while (true)
+ {
+ memset(&pb, 0, sizeof(DTPBRec));
+ pb.ioCompletion = nil;
+ pb.ioIndex = i;
+ pb.ioFileCreator = sig;
+ pb.ioNamePtr = candidate.name;
+ pb.ioDTRefNum = ioDTRefNum;
+ err = PBDTGetAPPLSync(&pb);
+ if (err != noErr) break;
+ candidate.vRefNum = vRefNum;
+ candidate.parID = pb.ioAPPLParID;
+ err = GetLastModDateTime(file, &lastModDateTime);
+ if (err == noErr) {
+ if (lastModDateTime > maxLastModDateTime) {
+ maxLastModDateTime = lastModDateTime;
+ *file = candidate;
+ }
+ }
+ i++;
+ }
+
+ return maxLastModDateTime > 0 ? noErr : afpItemNotFound;
+}
+
+
+/*----------------------------------------------------------------------------
+ GetIndVolume
+
+ Get a volume reference number by volume index.
+
+ Entry: index = volume index
+
+ Exit: function result = error code.
+ *vRefNum = vol ref num of indexed volume.
+----------------------------------------------------------------------------*/
+
+static OSErr GetIndVolume(short index, short *vRefNum)
+{
+ HParamBlockRec pb;
+ Str63 volumeName;
+ OSErr err = noErr;
+
+ pb.volumeParam.ioCompletion = nil;
+ pb.volumeParam.ioNamePtr = volumeName;
+ pb.volumeParam.ioVolIndex = index;
+
+ err = PBHGetVInfoSync(&pb);
+
+ *vRefNum = pb.volumeParam.ioVRefNum;
+ return err;
+}
+
+
+// Private NSPR functions
+static unsigned long gJanuaryFirst1970Seconds = 0;
+/*
+ * The geographic location and time zone information of a Mac
+ * are stored in extended parameter RAM. The ReadLocation
+ * produdure uses the geographic location record, MachineLocation,
+ * to read the geographic location and time zone information in
+ * extended parameter RAM.
+ *
+ * Because serial port and SLIP conflict with ReadXPram calls,
+ * we cache the call here.
+ *
+ * Caveat: this caching will give the wrong result if a session
+ * extend across the DST changeover time.
+ */
+
+static void MyReadLocation(MachineLocation *loc)
+{
+ static MachineLocation storedLoc;
+ static Boolean didReadLocation = false;
+
+ if (!didReadLocation) {
+ ReadLocation(&storedLoc);
+ didReadLocation = true;
+ }
+ *loc = storedLoc;
+}
+
+static long GMTDelta(void)
+{
+ MachineLocation loc;
+ long gmtDelta;
+
+ MyReadLocation(&loc);
+ gmtDelta = loc.u.gmtDelta & 0x00ffffff;
+ if (gmtDelta & 0x00800000) { /* test sign extend bit */
+ gmtDelta |= 0xff000000;
+ }
+ return gmtDelta;
+}
+
+static void MacintoshInitializeTime(void)
+{
+ /*
+ * The NSPR epoch is midnight, Jan. 1, 1970 GMT.
+ *
+ * At midnight Jan. 1, 1970 GMT, the local time was
+ * midnight Jan. 1, 1970 + GMTDelta().
+ *
+ * Midnight Jan. 1, 1970 is 86400 * (365 * (1970 - 1904) + 17)
+ * = 2082844800 seconds since the Mac epoch.
+ * (There were 17 leap years from 1904 to 1970.)
+ *
+ * So the NSPR epoch is 2082844800 + GMTDelta() seconds since
+ * the Mac epoch. Whew! :-)
+ */
+ gJanuaryFirst1970Seconds = 2082844800 + GMTDelta();
+}
+
+static nsresult ConvertMacTimeToMilliseconds( PRInt64* aLastModifiedTime, PRUint32 timestamp )
+{
+ if ( gJanuaryFirst1970Seconds == 0)
+ MacintoshInitializeTime();
+ timestamp -= gJanuaryFirst1970Seconds;
+ PRTime usecPerSec, dateInMicroSeconds;
+ LL_I2L(dateInMicroSeconds, timestamp);
+ LL_I2L(usecPerSec, PR_MSEC_PER_SEC);
+ LL_MUL(*aLastModifiedTime, usecPerSec, dateInMicroSeconds);
+ return NS_OK;
+}
+
+static nsresult ConvertMillisecondsToMacTime(PRInt64 aTime, PRUint32 *aOutMacTime)
+{
+ NS_ENSURE_ARG( aOutMacTime );
+
+ PRTime usecPerSec, dateInSeconds;
+ dateInSeconds = LL_ZERO;
+
+ LL_I2L(usecPerSec, PR_MSEC_PER_SEC);
+ LL_DIV(dateInSeconds, aTime, usecPerSec); // dateInSeconds = aTime/1,000
+ LL_L2UI(*aOutMacTime, dateInSeconds);
+ *aOutMacTime += 2082844800; // date + Mac epoch
+
+ return NS_OK;
+}
+
+static void myPLstrcpy(Str255 dst, const char* src)
+{
+ int srcLength = strlen(src);
+ NS_ASSERTION(srcLength <= 255, "Oops, Str255 can't hold >255 chars");
+ if (srcLength > 255)
+ srcLength = 255;
+ dst[0] = srcLength;
+ memcpy(&dst[1], src, srcLength);
+}
+
+static void myPLstrncpy(Str255 dst, const char* src, int inMax)
+{
+ int srcLength = strlen(src);
+ if (srcLength > inMax)
+ srcLength = inMax;
+ dst[0] = srcLength;
+ memcpy(&dst[1], src, srcLength);
+}
+
+/*
+ NS_TruncNodeName
+
+ Utility routine to do a mid-trunc on a potential file name so that it is
+ no longer than 31 characters. Until we move to the HFS+ APIs we need this
+ to come up with legal Mac file names.
+
+ Entry: aNode = initial file name
+ outBuf = scratch buffer for the truncated name (MUST be >= 32 characters)
+
+ Exit: function result = pointer to truncated name. Will be either aNode or outBuf.
+
+*/
+const char* NS_TruncNodeName(const char *aNode, char *outBuf)
+{
+ PRUint32 nodeLen;
+ if ((nodeLen = strlen(aNode)) > 31)
+ {
+ static PRBool sInitialized = PR_FALSE;
+ static CharByteTable sTable;
+ // Init to "..." in case we fail to get the ellipsis token
+ static char sEllipsisTokenStr[4] = { '.', '.', '.', 0 };
+ static PRUint8 sEllipsisTokenLen = 3;
+
+ if (!sInitialized)
+ {
+ // Entries in the table are:
+ // 0 == 1 byte char
+ // 1 == 2 byte char
+ FillParseTable(sTable, smSystemScript);
+
+ Handle itl4ResHandle = nsnull;
+ long offset, len;
+ ::GetIntlResourceTable(smSystemScript, smUnTokenTable, &itl4ResHandle, &offset, &len);
+ if (itl4ResHandle)
+ {
+ UntokenTable *untokenTableRec = (UntokenTable *)(*itl4ResHandle + offset);
+ if (untokenTableRec->lastToken >= tokenEllipsis)
+ {
+ offset += untokenTableRec->index[tokenEllipsis];
+ char *tokenStr = (*itl4ResHandle + offset);
+ sEllipsisTokenLen = tokenStr[0];
+ memcpy(sEllipsisTokenStr, &tokenStr[1], sEllipsisTokenLen);
+ }
+ ::ReleaseResource(itl4ResHandle);
+ }
+ sInitialized = PR_TRUE;
+ }
+
+ PRInt32 halfLen = (31 - sEllipsisTokenLen) / 2;
+ PRInt32 charSize = 0, srcPos, destPos;
+ for (srcPos = 0; srcPos + charSize <= halfLen; srcPos += charSize)
+ charSize = sTable[aNode[srcPos]] ? 2 : 1;
+
+ memcpy(outBuf, aNode, srcPos);
+ memcpy(outBuf + srcPos, sEllipsisTokenStr, sEllipsisTokenLen);
+ destPos = srcPos + sEllipsisTokenLen;
+
+ for (; srcPos < nodeLen - halfLen; srcPos += charSize)
+ charSize = sTable[aNode[srcPos]] ? 2 : 1;
+
+ memcpy(outBuf + destPos, aNode + srcPos, nodeLen - srcPos);
+ destPos += (nodeLen - srcPos);
+ outBuf[destPos] = '\0';
+ return outBuf;
+ }
+ return aNode;
+}
+
+/**
+ * HFSPlusGetRawPath returns the path for an FSSpec as a unicode string.
+ *
+ * The reason for this routine instead of just calling FSRefMakePath is
+ * (1) inSpec does not have to exist
+ * (2) FSRefMakePath uses '/' as the separator under OSX and ':' under OS9
+ */
+static OSErr HFSPlusGetRawPath(const FSSpec& inSpec, nsAString& outStr)
+{
+ OSErr err;
+ nsAutoString ucPathString;
+
+ outStr.Truncate(0);
+
+ FSRef nodeRef;
+ FSCatalogInfo catalogInfo;
+ catalogInfo.parentDirID = 0;
+ err = ::FSpMakeFSRef(&inSpec, &nodeRef);
+
+ if (err == fnfErr) {
+ FSSpec parentDirSpec;
+ err = GetParentFolderSpec(inSpec, parentDirSpec);
+ if (err == noErr) {
+ const char *startPtr = (const char*)&inSpec.name[1];
+ NS_CopyNativeToUnicode(Substring(startPtr, startPtr + PRUint32(inSpec.name[0])), outStr);
+ err = ::FSpMakeFSRef(&parentDirSpec, &nodeRef);
+ }
+ }
+
+ while (err == noErr && catalogInfo.parentDirID != fsRtParID) {
+ HFSUniStr255 nodeName;
+ FSRef parentRef;
+ err = ::FSGetCatalogInfo(&nodeRef,
+ kFSCatInfoNodeFlags + kFSCatInfoParentDirID,
+ &catalogInfo,
+ &nodeName,
+ nsnull,
+ &parentRef);
+ if (err == noErr)
+ {
+ if (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask)
+ nodeName.unicode[nodeName.length++] = PRUnichar(':');
+ const PRUnichar* nodeNameUni = (const PRUnichar*) nodeName.unicode;
+ outStr.Insert(Substring(nodeNameUni, nodeNameUni + nodeName.length), 0);
+ nodeRef = parentRef;
+ }
+ }
+ return err;
+}
+
+
+// The R**co FSSpec resolver -
+// it slices, it dices, it juliannes fries and it even creates FSSpecs out of whatever you feed it
+// This function will take a path and a starting FSSpec and generate a FSSpec to represent
+// the target of the two. If the intial FSSpec is null the path alone will be resolved
+static OSErr ResolvePathAndSpec(const char * filePath, FSSpec *inSpec, PRBool createDirs, FSSpec *outSpec)
+{
+ OSErr err = noErr;
+ size_t inLength = strlen(filePath);
+ Boolean isRelative = (filePath && inSpec);
+ FSSpec tempSpec;
+ Str255 ppath;
+ Boolean isDirectory;
+
+ if (isRelative && inSpec)
+ {
+ outSpec->vRefNum = inSpec->vRefNum;
+ outSpec->parID = inSpec->parID;
+
+ if (inSpec->name[0] != 0)
+ {
+ long theDirID;
+
+ err = FSpGetDirectoryID(inSpec, &theDirID, &isDirectory);
+
+ if (err == noErr && isDirectory)
+ outSpec->parID = theDirID;
+ else if (err == fnfErr && createDirs)
+ {
+ err = FSpDirCreate(inSpec, smCurrentScript, &theDirID);
+ if (err == noErr)
+ outSpec->parID = theDirID;
+ else if (err == fnfErr)
+ err = dirNFErr;
+ }
+ }
+ }
+ else
+ {
+ outSpec->vRefNum = 0;
+ outSpec->parID = 0;
+ }
+
+ if (err)
+ return err;
+
+ // Try making an FSSpec from the path
+ if (inLength < 255)
+ {
+ // Use tempSpec as dest because if FSMakeFSSpec returns dirNFErr, it
+ // will reset the dest spec and we'll lose what we determined above.
+
+ myPLstrcpy(ppath, filePath);
+ err = ::FSMakeFSSpec(outSpec->vRefNum, outSpec->parID, ppath, &tempSpec);
+ if (err == noErr || err == fnfErr)
+ *outSpec = tempSpec;
+ }
+ else if (!isRelative)
+ {
+ err = ::FSpLocationFromFullPath(inLength, filePath, outSpec);
+ }
+ else
+ { // If the path is relative and >255 characters we need to manually walk the
+ // path appending each node to the initial FSSpec so to reach that code we
+ // set the err to bdNamErr and fall into the code below
+ err = bdNamErr;
+ }
+
+ // If we successfully created a spec then leave
+ if (err == noErr)
+ return err;
+
+ // We get here when the directory hierarchy needs to be created or we're resolving
+ // a relative path >255 characters long
+ if (err == dirNFErr || err == bdNamErr)
+ {
+ const char* path = filePath;
+
+ if (!isRelative) // If path is relative, we still need vRefNum & parID.
+ {
+ outSpec->vRefNum = 0;
+ outSpec->parID = 0;
+ }
+
+ do
+ {
+ // Locate the colon that terminates the node.
+ // But if we've a partial path (starting with a colon), find the second one.
+ const char* nextColon = strchr(path + (*path == ':'), ':');
+ // Well, if there are no more colons, point to the end of the string.
+ if (!nextColon)
+ nextColon = path + strlen(path);
+
+ // Make a pascal string out of this node. Include initial
+ // and final colon, if any!
+ myPLstrncpy(ppath, path, nextColon - path + 1);
+
+ // Use this string as a relative path using the directory created
+ // on the previous round (or directory 0,0 on the first round).
+ err = ::FSMakeFSSpec(outSpec->vRefNum, outSpec->parID, ppath, outSpec);
+
+ // If this was the leaf node, then we are done.
+ if (!*nextColon)
+ break;
+
+ // Since there's more to go, we have to get the directory ID, which becomes
+ // the parID for the next round.
+ if (err == noErr)
+ {
+ // The directory (or perhaps a file) exists. Find its dirID.
+ long dirID;
+ err = ::FSpGetDirectoryID(outSpec, &dirID, &isDirectory);
+ if (!isDirectory)
+ err = dupFNErr; // oops! a file exists with that name.
+ if (err != noErr)
+ break; // bail if we've got an error
+ outSpec->parID = dirID;
+ }
+ else if ((err == fnfErr) && createDirs)
+ {
+ // If we got "file not found" and we're allowed to create directories
+ // then we need to create one
+ err = ::FSpDirCreate(outSpec, smCurrentScript, &outSpec->parID);
+ // For some reason, this usually returns fnfErr, even though it works.
+ if (err == fnfErr)
+ err = noErr;
+ }
+ if (err != noErr)
+ break;
+ path = nextColon; // next round
+ } while (true);
+ }
+
+ return err;
+}
+
+
+#pragma mark -
+#pragma mark [StFollowLinksState]
+class StFollowLinksState
+{
+ public:
+ StFollowLinksState(nsILocalFile *aFile) :
+ mFile(aFile)
+ {
+ NS_ASSERTION(mFile, "StFollowLinksState passed a NULL file.");
+ if (mFile)
+ mFile->GetFollowLinks(&mSavedState);
+ }
+
+ StFollowLinksState(nsILocalFile *aFile, PRBool followLinksState) :
+ mFile(aFile)
+ {
+ NS_ASSERTION(mFile, "StFollowLinksState passed a NULL file.");
+ if (mFile) {
+ mFile->GetFollowLinks(&mSavedState);
+ mFile->SetFollowLinks(followLinksState);
+ }
+ }
+
+ ~StFollowLinksState()
+ {
+ if (mFile)
+ mFile->SetFollowLinks(mSavedState);
+ }
+
+ private:
+ nsCOMPtr<nsILocalFile> mFile;
+ PRBool mSavedState;
+};
+
+#pragma mark -
+#pragma mark [nsDirEnumerator]
+class nsDirEnumerator : public nsISimpleEnumerator
+{
+ public:
+
+ NS_DECL_ISUPPORTS
+
+ nsDirEnumerator()
+ {
+ }
+
+ nsresult Init(nsILocalFileMac* parent)
+ {
+ NS_ENSURE_ARG(parent);
+ nsresult rv;
+ FSSpec fileSpec;
+
+ rv = parent->GetFSSpec(&fileSpec);
+ if (NS_FAILED(rv))
+ return rv;
+
+ OSErr err;
+ Boolean isDirectory;
+
+ err = ::FSpGetDirectoryID(&fileSpec, &mDirID, &isDirectory);
+ if (err || !isDirectory)
+ return NS_ERROR_FILE_NOT_DIRECTORY;
+
+ mCatInfo.hFileInfo.ioNamePtr = mItemName;
+ mCatInfo.hFileInfo.ioVRefNum = fileSpec.vRefNum;
+ mItemIndex = 1;
+
+ return NS_OK;
+ }
+
+ NS_IMETHOD HasMoreElements(PRBool *result)
+ {
+ nsresult rv = NS_OK;
+ if (mNext == nsnull)
+ {
+ mItemName[0] = 0;
+ mCatInfo.dirInfo.ioFDirIndex = mItemIndex;
+ mCatInfo.dirInfo.ioDrDirID = mDirID;
+
+ OSErr err = ::PBGetCatInfoSync(&mCatInfo);
+ if (err == fnfErr)
+ {
+ // end of dir entries
+ *result = PR_FALSE;
+ return NS_OK;
+ }
+
+ // Make a new nsILocalFile for the new element
+ FSSpec tempSpec;
+ tempSpec.vRefNum = mCatInfo.hFileInfo.ioVRefNum;
+ tempSpec.parID = mDirID;
+ ::BlockMoveData(mItemName, tempSpec.name, mItemName[0] + 1);
+
+ rv = NS_NewLocalFileWithFSSpec(&tempSpec, PR_TRUE, getter_AddRefs(mNext));
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ *result = mNext != nsnull;
+ return NS_OK;
+ }
+
+ NS_IMETHOD GetNext(nsISupports **result)
+ {
+ NS_ENSURE_ARG_POINTER(result);
+ *result = nsnull;
+
+ nsresult rv;
+ PRBool hasMore;
+ rv = HasMoreElements(&hasMore);
+ if (NS_FAILED(rv)) return rv;
+
+ *result = mNext; // might return nsnull
+ NS_IF_ADDREF(*result);
+
+ mNext = nsnull;
+ ++mItemIndex;
+ return NS_OK;
+ }
+
+ private:
+ ~nsDirEnumerator() {}
+
+ protected:
+ nsCOMPtr<nsILocalFileMac> mNext;
+
+ CInfoPBRec mCatInfo;
+ short mItemIndex;
+ long mDirID;
+ Str63 mItemName;
+};
+
+NS_IMPL_ISUPPORTS1(nsDirEnumerator, nsISimpleEnumerator)
+
+#pragma mark -
+
+OSType nsLocalFile::sCurrentProcessSignature = 0;
+PRBool nsLocalFile::sHasHFSPlusAPIs = PR_FALSE;
+PRBool nsLocalFile::sRunningOSX = PR_FALSE;
+
+#pragma mark [CTOR/DTOR]
+nsLocalFile::nsLocalFile() :
+ mFollowLinks(PR_TRUE),
+ mFollowLinksDirty(PR_TRUE),
+ mSpecDirty(PR_TRUE),
+ mCatInfoDirty(PR_TRUE),
+ mType('TEXT'),
+ mCreator(kDefaultCreator)
+{
+ ClearFSSpec(mSpec);
+ ClearFSSpec(mTargetSpec);
+
+ InitClassStatics();
+ if (sCurrentProcessSignature != 0)
+ mCreator = sCurrentProcessSignature;
+}
+
+nsLocalFile::nsLocalFile(const nsLocalFile& srcFile)
+{
+ *this = srcFile;
+}
+
+nsLocalFile::nsLocalFile(const FSSpec& aSpec, const nsACString& aAppendedPath) :
+ mFollowLinks(PR_TRUE),
+ mFollowLinksDirty(PR_TRUE),
+ mSpecDirty(PR_TRUE),
+ mSpec(aSpec),
+ mAppendedPath(aAppendedPath),
+ mCatInfoDirty(PR_TRUE),
+ mType('TEXT'),
+ mCreator(kDefaultCreator)
+{
+ ClearFSSpec(mTargetSpec);
+
+ InitClassStatics();
+ if (sCurrentProcessSignature != 0)
+ mCreator = sCurrentProcessSignature;
+}
+
+nsLocalFile& nsLocalFile::operator=(const nsLocalFile& rhs)
+{
+ mFollowLinks = rhs.mFollowLinks;
+ mFollowLinksDirty = rhs.mFollowLinksDirty;
+ mSpecDirty = rhs.mSpecDirty;
+ mSpec = rhs.mSpec;
+ mAppendedPath = rhs.mAppendedPath;
+ mTargetSpec = rhs.mTargetSpec;
+ mCatInfoDirty = rhs.mCatInfoDirty;
+ mType = rhs.mType;
+ mCreator = rhs.mCreator;
+
+ if (!rhs.mCatInfoDirty)
+ mCachedCatInfo = rhs.mCachedCatInfo;
+
+ return *this;
+}
+
+#pragma mark -
+#pragma mark [nsISupports interface implementation]
+
+NS_IMPL_THREADSAFE_ISUPPORTS3(nsLocalFile,
+ nsILocalFileMac,
+ nsILocalFile,
+ nsIFile)
+
+NS_METHOD
+nsLocalFile::nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
+{
+ NS_ENSURE_ARG_POINTER(aInstancePtr);
+ NS_ENSURE_NO_AGGREGATION(outer);
+
+ nsLocalFile* inst = new nsLocalFile();
+ if (inst == NULL)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = inst->QueryInterface(aIID, aInstancePtr);
+ if (NS_FAILED(rv))
+ {
+ delete inst;
+ return rv;
+ }
+ return NS_OK;
+}
+
+// This function resets any cached information about the file.
+void
+nsLocalFile::MakeDirty()
+{
+ mSpecDirty = PR_TRUE;
+ mFollowLinksDirty = PR_TRUE;
+ mCatInfoDirty = PR_TRUE;
+
+ ClearFSSpec(mTargetSpec);
+}
+
+
+/* attribute PRBool followLinks; */
+NS_IMETHODIMP
+nsLocalFile::GetFollowLinks(PRBool *aFollowLinks)
+{
+ NS_ENSURE_ARG_POINTER(aFollowLinks);
+ *aFollowLinks = mFollowLinks;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetFollowLinks(PRBool aFollowLinks)
+{
+ if (aFollowLinks != mFollowLinks)
+ {
+ mFollowLinks = aFollowLinks;
+ mFollowLinksDirty = PR_TRUE;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::ResolveAndStat()
+{
+ OSErr err = noErr;
+ FSSpec resolvedSpec;
+
+ // fnfErr means target spec is valid but doesn't exist.
+ // If the end result is fnfErr, we're cleanly resolved.
+
+ if (mSpecDirty)
+ {
+ if (mAppendedPath.Length())
+ {
+ err = ResolvePathAndSpec(mAppendedPath.get(), &mSpec, PR_FALSE, &resolvedSpec);
+ if (err == noErr)
+ mAppendedPath.Truncate(0);
+ }
+ else
+ err = ::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, mSpec.name, &resolvedSpec);
+ if (err == noErr)
+ {
+ mSpec = resolvedSpec;
+ mSpecDirty = PR_FALSE;
+ }
+ mFollowLinksDirty = PR_TRUE;
+ }
+ if (mFollowLinksDirty && (err == noErr))
+ {
+ if (mFollowLinks)
+ {
+ // Resolve the alias to the original file.
+ resolvedSpec = mSpec;
+ Boolean resolvedWasFolder, resolvedWasAlias;
+ err = ::ResolveAliasFile(&resolvedSpec, TRUE, &resolvedWasFolder, &resolvedWasAlias);
+ if (err == noErr || err == fnfErr) {
+ err = noErr;
+ mTargetSpec = resolvedSpec;
+ mFollowLinksDirty = PR_FALSE;
+ }
+ }
+ else
+ {
+ mTargetSpec = mSpec;
+ mFollowLinksDirty = PR_FALSE;
+ }
+ mCatInfoDirty = PR_TRUE;
+ }
+
+ return (MacErrorMapper(err));
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::Clone(nsIFile **file)
+{
+ // Just copy-construct ourselves
+ *file = new nsLocalFile(*this);
+ if (!*file)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(*file);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::InitWithNativePath(const nsACString &filePath)
+{
+ // The incoming path must be a FULL path
+
+ if (filePath.IsEmpty())
+ return NS_ERROR_INVALID_ARG;
+
+ MakeDirty();
+
+ // If it starts with a colon, it's invalid
+ if (filePath.First() == ':')
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ nsPathParser parser(filePath);
+ OSErr err;
+ Str255 pascalNode;
+ FSSpec nodeSpec;
+
+ const char *root = parser.First();
+ if (root == nsnull)
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ // The first component must be an existing volume
+ myPLstrcpy(pascalNode, root);
+ pascalNode[++pascalNode[0]] = ':';
+ err = ::FSMakeFSSpec(0, 0, pascalNode, &nodeSpec);
+ if (err)
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ // Build as much of a spec as possible from the rest of the path
+ // What doesn't exist will be left over in mAppendedPath
+ const char *nextNode;
+ while ((nextNode = parser.Next()) != nsnull) {
+ long dirID;
+ Boolean isDir;
+ err = ::FSpGetDirectoryID(&nodeSpec, &dirID, &isDir);
+ if (err || !isDir)
+ break;
+ myPLstrcpy(pascalNode, nextNode);
+ err = ::FSMakeFSSpec(nodeSpec.vRefNum, dirID, pascalNode, &nodeSpec);
+ if (err == fnfErr)
+ break;
+ }
+ mSpec = nodeSpec;
+ mAppendedPath = parser.Remainder();
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::InitWithPath(const nsAString &filePath)
+{
+ nsresult rv;
+ nsCAutoString fsStr;
+
+ if (NS_SUCCEEDED(rv = NS_CopyUnicodeToNative(filePath, fsStr)))
+ rv = InitWithNativePath(fsStr);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::InitWithFile(nsILocalFile *aFile)
+{
+ NS_ENSURE_ARG(aFile);
+ nsLocalFile *asLocalFile = dynamic_cast<nsLocalFile*>(aFile);
+ if (!asLocalFile)
+ return NS_ERROR_NO_INTERFACE; // Well, sort of.
+ *this = *asLocalFile;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::OpenNSPRFileDesc(PRInt32 flags, PRInt32 mode, PRFileDesc **_retval)
+{
+// Macintosh doesn't really have mode bits, just drop them
+#pragma unused (mode)
+
+ NS_ENSURE_ARG(_retval);
+
+ nsresult rv = NS_OK;
+ FSSpec spec;
+ OSErr err = noErr;
+
+ rv = ResolveAndStat();
+ if (rv == NS_ERROR_FILE_NOT_FOUND && (flags & PR_CREATE_FILE))
+ rv = NS_OK;
+
+ if (flags & PR_CREATE_FILE) {
+ rv = Create(nsIFile::NORMAL_FILE_TYPE, 0);
+ /* If opening with the PR_EXCL flag the existence of the file prior to opening is an error */
+ if ((flags & PR_EXCL) && (rv == NS_ERROR_FILE_ALREADY_EXISTS))
+ return rv;
+ }
+
+ rv = GetFSSpec(&spec);
+ if (NS_FAILED(rv))
+ return rv;
+
+ SInt8 perm;
+ if (flags & PR_RDWR)
+ perm = fsRdWrPerm;
+ else if (flags & PR_WRONLY)
+ perm = fsWrPerm;
+ else
+ perm = fsRdPerm;
+
+ short refnum;
+ err = ::FSpOpenDF(&spec, perm, &refnum);
+
+ if (err == noErr && (flags & PR_TRUNCATE))
+ err = ::SetEOF(refnum, 0);
+ if (err == noErr && (flags & PR_APPEND))
+ err = ::SetFPos(refnum, fsFromLEOF, 0);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ if ((*_retval = PR_ImportFile(refnum)) == 0)
+ return NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES,(PR_GetError() & 0xFFFF));
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::OpenANSIFileDesc(const char *mode, FILE * *_retval)
+{
+ NS_ENSURE_ARG(mode);
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ nsresult rv;
+ FSSpec spec;
+
+ rv = ResolveAndStat();
+ if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
+ return rv;
+
+ if (mode[0] == 'w' || mode[0] == 'a') // Create if it doesn't exist
+ {
+ if (rv == NS_ERROR_FILE_NOT_FOUND) {
+ mType = (mode[1] == 'b') ? 'BiNA' : 'TEXT';
+ rv = Create(nsIFile::NORMAL_FILE_TYPE, 0);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ }
+
+ rv = GetFSSpec(&spec);
+ if (NS_FAILED(rv))
+ return rv;
+
+#ifdef MACOSX
+ // FSp_fopen() doesn't exist under macosx :-(
+ nsXPIDLCString ourPath;
+ rv = GetPath(getter_Copies(ourPath));
+ if (NS_FAILED(rv))
+ return rv;
+ *_retval = fopen(ourPath, mode);
+#else
+ *_retval = FSp_fopen(&spec, mode);
+#endif
+
+ if (*_retval)
+ return NS_OK;
+
+ return NS_ERROR_FAILURE;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::Create(PRUint32 type, PRUint32 attributes)
+{
+ OSErr err;
+
+ if (type != NORMAL_FILE_TYPE && type != DIRECTORY_TYPE)
+ return NS_ERROR_FILE_UNKNOWN_TYPE;
+
+ FSSpec newSpec;
+
+ if (mAppendedPath.Length())
+ { // We've got an FSSpec and an appended path so pass 'em both to ResolvePathAndSpec
+ err = ResolvePathAndSpec(mAppendedPath.get(), &mSpec, PR_TRUE, &newSpec);
+ }
+ else
+ {
+ err = ::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, mSpec.name, &newSpec);
+ }
+
+ if (err != noErr && err != fnfErr)
+ return (MacErrorMapper(err));
+
+ switch (type)
+ {
+ case NORMAL_FILE_TYPE:
+ SetOSTypeAndCreatorFromExtension();
+ err = ::FSpCreate(&newSpec, mCreator, mType, smCurrentScript);
+ break;
+
+ case DIRECTORY_TYPE:
+ {
+ long newDirID;
+ err = ::FSpDirCreate(&newSpec, smCurrentScript, &newDirID);
+ // For some reason, this usually returns fnfErr, even though it works.
+ if (err == fnfErr)
+ err = noErr;
+ }
+ break;
+
+ default:
+ return NS_ERROR_FILE_UNKNOWN_TYPE;
+ break;
+ }
+
+ if (err == noErr)
+ {
+ mSpec = mTargetSpec = newSpec;
+ mAppendedPath.Truncate(0);
+ }
+
+ return (MacErrorMapper(err));
+}
+
+NS_IMETHODIMP
+nsLocalFile::AppendNative(const nsACString &aNode)
+{
+ if (aNode.IsEmpty())
+ return NS_OK;
+
+ nsACString::const_iterator start, end;
+ aNode.BeginReading(start);
+ aNode.EndReading(end);
+ if (FindCharInReadable(':', start, end))
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ MakeDirty();
+
+ char truncBuffer[32];
+ const char *node = NS_TruncNodeName(PromiseFlatCString(aNode).get(), truncBuffer);
+
+ if (!mAppendedPath.Length())
+ {
+ OSErr err;
+ Boolean resolvedWasFolder, resolvedWasAlias;
+ err = ::ResolveAliasFile(&mSpec, TRUE, &resolvedWasFolder, &resolvedWasAlias);
+ if (err == noErr)
+ {
+ long dirID;
+ Boolean isDir;
+
+ if (!resolvedWasFolder)
+ return NS_ERROR_FILE_NOT_DIRECTORY;
+ if ((err = ::FSpGetDirectoryID(&mSpec, &dirID, &isDir)) != noErr)
+ return MacErrorMapper(err);
+
+ FSSpec childSpec;
+ Str255 pascalNode;
+ myPLstrcpy(pascalNode, node);
+ err = ::FSMakeFSSpec(mSpec.vRefNum, dirID, pascalNode, &childSpec);
+ if (err && err != fnfErr)
+ return MacErrorMapper(err);
+ mSpec = childSpec;
+ }
+ else if (err == fnfErr)
+ mAppendedPath.Assign(node);
+ else
+ return MacErrorMapper(err);
+ }
+ else
+ {
+ if (mAppendedPath.First() != ':')
+ mAppendedPath.Insert(':', 0);
+ mAppendedPath.Append(":");
+ mAppendedPath.Append(node);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Append(const nsAString &node)
+{
+ nsresult rv;
+ nsCAutoString fsStr;
+
+ if (NS_SUCCEEDED(rv = NS_CopyUnicodeToNative(node, fsStr)))
+ rv = AppendNative(fsStr);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::AppendRelativeNativePath(const nsACString &relPath)
+{
+ if (relPath.IsEmpty())
+ return NS_ERROR_INVALID_ARG;
+
+ nsresult rv;
+ nsPathParser parser(relPath);
+ const char* node = parser.First();
+
+ while (node)
+ {
+ if (NS_FAILED(rv = AppendNative(nsDependentCString(node))))
+ return rv;
+ node = parser.Next();
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::AppendRelativePath(const nsAString &relPath)
+{
+ nsresult rv;
+ nsCAutoString fsStr;
+
+ if (NS_SUCCEEDED(rv = NS_CopyUnicodeToNative(relPath, fsStr)))
+ rv = AppendRelativeNativePath(fsStr);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetNativeLeafName(nsACString &aLeafName)
+{
+ aLeafName.Truncate();
+
+ // See if we've had a path appended
+ if (mAppendedPath.Length())
+ {
+ const char* temp = mAppendedPath.get();
+ if (temp == nsnull)
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ const char* leaf = strrchr(temp, ':');
+
+ // if the working path is just a node without any directory delimeters.
+ if (leaf == nsnull)
+ leaf = temp;
+ else
+ leaf++;
+
+ aLeafName = leaf;
+ }
+ else
+ {
+ // We don't have an appended path so grab the leaf name from the FSSpec
+ // Convert the Pascal string to a C string
+ PRInt32 len = mSpec.name[0];
+ char* leafName = (char *)malloc(len + 1);
+ if (!leafName) return NS_ERROR_OUT_OF_MEMORY;
+ ::BlockMoveData(&mSpec.name[1], leafName, len);
+ leafName[len] = '\0';
+ aLeafName = leafName;
+ free(leafName);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetLeafName(nsAString &aLeafName)
+{
+ nsresult rv;
+ nsCAutoString fsStr;
+
+ if (NS_SUCCEEDED(rv = GetNativeLeafName(fsStr)))
+ rv = NS_CopyNativeToUnicode(fsStr, aLeafName);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetNativeLeafName(const nsACString &aLeafName)
+{
+ if (aLeafName.IsEmpty())
+ return NS_ERROR_INVALID_ARG;
+
+ MakeDirty();
+
+ char truncBuffer[32];
+ const char *leafName = NS_TruncNodeName(PromiseFlatCString(aLeafName).get(), truncBuffer);
+
+ if (mAppendedPath.Length())
+ { // Lop off the end of the appended path and replace it with the new leaf name
+ PRInt32 offset = mAppendedPath.RFindChar(':');
+ if (offset || ((!offset) && (1 < mAppendedPath.Length())))
+ {
+ mAppendedPath.Truncate(offset + 1);
+ }
+ mAppendedPath.Append(leafName);
+ }
+ else
+ {
+ // We don't have an appended path so directly modify the FSSpec
+ myPLstrcpy(mSpec.name, leafName);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetLeafName(const nsAString &aLeafName)
+{
+ nsresult rv;
+ nsCAutoString fsStr;
+
+ if (NS_SUCCEEDED(rv = NS_CopyUnicodeToNative(aLeafName, fsStr)))
+ rv = SetNativeLeafName(fsStr);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetNativePath(nsACString &_retval)
+{
+ _retval.Truncate();
+
+ nsCAutoString fsCharSetPathStr;
+
+#if TARGET_CARBON
+ if (sHasHFSPlusAPIs) // should always be true under Carbon, but in case...
+ {
+ OSErr err;
+ nsresult rv;
+ nsAutoString ucPathString;
+
+ if ((err = HFSPlusGetRawPath(mSpec, ucPathString)) != noErr)
+ return MacErrorMapper(err);
+ rv = NS_CopyUnicodeToNative(ucPathString, fsCharSetPathStr);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ else
+#endif
+ {
+ // Now would be a good time to call the code that makes an FSSpec into a path
+ short fullPathLen;
+ Handle fullPathHandle;
+ (void)::FSpGetFullPath(&mSpec, &fullPathLen, &fullPathHandle);
+ if (!fullPathHandle)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ ::HLock(fullPathHandle);
+ fsCharSetPathStr.Assign(*fullPathHandle, fullPathLen);
+ ::DisposeHandle(fullPathHandle);
+ }
+
+ // We need to make sure that even if we have a path to a
+ // directory we don't return the trailing colon. It breaks
+ // the component manager. (Bugzilla bug #26102)
+ if (fsCharSetPathStr.Last() == ':')
+ fsCharSetPathStr.Truncate(fsCharSetPathStr.Length() - 1);
+
+ // Now, tack on mAppendedPath. It never ends in a colon.
+ if (mAppendedPath.Length())
+ {
+ if (mAppendedPath.First() != ':')
+ fsCharSetPathStr.Append(":");
+ fsCharSetPathStr.Append(mAppendedPath);
+ }
+
+ _retval = fsCharSetPathStr;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPath(nsAString &_retval)
+{
+ nsresult rv = NS_OK;
+
+#if TARGET_CARBON
+ if (sHasHFSPlusAPIs) // should always be true under Carbon, but in case...
+ {
+ OSErr err;
+ nsAutoString ucPathString;
+
+ if ((err = HFSPlusGetRawPath(mSpec, ucPathString)) != noErr)
+ return MacErrorMapper(err);
+
+ // We need to make sure that even if we have a path to a
+ // directory we don't return the trailing colon. It breaks
+ // the component manager. (Bugzilla bug #26102)
+ if (ucPathString.Last() == PRUnichar(':'))
+ ucPathString.Truncate(ucPathString.Length() - 1);
+
+ // Now, tack on mAppendedPath. It never ends in a colon.
+ if (mAppendedPath.Length())
+ {
+ nsAutoString ucAppendage;
+ if (mAppendedPath.First() != ':')
+ ucPathString.Append(PRUnichar(':'));
+ rv = NS_CopyNativeToUnicode(mAppendedPath, ucAppendage);
+ if (NS_FAILED(rv))
+ return rv;
+ ucPathString.Append(ucAppendage);
+ }
+
+ _retval = ucPathString;
+ }
+ else
+#endif
+ {
+ nsCAutoString fsStr;
+
+ if (NS_SUCCEEDED(rv = GetNativePath(fsStr))) {
+ rv = NS_CopyNativeToUnicode(fsStr, _retval);
+ }
+ }
+ return rv;
+}
+
+nsresult nsLocalFile::MoveCopy( nsIFile* newParentDir, const nsACString &newName, PRBool isCopy, PRBool followLinks )
+{
+ OSErr macErr;
+ FSSpec srcSpec;
+ Str255 newPascalName;
+ nsresult rv;
+
+ StFollowLinksState srcFollowState(this, followLinks);
+ rv = GetFSSpec(&srcSpec);
+ if ( NS_FAILED( rv ) )
+ return rv;
+
+ // If newParentDir == nsnull, it's a simple rename
+ if ( !newParentDir )
+ {
+ myPLstrncpy( newPascalName, PromiseFlatCString(newName).get(), 255 );
+ macErr = ::FSpRename( &srcSpec, newPascalName );
+ return MacErrorMapper( macErr );
+ }
+
+ nsCOMPtr<nsILocalFileMac> destDir(do_QueryInterface( newParentDir ));
+ StFollowLinksState destFollowState(destDir, followLinks);
+ FSSpec destSpec;
+ rv = destDir->GetFSSpec(&destSpec);
+ if ( NS_FAILED( rv ) )
+ return rv;
+
+ long dirID;
+ Boolean isDirectory;
+ macErr = ::FSpGetDirectoryID(&destSpec, &dirID, &isDirectory);
+ if ( macErr || !isDirectory )
+ return NS_ERROR_FILE_DESTINATION_NOT_DIR;
+
+ if ( !newName.IsEmpty() )
+ myPLstrncpy( newPascalName, PromiseFlatCString(newName).get(), 255);
+ else
+ memcpy(newPascalName, srcSpec.name, srcSpec.name[0] + 1);
+ if ( isCopy )
+ {
+ macErr = ::FSpGetDirectoryID(&srcSpec, &dirID, &isDirectory);
+ if (macErr == noErr)
+ {
+ const PRInt32 kCopyBufferSize = (1024 * 512); // allocate our own buffer to speed file copies. Bug #103202
+ OSErr tempErr;
+ Handle copyBufferHand = ::TempNewHandle(kCopyBufferSize, &tempErr);
+ void* copyBuffer = nsnull;
+ PRInt32 copyBufferSize = 0;
+
+ // it's OK if the allocated failed; FSpFileCopy will just fall back on its own internal 16k buffer
+ if (copyBufferHand)
+ {
+ ::HLock(copyBufferHand);
+ copyBuffer = *copyBufferHand;
+ copyBufferSize = kCopyBufferSize;
+ }
+
+ if ( isDirectory )
+ macErr = MacFSpDirectoryCopyRename( &srcSpec, &destSpec, newPascalName, copyBuffer, copyBufferSize, true, NULL );
+ else
+ macErr = ::FSpFileCopy( &srcSpec, &destSpec, newPascalName, copyBuffer, copyBufferSize, true );
+
+ if (copyBufferHand)
+ ::DisposeHandle(copyBufferHand);
+ }
+ }
+ else
+ {
+ macErr= ::FSpMoveRenameCompat(&srcSpec, &destSpec, newPascalName);
+ if ( macErr == diffVolErr)
+ {
+ // On a different Volume so go for Copy and then delete
+ rv = CopyToNative( newParentDir, newName );
+ if ( NS_FAILED ( rv ) )
+ return rv;
+ return Remove( PR_TRUE );
+ }
+ }
+ return MacErrorMapper( macErr );
+}
+
+NS_IMETHODIMP
+nsLocalFile::CopyToNative(nsIFile *newParentDir, const nsACString &newName)
+{
+ return MoveCopy( newParentDir, newName, PR_TRUE, PR_FALSE );
+}
+
+NS_IMETHODIMP
+nsLocalFile::CopyTo(nsIFile *newParentDir, const nsAString &newName)
+{
+ if (newName.IsEmpty())
+ return CopyToNative(newParentDir, nsCString());
+
+ nsresult rv;
+ nsCAutoString fsStr;
+ if (NS_SUCCEEDED(rv = NS_CopyUnicodeToNative(newName, fsStr)))
+ rv = CopyToNative(newParentDir, fsStr);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::CopyToFollowingLinksNative(nsIFile *newParentDir, const nsACString &newName)
+{
+ return MoveCopy( newParentDir, newName, PR_TRUE, PR_TRUE );
+}
+
+NS_IMETHODIMP
+nsLocalFile::CopyToFollowingLinks(nsIFile *newParentDir, const nsAString &newName)
+{
+ if (newName.IsEmpty())
+ return CopyToFollowingLinksNative(newParentDir, nsCString());
+
+ nsresult rv;
+ nsCAutoString fsStr;
+ if (NS_SUCCEEDED(rv = NS_CopyUnicodeToNative(newName, fsStr)))
+ rv = CopyToFollowingLinksNative(newParentDir, fsStr);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::MoveToNative(nsIFile *newParentDir, const nsACString &newName)
+{
+ return MoveCopy( newParentDir, newName, PR_FALSE, PR_FALSE );
+}
+
+NS_IMETHODIMP
+nsLocalFile::MoveTo(nsIFile *newParentDir, const nsAString &newName)
+{
+ if (newName.IsEmpty())
+ return MoveToNative(newParentDir, nsCString());
+
+ nsresult rv;
+ nsCAutoString fsStr;
+ if (NS_SUCCEEDED(rv = NS_CopyUnicodeToNative(newName, fsStr)))
+ rv = MoveToNative(newParentDir, fsStr);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Load(PRLibrary * *_retval)
+{
+ PRBool isFile;
+ nsresult rv = IsFile(&isFile);
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (! isFile)
+ return NS_ERROR_FILE_IS_DIRECTORY;
+
+ NS_TIMELINE_START_TIMER("PR_LoadLibrary");
+
+#if !TARGET_CARBON
+ // This call to SystemTask is here to give the OS time to grow its
+ // FCB (file control block) list, which it seems to be unable to
+ // do unless we yield some time to the OS. See bugs 64978 & 70543
+ // for the whole story.
+ ::SystemTask();
+#endif
+
+ // Use the new PR_LoadLibraryWithFlags which allows us to use a FSSpec
+ PRLibSpec libSpec;
+ libSpec.type = PR_LibSpec_MacIndexedFragment;
+ libSpec.value.mac_indexed_fragment.fsspec = &mTargetSpec;
+ libSpec.value.mac_indexed_fragment.index = 0;
+ *_retval = PR_LoadLibraryWithFlags(libSpec, 0);
+
+ NS_TIMELINE_STOP_TIMER("PR_LoadLibrary");
+ NS_TIMELINE_MARK_TIMER("PR_LoadLibrary");
+
+ if (*_retval)
+ return NS_OK;
+
+ return NS_ERROR_NULL_POINTER;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Remove(PRBool recursive)
+{
+ OSErr err;
+ nsresult rv;
+ FSSpec specToDelete;
+ PRBool isDir;
+
+ StFollowLinksState(this, PR_FALSE);
+
+ rv = IsDirectory(&isDir); // Calls ResolveAndStat()
+ if (NS_FAILED(rv))
+ return rv;
+ rv = GetFSSpec(&specToDelete);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (isDir && recursive)
+ err = ::DeleteDirectory( specToDelete.vRefNum, specToDelete.parID, specToDelete.name );
+ else
+ err = ::HDelete( specToDelete.vRefNum, specToDelete.parID, specToDelete.name );
+
+ return MacErrorMapper( err );
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetLastModifiedTime(PRInt64 *aLastModifiedTime)
+{
+ NS_ENSURE_ARG(aLastModifiedTime);
+ *aLastModifiedTime = 0;
+
+ nsresult rv = ResolveAndStat();
+ if ( NS_FAILED( rv ) )
+ return rv;
+ rv = UpdateCachedCatInfo(PR_TRUE);
+ if ( NS_FAILED( rv ) )
+ return rv;
+
+ // The mod date is in the same spot for files and dirs.
+ return ConvertMacTimeToMilliseconds( aLastModifiedTime, mCachedCatInfo.hFileInfo.ioFlMdDat );
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetLastModifiedTime(PRInt64 aLastModifiedTime)
+{
+ nsresult rv = ResolveAndStat();
+ if ( NS_FAILED(rv) )
+ return rv;
+
+ PRUint32 macTime = 0;
+ OSErr err = noErr;
+
+ ConvertMillisecondsToMacTime(aLastModifiedTime, &macTime);
+
+ if (NS_SUCCEEDED(rv = UpdateCachedCatInfo(PR_TRUE)))
+ {
+ if (mCachedCatInfo.hFileInfo.ioFlAttrib & ioDirMask)
+ {
+ mCachedCatInfo.dirInfo.ioDrMdDat = macTime;
+ mCachedCatInfo.dirInfo.ioDrParID = mFollowLinks ? mTargetSpec.parID : mSpec.parID;
+ }
+ else
+ {
+ mCachedCatInfo.hFileInfo.ioFlMdDat = macTime;
+ mCachedCatInfo.hFileInfo.ioDirID = mFollowLinks ? mTargetSpec.parID : mSpec.parID;
+ }
+
+ err = ::PBSetCatInfoSync(&mCachedCatInfo);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ }
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetLastModifiedTimeOfLink(PRInt64 *aLastModifiedTime)
+{
+ NS_ENSURE_ARG(aLastModifiedTime);
+
+ nsresult rv;
+ PRBool isLink;
+
+ rv = IsSymlink(&isLink);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!isLink)
+ return NS_ERROR_FAILURE;
+
+ StFollowLinksState followState(this, PR_FALSE);
+ return GetLastModifiedTime(aLastModifiedTime);
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetLastModifiedTimeOfLink(PRInt64 aLastModifiedTime)
+{
+ nsresult rv;
+ PRBool isLink;
+
+ rv = IsSymlink(&isLink);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!isLink)
+ return NS_ERROR_FAILURE;
+
+ StFollowLinksState followState(this, PR_FALSE);
+ return SetLastModifiedTime(aLastModifiedTime);
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::GetFileSize(PRInt64 *aFileSize)
+{
+ NS_ENSURE_ARG(aFileSize);
+ nsresult rv;
+
+ *aFileSize = LL_Zero();
+
+ if (NS_SUCCEEDED(rv = ResolveAndStat()) && NS_SUCCEEDED(rv = UpdateCachedCatInfo(PR_TRUE)))
+ {
+ if (!(mCachedCatInfo.hFileInfo.ioFlAttrib & ioDirMask))
+ {
+ long dataSize = mCachedCatInfo.hFileInfo.ioFlLgLen;
+ long resSize = mCachedCatInfo.hFileInfo.ioFlRLgLen;
+
+ // For now we've only got 32 bits of file size info
+ PRInt64 dataInt64 = LL_Zero();
+ PRInt64 resInt64 = LL_Zero();
+
+ // WARNING!!!!!!
+ //
+ // For now we do NOT add the data and resource fork sizes as there are several
+ // assumptions in the code (notably in form submit) that only the data fork is
+ // used.
+ // LL_I2L(resInt64, resSize);
+
+ LL_I2L(dataInt64, dataSize);
+
+ LL_ADD((*aFileSize), dataInt64, resInt64);
+ }
+ // leave size at zero for dirs
+ }
+
+ return rv;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::SetFileSize(PRInt64 aFileSize)
+{
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ short refNum;
+ OSErr err;
+ PRInt32 aNewLength;
+
+ LL_L2I(aNewLength, aFileSize);
+
+ // Need to open the file to set the size
+ if (::FSpOpenDF(&mTargetSpec, fsWrPerm, &refNum) != noErr)
+ return NS_ERROR_FILE_ACCESS_DENIED;
+
+ err = ::SetEOF(refNum, aNewLength);
+
+ // Close the file unless we got an error that it was already closed
+ if (err != fnOpnErr)
+ (void)::FSClose(refNum);
+
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ return MacErrorMapper(err);
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetFileSizeOfLink(PRInt64 *aFileSize)
+{
+ NS_ENSURE_ARG(aFileSize);
+
+ StFollowLinksState followState(this, PR_FALSE);
+ return GetFileSize(aFileSize);
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable)
+{
+ NS_ENSURE_ARG(aDiskSpaceAvailable);
+
+ PRInt64 space64Bits;
+
+ LL_I2L(space64Bits , LONG_MAX);
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ XVolumeParam pb;
+ pb.ioCompletion = nsnull;
+ pb.ioVolIndex = 0;
+ pb.ioNamePtr = nsnull;
+ pb.ioVRefNum = mFollowLinks ? mTargetSpec.vRefNum : mSpec.vRefNum;
+
+ // we should check if this call is available
+ OSErr err = ::PBXGetVolInfoSync(&pb);
+
+ if (err == noErr)
+ {
+ const UnsignedWide& freeBytes = UInt64ToUnsignedWide(pb.ioVFreeBytes);
+#ifdef HAVE_LONG_LONG
+ space64Bits = UnsignedWideToUInt64(freeBytes);
+#else
+ space64Bits.lo = freeBytes.lo;
+ space64Bits.hi = freeBytes.hi;
+#endif
+ }
+
+ *aDiskSpaceAvailable = space64Bits;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetParent(nsIFile * *aParent)
+{
+ NS_ENSURE_ARG_POINTER(aParent);
+ *aParent = nsnull;
+
+ nsresult rv = NS_OK;
+ PRInt32 offset;
+
+ nsCOMPtr<nsILocalFileMac> localFile;
+ PRInt32 appendedLen = mAppendedPath.Length();
+ OSErr err;
+
+ if (!appendedLen || (appendedLen == 1 && mAppendedPath.CharAt(0) == ':'))
+ {
+ rv = ResolveAndStat();
+ //if the file does not exist, does not mean that the parent does not.
+ if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
+ return rv;
+
+ CInfoPBRec pBlock = {0};
+ FSSpec parentFolderSpec;
+ parentFolderSpec.name[0] = 0;
+
+ pBlock.dirInfo.ioVRefNum = mSpec.vRefNum;
+ pBlock.dirInfo.ioDrDirID = mSpec.parID;
+ pBlock.dirInfo.ioNamePtr = (StringPtr)parentFolderSpec.name;
+ pBlock.dirInfo.ioFDirIndex = -1; //get info on parID
+ err = PBGetCatInfoSync(&pBlock);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ parentFolderSpec.vRefNum = mSpec.vRefNum;
+ parentFolderSpec.parID = pBlock.dirInfo.ioDrParID;
+
+ localFile = new nsLocalFile;
+ if (!localFile)
+ return NS_ERROR_OUT_OF_MEMORY;
+ rv = localFile->InitWithFSSpec(&parentFolderSpec);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ else
+ {
+ // trim off the last component of the appended path
+ // construct a new file from our spec + trimmed path
+
+ nsCAutoString parentAppendage(mAppendedPath);
+
+ if (parentAppendage.Last() == ':')
+ parentAppendage.Truncate(appendedLen - 1);
+ if ((offset = parentAppendage.RFindChar(':')) != -1)
+ parentAppendage.Truncate(offset);
+ else
+ parentAppendage.Truncate(0);
+
+ localFile = new nsLocalFile(mSpec, parentAppendage);
+ if (!localFile)
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ *aParent = localFile;
+ NS_ADDREF(*aParent);
+
+ return rv;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::Exists(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv = ResolveAndStat();
+ if (NS_SUCCEEDED(rv)) {
+ if (NS_SUCCEEDED(UpdateCachedCatInfo(PR_TRUE)))
+ *_retval = PR_TRUE;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsPackage(PRBool *outIsPackage)
+{
+ NS_ENSURE_ARG(outIsPackage);
+ *outIsPackage = PR_FALSE;
+
+ // Note: IsDirectory() calls ResolveAndStat() & UpdateCachedCatInfo
+ PRBool isDir;
+ nsresult rv = IsDirectory(&isDir);
+ if (NS_FAILED(rv)) return rv;
+
+ *outIsPackage = ((mCachedCatInfo.dirInfo.ioFlAttrib & kioFlAttribDirMask) &&
+ (mCachedCatInfo.dirInfo.ioDrUsrWds.frFlags & kHasBundle));
+
+ if ((!*outIsPackage) && isDir)
+ {
+ // Believe it or not, folders ending with ".app" are also considered
+ // to be packages, even if the top-level folder doesn't have bundle set
+ nsCAutoString name;
+ if (NS_SUCCEEDED(rv = GetNativeLeafName(name)))
+ {
+ const char *extPtr = strrchr(name.get(), '.');
+ if (extPtr)
+ {
+ if (!nsCRT::strcasecmp(extPtr, ".app"))
+ {
+ *outIsPackage = PR_TRUE;
+ }
+ }
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsWritable(PRBool *outIsWritable)
+{
+ NS_ENSURE_ARG(outIsWritable);
+ *outIsWritable = PR_TRUE;
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv)) return rv;
+
+ rv = UpdateCachedCatInfo(PR_TRUE);
+ if (NS_FAILED(rv)) return rv;
+
+ *outIsWritable = !(mCachedCatInfo.hFileInfo.ioFlAttrib & kioFlAttribLockedMask);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsReadable(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+
+ // is it ever not readable on Mac?
+ *_retval = PR_TRUE;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::IsExecutable(PRBool *outIsExecutable)
+{
+ NS_ENSURE_ARG(outIsExecutable);
+ *outIsExecutable = PR_FALSE; // Assume failure
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv)) return rv;
+
+#if TARGET_CARBON
+ // If we're running under OS X ask LaunchServices if we're executable
+ if (sRunningOSX)
+ {
+ if ( (UInt32)LSCopyItemInfoForRef != (UInt32)kUnresolvedCFragSymbolAddress )
+ {
+ FSRef theRef;
+ LSRequestedInfo theInfoRequest = kLSRequestAllInfo;
+ LSItemInfoRecord theInfo;
+
+ if (::FSpMakeFSRef(&mTargetSpec, &theRef) == noErr)
+ {
+ if (::LSCopyItemInfoForRef(&theRef, theInfoRequest, &theInfo) == noErr)
+ {
+ if ((theInfo.flags & kLSItemInfoIsApplication) != 0)
+ *outIsExecutable = PR_TRUE;
+ }
+ }
+ }
+ }
+ else
+#endif
+ {
+ OSType fileType;
+ rv = GetFileType(&fileType);
+ if (NS_FAILED(rv)) return rv;
+
+ *outIsExecutable = (fileType == 'APPL' || fileType == 'appe' || fileType == 'FNDR');
+ }
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::IsDirectory(PRBool *outIsDir)
+{
+ NS_ENSURE_ARG(outIsDir);
+ *outIsDir = PR_FALSE;
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv)) return rv;
+
+ rv = UpdateCachedCatInfo(PR_FALSE);
+ if (NS_FAILED(rv)) return rv;
+
+ *outIsDir = (mCachedCatInfo.hFileInfo.ioFlAttrib & ioDirMask) != 0;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsFile(PRBool *outIsFile)
+{
+ NS_ENSURE_ARG(outIsFile);
+ *outIsFile = PR_FALSE;
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv)) return rv;
+
+ rv = UpdateCachedCatInfo(PR_FALSE);
+ if (NS_FAILED(rv)) return rv;
+
+ *outIsFile = (mCachedCatInfo.hFileInfo.ioFlAttrib & ioDirMask) == 0;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsHidden(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv)) return rv;
+
+ rv = UpdateCachedCatInfo(PR_FALSE);
+ if (NS_FAILED(rv)) return rv;
+
+ *_retval = (mCachedCatInfo.hFileInfo.ioFlFndrInfo.fdFlags & kIsInvisible) != 0;
+
+ if (sRunningOSX)
+ {
+ // on Mac OS X, also follow Unix "convention" where files
+ // beginning with a period are considered to be hidden
+ nsCAutoString name;
+ if (NS_SUCCEEDED(rv = GetNativeLeafName(name)))
+ {
+ if (name.First() == '.')
+ {
+ *_retval = PR_TRUE;
+ }
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsSymlink(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv)) return rv;
+
+ Boolean isAlias, isFolder;
+ if (::IsAliasFile(&mSpec, &isAlias, &isFolder) == noErr)
+ *_retval = isAlias;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Equals(nsIFile *inFile, PRBool *_retval)
+{
+ NS_ENSURE_ARG(inFile);
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ // Building paths is expensive. If we can get the FSSpecs of
+ // both (they or their parents exist) just compare the specs.
+ nsCOMPtr<nsILocalFileMac> inMacFile(do_QueryInterface(inFile));
+ FSSpec fileSpec, inFileSpec;
+ if (NS_SUCCEEDED(GetFSSpec(&fileSpec)) && inMacFile && NS_SUCCEEDED(inMacFile->GetFSSpec(&inFileSpec)))
+ *_retval = IsEqualFSSpec(fileSpec, inFileSpec);
+ else
+ {
+ nsCAutoString filePath;
+ GetNativePath(filePath);
+
+ nsXPIDLCString inFilePath;
+ inFile->GetNativePath(inFilePath);
+
+ if (nsCRT::strcasecmp(inFilePath.get(), filePath.get()) == 0)
+ *_retval = PR_TRUE;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Contains(nsIFile *inFile, PRBool recur, PRBool *outContains)
+{
+ /* Note here that we make no attempt to deal with the problem
+ of folder aliases. Doing a 'Contains' test and dealing with
+ folder aliases is Hard. Think about it.
+ */
+ *outContains = PR_FALSE;
+
+ PRBool isDir;
+ nsresult rv = IsDirectory(&isDir); // need to cache this
+ if (NS_FAILED(rv)) return rv;
+ if (!isDir) return NS_OK; // must be a dir to contain someone
+
+ nsCOMPtr<nsILocalFileMac> macFile(do_QueryInterface(inFile));
+ if (!macFile) return NS_OK; // trying to compare non-local with local file
+
+ FSSpec mySpec = mSpec;
+ FSSpec compareSpec;
+
+ // NOTE: we're not resolving inFile if it was an alias
+ StFollowLinksState followState(macFile, PR_FALSE);
+ rv = macFile->GetFSSpec(&compareSpec);
+ if (NS_FAILED(rv)) return rv;
+
+ // if they are on different volumes, bail
+ if (mSpec.vRefNum != compareSpec.vRefNum)
+ return NS_OK;
+
+ // if recur == true, test every parent, otherwise just test the first one
+ // (yes, recur does not get set in this loop)
+ OSErr err = noErr;
+ do
+ {
+ FSSpec parentFolderSpec;
+ err = GetParentFolderSpec(compareSpec, parentFolderSpec);
+ if (err != noErr) break; // we reached the top
+
+ if (IsEqualFSSpec(parentFolderSpec, mySpec))
+ {
+ *outContains = PR_TRUE;
+ break;
+ }
+
+ compareSpec = parentFolderSpec;
+ } while (recur);
+
+ return NS_OK;
+}
+
+
+
+NS_IMETHODIMP
+nsLocalFile::GetNativeTarget(nsACString &_retval)
+{
+ _retval.Truncate();
+
+ PRBool symLink;
+
+ nsresult rv = IsSymlink(&symLink);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (!symLink)
+ return NS_ERROR_FILE_INVALID_PATH;
+
+ StFollowLinksState followState(this, PR_TRUE);
+ return GetNativePath(_retval);
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetTarget(nsAString &_retval)
+{
+ nsresult rv;
+ nsCAutoString fsStr;
+
+ if (NS_SUCCEEDED(rv = GetNativeTarget(fsStr))) {
+ rv = NS_CopyNativeToUnicode(fsStr, _retval);
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetDirectoryEntries(nsISimpleEnumerator * *entries)
+{
+ nsresult rv;
+
+ *entries = nsnull;
+
+ PRBool isDir;
+ rv = IsDirectory(&isDir);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!isDir)
+ return NS_ERROR_FILE_NOT_DIRECTORY;
+
+ nsDirEnumerator* dirEnum = new nsDirEnumerator();
+ if (dirEnum == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(dirEnum);
+ rv = dirEnum->Init(this);
+ if (NS_FAILED(rv))
+ {
+ NS_RELEASE(dirEnum);
+ return rv;
+ }
+
+ *entries = dirEnum;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPersistentDescriptor(nsACString &aPersistentDescriptor)
+{
+ aPersistentDescriptor.Truncate();
+
+ nsresult rv = ResolveAndStat();
+ if ( NS_FAILED( rv ) )
+ return rv;
+
+ AliasHandle aliasH;
+ OSErr err = ::NewAlias(nil, &mTargetSpec, &aliasH);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ PRUint32 bytes = ::GetHandleSize((Handle) aliasH);
+ HLock((Handle) aliasH);
+ char* buf = PL_Base64Encode((const char*)*aliasH, bytes, nsnull); // Passing nsnull for dest makes NULL-term string
+ ::DisposeHandle((Handle) aliasH);
+ NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY);
+
+ aPersistentDescriptor = buf;
+ PR_Free(buf);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetPersistentDescriptor(const nsACString &aPersistentDescriptor)
+{
+ if (aPersistentDescriptor.IsEmpty())
+ return NS_ERROR_INVALID_ARG;
+
+ nsresult rv = NS_OK;
+
+ PRUint32 dataSize = aPersistentDescriptor.Length();
+ char* decodedData = PL_Base64Decode(PromiseFlatCString(aPersistentDescriptor).get(), dataSize, nsnull);
+ // Cast to an alias record and resolve.
+ AliasHandle aliasH = nsnull;
+ if (::PtrToHand(decodedData, &(Handle)aliasH, (dataSize * 3) / 4) != noErr)
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ PR_Free(decodedData);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ Boolean changed;
+ FSSpec resolvedSpec;
+ OSErr err;
+ err = ::ResolveAlias(nsnull, aliasH, &resolvedSpec, &changed);
+ if (err == fnfErr) // resolvedSpec is valid in this case
+ err = noErr;
+ rv = MacErrorMapper(err);
+ DisposeHandle((Handle) aliasH);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return InitWithFSSpec(&resolvedSpec);
+}
+
+#pragma mark -
+
+// a stack-based, exception safe class for an AEDesc
+
+#pragma mark
+class StAEDesc: public AEDesc
+{
+public:
+ StAEDesc()
+ {
+ descriptorType = typeNull;
+ dataHandle = nil;
+ }
+
+ ~StAEDesc()
+ {
+ ::AEDisposeDesc(this);
+ }
+
+ void Clear()
+ {
+ ::AEDisposeDesc(this);
+ descriptorType = typeNull;
+ dataHandle = nil;
+ }
+
+private:
+ // disallow copies and assigns
+ StAEDesc(const StAEDesc& rhs); // copy constructor
+ StAEDesc& operator= (const StAEDesc&rhs); // throws OSErrs
+
+};
+
+#pragma mark -
+#pragma mark [Utility methods]
+
+
+nsresult nsLocalFile::UpdateCachedCatInfo(PRBool forceUpdate)
+{
+ if (!mCatInfoDirty && !forceUpdate)
+ return NS_OK;
+
+ FSSpec spectoUse = mFollowLinks ? mTargetSpec : mSpec;
+ mCachedCatInfo.hFileInfo.ioCompletion = nsnull;
+ mCachedCatInfo.hFileInfo.ioFDirIndex = 0; // use dirID and name
+ mCachedCatInfo.hFileInfo.ioVRefNum = spectoUse.vRefNum;
+ mCachedCatInfo.hFileInfo.ioDirID = spectoUse.parID;
+ mCachedCatInfo.hFileInfo.ioNamePtr = spectoUse.name;
+
+ OSErr err = ::PBGetCatInfoSync(&mCachedCatInfo);
+ if (err == noErr)
+ {
+ mCatInfoDirty = PR_FALSE;
+ return NS_OK;
+ }
+ return MacErrorMapper(err);
+}
+
+
+nsresult nsLocalFile::FindRunningAppBySignature (OSType aAppSig, FSSpec& outSpec, ProcessSerialNumber& outPsn)
+{
+ ProcessInfoRec info;
+ FSSpec tempFSSpec;
+ OSErr err = noErr;
+
+ outPsn.highLongOfPSN = 0;
+ outPsn.lowLongOfPSN = kNoProcess;
+
+ while (PR_TRUE)
+ {
+ err = ::GetNextProcess(&outPsn);
+ if (err == procNotFound) break;
+ if (err != noErr) return NS_ERROR_FAILURE;
+ info.processInfoLength = sizeof(ProcessInfoRec);
+ info.processName = nil;
+ info.processAppSpec = &tempFSSpec;
+ err = ::GetProcessInformation(&outPsn, &info);
+ if (err != noErr) return NS_ERROR_FAILURE;
+
+ if (info.processSignature == aAppSig)
+ {
+ outSpec = tempFSSpec;
+ return NS_OK;
+ }
+ }
+
+ return NS_ERROR_FILE_NOT_FOUND; // really process not found
+}
+
+
+nsresult nsLocalFile::FindRunningAppByFSSpec(const FSSpec& appSpec, ProcessSerialNumber& outPsn)
+{
+ ProcessInfoRec info;
+ FSSpec tempFSSpec;
+ OSErr err = noErr;
+
+ outPsn.highLongOfPSN = 0;
+ outPsn.lowLongOfPSN = kNoProcess;
+
+ while (PR_TRUE)
+ {
+ err = ::GetNextProcess(&outPsn);
+ if (err == procNotFound) break;
+ if (err != noErr) return NS_ERROR_FAILURE;
+ info.processInfoLength = sizeof(ProcessInfoRec);
+ info.processName = nil;
+ info.processAppSpec = &tempFSSpec;
+ err = ::GetProcessInformation(&outPsn, &info);
+ if (err != noErr) return NS_ERROR_FAILURE;
+
+ if (IsEqualFSSpec(appSpec, *info.processAppSpec))
+ {
+ return NS_OK;
+ }
+ }
+
+ return NS_ERROR_FILE_NOT_FOUND; // really process not found
+}
+
+
+nsresult nsLocalFile::FindAppOnLocalVolumes(OSType sig, FSSpec &outSpec)
+{
+ OSErr err;
+
+ // get the system volume
+ long systemFolderDirID;
+ short sysVRefNum;
+ err = FindFolder(kOnSystemDisk, kSystemFolderType, false, &sysVRefNum, &systemFolderDirID);
+ if (err != noErr) return NS_ERROR_FAILURE;
+
+ short vRefNum = sysVRefNum;
+ short index = 0;
+
+ while (true)
+ {
+ if (index == 0 || vRefNum != sysVRefNum)
+ {
+ // should we avoid AppleShare volumes?
+
+ Boolean hasDesktopDB;
+ err = VolHasDesktopDB(vRefNum, &hasDesktopDB);
+ if (err != noErr) return err;
+ if (hasDesktopDB)
+ {
+ err = FindAppOnVolume(sig, vRefNum, &outSpec);
+ if (err != afpItemNotFound) return err;
+ }
+ }
+ index++;
+ err = GetIndVolume(index, &vRefNum);
+ if (err == nsvErr) return fnfErr;
+ if (err != noErr) return err;
+ }
+
+ return NS_OK;
+}
+
+#define aeSelectionKeyword 'fsel'
+#define kAEOpenSelection 'sope'
+#define kAERevealSelection 'srev'
+#define kFinderType 'FNDR'
+
+NS_IMETHODIMP nsLocalFile::Launch()
+{
+ AppleEvent aeEvent = {0, nil};
+ AppleEvent aeReply = {0, nil};
+ StAEDesc aeDirDesc, listElem, myAddressDesc, fileList;
+ FSSpec dirSpec, appSpec;
+ AliasHandle DirAlias, FileAlias;
+ OSErr errorResult = noErr;
+ ProcessSerialNumber process;
+
+ // for launching a file, we'll use mTargetSpec (which is both a resolved spec and a resolved alias)
+ ResolveAndStat();
+
+#if TARGET_CARBON
+ if (sRunningOSX)
+ { // We're running under Mac OS X, LaunchServices here we come
+
+ // First we make sure the LaunchServices routine we want is implemented
+ if ( (UInt32)LSOpenFSRef != (UInt32)kUnresolvedCFragSymbolAddress )
+ {
+ FSRef theRef;
+ if (::FSpMakeFSRef(&mTargetSpec, &theRef) == noErr)
+ {
+ (void)::LSOpenFSRef(&theRef, NULL);
+ }
+ }
+ }
+ else
+#endif
+ { // We're running under Mac OS 8.x/9.x, use the Finder Luke
+ nsresult rv = FindRunningAppBySignature ('MACS', appSpec, process);
+ if (NS_SUCCEEDED(rv))
+ {
+ errorResult = AECreateDesc(typeProcessSerialNumber, (Ptr)&process, sizeof(process), &myAddressDesc);
+ if (errorResult == noErr)
+ {
+ /* Create the FinderEvent */
+ errorResult = AECreateAppleEvent(kFinderType, kAEOpenSelection, &myAddressDesc, kAutoGenerateReturnID, kAnyTransactionID,
+ &aeEvent);
+ if (errorResult == noErr)
+ {
+ errorResult = FSMakeFSSpec(mTargetSpec.vRefNum, mTargetSpec.parID, nil, &dirSpec);
+ NewAlias(nil, &dirSpec, &DirAlias);
+ /* Create alias for file */
+ NewAlias(nil, &mTargetSpec, &FileAlias);
+
+ /* Create the file list */
+ errorResult = AECreateList(nil, 0, false, &fileList);
+ /* create the folder descriptor */
+ HLock((Handle)DirAlias);
+ errorResult = AECreateDesc(typeAlias, (Ptr)*DirAlias, GetHandleSize((Handle)DirAlias), &aeDirDesc);
+ HUnlock((Handle)DirAlias);
+ if (errorResult == noErr)
+ {
+ errorResult = AEPutParamDesc(&aeEvent, keyDirectObject, &aeDirDesc);
+ if ( errorResult == noErr)
+ {
+ /* create the file descriptor and add to aliasList */
+ HLock((Handle)FileAlias);
+ errorResult = AECreateDesc(typeAlias, (Ptr)*FileAlias, GetHandleSize((Handle)FileAlias), &listElem);
+ HLock((Handle)FileAlias);
+ if (errorResult == noErr)
+ {
+ errorResult = AEPutDesc(&fileList, 0, &listElem);
+ if (errorResult == noErr)
+ {
+ /* Add the file alias list to the event */
+ errorResult = AEPutParamDesc(&aeEvent, aeSelectionKeyword, &fileList);
+ if (errorResult == noErr)
+ AESend(&aeEvent, &aeReply, kAEWaitReply + kAENeverInteract
+ + kAECanSwitchLayer, kAEHighPriority, kAEDefaultTimeout, nil, nil);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::Reveal()
+{
+ FSSpec specToReveal;
+ AppleEvent aeEvent = {0, nil};
+ AppleEvent aeReply = {0, nil};
+ StAEDesc aeDirDesc, listElem, myAddressDesc, fileList;
+ OSErr errorResult = noErr;
+ ProcessSerialNumber process;
+ FSSpec appSpec;
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+ rv = GetFSSpec(&specToReveal); // Pay attention to followLinks
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = FindRunningAppBySignature ('MACS', appSpec, process);
+ if (NS_SUCCEEDED(rv))
+ {
+ errorResult = AECreateDesc(typeProcessSerialNumber, (Ptr)&process, sizeof(process), &myAddressDesc);
+ if (errorResult == noErr)
+ {
+ /* Create the FinderEvent */
+#if TARGET_CARBON
+ // The Finder under OS X uses a different event to reveal
+ if (sRunningOSX)
+ errorResult = AECreateAppleEvent(kAEMiscStandards, kAEMakeObjectsVisible, &myAddressDesc, kAutoGenerateReturnID, kAnyTransactionID,
+ &aeEvent);
+ else
+#endif
+ errorResult = AECreateAppleEvent(kFinderType, kAERevealSelection, &myAddressDesc, kAutoGenerateReturnID, kAnyTransactionID,
+ &aeEvent);
+ if (errorResult == noErr)
+ {
+ /* Create the file list */
+ errorResult = AECreateList(nil, 0, false, &fileList);
+ if (errorResult == noErr)
+ {
+ errorResult = AEPutPtr(&fileList, 0, typeFSS, &specToReveal, sizeof(FSSpec));
+
+ if (errorResult == noErr)
+ {
+#if TARGET_CARBON
+ // When we're sending the event under OS X the FSSpec must be a keyDirectObject
+ if (sRunningOSX)
+ errorResult = AEPutParamDesc(&aeEvent, keyDirectObject, &fileList);
+ else
+#endif
+ errorResult = AEPutParamDesc(&aeEvent,keySelection, &fileList);
+
+ if (errorResult == noErr)
+ {
+ errorResult = AESend(&aeEvent, &aeReply, kAENoReply, kAENormalPriority, kAEDefaultTimeout, nil, nil);
+ if (errorResult == noErr)
+ SetFrontProcess(&process);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return NS_OK;
+}
+
+nsresult nsLocalFile::MyLaunchAppWithDoc(const FSSpec& appSpec, const FSSpec* aDocToLoad, PRBool aLaunchInBackground)
+{
+ ProcessSerialNumber thePSN = {0};
+ StAEDesc target;
+ StAEDesc docDesc;
+ StAEDesc launchDesc;
+ StAEDesc docList;
+ AppleEvent theEvent = {0, nil};
+ AppleEvent theReply = {0, nil};
+ OSErr err = noErr;
+ Boolean autoParamValue = false;
+ Boolean running = false;
+ nsresult rv = NS_OK;
+
+#if TARGET_CARBON
+ if (sRunningOSX)
+ { // Under Mac OS X we'll use LaunchServices
+
+ // First we make sure the LaunchServices routine we want is implemented
+ if ( (UInt32)LSOpenFromRefSpec != (UInt32)kUnresolvedCFragSymbolAddress )
+ {
+ FSRef appRef;
+ FSRef docRef;
+ LSLaunchFlags theLaunchFlags = kLSLaunchDefaults;
+ LSLaunchFSRefSpec thelaunchSpec;
+
+ if (::FSpMakeFSRef(&appSpec, &appRef) != noErr)
+ return NS_ERROR_FAILURE;
+
+ if (aDocToLoad)
+ if (::FSpMakeFSRef(aDocToLoad, &docRef) != noErr)
+ return NS_ERROR_FAILURE;
+
+ if (aLaunchInBackground)
+ theLaunchFlags |= kLSLaunchDontSwitch;
+
+ memset(&thelaunchSpec, 0, sizeof(LSLaunchFSRefSpec));
+
+ thelaunchSpec.appRef = &appRef;
+ if (aDocToLoad)
+ {
+ thelaunchSpec.numDocs = 1;
+ thelaunchSpec.itemRefs = &docRef;
+ }
+ thelaunchSpec.launchFlags = theLaunchFlags;
+
+ err = ::LSOpenFromRefSpec(&thelaunchSpec, NULL);
+ NS_ASSERTION((err != noErr), "Error calling LSOpenFromRefSpec");
+ if (err != noErr) return NS_ERROR_FAILURE;
+ }
+ }
+ else
+#endif
+ { // The old fashioned way for Mac OS 8.x/9.x
+ rv = FindRunningAppByFSSpec(appSpec, thePSN);
+ running = NS_SUCCEEDED(rv);
+
+ err = AECreateDesc(typeProcessSerialNumber, &thePSN, sizeof(thePSN), &target);
+ if (err != noErr) return NS_ERROR_FAILURE;
+
+ err = AECreateAppleEvent(kCoreEventClass, aDocToLoad ? kAEOpenDocuments : kAEOpenApplication, &target,
+ kAutoGenerateReturnID, kAnyTransactionID, &theEvent);
+ if (err != noErr) return NS_ERROR_FAILURE;
+
+ if (aDocToLoad)
+ {
+ err = AECreateList(nil, 0, false, &docList);
+ if (err != noErr) return NS_ERROR_FAILURE;
+
+ err = AECreateDesc(typeFSS, aDocToLoad, sizeof(FSSpec), &docDesc);
+ if (err != noErr) return NS_ERROR_FAILURE;
+
+ err = AEPutDesc(&docList, 0, &docDesc);
+ if (err != noErr) return NS_ERROR_FAILURE;
+
+ err = AEPutParamDesc(&theEvent, keyDirectObject, &docList);
+ if (err != noErr) return NS_ERROR_FAILURE;
+ }
+
+ if (running)
+ {
+ err = AESend(&theEvent, &theReply, kAENoReply, kAENormalPriority, kNoTimeOut, nil, nil);
+ if (err != noErr) return NS_ERROR_FAILURE;
+
+ if (!aLaunchInBackground)
+ {
+ err = ::SetFrontProcess(&thePSN);
+ if (err != noErr) return NS_ERROR_FAILURE;
+ }
+ }
+ else
+ {
+ LaunchParamBlockRec launchThis = {0};
+ PRUint16 launchControlFlags = (launchContinue | launchNoFileFlags);
+ if (aLaunchInBackground)
+ launchControlFlags |= launchDontSwitch;
+
+ err = AECoerceDesc(&theEvent, typeAppParameters, &launchDesc);
+ if (err != noErr) return NS_ERROR_FAILURE;
+
+ launchThis.launchAppSpec = (FSSpecPtr)&appSpec;
+#if TARGET_CARBON && ACCESSOR_CALLS_ARE_FUNCTIONS
+ ::AEGetDescData(&launchDesc, &launchThis.launchAppParameters, sizeof(launchThis.launchAppParameters));
+#else
+ // no need to lock this handle.
+ launchThis.launchAppParameters = (AppParametersPtr) *(launchDesc.dataHandle);
+#endif
+ launchThis.launchBlockID = extendedBlock;
+ launchThis.launchEPBLength = extendedBlockLen;
+ launchThis.launchFileFlags = 0;
+ launchThis.launchControlFlags = launchControlFlags;
+ err = ::LaunchApplication(&launchThis);
+ if (err != noErr) return NS_ERROR_FAILURE;
+
+ // let's be nice and wait until it's running
+ const PRUint32 kMaxTimeToWait = 60; // wait 1 sec max
+ PRUint32 endTicks = ::TickCount() + kMaxTimeToWait;
+
+ PRBool foundApp = PR_FALSE;
+
+ do
+ {
+ EventRecord theEvent;
+ (void)WaitNextEvent(nullEvent, &theEvent, 1, NULL);
+
+ ProcessSerialNumber psn;
+ foundApp = NS_SUCCEEDED(FindRunningAppByFSSpec(appSpec, psn));
+
+ } while (!foundApp && (::TickCount() <= endTicks));
+
+ NS_ASSERTION(foundApp, "Failed to find app after launching it");
+ }
+
+ if (theEvent.dataHandle != nil) AEDisposeDesc(&theEvent);
+ if (theReply.dataHandle != nil) AEDisposeDesc(&theReply);
+ }
+
+ return NS_OK;
+}
+
+
+#pragma mark -
+#pragma mark [Methods that will not be implemented on Mac]
+
+NS_IMETHODIMP
+nsLocalFile::Normalize()
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPermissions(PRUint32 *aPermissions)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPermissionsOfLink(PRUint32 *aPermissionsOfLink)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::SetPermissions(PRUint32 aPermissions)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetPermissionsOfLink(PRUint32 aPermissions)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsSpecial(PRBool *_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+#pragma mark -
+#pragma mark [nsILocalFileMac]
+// Implementation of Mac specific finctions from nsILocalFileMac
+
+
+NS_IMETHODIMP nsLocalFile::InitWithCFURL(CFURLRef aCFURL)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+
+#if TARGET_CARBON
+ NS_ENSURE_ARG(aCFURL);
+
+ // CFURLGetFSRef can only succeed if the entire path exists.
+ FSRef fsRef;
+ if (::CFURLGetFSRef(aCFURL, &fsRef) == PR_TRUE)
+ rv = InitWithFSRef(&fsRef);
+ else
+ {
+ CFURLRef parentURL = ::CFURLCreateCopyDeletingLastPathComponent(NULL, aCFURL);
+ if (!parentURL)
+ return NS_ERROR_FAILURE;
+
+ // Get the FSRef from the parent and the FSSpec from that
+ FSRef parentFSRef;
+ FSSpec parentFSSpec;
+ if ((::CFURLGetFSRef(parentURL, &parentFSRef) == PR_TRUE) &&
+ (::FSGetCatalogInfo(&parentFSRef, kFSCatInfoNone,
+ nsnull, nsnull, &parentFSSpec, nsnull) == noErr))
+ {
+ // Get the leaf name of the file and turn it into a string HFS can use.
+ CFStringRef fileNameRef = ::CFURLCopyLastPathComponent(aCFURL);
+ if (fileNameRef)
+ {
+ TextEncoding theEncoding;
+ if (::UpgradeScriptInfoToTextEncoding(smSystemScript,
+ kTextLanguageDontCare,
+ kTextRegionDontCare,
+ NULL,
+ &theEncoding) != noErr)
+ theEncoding = kTextEncodingMacRoman;
+
+ char origName[256];
+ char truncBuf[32];
+ if (::CFStringGetCString(fileNameRef, origName, sizeof(origName), theEncoding))
+ {
+ MakeDirty();
+ mSpec = parentFSSpec;
+ mAppendedPath = NS_TruncNodeName(origName, truncBuf);
+ rv = NS_OK;
+ }
+ ::CFRelease(fileNameRef);
+ }
+ }
+ ::CFRelease(parentURL);
+ }
+#endif
+
+ return rv;
+}
+
+
+NS_IMETHODIMP nsLocalFile::InitWithFSRef(const FSRef * aFSRef)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+
+#if TARGET_CARBON
+ NS_ENSURE_ARG(aFSRef);
+
+ FSSpec fsSpec;
+ OSErr err = ::FSGetCatalogInfo(aFSRef, kFSCatInfoNone, nsnull,
+ nsnull, &fsSpec, nsnull);
+ if (err == noErr)
+ rv = InitWithFSSpec(&fsSpec);
+ else
+ rv = MacErrorMapper(err);
+#endif
+
+ return rv;
+}
+
+
+NS_IMETHODIMP nsLocalFile::InitWithFSSpec(const FSSpec *fileSpec)
+{
+ MakeDirty();
+ mSpec = *fileSpec;
+ mTargetSpec = *fileSpec;
+ mAppendedPath = "";
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP nsLocalFile::InitToAppWithCreatorCode(OSType aAppCreator)
+{
+ FSSpec appSpec;
+ ProcessSerialNumber psn;
+
+#if TARGET_CARBON
+ if (sRunningOSX)
+ { // If we're running under OS X use LaunchServices to determine the app
+ // corresponding to the creator code
+ if ( (UInt32)LSFindApplicationForInfo != (UInt32)kUnresolvedCFragSymbolAddress )
+ {
+ FSRef theRef;
+ if (::LSFindApplicationForInfo(aAppCreator, NULL, NULL, &theRef, NULL) == noErr)
+ {
+ FSCatalogInfoBitmap whichInfo = kFSCatInfoNone;
+
+ if (::FSGetCatalogInfo(&theRef, whichInfo, NULL, NULL, &appSpec, NULL) == noErr)
+ return InitWithFSSpec(&appSpec);
+ }
+
+ // If we get here we didn't find an app
+ return NS_ERROR_FILE_NOT_FOUND;
+ }
+ }
+#endif
+
+ // is the app running?
+ nsresult rv = FindRunningAppBySignature(aAppCreator, appSpec, psn);
+ if (rv == NS_ERROR_FILE_NOT_FOUND)
+ {
+ // we have to look on disk
+ rv = FindAppOnLocalVolumes(aAppCreator, appSpec);
+ if (NS_FAILED(rv)) return rv;
+ }
+ else if (NS_FAILED(rv))
+ return rv;
+
+ // init with the spec here
+ return InitWithFSSpec(&appSpec);
+}
+
+NS_IMETHODIMP nsLocalFile::GetCFURL(CFURLRef *_retval)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+
+#if TARGET_CARBON
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = nsnull;
+
+ PRBool exists;
+ if (NS_SUCCEEDED(Exists(&exists)) && exists)
+ {
+ FSRef fsRef;
+ FSSpec fsSpec = mFollowLinks ? mTargetSpec : mSpec;
+ if (::FSpMakeFSRef(&fsSpec, &fsRef) == noErr)
+ {
+ *_retval = ::CFURLCreateFromFSRef(NULL, &fsRef);
+ if (*_retval)
+ return NS_OK;
+ }
+ }
+ else
+ {
+ nsCAutoString tempPath;
+ if (NS_SUCCEEDED(GetNativePath(tempPath)))
+ {
+ CFStringRef pathStrRef = ::CFStringCreateWithCString(NULL, tempPath.get(), kCFStringEncodingMacRoman);
+ if (!pathStrRef)
+ return NS_ERROR_FAILURE;
+ *_retval = ::CFURLCreateWithFileSystemPath(NULL, pathStrRef, kCFURLHFSPathStyle, false);
+ ::CFRelease(pathStrRef);
+ if (*_retval)
+ return NS_OK;
+ }
+ }
+#endif
+
+ return rv;
+}
+
+NS_IMETHODIMP nsLocalFile::GetFSRef(FSRef *_retval)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+
+#if TARGET_CARBON
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ FSSpec fsSpec;
+ rv = GetFSSpec(&fsSpec);
+ if (NS_SUCCEEDED(rv))
+ rv = MacErrorMapper(::FSpMakeFSRef(&fsSpec, _retval));
+#endif
+
+ return rv;
+}
+
+NS_IMETHODIMP nsLocalFile::GetFSSpec(FSSpec *fileSpec)
+{
+ NS_ENSURE_ARG(fileSpec);
+ nsresult rv = ResolveAndStat();
+ if (rv == NS_ERROR_FILE_NOT_FOUND)
+ rv = NS_OK;
+ if (NS_SUCCEEDED(rv))
+ *fileSpec = mFollowLinks ? mTargetSpec : mSpec;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::GetFileType(OSType *aFileType)
+{
+ NS_ENSURE_ARG(aFileType);
+
+ FSSpec fileSpec;
+ (void)GetFSSpec(&fileSpec);
+
+ FInfo info;
+ OSErr err = ::FSpGetFInfo(&fileSpec, &info);
+ if (err != noErr)
+ {
+ *aFileType = mType;
+ return NS_ERROR_FILE_NOT_FOUND;
+ }
+
+ *aFileType = info.fdType;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::SetFileType(OSType aFileType)
+{
+ mType = aFileType;
+
+ FSSpec fileSpec;
+ (void)GetFSSpec(&fileSpec);
+
+ FInfo info;
+ OSErr err = ::FSpGetFInfo(&fileSpec, &info);
+ if (err != noErr)
+ return NS_ERROR_FILE_NOT_FOUND;
+
+ info.fdType = aFileType;
+ err = ::FSpSetFInfo(&fileSpec, &info);
+ if (err != noErr)
+ return NS_ERROR_FILE_ACCESS_DENIED;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::GetFileCreator(OSType *aCreator)
+{
+ NS_ENSURE_ARG(aCreator);
+
+ FSSpec fileSpec;
+ (void)GetFSSpec(&fileSpec);
+
+ FInfo info;
+ OSErr err = ::FSpGetFInfo(&fileSpec, &info);
+ if (err != noErr)
+ {
+ *aCreator = mCreator;
+ return NS_ERROR_FILE_NOT_FOUND;
+ }
+
+ *aCreator = info.fdCreator;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::SetFileCreator(OSType aCreator)
+{
+ if (aCreator == CURRENT_PROCESS_CREATOR)
+ aCreator = sCurrentProcessSignature;
+
+ mCreator = aCreator;
+
+ FSSpec fileSpec;
+ (void)GetFSSpec(&fileSpec);
+
+ FInfo info;
+ OSErr err = ::FSpGetFInfo(&fileSpec, &info);
+ if (err != noErr)
+ return NS_ERROR_FILE_NOT_FOUND;
+
+ info.fdCreator = aCreator;
+ err = ::FSpSetFInfo(&fileSpec, &info);
+ if (err != noErr)
+ return NS_ERROR_FILE_ACCESS_DENIED;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::SetFileTypeAndCreatorFromExtension(const char *aExtension)
+{
+ NS_ENSURE_ARG(aExtension);
+ return SetOSTypeAndCreatorFromExtension(aExtension);
+}
+
+NS_IMETHODIMP nsLocalFile::SetFileTypeAndCreatorFromMIMEType(const char *aMIMEType)
+{
+ NS_ENSURE_ARG(aMIMEType);
+
+ nsresult rv;
+ nsCOMPtr<nsIInternetConfigService> icService(do_GetService
+ (NS_INTERNETCONFIGSERVICE_CONTRACTID, &rv));
+
+ if (NS_SUCCEEDED(rv))
+ {
+ nsCOMPtr<nsIMIMEInfo> mimeInfo;
+ PRUint32 fileType = 'TEXT';
+ PRUint32 fileCreator = nsILocalFileMac::CURRENT_PROCESS_CREATOR;
+
+ rv = icService->FillInMIMEInfo(aMIMEType,
+ nsnull, getter_AddRefs(mimeInfo));
+ if (NS_SUCCEEDED(rv))
+ rv = mimeInfo->GetMacType(&fileType);
+ if (NS_SUCCEEDED(rv))
+ rv = mimeInfo->GetMacCreator(&fileCreator);
+ if (NS_SUCCEEDED(rv))
+ rv = SetFileType(fileType);
+ if (NS_SUCCEEDED(rv))
+ rv = SetFileCreator(fileCreator);
+ }
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetFileSizeWithResFork(PRInt64 *aFileSize)
+{
+ NS_ENSURE_ARG(aFileSize);
+
+ *aFileSize = LL_Zero();
+
+ ResolveAndStat();
+
+ long dataSize = 0;
+ long resSize = 0;
+
+ OSErr err = FSpGetFileSize(&mTargetSpec, &dataSize, &resSize);
+
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ // For now we've only got 32 bits of file size info
+ PRInt64 dataInt64 = LL_Zero();
+ PRInt64 resInt64 = LL_Zero();
+
+ // Combine the size of the resource and data forks
+ LL_I2L(resInt64, resSize);
+ LL_I2L(dataInt64, dataSize);
+ LL_ADD((*aFileSize), dataInt64, resInt64);
+
+ return NS_OK;
+}
+
+
+// this nsLocalFile points to the app. We want to launch it, optionally with the document.
+NS_IMETHODIMP
+nsLocalFile::LaunchWithDoc(nsILocalFile* aDocToLoad, PRBool aLaunchInBackground)
+{
+ // are we launchable?
+ PRBool isExecutable;
+ nsresult rv = IsExecutable(&isExecutable);
+ if (NS_FAILED(rv)) return rv;
+ if (!isExecutable) return NS_ERROR_FILE_EXECUTION_FAILED;
+
+ FSSpec docSpec;
+ FSSpecPtr docSpecPtr = nsnull;
+
+ nsCOMPtr<nsILocalFileMac> macDoc = do_QueryInterface(aDocToLoad);
+ if (macDoc)
+ {
+ rv = macDoc->GetFSSpec(&docSpec); // XXX GetTargetFSSpec
+ if (NS_FAILED(rv)) return rv;
+
+ docSpecPtr = &docSpec;
+ }
+
+ FSSpec appSpec;
+ rv = GetFSSpec(&appSpec); // XXX GetResolvedFSSpec
+ if (NS_FAILED(rv)) return rv;
+
+ rv = MyLaunchAppWithDoc(appSpec, docSpecPtr, aLaunchInBackground);
+ return rv;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::OpenDocWithApp(nsILocalFile* aAppToOpenWith, PRBool aLaunchInBackground)
+{
+ // if aAppToOpenWith is nil, we have to find the app from the creator code
+ // of the document
+ nsresult rv = NS_OK;
+
+ FSSpec appSpec;
+
+ if (aAppToOpenWith)
+ {
+ nsCOMPtr<nsILocalFileMac> appFileMac = do_QueryInterface(aAppToOpenWith, &rv);
+ if (!appFileMac) return rv;
+
+ rv = appFileMac->GetFSSpec(&appSpec); // XXX GetTargetFSSpec
+ if (NS_FAILED(rv)) return rv;
+
+ // is it launchable?
+ PRBool isExecutable;
+ rv = aAppToOpenWith->IsExecutable(&isExecutable);
+ if (NS_FAILED(rv)) return rv;
+ if (!isExecutable) return NS_ERROR_FILE_EXECUTION_FAILED;
+ }
+ else
+ {
+ // look for one
+ OSType fileCreator;
+ rv = GetFileCreator(&fileCreator);
+ if (NS_FAILED(rv)) return rv;
+
+ // just make one on the stack
+ nsLocalFile localAppFile;
+ rv = localAppFile.InitToAppWithCreatorCode(fileCreator);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = localAppFile.GetFSSpec(&appSpec); // GetTargetFSSpec
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ FSSpec docSpec;
+ rv = GetFSSpec(&docSpec); // XXX GetResolvedFSSpec
+ if (NS_FAILED(rv)) return rv;
+
+ rv = MyLaunchAppWithDoc(appSpec, &docSpec, aLaunchInBackground);
+ return rv;
+}
+
+nsresult nsLocalFile::SetOSTypeAndCreatorFromExtension(const char* extension)
+{
+ nsresult rv;
+
+ nsCAutoString localExtBuf;
+ const char *extPtr;
+
+ if (!extension)
+ {
+ rv = GetNativeLeafName(localExtBuf);
+ extPtr = strrchr(localExtBuf.get(), '.');
+ if (!extPtr)
+ return NS_ERROR_FAILURE;
+ ++extPtr;
+ }
+ else
+ {
+ extPtr = extension;
+ if (*extPtr == '.')
+ ++extPtr;
+ }
+
+ nsCOMPtr<nsIInternetConfigService> icService =
+ do_GetService(NS_INTERNETCONFIGSERVICE_CONTRACTID, &rv);
+ if (NS_SUCCEEDED(rv))
+ {
+ nsCOMPtr<nsIMIMEInfo> mimeInfo;
+ rv = icService->GetMIMEInfoFromExtension(extPtr, getter_AddRefs(mimeInfo));
+ if (NS_SUCCEEDED(rv))
+ {
+ PRUint32 osType;
+ rv = mimeInfo->GetMacType(&osType);
+ if (NS_SUCCEEDED(rv))
+ mType = osType;
+ PRBool skip;
+ rv = ExtensionIsOnExceptionList(extPtr, &skip);
+ if (NS_SUCCEEDED(rv) && !skip)
+ {
+ rv = mimeInfo->GetMacCreator(&osType);
+ if (NS_SUCCEEDED(rv))
+ mCreator = osType;
+ }
+ }
+ }
+ return rv;
+}
+
+nsresult nsLocalFile::ExtensionIsOnExceptionList(const char *extension, PRBool *onList)
+{
+ // Probably want to make a global list somewhere in the future
+ // for now, just check for "html" and "htm"
+
+ *onList = PR_FALSE;
+
+ if (!nsCRT::strcasecmp(extension, "html") ||
+ !nsCRT::strcasecmp(extension, "htm"))
+ *onList = PR_TRUE;
+ return NS_OK;
+}
+
+
+void nsLocalFile::InitClassStatics()
+{
+ OSErr err;
+
+
+ if (sCurrentProcessSignature == 0)
+ {
+ ProcessSerialNumber psn;
+ ProcessInfoRec info;
+
+ psn.highLongOfPSN = 0;
+ psn.lowLongOfPSN = kCurrentProcess;
+
+ info.processInfoLength = sizeof(ProcessInfoRec);
+ info.processName = nil;
+ info.processAppSpec = nil;
+ err = ::GetProcessInformation(&psn, &info);
+ if (err == noErr)
+ sCurrentProcessSignature = info.processSignature;
+ // Try again next time if error
+ }
+
+ static PRBool didHFSPlusCheck = PR_FALSE;
+ if (!didHFSPlusCheck)
+ {
+ long response;
+ err = ::Gestalt(gestaltFSAttr, &response);
+ sHasHFSPlusAPIs = (err == noErr && (response & (1 << gestaltHasHFSPlusAPIs)) != 0);
+ didHFSPlusCheck = PR_TRUE;
+ }
+
+ static PRBool didOSXCheck = PR_FALSE;
+ if (!didOSXCheck)
+ {
+ long version;
+ sRunningOSX = (::Gestalt(gestaltSystemVersion, &version) == noErr && version >= 0x00001000);
+ didOSXCheck = PR_TRUE;
+ }
+}
+
+
+#pragma mark -
+
+// Handy dandy utility create routine for something or the other
+nsresult
+NS_NewNativeLocalFile(const nsACString &path, PRBool followLinks, nsILocalFile* *result)
+{
+ nsLocalFile* file = new nsLocalFile();
+ if (file == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(file);
+
+ file->SetFollowLinks(followLinks);
+
+ if (!path.IsEmpty()) {
+ nsresult rv = file->InitWithNativePath(path);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(file);
+ return rv;
+ }
+ }
+ *result = file;
+ return NS_OK;
+}
+
+nsresult
+NS_NewLocalFile(const nsAString &path, PRBool followLinks, nsILocalFile* *result)
+{
+ nsCAutoString fsCharSetStr;
+ nsresult rv = NS_CopyUnicodeToNative(path, fsCharSetStr);
+ if (NS_FAILED(rv))
+ return rv;
+ return NS_NewNativeLocalFile(fsCharSetStr, followLinks, result);
+}
+
+nsresult
+NS_NewLocalFileWithFSSpec(const FSSpec* inSpec, PRBool followLinks, nsILocalFileMac* *result)
+{
+ nsLocalFile* file = new nsLocalFile();
+ if (file == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(file);
+
+ file->SetFollowLinks(followLinks);
+
+ nsresult rv = file->InitWithFSSpec(inSpec);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(file);
+ return rv;
+ }
+ *result = file;
+ return NS_OK;
+}
+
+void
+nsLocalFile::GlobalInit()
+{
+}
+
+void
+nsLocalFile::GlobalShutdown()
+{
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFileMac.h b/src/libs/xpcom18a4/xpcom/io/nsLocalFileMac.h
new file mode 100644
index 00000000..42eb2556
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFileMac.h
@@ -0,0 +1,137 @@
+/* -*- 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 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):
+ * Steve Dagley <sdagley@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 _nsLocalFileMAC_H_
+#define _nsLocalFileMAC_H_
+
+#include "nscore.h"
+#include "nsError.h"
+#include "nsString.h"
+#include "nsCRT.h"
+#include "nsIFile.h"
+#include "nsILocalFileMac.h"
+#include "nsIFactory.h"
+
+#include <Processes.h>
+
+class NS_COM nsLocalFile : public nsILocalFileMac
+{
+public:
+ NS_DEFINE_STATIC_CID_ACCESSOR(NS_LOCAL_FILE_CID)
+
+ nsLocalFile();
+
+ static NS_METHOD nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+
+ // nsIFile interface
+ NS_DECL_NSIFILE
+
+ // nsILocalFile interface
+ NS_DECL_NSILOCALFILE
+
+ // nsILocalFileMac interface
+ NS_DECL_NSILOCALFILEMAC
+
+public:
+
+ static void GlobalInit();
+ static void GlobalShutdown();
+
+private:
+ ~nsLocalFile() {}
+
+protected:
+ void MakeDirty();
+ nsresult ResolveAndStat();
+ nsresult UpdateCachedCatInfo(PRBool forceUpdate);
+
+ nsresult FindAppOnLocalVolumes(OSType sig, FSSpec &outSpec);
+
+ nsresult FindRunningAppBySignature(OSType sig, FSSpec& outSpec, ProcessSerialNumber& outPsn);
+ nsresult FindRunningAppByFSSpec(const FSSpec& appSpec, ProcessSerialNumber& outPsn);
+
+ nsresult MyLaunchAppWithDoc(const FSSpec& appSpec, const FSSpec* aDocToLoad, PRBool aLaunchInBackground);
+
+ nsresult TestFinderFlag(PRUint16 flagMask, PRBool *outFlagSet, PRBool testTargetSpec = PR_TRUE);
+
+ nsresult MoveCopy( nsIFile* newParentDir, const nsACString &newName, PRBool isCopy, PRBool followLinks );
+
+ // Passing nsnull for the extension uses leaf name
+ nsresult SetOSTypeAndCreatorFromExtension(const char* extension = nsnull);
+
+ nsresult ExtensionIsOnExceptionList(const char *extension, PRBool *onList);
+
+private:
+ nsLocalFile(const nsLocalFile& srcFile);
+ nsLocalFile(const FSSpec& aSpec, const nsACString& aAppendedPath);
+
+ // Copies all members except mRefCnt, copies mCachedCatInfo only if it's valid.
+ nsLocalFile& operator=(const nsLocalFile& rhs);
+
+ PRPackedBool mFollowLinks;
+ PRPackedBool mFollowLinksDirty;
+
+ // The object we specify is always: mSpec + mAppendedPath.
+ // mSpec is a valid spec in that its parent is known to exist.
+ // Appending nodes with Append() will update mSpec immediately
+ // if the appended node exists. If not, appended nodes are stored
+ // in mAppendedPath.
+
+ PRPackedBool mSpecDirty;
+ FSSpec mSpec;
+ nsCString mAppendedPath;
+ FSSpec mTargetSpec; // If mSpec is an alias, this is the resolved alias.
+
+ CInfoPBRec mCachedCatInfo; // cached file info, for the GetFSSpec() spec
+ PRPackedBool mCatInfoDirty; // does this need to be updated?
+
+ OSType mType, mCreator;
+
+ static void InitClassStatics();
+
+ static OSType sCurrentProcessSignature;
+ static PRBool sHasHFSPlusAPIs;
+ static PRBool sRunningOSX;
+};
+
+#endif
+
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFileOS2.cpp b/src/libs/xpcom18a4/xpcom/io/nsLocalFileOS2.cpp
new file mode 100644
index 00000000..269a13d0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFileOS2.cpp
@@ -0,0 +1,1742 @@
+/* -*- 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-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henry Sobotka <sobotka@axess.com>
+ * IBM Corp.
+ *
+ * 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 "nsCOMPtr.h"
+#include "nsMemory.h"
+
+#include "nsLocalFile.h"
+#include "nsNativeCharsetUtils.h"
+
+#include "nsISimpleEnumerator.h"
+#include "nsIComponentManager.h"
+#include "prtypes.h"
+#include "prio.h"
+
+#include <ctype.h> // needed for toupper
+#include <string.h>
+
+#include "nsXPIDLString.h"
+#include "nsReadableUtils.h"
+#include "prproces.h"
+#include "prthread.h"
+
+
+static unsigned char* PR_CALLBACK
+_mbschr( const unsigned char* stringToSearch, int charToSearchFor);
+extern unsigned char*
+_mbsrchr( const unsigned char* stringToSearch, int charToSearchFor);
+static nsresult PR_CALLBACK
+CreateDirectoryA( PSZ path, PEAOP2 ppEABuf);
+static int isleadbyte(int c);
+
+#include <unistd.h>
+#include <io.h>
+
+
+static nsresult ConvertOS2Error(int err)
+{
+ nsresult rv;
+
+ switch (err)
+ {
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_PATH_NOT_FOUND:
+ case ERROR_INVALID_DRIVE:
+ rv = NS_ERROR_FILE_NOT_FOUND;
+ break;
+ case ERROR_ACCESS_DENIED:
+ case ERROR_NOT_SAME_DEVICE:
+ rv = NS_ERROR_FILE_ACCESS_DENIED;
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ case ERROR_INVALID_BLOCK:
+ case ERROR_INVALID_HANDLE:
+ case ERROR_ARENA_TRASHED:
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ case ERROR_CURRENT_DIRECTORY:
+ rv = NS_ERROR_FILE_DIR_NOT_EMPTY;
+ break;
+ case ERROR_WRITE_PROTECT:
+ rv = NS_ERROR_FILE_READ_ONLY;
+ break;
+ case ERROR_HANDLE_DISK_FULL:
+ rv = NS_ERROR_FILE_TOO_BIG;
+ break;
+ case ERROR_FILE_EXISTS:
+ case ERROR_ALREADY_EXISTS:
+ case ERROR_CANNOT_MAKE:
+ rv = NS_ERROR_FILE_ALREADY_EXISTS;
+ break;
+ case 0:
+ rv = NS_OK;
+ break;
+ default:
+ rv = NS_ERROR_FAILURE;
+ break;
+ }
+ return rv;
+}
+
+static void
+myLL_L2II(PRInt64 result, PRInt32 *hi, PRInt32 *lo )
+{
+ PRInt64 a64, b64; // probably could have been done with
+ // only one PRInt64, but these are macros,
+ // and I am a wimp.
+
+ // shift the hi word to the low word, then push it into a long.
+ LL_SHR(a64, result, 32);
+ LL_L2I(*hi, a64);
+
+ // shift the low word to the hi word first, then shift it back.
+ LL_SHL(b64, result, 32);
+ LL_SHR(a64, b64, 32);
+ LL_L2I(*lo, a64);
+}
+
+
+class nsDirEnumerator : public nsISimpleEnumerator
+{
+ public:
+
+ NS_DECL_ISUPPORTS
+
+ nsDirEnumerator() : mDir(nsnull)
+ {
+ }
+
+ nsresult Init(nsILocalFile* parent)
+ {
+ nsCAutoString filepath;
+ parent->GetNativeTarget(filepath);
+
+ if (filepath.IsEmpty())
+ {
+ parent->GetNativePath(filepath);
+ }
+
+ if (filepath.IsEmpty())
+ {
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ mDir = PR_OpenDir(filepath.get());
+ if (mDir == nsnull) // not a directory?
+ return NS_ERROR_FAILURE;
+
+ mParent = parent;
+ return NS_OK;
+ }
+
+ NS_IMETHOD HasMoreElements(PRBool *result)
+ {
+ nsresult rv;
+ if (mNext == nsnull && mDir)
+ {
+ PRDirEntry* entry = PR_ReadDir(mDir, PR_SKIP_BOTH);
+ if (entry == nsnull)
+ {
+ // end of dir entries
+
+ PRStatus status = PR_CloseDir(mDir);
+ if (status != PR_SUCCESS)
+ return NS_ERROR_FAILURE;
+ mDir = nsnull;
+
+ *result = PR_FALSE;
+ return NS_OK;
+ }
+
+ nsCOMPtr<nsIFile> file;
+ rv = mParent->Clone(getter_AddRefs(file));
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = file->AppendNative(nsDependentCString(entry->name));
+ if (NS_FAILED(rv))
+ return rv;
+
+ // make sure the thing exists. If it does, try the next one.
+ PRBool exists;
+ rv = file->Exists(&exists);
+ if (NS_FAILED(rv) || !exists)
+ {
+ return HasMoreElements(result);
+ }
+
+ mNext = do_QueryInterface(file);
+ }
+ *result = mNext != nsnull;
+ return NS_OK;
+ }
+
+ NS_IMETHOD GetNext(nsISupports **result)
+ {
+ nsresult rv;
+ PRBool hasMore;
+ rv = HasMoreElements(&hasMore);
+ if (NS_FAILED(rv)) return rv;
+
+ *result = mNext; // might return nsnull
+ NS_IF_ADDREF(*result);
+
+ mNext = nsnull;
+ return NS_OK;
+ }
+
+ private:
+ ~nsDirEnumerator()
+ {
+ if (mDir)
+ {
+ PRStatus status = PR_CloseDir(mDir);
+ NS_ASSERTION(status == PR_SUCCESS, "close failed");
+ }
+ }
+
+ protected:
+ PRDir* mDir;
+ nsCOMPtr<nsILocalFile> mParent;
+ nsCOMPtr<nsILocalFile> mNext;
+};
+
+NS_IMPL_ISUPPORTS1(nsDirEnumerator, nsISimpleEnumerator)
+
+
+nsLocalFile::nsLocalFile()
+{
+ MakeDirty();
+}
+
+nsLocalFile::nsLocalFile(const nsLocalFile& other)
+ : mDirty(other.mDirty)
+ , mWorkingPath(other.mWorkingPath)
+ , mFileInfo64(other.mFileInfo64)
+{
+}
+
+/* nsISupports interface implementation. */
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsLocalFile, nsILocalFile, nsIFile)
+
+NS_METHOD
+nsLocalFile::nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
+{
+ NS_ENSURE_ARG_POINTER(aInstancePtr);
+ NS_ENSURE_NO_AGGREGATION(outer);
+
+ nsLocalFile* inst = new nsLocalFile();
+ if (inst == NULL)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = inst->QueryInterface(aIID, aInstancePtr);
+ if (NS_FAILED(rv))
+ {
+ delete inst;
+ return rv;
+ }
+ return NS_OK;
+}
+
+// This function resets any cached information about the file.
+void
+nsLocalFile::MakeDirty()
+{
+ mDirty = PR_TRUE;
+}
+
+nsresult
+nsLocalFile::Stat()
+{
+ if (!mDirty)
+ return NS_OK;
+
+ char temp[4];
+ const char* workingFilePath = mWorkingPath.get();
+ const char* nsprPath = workingFilePath;
+
+ if (mWorkingPath.Length() == 2 && mWorkingPath.CharAt(1) == ':') {
+ temp[0] = workingFilePath[0];
+ temp[1] = workingFilePath[1];
+ temp[2] = '\\';
+ temp[3] = '\0';
+ nsprPath = temp;
+ }
+
+ DosError(FERR_DISABLEHARDERR);
+ PRStatus status = PR_GetFileInfo64(nsprPath, &mFileInfo64);
+ DosError(FERR_ENABLEHARDERR);
+ if ( status == PR_SUCCESS )
+ return NS_OK;
+
+ return NS_ERROR_FILE_NOT_FOUND;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Clone(nsIFile **file)
+{
+ // Just copy-construct ourselves
+ *file = new nsLocalFile(*this);
+ if (!*file)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(*file);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::InitWithNativePath(const nsACString &filePath)
+{
+ MakeDirty();
+
+ nsACString::const_iterator begin, end;
+ filePath.BeginReading(begin);
+ filePath.EndReading(end);
+
+ // input string must not be empty
+ if (begin == end)
+ return NS_ERROR_FAILURE;
+
+ char firstChar = *begin;
+ char secondChar = *(++begin);
+
+ // just do a sanity check. if it has any forward slashes, it is not a Native path
+ // on windows. Also, it must have a colon at after the first char.
+
+ char *path = nsnull;
+ PRInt32 pathLen = 0;
+
+ if ( ( (secondChar == ':') && !FindCharInReadable('/', begin, end) ) || // normal path
+ ( (firstChar == '\\') && (secondChar == '\\') ) ) // network path
+ {
+ // This is a native path
+ path = ToNewCString(filePath);
+ pathLen = filePath.Length();
+ }
+
+ if (path == nsnull)
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ // kill any trailing '\' provided it isn't the second char of DBCS
+ PRInt32 len = pathLen - 1;
+ if (path[len] == '\\' && !::isleadbyte(path[len-1]))
+ {
+ path[len] = '\0';
+ pathLen = len;
+ }
+
+ mWorkingPath.Adopt(path, pathLen);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::OpenNSPRFileDesc(PRInt32 flags, PRInt32 mode, PRFileDesc **_retval)
+{
+ nsresult rv = Stat();
+ if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
+ return rv;
+
+ *_retval = PR_Open(mWorkingPath.get(), flags, mode);
+
+ if (*_retval)
+ return NS_OK;
+
+ return NS_ErrorAccordingToNSPR();
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::OpenANSIFileDesc(const char *mode, FILE * *_retval)
+{
+ nsresult rv = Stat();
+ if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
+ return rv;
+
+ *_retval = fopen(mWorkingPath.get(), mode);
+
+ if (*_retval)
+ return NS_OK;
+
+ return NS_ERROR_FAILURE;
+}
+
+
+
+NS_IMETHODIMP
+nsLocalFile::Create(PRUint32 type, PRUint32 attributes)
+{
+ if (type != NORMAL_FILE_TYPE && type != DIRECTORY_TYPE)
+ return NS_ERROR_FILE_UNKNOWN_TYPE;
+
+ nsresult rv = Stat();
+ if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
+ return rv;
+
+ // create nested directories to target
+ unsigned char* slash = _mbschr((const unsigned char*) mWorkingPath.get(), '\\');
+
+
+ if (slash)
+ {
+ // skip the first '\\'
+ ++slash;
+ slash = _mbschr(slash, '\\');
+
+ while (slash)
+ {
+ *slash = '\0';
+
+ rv = CreateDirectoryA(NS_CONST_CAST(char*, mWorkingPath.get()), NULL);
+ if (rv) {
+ rv = ConvertOS2Error(rv);
+ if (rv != NS_ERROR_FILE_ALREADY_EXISTS) return rv;
+ }
+ *slash = '\\';
+ ++slash;
+ slash = _mbschr(slash, '\\');
+ }
+ }
+
+ if (type == NORMAL_FILE_TYPE)
+ {
+ PRFileDesc* file = PR_Open(mWorkingPath.get(), PR_RDONLY | PR_CREATE_FILE | PR_APPEND | PR_EXCL, attributes);
+ if (!file) return NS_ERROR_FILE_ALREADY_EXISTS;
+
+ PR_Close(file);
+ return NS_OK;
+ }
+
+ if (type == DIRECTORY_TYPE)
+ {
+ rv = CreateDirectoryA(NS_CONST_CAST(char*, mWorkingPath.get()), NULL);
+ if (rv)
+ return ConvertOS2Error(rv);
+ else
+ return NS_OK;
+ }
+
+ return NS_ERROR_FILE_UNKNOWN_TYPE;
+}
+
+NS_IMETHODIMP
+nsLocalFile::AppendNative(const nsACString &node)
+{
+ if (node.IsEmpty())
+ return NS_OK;
+
+ // Append only one component. Check for subdirs.
+ // XXX can we avoid the PromiseFlatCString call?
+ if (_mbschr((const unsigned char*) PromiseFlatCString(node).get(), '\\') != nsnull)
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ return AppendRelativeNativePath(node);
+}
+
+NS_IMETHODIMP
+nsLocalFile::AppendRelativeNativePath(const nsACString &node)
+{
+ // Cannot start with a / or have .. or have / anywhere
+ nsACString::const_iterator begin, end;
+ node.BeginReading(begin);
+ node.EndReading(end);
+ if (node.IsEmpty() || FindCharInReadable('/', begin, end))
+ {
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+ }
+ MakeDirty();
+ mWorkingPath.Append(NS_LITERAL_CSTRING("\\") + node);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Normalize()
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetNativeLeafName(nsACString &aLeafName)
+{
+ aLeafName.Truncate();
+
+ const char* temp = mWorkingPath.get();
+ if(temp == nsnull)
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ const char* leaf = (const char*) _mbsrchr((const unsigned char*) temp, '\\');
+
+ // if the working path is just a node without any lashes.
+ if (leaf == nsnull)
+ leaf = temp;
+ else
+ leaf++;
+
+ aLeafName.Assign(leaf);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetNativeLeafName(const nsACString &aLeafName)
+{
+ MakeDirty();
+
+ const unsigned char* temp = (const unsigned char*) mWorkingPath.get();
+ if(temp == nsnull)
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ // cannot use nsCString::RFindChar() due to 0x5c problem
+ PRInt32 offset = (PRInt32) (_mbsrchr(temp, '\\') - temp);
+ if (offset)
+ {
+ mWorkingPath.Truncate(offset+1);
+ }
+ mWorkingPath.Append(aLeafName);
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::GetNativePath(nsACString &_retval)
+{
+ _retval = mWorkingPath;
+ return NS_OK;
+}
+
+nsresult
+nsLocalFile::CopySingleFile(nsIFile *sourceFile, nsIFile *destParent, const nsACString &newName, PRBool move)
+{
+ nsresult rv;
+ nsCAutoString filePath;
+
+ nsCAutoString destPath;
+ destParent->GetNativeTarget(destPath);
+
+ destPath.Append("\\");
+
+ if (newName.IsEmpty())
+ {
+ nsCAutoString aFileName;
+ sourceFile->GetNativeLeafName(aFileName);
+ destPath.Append(aFileName);
+ }
+ else
+ {
+ destPath.Append(newName);
+ }
+
+ rv = sourceFile->GetNativePath(filePath);
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ APIRET rc = NO_ERROR;
+
+ if( move )
+ {
+ rc = DosMove(filePath.get(), (PSZ)NS_CONST_CAST(char*, destPath.get()));
+ }
+
+ if (!move || rc == ERROR_NOT_SAME_DEVICE || rc == ERROR_ACCESS_DENIED) {
+ /* will get an error if the destination and source files aren't on the
+ * same drive. "MoveFile()" on Windows will go ahead and move the
+ * file without error, so we need to do the same IBM-AKR
+ */
+ do {
+ rc = DosCopy(filePath.get(), (PSZ)NS_CONST_CAST(char*, destPath.get()), DCPY_EXISTING);
+ if (rc == ERROR_TOO_MANY_OPEN_FILES) {
+ ULONG CurMaxFH = 0;
+ LONG ReqCount = 20;
+ APIRET rc2;
+ rc2 = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
+ if (rc2 != NO_ERROR) {
+ break;
+ }
+ }
+ } while (rc == ERROR_TOO_MANY_OPEN_FILES);
+
+ /* WSOD2 HACK */
+ if (rc == 65) { // NETWORK_ACCESS_DENIED
+ CHAR achProgram[CCHMAXPATH]; // buffer for program name, parameters
+ RESULTCODES rescResults; // buffer for results of dosexecpgm
+
+ strcpy(achProgram, "CMD.EXE /C ");
+ strcat(achProgram, """COPY ");
+ strcat(achProgram, filePath.get());
+ strcat(achProgram, " ");
+ strcat(achProgram, (PSZ)NS_CONST_CAST(char*, destPath.get()));
+ strcat(achProgram, """");
+ achProgram[strlen(achProgram) + 1] = '\0';
+ achProgram[7] = '\0';
+ DosExecPgm(NULL, 0,
+ EXEC_SYNC, achProgram, (PSZ)NULL,
+ &rescResults, achProgram);
+ rc = 0; // Assume it worked
+
+ } /* rc == 65 */
+ /* moving the file is supposed to act like a rename, so delete the
+ * original file if we got this far without error
+ */
+ if( move && (rc == NO_ERROR) )
+ {
+ DosDelete( filePath.get() );
+ }
+ } /* !move or ERROR */
+
+ if (rc)
+ rv = ConvertOS2Error(rc);
+
+ return rv;
+}
+
+
+nsresult
+nsLocalFile::CopyMove(nsIFile *aParentDir, const nsACString &newName, PRBool move)
+{
+ nsCOMPtr<nsIFile> newParentDir = aParentDir;
+
+ nsresult rv = Stat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (!newParentDir)
+ {
+ // no parent was specified. We must rename.
+
+ if (newName.IsEmpty())
+ return NS_ERROR_INVALID_ARG;
+
+ rv = GetParent(getter_AddRefs(newParentDir));
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ if (!newParentDir)
+ return NS_ERROR_FILE_DESTINATION_NOT_DIR;
+
+ // make sure it exists and is a directory. Create it if not there.
+ PRBool exists;
+ newParentDir->Exists(&exists);
+ if (exists == PR_FALSE)
+ {
+ rv = newParentDir->Create(DIRECTORY_TYPE, 0644); // TODO, what permissions should we use
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ else
+ {
+ PRBool isDir;
+ newParentDir->IsDirectory(&isDir);
+ if (isDir == PR_FALSE)
+ {
+ return NS_ERROR_FILE_DESTINATION_NOT_DIR;
+ }
+ }
+
+ // check to see if we are a directory, if so enumerate it.
+
+ PRBool isDir;
+ IsDirectory(&isDir);
+
+ if (!isDir)
+ {
+ rv = CopySingleFile(this, newParentDir, newName, move);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ else
+ {
+ // create a new target destination in the new parentDir;
+ nsCOMPtr<nsIFile> target;
+ rv = newParentDir->Clone(getter_AddRefs(target));
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCAutoString allocatedNewName;
+ if (newName.IsEmpty())
+ {
+ GetNativeLeafName(allocatedNewName);// this should be the leaf name of the
+ }
+ else
+ {
+ allocatedNewName = newName;
+ }
+
+ rv = target->AppendNative(allocatedNewName);
+ if (NS_FAILED(rv))
+ return rv;
+
+ allocatedNewName.Truncate();
+
+ target->Create(DIRECTORY_TYPE, 0644); // TODO, what permissions should we use
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsDirEnumerator* dirEnum = new nsDirEnumerator();
+ if (!dirEnum)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ rv = dirEnum->Init(this);
+
+ nsCOMPtr<nsISimpleEnumerator> iterator = do_QueryInterface(dirEnum);
+
+ PRBool more;
+ iterator->HasMoreElements(&more);
+ while (more)
+ {
+ nsCOMPtr<nsISupports> item;
+ nsCOMPtr<nsIFile> file;
+ iterator->GetNext(getter_AddRefs(item));
+ file = do_QueryInterface(item);
+ PRBool isDir, isLink;
+
+ file->IsDirectory(&isDir);
+
+ if (move)
+ {
+ rv = file->MoveToNative(target, nsCString());
+ }
+ else
+ {
+ rv = file->CopyToNative(target, nsCString());
+ }
+
+ iterator->HasMoreElements(&more);
+ }
+ // we've finished moving all the children of this directory
+ // in the new directory. so now delete the directory
+ // note, we don't need to do a recursive delete.
+ // MoveTo() is recursive. At this point,
+ // we've already moved the children of the current folder
+ // to the new location. nothing should be left in the folder.
+ if (move)
+ {
+ rv = Remove(PR_FALSE);
+ NS_ENSURE_SUCCESS(rv,rv);
+ }
+ }
+
+
+ // If we moved, we want to adjust this.
+ if (move)
+ {
+ MakeDirty();
+
+ nsCAutoString newParentPath;
+ newParentDir->GetNativePath(newParentPath);
+
+ if (newParentPath.IsEmpty())
+ return NS_ERROR_FAILURE;
+
+ if (newName.IsEmpty())
+ {
+ nsCAutoString aFileName;
+ GetNativeLeafName(aFileName);
+
+ InitWithNativePath(newParentPath);
+ AppendNative(aFileName);
+ }
+ else
+ {
+ InitWithNativePath(newParentPath);
+ AppendNative(newName);
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::CopyToNative(nsIFile *newParentDir, const nsACString &newName)
+{
+ return CopyMove(newParentDir, newName, PR_FALSE);
+}
+
+NS_IMETHODIMP
+nsLocalFile::CopyToFollowingLinksNative(nsIFile *newParentDir, const nsACString &newName)
+{
+ return CopyMove(newParentDir, newName, PR_FALSE);
+}
+
+NS_IMETHODIMP
+nsLocalFile::MoveToNative(nsIFile *newParentDir, const nsACString &newName)
+{
+ return CopyMove(newParentDir, newName, PR_TRUE);
+}
+
+NS_IMETHODIMP
+nsLocalFile::Load(PRLibrary * *_retval)
+{
+ PRBool isFile;
+ nsresult rv = IsFile(&isFile);
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (! isFile)
+ return NS_ERROR_FILE_IS_DIRECTORY;
+
+ *_retval = PR_LoadLibrary(mWorkingPath.get());
+
+ if (*_retval)
+ return NS_OK;
+
+ return NS_ERROR_NULL_POINTER;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Remove(PRBool recursive)
+{
+ PRBool isDir;
+
+ nsresult rv = IsDirectory(&isDir);
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char *filePath = mWorkingPath.get();
+
+ if (isDir)
+ {
+ if (recursive)
+ {
+ nsDirEnumerator* dirEnum = new nsDirEnumerator();
+ if (dirEnum == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ rv = dirEnum->Init(this);
+
+ nsCOMPtr<nsISimpleEnumerator> iterator = do_QueryInterface(dirEnum);
+
+ PRBool more;
+ iterator->HasMoreElements(&more);
+ while (more)
+ {
+ nsCOMPtr<nsISupports> item;
+ nsCOMPtr<nsIFile> file;
+ iterator->GetNext(getter_AddRefs(item));
+ file = do_QueryInterface(item);
+
+ file->Remove(recursive);
+
+ iterator->HasMoreElements(&more);
+ }
+ }
+ rv = rmdir(filePath) == -1 ? NSRESULT_FOR_ERRNO() : NS_OK;
+ }
+ else
+ {
+ rv = remove(filePath) == -1 ? NSRESULT_FOR_ERRNO() : NS_OK;
+ }
+
+ MakeDirty();
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetLastModifiedTime(PRInt64 *aLastModifiedTime)
+{
+ NS_ENSURE_ARG(aLastModifiedTime);
+
+ *aLastModifiedTime = 0;
+
+ nsresult rv = Stat();
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ // microseconds -> milliseconds
+ *aLastModifiedTime = mFileInfo64.modifyTime / PR_USEC_PER_MSEC;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::GetLastModifiedTimeOfLink(PRInt64 *aLastModifiedTime)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::SetLastModifiedTime(PRInt64 aLastModifiedTime)
+{
+ return nsLocalFile::SetModDate(aLastModifiedTime);
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::SetLastModifiedTimeOfLink(PRInt64 aLastModifiedTime)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+nsLocalFile::SetModDate(PRInt64 aLastModifiedTime)
+{
+ nsresult rv = Stat();
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char *filePath = mWorkingPath.get();
+
+ PRExplodedTime pret;
+ FILESTATUS3 pathInfo;
+
+ rv = DosQueryPathInfo(filePath,
+ FIL_STANDARD, // Level 1 info
+ &pathInfo,
+ sizeof(pathInfo));
+
+ if (NS_FAILED(rv))
+ {
+ rv = ConvertOS2Error(rv);
+ return rv;
+ }
+
+ // PR_ExplodeTime expects usecs...
+ PR_ExplodeTime(aLastModifiedTime * PR_USEC_PER_MSEC, PR_LocalTimeParameters, &pret);
+ /* fdateLastWrite.year is based off of 1980 */
+ if (pret.tm_year >= 1980)
+ pathInfo.fdateLastWrite.year = pret.tm_year-1980;
+ else
+ pathInfo.fdateLastWrite.year = pret.tm_year;
+ pathInfo.fdateLastWrite.month = pret.tm_month + 1; // Convert start offset -- Win32: Jan=1; NSPR: Jan=0
+// ???? OS2TODO st.wDayOfWeek = pret.tm_wday;
+ pathInfo.fdateLastWrite.day = pret.tm_mday;
+ pathInfo.ftimeLastWrite.hours = pret.tm_hour;
+ pathInfo.ftimeLastWrite.minutes = pret.tm_min;
+ pathInfo.ftimeLastWrite.twosecs = pret.tm_sec / 2; // adjust for twosecs?
+// ??? OS2TODO st.wMilliseconds = pret.tm_usec/1000;
+
+ rv = DosSetPathInfo(filePath,
+ FIL_STANDARD, // Level 1 info
+ &pathInfo,
+ sizeof(pathInfo),
+ 0UL);
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ MakeDirty();
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPermissions(PRUint32 *aPermissions)
+{
+ nsresult rv = Stat();
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char *filePath = mWorkingPath.get();
+
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPermissionsOfLink(PRUint32 *aPermissionsOfLink)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::SetPermissions(PRUint32 aPermissions)
+{
+ nsresult rv = Stat();
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char *filePath = mWorkingPath.get();
+ if( chmod(filePath, aPermissions) == -1 )
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetPermissionsOfLink(PRUint32 aPermissions)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::GetFileSize(PRInt64 *aFileSize)
+{
+ NS_ENSURE_ARG(aFileSize);
+
+ *aFileSize = 0;
+
+ nsresult rv = Stat();
+
+ if (NS_FAILED(rv))
+ return rv;
+
+
+ *aFileSize = mFileInfo64.size;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::SetFileSize(PRInt64 aFileSize)
+{
+
+ nsresult rv = Stat();
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char *filePath = mWorkingPath.get();
+
+
+ APIRET rc;
+ HFILE hFile;
+ ULONG actionTaken;
+
+ rc = DosOpen(filePath,
+ &hFile,
+ &actionTaken,
+ 0,
+ FILE_NORMAL,
+ OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
+ OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE,
+ NULL);
+
+ if (rc != NO_ERROR)
+ {
+ MakeDirty();
+ return NS_ERROR_FAILURE;
+ }
+
+ // Seek to new, desired end of file
+ PRInt32 hi, lo;
+ myLL_L2II(aFileSize, &hi, &lo );
+
+ rc = DosSetFileSize(hFile, lo);
+ if (rc == NO_ERROR)
+ DosClose(hFile);
+ else
+ goto error;
+
+ MakeDirty();
+ return NS_OK;
+
+ error:
+ MakeDirty();
+ DosClose(hFile);
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetFileSizeOfLink(PRInt64 *aFileSize)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable)
+{
+ NS_ENSURE_ARG(aDiskSpaceAvailable);
+
+ ULONG ulDriveNo = toupper(mWorkingPath.CharAt(0)) + 1 - 'A';
+ FSALLOCATE fsAllocate;
+ APIRET rc = DosQueryFSInfo(ulDriveNo,
+ FSIL_ALLOC,
+ &fsAllocate,
+ sizeof(fsAllocate));
+
+ if (rc != NO_ERROR)
+ return NS_ERROR_FAILURE;
+
+ *aDiskSpaceAvailable = fsAllocate.cUnitAvail;
+ *aDiskSpaceAvailable *= fsAllocate.cSectorUnit;
+ *aDiskSpaceAvailable *= fsAllocate.cbSector;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetParent(nsIFile * *aParent)
+{
+ NS_ENSURE_ARG_POINTER(aParent);
+
+ nsCAutoString parentPath(mWorkingPath);
+
+ // cannot use nsCString::RFindChar() due to 0x5c problem
+ PRInt32 offset = (PRInt32) (_mbsrchr((const unsigned char *) parentPath.get(), '\\')
+ - (const unsigned char *) parentPath.get());
+ if (offset < 0)
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ parentPath.Truncate(offset);
+
+ nsCOMPtr<nsILocalFile> localFile;
+ nsresult rv = NS_NewNativeLocalFile(parentPath, PR_TRUE, getter_AddRefs(localFile));
+
+ if(NS_SUCCEEDED(rv) && localFile)
+ {
+ return CallQueryInterface(localFile, aParent);
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Exists(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+
+ MakeDirty();
+ *_retval = NS_SUCCEEDED(Stat());
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsWritable(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv = Stat();
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char *workingFilePath = mWorkingPath.get();
+
+ APIRET rc;
+ FILESTATUS3 pathInfo;
+
+ rc = DosQueryPathInfo(workingFilePath,
+ FIL_STANDARD, // Level 1 info
+ &pathInfo,
+ sizeof(pathInfo));
+
+ if (rc != NO_ERROR)
+ {
+ rc = ConvertOS2Error(rc);
+ return rc;
+ }
+
+ *_retval = !((pathInfo.attrFile & FILE_READONLY) != 0);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsReadable(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv = Stat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ *_retval = PR_TRUE;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::IsExecutable(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv = Stat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCAutoString path;
+ GetNativeTarget(path);
+
+ const char* leaf = (const char*) _mbsrchr((const unsigned char*) path.get(), '\\');
+
+ if ( (strstr(leaf, ".bat") != nsnull) ||
+ (strstr(leaf, ".exe") != nsnull) ||
+ (strstr(leaf, ".cmd") != nsnull) ||
+ (strstr(leaf, ".com") != nsnull) ) {
+ *_retval = PR_TRUE;
+ } else {
+ *_retval = PR_FALSE;
+ }
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::IsDirectory(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv = Stat();
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ *_retval = (mFileInfo64.type == PR_FILE_DIRECTORY);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsFile(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv = Stat();
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ *_retval = (mFileInfo64.type == PR_FILE_FILE);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsHidden(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv = Stat();
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char *workingFilePath = mWorkingPath.get();
+
+ APIRET rc;
+ FILESTATUS3 pathInfo;
+
+ rc = DosQueryPathInfo(workingFilePath,
+ FIL_STANDARD, // Level 1 info
+ &pathInfo,
+ sizeof(pathInfo));
+
+ if (rc != NO_ERROR)
+ {
+ rc = ConvertOS2Error(rc);
+ return rc;
+ }
+
+ *_retval = ((pathInfo.attrFile & FILE_HIDDEN) != 0);
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::IsSymlink(PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ // No Symlinks on OS/2
+ *_retval = PR_FALSE;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsSpecial(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv = Stat();
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char *workingFilePath = mWorkingPath.get();
+
+ APIRET rc;
+ FILESTATUS3 pathInfo;
+
+ rc = DosQueryPathInfo(workingFilePath,
+ FIL_STANDARD, // Level 1 info
+ &pathInfo,
+ sizeof(pathInfo));
+
+ if (rc != NO_ERROR)
+ {
+ rc = ConvertOS2Error(rc);
+ return rc;
+ }
+
+ *_retval = ((pathInfo.attrFile & FILE_SYSTEM) != 0);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Equals(nsIFile *inFile, PRBool *_retval)
+{
+ NS_ENSURE_ARG(inFile);
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsCAutoString inFilePath;
+ inFile->GetNativePath(inFilePath);
+
+ *_retval = inFilePath.Equals(mWorkingPath);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Contains(nsIFile *inFile, PRBool recur, PRBool *_retval)
+{
+ *_retval = PR_FALSE;
+
+ nsCAutoString myFilePath;
+ if ( NS_FAILED(GetNativeTarget(myFilePath)))
+ GetNativePath(myFilePath);
+
+ PRInt32 myFilePathLen = myFilePath.Length();
+
+ nsCAutoString inFilePath;
+ if ( NS_FAILED(inFile->GetNativeTarget(inFilePath)))
+ inFile->GetNativePath(inFilePath);
+
+ if ( strnicmp( myFilePath.get(), inFilePath.get(), myFilePathLen) == 0)
+ {
+ // now make sure that the |inFile|'s path has a trailing
+ // separator.
+
+ if (inFilePath[myFilePathLen] == '\\')
+ {
+ *_retval = PR_TRUE;
+ }
+
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetNativeTarget(nsACString &_retval)
+{
+ _retval = mWorkingPath;
+ return NS_OK;
+}
+
+/* attribute PRBool followLinks; */
+NS_IMETHODIMP
+nsLocalFile::GetFollowLinks(PRBool *aFollowLinks)
+{
+ *aFollowLinks = PR_TRUE;
+ return NS_OK;
+}
+NS_IMETHODIMP
+nsLocalFile::SetFollowLinks(PRBool aFollowLinks)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetDirectoryEntries(nsISimpleEnumerator * *entries)
+{
+ nsresult rv;
+
+ *entries = nsnull;
+
+ PRBool isDir;
+ rv = IsDirectory(&isDir);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!isDir)
+ return NS_ERROR_FILE_NOT_DIRECTORY;
+
+ nsDirEnumerator* dirEnum = new nsDirEnumerator();
+ if (dirEnum == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(dirEnum);
+ rv = dirEnum->Init(this);
+ if (NS_FAILED(rv))
+ {
+ NS_RELEASE(dirEnum);
+ return rv;
+ }
+
+ *entries = dirEnum;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPersistentDescriptor(nsACString &aPersistentDescriptor)
+{
+ return GetNativePath(aPersistentDescriptor);
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetPersistentDescriptor(const nsACString &aPersistentDescriptor)
+{
+ return InitWithNativePath(aPersistentDescriptor);
+}
+
+#ifndef OPEN_DEFAULT
+#define OPEN_DEFAULT 0
+#define OPEN_CONTENTS 1
+#endif
+
+
+NS_IMETHODIMP
+nsLocalFile::Reveal()
+{
+ PRBool isDirectory = PR_FALSE;
+ nsCAutoString path;
+
+ IsDirectory(&isDirectory);
+ if (isDirectory)
+ {
+ GetNativePath(path);
+ }
+ else
+ {
+ nsCOMPtr<nsIFile> parent;
+ GetParent(getter_AddRefs(parent));
+ if (parent)
+ parent->GetNativePath(path);
+ }
+
+ HOBJECT hobject = WinQueryObject(path.get());
+ WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
+ WinOpenObject( hobject, OPEN_CONTENTS, TRUE);
+
+ // we don't care if it succeeded or failed.
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::Launch()
+{
+ HOBJECT hobject = WinQueryObject(mWorkingPath.get());
+ WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
+ WinOpenObject( hobject, OPEN_DEFAULT, TRUE);
+
+ // we don't care if it succeeded or failed.
+ return NS_OK;
+}
+
+nsresult
+NS_NewNativeLocalFile(const nsACString &path, PRBool followLinks, nsILocalFile* *result)
+{
+ nsLocalFile* file = new nsLocalFile();
+ if (file == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(file);
+
+ if (!path.IsEmpty()) {
+ nsresult rv = file->InitWithNativePath(path);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(file);
+ return rv;
+ }
+ }
+
+ *result = file;
+ return NS_OK;
+}
+
+// Locates the first occurrence of charToSearchFor in the stringToSearch
+static unsigned char* PR_CALLBACK
+_mbschr( const unsigned char* stringToSearch, int charToSearchFor)
+{
+ const unsigned char* p = stringToSearch;
+ do {
+ if (*p == charToSearchFor)
+ break;
+ p = (const unsigned char*)WinNextChar(0,0,0,(char*)p);
+ } while (*p); /* enddo */
+ // Result is p or NULL
+ return *p ? (unsigned char*)p : NULL;
+}
+
+// Locates last occurence of charToSearchFor in the stringToSearch
+extern unsigned char*
+_mbsrchr( const unsigned char* stringToSearch, int charToSearchFor)
+{
+ int length = strlen((const char*)stringToSearch);
+ const unsigned char* p = stringToSearch+length;
+ do {
+ if (*p == charToSearchFor)
+ break;
+ p = (const unsigned char*)WinPrevChar(0,0,0,(char*)stringToSearch,(char*)p);
+ } while (p > stringToSearch); /* enddo */
+ // Result is p or NULL
+ return (*p == charToSearchFor) ? (unsigned char*)p : NULL;
+}
+
+// Implement equivalent of Win32 CreateDirectoryA
+static nsresult PR_CALLBACK
+CreateDirectoryA( PSZ path, PEAOP2 ppEABuf)
+{
+ APIRET rc;
+ nsresult rv;
+ FILESTATUS3 pathInfo;
+
+ rc = DosCreateDir( path, ppEABuf );
+ if (rc != NO_ERROR) {
+ rv = ConvertOS2Error(rc);
+
+ // Check if directory already exists and if so, reflect that in the return value
+ rc = DosQueryPathInfo(path,
+ FIL_STANDARD, // Level 1 info
+ &pathInfo,
+ sizeof(pathInfo));
+ if (rc == NO_ERROR)
+ rv = ERROR_FILE_EXISTS;
+ }
+ else
+ rv = rc;
+
+ return rv;
+}
+
+static int isleadbyte(int c)
+{
+ static BOOL bDBCSFilled=FALSE;
+ static BYTE DBCSInfo[12] = { 0 }; /* According to the Control Program Guide&Ref,
+ 12 bytes is sufficient */
+ BYTE *curr;
+ BOOL retval = FALSE;
+
+ if( !bDBCSFilled ) {
+ COUNTRYCODE ctrycodeInfo = { 0 };
+ APIRET rc = NO_ERROR;
+ ctrycodeInfo.country = 0; /* Current Country */
+ ctrycodeInfo.codepage = 0; /* Current Codepage */
+
+ rc = DosQueryDBCSEnv( sizeof( DBCSInfo ),
+ &ctrycodeInfo,
+ DBCSInfo );
+ if( rc != NO_ERROR ) {
+ /* we had an error, do something? */
+ return FALSE;
+ }
+ bDBCSFilled=TRUE;
+ }
+
+ curr = DBCSInfo;
+ /* DBCSInfo returned by DosQueryDBCSEnv is terminated with two '0' bytes in a row */
+ while(( *curr != 0 ) && ( *(curr+1) != 0)) {
+ if(( c >= *curr ) && ( c <= *(curr+1) )) {
+ retval=TRUE;
+ break;
+ }
+ curr+=2;
+ }
+
+ return retval;
+}
+
+NS_IMETHODIMP
+nsLocalFile::InitWithPath(const nsAString &filePath)
+{
+ if (filePath.IsEmpty())
+ return InitWithNativePath(nsCString());
+
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(filePath, tmp);
+
+ if (NS_SUCCEEDED(rv))
+ return InitWithNativePath(tmp);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Append(const nsAString &node)
+{
+ if (node.IsEmpty())
+ return NS_OK;
+
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(node, tmp);
+
+ if (NS_SUCCEEDED(rv))
+ return AppendNative(tmp);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::AppendRelativePath(const nsAString &node)
+{
+ if (node.IsEmpty())
+ return NS_OK;
+
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(node, tmp);
+
+ if (NS_SUCCEEDED(rv))
+ return AppendRelativeNativePath(tmp);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetLeafName(nsAString &aLeafName)
+{
+ nsCAutoString tmp;
+ nsresult rv = GetNativeLeafName(tmp);
+
+ if (NS_SUCCEEDED(rv))
+ rv = NS_CopyNativeToUnicode(tmp, aLeafName);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetLeafName(const nsAString &aLeafName)
+{
+ if (aLeafName.IsEmpty())
+ return SetNativeLeafName(nsCString());
+
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(aLeafName, tmp);
+
+ if (NS_SUCCEEDED(rv))
+ return SetNativeLeafName(tmp);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPath(nsAString &_retval)
+{
+ return NS_CopyNativeToUnicode(mWorkingPath, _retval);
+}
+
+NS_IMETHODIMP
+nsLocalFile::CopyTo(nsIFile *newParentDir, const nsAString &newName)
+{
+ if (newName.IsEmpty())
+ return CopyToNative(newParentDir, nsCString());
+
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(newName, tmp);
+
+ if (NS_SUCCEEDED(rv))
+ return CopyToNative(newParentDir, tmp);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::CopyToFollowingLinks(nsIFile *newParentDir, const nsAString &newName)
+{
+ if (newName.IsEmpty())
+ return CopyToFollowingLinksNative(newParentDir, nsCString());
+
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(newName, tmp);
+
+ if (NS_SUCCEEDED(rv))
+ return CopyToFollowingLinksNative(newParentDir, tmp);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::MoveTo(nsIFile *newParentDir, const nsAString &newName)
+{
+ if (newName.IsEmpty())
+ return MoveToNative(newParentDir, nsCString());
+
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(newName, tmp);
+
+ if (NS_SUCCEEDED(rv))
+ return MoveToNative(newParentDir, tmp);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetTarget(nsAString &_retval)
+{
+ nsCAutoString tmp;
+ nsresult rv = GetNativeTarget(tmp);
+
+ if (NS_SUCCEEDED(rv))
+ rv = NS_CopyNativeToUnicode(tmp, _retval);
+
+ return rv;
+}
+
+nsresult
+NS_NewLocalFile(const nsAString &path, PRBool followLinks, nsILocalFile* *result)
+{
+ nsCAutoString buf;
+ nsresult rv = NS_CopyUnicodeToNative(path, buf);
+ if (NS_FAILED(rv)) {
+ *result = nsnull;
+ return rv;
+ }
+ return NS_NewNativeLocalFile(buf, followLinks, result);
+}
+
+//----------------------------------------------------------------------------
+// global init/shutdown
+//----------------------------------------------------------------------------
+
+void
+nsLocalFile::GlobalInit()
+{
+}
+
+void
+nsLocalFile::GlobalShutdown()
+{
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFileOS2.h b/src/libs/xpcom18a4/xpcom/io/nsLocalFileOS2.h
new file mode 100644
index 00000000..72f3127a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFileOS2.h
@@ -0,0 +1,113 @@
+/* -*- 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-2000
+ * 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
+ * 05/26/2000 IBM Corp. Make more like Windows.
+ */
+
+#ifndef _nsLocalFileOS2_H_
+#define _nsLocalFileOS2_H_
+
+#include "nscore.h"
+#include "nsError.h"
+#include "nsString.h"
+#include "nsCRT.h"
+#include "nsIFile.h"
+#include "nsIFactory.h"
+
+#define INCL_DOSFILEMGR
+#define INCL_DOSERRORS
+#define INCL_DOSPROCESS
+#define INCL_DOSSESMGR
+#define INCL_DOSMODULEMGR
+#define INCL_DOSNLS
+#define INCL_DOSMISC
+#define INCL_WINCOUNTRY
+#define INCL_WINWORKPLACE
+
+#include <os2.h>
+
+class NS_COM nsLocalFile : public nsILocalFile
+{
+public:
+ NS_DEFINE_STATIC_CID_ACCESSOR(NS_LOCAL_FILE_CID)
+
+ nsLocalFile();
+
+ static NS_METHOD nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+
+ // nsIFile interface
+ NS_DECL_NSIFILE
+
+ // nsILocalFile interface
+ NS_DECL_NSILOCALFILE
+
+public:
+ static void GlobalInit();
+ static void GlobalShutdown();
+
+private:
+ ~nsLocalFile() {}
+
+ nsLocalFile(const nsLocalFile& other);
+
+ // this is the flag which indicates if I can used cached information about the file
+ PRPackedBool mDirty;
+
+ // this string will alway be in native format!
+ nsCString mWorkingPath;
+
+ PRFileInfo64 mFileInfo64;
+
+ void MakeDirty();
+ nsresult Stat();
+
+ nsresult CopyMove(nsIFile *newParentDir, const nsACString &newName, PRBool move);
+ nsresult CopySingleFile(nsIFile *source, nsIFile* dest, const nsACString &newName, PRBool move);
+
+ nsresult SetModDate(PRInt64 aLastModifiedTime);
+};
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFileOSX.cpp b/src/libs/xpcom18a4/xpcom/io/nsLocalFileOSX.cpp
new file mode 100644
index 00000000..dfc431d8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFileOSX.cpp
@@ -0,0 +1,2542 @@
+/* -*- 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) 2001, 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Conrad Carlen <ccarlen@netscape.com>
+ * Jungshik Shin <jshin@mailaps.org>
+ * Asaf Romano <mozilla.mano@sent.com>
+ * Mark Mentovai <mark@moxienet.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 "nsLocalFile.h"
+#include "nsDirectoryServiceDefs.h"
+
+#include "nsString.h"
+#include "nsReadableUtils.h"
+#include "nsIDirectoryEnumerator.h"
+#include "nsISimpleEnumerator.h"
+#include "nsITimelineService.h"
+#include "nsVoidArray.h"
+
+#include "plbase64.h"
+#include "prmem.h"
+#include "nsCRT.h"
+#include "nsHashKeys.h"
+
+#include "MoreFilesX.h"
+#include "FSCopyObject.h"
+#include "nsAutoBuffer.h"
+#include "nsTraceRefcntImpl.h"
+
+// Mac Includes
+#include <Carbon/Carbon.h>
+
+// Unix Includes
+#include <unistd.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+
+#if !defined(MAC_OS_X_VERSION_10_4) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4
+#define GetAliasSizeFromRecord(aliasRecord) aliasRecord.aliasSize
+#else
+#define GetAliasSizeFromRecord(aliasRecord) GetAliasSizeFromPtr(&aliasRecord)
+#endif
+
+#define CHECK_mBaseRef() \
+ PR_BEGIN_MACRO \
+ if (!mBaseRef) \
+ return NS_ERROR_NOT_INITIALIZED; \
+ PR_END_MACRO
+
+//*****************************************************************************
+// Static Function Prototypes
+//*****************************************************************************
+
+static nsresult MacErrorMapper(OSErr inErr);
+static OSErr FindRunningAppBySignature(OSType aAppSig, ProcessSerialNumber& outPsn);
+static void CopyUTF8toUTF16NFC(const nsACString& aSrc, nsAString& aResult);
+
+//*****************************************************************************
+// Local Helper Classes
+//*****************************************************************************
+
+#pragma mark -
+#pragma mark [FSRef operator==]
+
+bool operator==(const FSRef& lhs, const FSRef& rhs)
+{
+ return (::FSCompareFSRefs(&lhs, &rhs) == noErr);
+}
+
+#pragma mark -
+#pragma mark [StFollowLinksState]
+
+class StFollowLinksState
+{
+ public:
+ StFollowLinksState(nsLocalFile& aFile) :
+ mFile(aFile)
+ {
+ mFile.GetFollowLinks(&mSavedState);
+ }
+
+ StFollowLinksState(nsLocalFile& aFile, PRBool followLinksState) :
+ mFile(aFile)
+ {
+ mFile.GetFollowLinks(&mSavedState);
+ mFile.SetFollowLinks(followLinksState);
+ }
+
+ ~StFollowLinksState()
+ {
+ mFile.SetFollowLinks(mSavedState);
+ }
+
+ private:
+ nsLocalFile& mFile;
+ PRBool mSavedState;
+};
+
+#pragma mark -
+#pragma mark [nsDirEnumerator]
+
+class nsDirEnumerator : public nsISimpleEnumerator,
+ public nsIDirectoryEnumerator
+{
+ public:
+
+ NS_DECL_ISUPPORTS
+
+ nsDirEnumerator() :
+ mIterator(nsnull),
+ mFSRefsArray(nsnull),
+ mArrayCnt(0), mArrayIndex(0)
+ {
+ }
+
+ nsresult Init(nsILocalFileMac* parent)
+ {
+ NS_ENSURE_ARG(parent);
+
+ OSErr err;
+ nsresult rv;
+ FSRef parentRef;
+
+ rv = parent->GetFSRef(&parentRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ mFSRefsArray = (FSRef *)nsMemory::Alloc(sizeof(FSRef)
+ * kRequestCountPerIteration);
+ if (!mFSRefsArray)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ err = ::FSOpenIterator(&parentRef, kFSIterateFlat, &mIterator);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ return NS_OK;
+ }
+
+ NS_IMETHOD HasMoreElements(PRBool *result)
+ {
+ if (mNext == nsnull) {
+ if (mArrayIndex >= mArrayCnt) {
+ ItemCount actualCnt;
+ OSErr err = ::FSGetCatalogInfoBulk(mIterator,
+ kRequestCountPerIteration,
+ &actualCnt,
+ nsnull,
+ kFSCatInfoNone,
+ nsnull,
+ mFSRefsArray,
+ nsnull,
+ nsnull);
+
+ if (err == noErr || err == errFSNoMoreItems) {
+ mArrayCnt = actualCnt;
+ mArrayIndex = 0;
+ }
+ }
+ if (mArrayIndex < mArrayCnt) {
+ nsLocalFile *newFile = new nsLocalFile;
+ if (!newFile)
+ return NS_ERROR_OUT_OF_MEMORY;
+ FSRef fsRef = mFSRefsArray[mArrayIndex];
+ if (NS_FAILED(newFile->InitWithFSRef(&fsRef)))
+ return NS_ERROR_FAILURE;
+ mArrayIndex++;
+ mNext = newFile;
+ }
+ }
+ *result = mNext != nsnull;
+ if (!*result)
+ Close();
+ return NS_OK;
+ }
+
+ NS_IMETHOD GetNext(nsISupports **result)
+ {
+ NS_ENSURE_ARG_POINTER(result);
+ *result = nsnull;
+
+ nsresult rv;
+ PRBool hasMore;
+ rv = HasMoreElements(&hasMore);
+ if (NS_FAILED(rv)) return rv;
+
+ *result = mNext; // might return nsnull
+ NS_IF_ADDREF(*result);
+
+ mNext = nsnull;
+ return NS_OK;
+ }
+
+ NS_IMETHOD GetNextFile(nsIFile **result)
+ {
+ *result = nsnull;
+ PRBool hasMore = PR_FALSE;
+ nsresult rv = HasMoreElements(&hasMore);
+ if (NS_FAILED(rv) || !hasMore)
+ return rv;
+ *result = mNext;
+ NS_IF_ADDREF(*result);
+ mNext = nsnull;
+ return NS_OK;
+ }
+
+ NS_IMETHOD Close()
+ {
+ if (mIterator) {
+ ::FSCloseIterator(mIterator);
+ mIterator = nsnull;
+ }
+ if (mFSRefsArray) {
+ nsMemory::Free(mFSRefsArray);
+ mFSRefsArray = nsnull;
+ }
+ return NS_OK;
+ }
+
+ private:
+ ~nsDirEnumerator()
+ {
+ Close();
+ }
+
+ protected:
+ // According to Apple doc, request the number of objects
+ // per call that will fit in 4 VM pages.
+ enum {
+ kRequestCountPerIteration = ((4096 * 4) / sizeof(FSRef))
+ };
+
+ nsCOMPtr<nsILocalFileMac> mNext;
+
+ FSIterator mIterator;
+ FSRef *mFSRefsArray;
+ PRInt32 mArrayCnt, mArrayIndex;
+};
+
+NS_IMPL_ISUPPORTS2(nsDirEnumerator, nsISimpleEnumerator, nsIDirectoryEnumerator)
+
+#pragma mark -
+#pragma mark [StAEDesc]
+
+class StAEDesc: public AEDesc
+{
+public:
+ StAEDesc()
+ {
+ descriptorType = typeNull;
+ dataHandle = nil;
+ }
+
+ ~StAEDesc()
+ {
+ ::AEDisposeDesc(this);
+ }
+};
+
+#define FILENAME_BUFFER_SIZE 512
+
+//*****************************************************************************
+// nsLocalFile
+//*****************************************************************************
+
+const char nsLocalFile::kPathSepChar = '/';
+const PRUnichar nsLocalFile::kPathSepUnichar = '/';
+
+// The HFS+ epoch is Jan. 1, 1904 GMT - differs from HFS in which times were local
+// The NSPR epoch is Jan. 1, 1970 GMT
+// 2082844800 is the difference in seconds between those dates
+const PRInt64 nsLocalFile::kJanuaryFirst1970Seconds = 2082844800LL;
+
+#pragma mark -
+#pragma mark [CTORs/DTOR]
+
+nsLocalFile::nsLocalFile() :
+ mBaseRef(nsnull),
+ mTargetRef(nsnull),
+ mCachedFSRefValid(PR_FALSE),
+ mFollowLinks(PR_TRUE),
+ mFollowLinksDirty(PR_TRUE)
+{
+}
+
+nsLocalFile::nsLocalFile(const nsLocalFile& src) :
+ mBaseRef(src.mBaseRef),
+ mTargetRef(src.mTargetRef),
+ mCachedFSRef(src.mCachedFSRef),
+ mCachedFSRefValid(src.mCachedFSRefValid),
+ mFollowLinks(src.mFollowLinks),
+ mFollowLinksDirty(src.mFollowLinksDirty)
+{
+ // A CFURLRef is immutable so no need to copy, just retain.
+ if (mBaseRef)
+ ::CFRetain(mBaseRef);
+ if (mTargetRef)
+ ::CFRetain(mTargetRef);
+}
+
+nsLocalFile::~nsLocalFile()
+{
+ if (mBaseRef)
+ ::CFRelease(mBaseRef);
+ if (mTargetRef)
+ ::CFRelease(mTargetRef);
+}
+
+
+//*****************************************************************************
+// nsLocalFile::nsISupports
+//*****************************************************************************
+#pragma mark -
+#pragma mark [nsISupports]
+
+NS_IMPL_THREADSAFE_ISUPPORTS4(nsLocalFile,
+ nsILocalFileMac,
+ nsILocalFile,
+ nsIFile,
+ nsIHashable)
+
+NS_METHOD nsLocalFile::nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
+{
+ NS_ENSURE_ARG_POINTER(aInstancePtr);
+ NS_ENSURE_NO_AGGREGATION(outer);
+
+ nsLocalFile* inst = new nsLocalFile();
+ if (inst == NULL)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = inst->QueryInterface(aIID, aInstancePtr);
+ if (NS_FAILED(rv))
+ {
+ delete inst;
+ return rv;
+ }
+ return NS_OK;
+}
+
+
+//*****************************************************************************
+// nsLocalFile::nsIFile
+//*****************************************************************************
+#pragma mark -
+#pragma mark [nsIFile]
+
+/* void append (in AString node); */
+NS_IMETHODIMP nsLocalFile::Append(const nsAString& aNode)
+{
+ return AppendNative(NS_ConvertUTF16toUTF8(aNode));
+}
+
+/* [noscript] void appendNative (in ACString node); */
+NS_IMETHODIMP nsLocalFile::AppendNative(const nsACString& aNode)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ nsACString::const_iterator start, end;
+ aNode.BeginReading(start);
+ aNode.EndReading(end);
+ if (FindCharInReadable(kPathSepChar, start, end))
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ CFStringRef nodeStrRef = ::CFStringCreateWithCString(kCFAllocatorDefault,
+ PromiseFlatCString(aNode).get(),
+ kCFStringEncodingUTF8);
+ if (nodeStrRef) {
+ CFURLRef newRef = ::CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault,
+ mBaseRef, nodeStrRef, PR_FALSE);
+ ::CFRelease(nodeStrRef);
+ if (newRef) {
+ SetBaseRef(newRef);
+ ::CFRelease(newRef);
+ return NS_OK;
+ }
+ }
+ return NS_ERROR_FAILURE;
+}
+
+/* void normalize (); */
+NS_IMETHODIMP nsLocalFile::Normalize()
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ // CFURL doesn't doesn't seem to resolve paths containing relative
+ // components, so we'll nick the stdlib code from nsLocalFileUnix
+ UInt8 path[PATH_MAX] = "";
+ Boolean success;
+ success = ::CFURLGetFileSystemRepresentation(mBaseRef, true, path, PATH_MAX);
+ if (!success)
+ return NS_ERROR_FAILURE;
+
+ char resolved_path[PATH_MAX] = "";
+ char *resolved_path_ptr = nsnull;
+ resolved_path_ptr = realpath((char*)path, resolved_path);
+
+ // if there is an error, the return is null.
+ if (!resolved_path_ptr)
+ return NSRESULT_FOR_ERRNO();
+
+ // Need to know whether we're a directory to create a new CFURLRef
+ PRBool isDirectory;
+ nsresult rv = IsDirectory(&isDirectory);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = NS_ERROR_FAILURE;
+ CFStringRef pathStrRef =
+ ::CFStringCreateWithCString(kCFAllocatorDefault,
+ resolved_path,
+ kCFStringEncodingUTF8);
+ if (pathStrRef) {
+ CFURLRef newURLRef =
+ ::CFURLCreateWithFileSystemPath(kCFAllocatorDefault, pathStrRef,
+ kCFURLPOSIXPathStyle, isDirectory);
+ if (newURLRef) {
+ SetBaseRef(newURLRef);
+ ::CFRelease(newURLRef);
+ rv = NS_OK;
+ }
+ ::CFRelease(pathStrRef);
+ }
+
+ return rv;
+}
+
+/* void create (in unsigned long type, in unsigned long permissions); */
+NS_IMETHODIMP nsLocalFile::Create(PRUint32 type, PRUint32 permissions)
+{
+ if (type != NORMAL_FILE_TYPE && type != DIRECTORY_TYPE)
+ return NS_ERROR_FILE_UNKNOWN_TYPE;
+
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ nsStringArray nonExtantNodes;
+ CFURLRef pathURLRef = mBaseRef;
+ FSRef pathFSRef;
+ CFStringRef leafStrRef = nsnull;
+ nsAutoBuffer<UniChar, FILENAME_BUFFER_SIZE> buffer;
+ Boolean success;
+
+ // Work backwards through the path to find the last node which
+ // exists. Place the nodes which don't exist in an array and we'll
+ // create those below.
+ while ((success = ::CFURLGetFSRef(pathURLRef, &pathFSRef)) == false) {
+ leafStrRef = ::CFURLCopyLastPathComponent(pathURLRef);
+ if (!leafStrRef)
+ break;
+ CFIndex leafLen = ::CFStringGetLength(leafStrRef);
+ if (!buffer.EnsureElemCapacity(leafLen + 1))
+ break;
+ ::CFStringGetCharacters(leafStrRef, CFRangeMake(0, leafLen), buffer.get());
+ buffer.get()[leafLen] = '\0';
+ nonExtantNodes.AppendString(nsString(nsDependentString(buffer.get())));
+ ::CFRelease(leafStrRef);
+ leafStrRef = nsnull;
+
+ // Get the parent of the leaf for the next go round
+ CFURLRef parent = ::CFURLCreateCopyDeletingLastPathComponent(NULL, pathURLRef);
+ if (!parent)
+ break;
+ if (pathURLRef != mBaseRef)
+ ::CFRelease(pathURLRef);
+ pathURLRef = parent;
+ }
+ if (pathURLRef != mBaseRef)
+ ::CFRelease(pathURLRef);
+ if (leafStrRef != nsnull)
+ ::CFRelease(leafStrRef);
+ if (!success)
+ return NS_ERROR_FAILURE;
+ PRInt32 nodesToCreate = nonExtantNodes.Count();
+ if (nodesToCreate == 0)
+ return NS_ERROR_FILE_ALREADY_EXISTS;
+
+ OSErr err;
+ nsAutoString nextNodeName;
+ for (PRInt32 i = nodesToCreate - 1; i > 0; i--) {
+ nonExtantNodes.StringAt(i, nextNodeName);
+ err = ::FSCreateDirectoryUnicode(&pathFSRef,
+ nextNodeName.Length(),
+ (const UniChar *)nextNodeName.get(),
+ kFSCatInfoNone,
+ nsnull, &pathFSRef, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ }
+ nonExtantNodes.StringAt(0, nextNodeName);
+ if (type == NORMAL_FILE_TYPE) {
+ err = ::FSCreateFileUnicode(&pathFSRef,
+ nextNodeName.Length(),
+ (const UniChar *)nextNodeName.get(),
+ kFSCatInfoNone,
+ nsnull, nsnull, nsnull);
+ }
+ else {
+ err = ::FSCreateDirectoryUnicode(&pathFSRef,
+ nextNodeName.Length(),
+ (const UniChar *)nextNodeName.get(),
+ kFSCatInfoNone,
+ nsnull, nsnull, nsnull, nsnull);
+ }
+
+ return MacErrorMapper(err);
+}
+
+/* attribute AString leafName; */
+NS_IMETHODIMP nsLocalFile::GetLeafName(nsAString& aLeafName)
+{
+ nsCAutoString nativeString;
+ nsresult rv = GetNativeLeafName(nativeString);
+ if (NS_FAILED(rv))
+ return rv;
+ CopyUTF8toUTF16NFC(nativeString, aLeafName);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::SetLeafName(const nsAString& aLeafName)
+{
+ return SetNativeLeafName(NS_ConvertUTF16toUTF8(aLeafName));
+}
+
+/* [noscript] attribute ACString nativeLeafName; */
+NS_IMETHODIMP nsLocalFile::GetNativeLeafName(nsACString& aNativeLeafName)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ nsresult rv = NS_ERROR_FAILURE;
+ CFStringRef leafStrRef = ::CFURLCopyLastPathComponent(mBaseRef);
+ if (leafStrRef) {
+ rv = CFStringReftoUTF8(leafStrRef, aNativeLeafName);
+ ::CFRelease(leafStrRef);
+ }
+ return rv;
+}
+
+NS_IMETHODIMP nsLocalFile::SetNativeLeafName(const nsACString& aNativeLeafName)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ nsresult rv = NS_ERROR_FAILURE;
+ CFURLRef parentURLRef = ::CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, mBaseRef);
+ if (parentURLRef) {
+ CFStringRef nodeStrRef = ::CFStringCreateWithCString(kCFAllocatorDefault,
+ PromiseFlatCString(aNativeLeafName).get(),
+ kCFStringEncodingUTF8);
+
+ if (nodeStrRef) {
+ CFURLRef newURLRef = ::CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault,
+ parentURLRef, nodeStrRef, PR_FALSE);
+ if (newURLRef) {
+ SetBaseRef(newURLRef);
+ ::CFRelease(newURLRef);
+ rv = NS_OK;
+ }
+ ::CFRelease(nodeStrRef);
+ }
+ ::CFRelease(parentURLRef);
+ }
+ return rv;
+}
+
+/* void copyTo (in nsIFile newParentDir, in AString newName); */
+NS_IMETHODIMP nsLocalFile::CopyTo(nsIFile *newParentDir, const nsAString& newName)
+{
+ return CopyInternal(newParentDir, newName, PR_FALSE);
+}
+
+/* [noscrpit] void CopyToNative (in nsIFile newParentDir, in ACString newName); */
+NS_IMETHODIMP nsLocalFile::CopyToNative(nsIFile *newParentDir, const nsACString& newName)
+{
+ return CopyInternal(newParentDir, NS_ConvertUTF8toUTF16(newName), PR_FALSE);
+}
+
+/* void copyToFollowingLinks (in nsIFile newParentDir, in AString newName); */
+NS_IMETHODIMP nsLocalFile::CopyToFollowingLinks(nsIFile *newParentDir, const nsAString& newName)
+{
+ return CopyInternal(newParentDir, newName, PR_TRUE);
+}
+
+/* [noscript] void copyToFollowingLinksNative (in nsIFile newParentDir, in ACString newName); */
+NS_IMETHODIMP nsLocalFile::CopyToFollowingLinksNative(nsIFile *newParentDir, const nsACString& newName)
+{
+ return CopyInternal(newParentDir, NS_ConvertUTF8toUTF16(newName), PR_TRUE);
+}
+
+/* void moveTo (in nsIFile newParentDir, in AString newName); */
+NS_IMETHODIMP nsLocalFile::MoveTo(nsIFile *newParentDir, const nsAString& newName)
+{
+ return MoveToNative(newParentDir, NS_ConvertUTF16toUTF8(newName));
+}
+
+/* [noscript] void moveToNative (in nsIFile newParentDir, in ACString newName); */
+NS_IMETHODIMP nsLocalFile::MoveToNative(nsIFile *newParentDir, const nsACString& newName)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ StFollowLinksState followLinks(*this, PR_FALSE);
+
+ PRBool isDirectory;
+ nsresult rv = IsDirectory(&isDirectory);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Get the source path.
+ nsCAutoString srcPath;
+ rv = GetNativePath(srcPath);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Build the destination path.
+ nsCOMPtr<nsIFile> parentDir = newParentDir;
+ if (!parentDir) {
+ if (newName.IsEmpty())
+ return NS_ERROR_INVALID_ARG;
+ rv = GetParent(getter_AddRefs(parentDir));
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ else {
+ PRBool exists;
+ rv = parentDir->Exists(&exists);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!exists) {
+ rv = parentDir->Create(nsIFile::DIRECTORY_TYPE, 0777);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ }
+
+ nsCAutoString destPath;
+ rv = parentDir->GetNativePath(destPath);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (!newName.IsEmpty())
+ destPath.Append(NS_LITERAL_CSTRING("/") + newName);
+ else {
+ nsCAutoString leafName;
+ rv = GetNativeLeafName(leafName);
+ if (NS_FAILED(rv))
+ return rv;
+ destPath.Append(NS_LITERAL_CSTRING("/") + leafName);
+ }
+
+ // Perform the move.
+ if (rename(srcPath.get(), destPath.get()) != 0) {
+ if (errno == EXDEV) {
+ // Can't move across volume (device) boundaries. Copy and remove.
+ rv = CopyToNative(parentDir, newName);
+ if (NS_SUCCEEDED(rv)) {
+ // Permit removal failure.
+ Remove(PR_TRUE);
+ }
+ }
+ else
+ rv = NSRESULT_FOR_ERRNO();
+
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ // Update |this| to refer to the moved file.
+ CFURLRef newBaseRef =
+ ::CFURLCreateFromFileSystemRepresentation(NULL, (UInt8*)destPath.get(),
+ destPath.Length(), isDirectory);
+ if (!newBaseRef)
+ return NS_ERROR_FAILURE;
+ SetBaseRef(newBaseRef);
+ ::CFRelease(newBaseRef);
+
+ return rv;
+}
+
+/* void remove (in boolean recursive); */
+NS_IMETHODIMP nsLocalFile::Remove(PRBool recursive)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ // XXX If we're an alias, never remove target
+ StFollowLinksState followLinks(*this, PR_FALSE);
+
+ PRBool isDirectory;
+ nsresult rv = IsDirectory(&isDirectory);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (recursive && isDirectory) {
+ FSRef fsRef;
+ rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // Call MoreFilesX to do a recursive removal.
+ OSStatus err = ::FSDeleteContainer(&fsRef);
+ rv = MacErrorMapper(err);
+ }
+ else {
+ nsCAutoString path;
+ rv = GetNativePath(path);
+ if (NS_FAILED(rv))
+ return rv;
+
+ const char* pathPtr = path.get();
+ int status;
+ if (isDirectory)
+ status = rmdir(pathPtr);
+ else
+ status = unlink(pathPtr);
+
+ if (status != 0)
+ rv = NSRESULT_FOR_ERRNO();
+ }
+
+ mCachedFSRefValid = PR_FALSE;
+ return rv;
+}
+
+/* attribute unsigned long permissions; */
+NS_IMETHODIMP nsLocalFile::GetPermissions(PRUint32 *aPermissions)
+{
+ NS_ENSURE_ARG_POINTER(aPermissions);
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ FSCatalogInfo catalogInfo;
+ OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoPermissions, &catalogInfo,
+ nsnull, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ FSPermissionInfo *permPtr = (FSPermissionInfo*)catalogInfo.permissions;
+ *aPermissions = permPtr->mode;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::SetPermissions(PRUint32 aPermissions)
+{
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ FSCatalogInfo catalogInfo;
+ OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoPermissions, &catalogInfo,
+ nsnull, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ FSPermissionInfo *permPtr = (FSPermissionInfo*)catalogInfo.permissions;
+ permPtr->mode = (UInt16)aPermissions;
+ err = ::FSSetCatalogInfo(&fsRef, kFSCatInfoPermissions, &catalogInfo);
+ return MacErrorMapper(err);
+}
+
+/* attribute unsigned long permissionsOfLink; */
+NS_IMETHODIMP nsLocalFile::GetPermissionsOfLink(PRUint32 *aPermissionsOfLink)
+{
+ NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP nsLocalFile::SetPermissionsOfLink(PRUint32 aPermissionsOfLink)
+{
+ NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute PRInt64 lastModifiedTime; */
+NS_IMETHODIMP nsLocalFile::GetLastModifiedTime(PRInt64 *aLastModifiedTime)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ NS_ENSURE_ARG_POINTER(aLastModifiedTime);
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ FSCatalogInfo catalogInfo;
+ OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoContentMod, &catalogInfo,
+ nsnull, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ *aLastModifiedTime = HFSPlustoNSPRTime(catalogInfo.contentModDate);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::SetLastModifiedTime(PRInt64 aLastModifiedTime)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ OSErr err;
+ nsresult rv;
+ FSRef fsRef;
+ FSCatalogInfo catalogInfo;
+
+ rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ FSRef parentRef;
+ PRBool notifyParent;
+
+ /* Get the node flags, the content modification date and time, and the parent ref */
+ err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoNodeFlags + kFSCatInfoContentMod,
+ &catalogInfo, NULL, NULL, &parentRef);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ /* Notify the parent if this is a file */
+ notifyParent = (0 == (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask));
+
+ NSPRtoHFSPlusTime(aLastModifiedTime, catalogInfo.contentModDate);
+ err = ::FSSetCatalogInfo(&fsRef, kFSCatInfoContentMod, &catalogInfo);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ /* Send a notification for the parent of the file, or for the directory */
+ err = FNNotify(notifyParent ? &parentRef : &fsRef, kFNDirectoryModifiedMessage, kNilOptions);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ return NS_OK;
+}
+
+/* attribute PRInt64 lastModifiedTimeOfLink; */
+NS_IMETHODIMP nsLocalFile::GetLastModifiedTimeOfLink(PRInt64 *aLastModifiedTimeOfLink)
+{
+ NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+NS_IMETHODIMP nsLocalFile::SetLastModifiedTimeOfLink(PRInt64 aLastModifiedTimeOfLink)
+{
+ NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* attribute PRInt64 fileSize; */
+NS_IMETHODIMP nsLocalFile::GetFileSize(PRInt64 *aFileSize)
+{
+ NS_ENSURE_ARG_POINTER(aFileSize);
+ *aFileSize = 0;
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ FSCatalogInfo catalogInfo;
+ OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoNodeFlags + kFSCatInfoDataSizes, &catalogInfo,
+ nsnull, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ // FSGetCatalogInfo can return a bogus size for directories sometimes, so only
+ // rely on the answer for files
+ if ((catalogInfo.nodeFlags & kFSNodeIsDirectoryMask) == 0)
+ *aFileSize = catalogInfo.dataLogicalSize;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::SetFileSize(PRInt64 aFileSize)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ SInt16 refNum;
+ OSErr err = ::FSOpenFork(&fsRef, 0, nsnull, fsWrPerm, &refNum);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ err = ::FSSetForkSize(refNum, fsFromStart, aFileSize);
+ ::FSCloseFork(refNum);
+
+ return MacErrorMapper(err);
+}
+
+/* readonly attribute PRInt64 fileSizeOfLink; */
+NS_IMETHODIMP nsLocalFile::GetFileSizeOfLink(PRInt64 *aFileSizeOfLink)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ NS_ENSURE_ARG_POINTER(aFileSizeOfLink);
+
+ StFollowLinksState followLinks(*this, PR_FALSE);
+ return GetFileSize(aFileSizeOfLink);
+}
+
+/* readonly attribute AString target; */
+NS_IMETHODIMP nsLocalFile::GetTarget(nsAString& aTarget)
+{
+ NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* [noscript] readonly attribute ACString nativeTarget; */
+NS_IMETHODIMP nsLocalFile::GetNativeTarget(nsACString& aNativeTarget)
+{
+ NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* readonly attribute AString path; */
+NS_IMETHODIMP nsLocalFile::GetPath(nsAString& aPath)
+{
+ nsCAutoString nativeString;
+ nsresult rv = GetNativePath(nativeString);
+ if (NS_FAILED(rv))
+ return rv;
+ CopyUTF8toUTF16NFC(nativeString, aPath);
+ return NS_OK;
+}
+
+/* [noscript] readonly attribute ACString nativePath; */
+NS_IMETHODIMP nsLocalFile::GetNativePath(nsACString& aNativePath)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ nsresult rv = NS_ERROR_FAILURE;
+ CFStringRef pathStrRef = ::CFURLCopyFileSystemPath(mBaseRef, kCFURLPOSIXPathStyle);
+ if (pathStrRef) {
+ rv = CFStringReftoUTF8(pathStrRef, aNativePath);
+ ::CFRelease(pathStrRef);
+ }
+ return rv;
+}
+
+/* boolean exists (); */
+NS_IMETHODIMP nsLocalFile::Exists(PRBool *_retval)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = PR_FALSE;
+
+ FSRef fsRef;
+ if (NS_SUCCEEDED(GetFSRefInternal(fsRef, PR_TRUE))) {
+ *_retval = PR_TRUE;
+ }
+
+ return NS_OK;
+}
+
+/* boolean isWritable (); */
+NS_IMETHODIMP nsLocalFile::IsWritable(PRBool *_retval)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = PR_FALSE;
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+ if (::FSCheckLock(&fsRef) == noErr) {
+ PRUint32 permissions;
+ rv = GetPermissions(&permissions);
+ if (NS_FAILED(rv))
+ return rv;
+ *_retval = ((permissions & S_IWUSR) != 0);
+ }
+ return NS_OK;
+}
+
+/* boolean isReadable (); */
+NS_IMETHODIMP nsLocalFile::IsReadable(PRBool *_retval)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = PR_FALSE;
+
+ PRUint32 permissions;
+ nsresult rv = GetPermissions(&permissions);
+ if (NS_FAILED(rv))
+ return rv;
+ *_retval = ((permissions & S_IRUSR) != 0);
+ return NS_OK;
+}
+
+/* boolean isExecutable (); */
+NS_IMETHODIMP nsLocalFile::IsExecutable(PRBool *_retval)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = PR_FALSE;
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ LSRequestedInfo theInfoRequest = kLSRequestAllInfo;
+ LSItemInfoRecord theInfo;
+ if (::LSCopyItemInfoForRef(&fsRef, theInfoRequest, &theInfo) == noErr) {
+ if ((theInfo.flags & kLSItemInfoIsApplication) != 0)
+ *_retval = PR_TRUE;
+ }
+ return NS_OK;
+}
+
+/* boolean isHidden (); */
+NS_IMETHODIMP nsLocalFile::IsHidden(PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = PR_FALSE;
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ FSCatalogInfo catalogInfo;
+ HFSUniStr255 leafName;
+ OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoFinderInfo, &catalogInfo,
+ &leafName, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ FileInfo *fInfoPtr = (FileInfo *)(catalogInfo.finderInfo); // Finder flags are in the same place whether we use FileInfo or FolderInfo
+ if ((fInfoPtr->finderFlags & kIsInvisible) != 0) {
+ *_retval = PR_TRUE;
+ }
+ else {
+ // If the leaf name begins with a '.', consider it invisible
+ if (leafName.length >= 1 && leafName.unicode[0] == UniChar('.'))
+ *_retval = PR_TRUE;
+ }
+ return NS_OK;
+}
+
+/* boolean isDirectory (); */
+NS_IMETHODIMP nsLocalFile::IsDirectory(PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = PR_FALSE;
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef, PR_FALSE);
+ if (NS_FAILED(rv))
+ return rv;
+
+ FSCatalogInfo catalogInfo;
+ OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoNodeFlags, &catalogInfo,
+ nsnull, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ *_retval = ((catalogInfo.nodeFlags & kFSNodeIsDirectoryMask) != 0);
+ return NS_OK;
+}
+
+/* boolean isFile (); */
+NS_IMETHODIMP nsLocalFile::IsFile(PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = PR_FALSE;
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef, PR_FALSE);
+ if (NS_FAILED(rv))
+ return rv;
+
+ FSCatalogInfo catalogInfo;
+ OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoNodeFlags, &catalogInfo,
+ nsnull, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ *_retval = ((catalogInfo.nodeFlags & kFSNodeIsDirectoryMask) == 0);
+ return NS_OK;
+}
+
+/* boolean isSymlink (); */
+NS_IMETHODIMP nsLocalFile::IsSymlink(PRBool *_retval)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ FSRef fsRef;
+ if (::CFURLGetFSRef(mBaseRef, &fsRef)) {
+ Boolean isAlias, isFolder;
+ if (::FSIsAliasFile(&fsRef, &isAlias, &isFolder) == noErr)
+ *_retval = isAlias;
+ }
+ return NS_OK;
+}
+
+/* boolean isSpecial (); */
+NS_IMETHODIMP nsLocalFile::IsSpecial(PRBool *_retval)
+{
+ NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* nsIFile clone (); */
+NS_IMETHODIMP nsLocalFile::Clone(nsIFile **_retval)
+{
+ // Just copy-construct ourselves
+ *_retval = new nsLocalFile(*this);
+ if (!*_retval)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(*_retval);
+
+ return NS_OK;
+}
+
+/* boolean equals (in nsIFile inFile); */
+NS_IMETHODIMP nsLocalFile::Equals(nsIFile *inFile, PRBool *_retval)
+{
+ return EqualsInternal(inFile, PR_TRUE, _retval);
+}
+
+nsresult
+nsLocalFile::EqualsInternal(nsISupports* inFile, PRBool aUpdateCache,
+ PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = PR_FALSE;
+
+ nsCOMPtr<nsILocalFileMac> inMacFile(do_QueryInterface(inFile));
+ if (!inFile)
+ return NS_OK;
+
+ nsLocalFile* inLF =
+ static_cast<nsLocalFile*>((nsILocalFileMac*) inMacFile);
+
+ // If both exist, compare FSRefs
+ FSRef thisFSRef, inFSRef;
+ nsresult rv1 = GetFSRefInternal(thisFSRef, aUpdateCache);
+ nsresult rv2 = inLF->GetFSRefInternal(inFSRef, aUpdateCache);
+ if (NS_SUCCEEDED(rv1) && NS_SUCCEEDED(rv2)) {
+ *_retval = (thisFSRef == inFSRef);
+ return NS_OK;
+ }
+ // If one exists and the other doesn't, not equal
+ if (rv1 != rv2)
+ return NS_OK;
+
+ // Arg, we have to get their paths and compare
+ nsCAutoString thisPath, inPath;
+ if (NS_FAILED(GetNativePath(thisPath)))
+ return NS_ERROR_FAILURE;
+ if (NS_FAILED(inMacFile->GetNativePath(inPath)))
+ return NS_ERROR_FAILURE;
+ *_retval = thisPath.Equals(inPath);
+
+ return NS_OK;
+}
+
+/* boolean contains (in nsIFile inFile, in boolean recur); */
+NS_IMETHODIMP nsLocalFile::Contains(nsIFile *inFile, PRBool recur, PRBool *_retval)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = PR_FALSE;
+
+ PRBool isDir;
+ nsresult rv = IsDirectory(&isDir);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!isDir)
+ return NS_OK; // must be a dir to contain someone
+
+ nsCAutoString thisPath, inPath;
+ if (NS_FAILED(GetNativePath(thisPath)) || NS_FAILED(inFile->GetNativePath(inPath)))
+ return NS_ERROR_FAILURE;
+ size_t thisPathLen = thisPath.Length();
+ if ((inPath.Length() > thisPathLen + 1) && (strncasecmp(thisPath.get(), inPath.get(), thisPathLen) == 0)) {
+ // Now make sure that the |inFile|'s path has a separator at thisPathLen,
+ // and there's at least one more character after that.
+ if (inPath[thisPathLen] == kPathSepChar)
+ *_retval = PR_TRUE;
+ }
+ return NS_OK;
+}
+
+/* readonly attribute nsIFile parent; */
+NS_IMETHODIMP nsLocalFile::GetParent(nsIFile * *aParent)
+{
+ NS_ENSURE_ARG_POINTER(aParent);
+ *aParent = nsnull;
+
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ nsLocalFile *newFile = nsnull;
+
+ // If it can be determined without error that a file does not
+ // have a parent, return nsnull for the parent and NS_OK as the result.
+ // See bug 133617.
+ nsresult rv = NS_OK;
+ CFURLRef parentURLRef = ::CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, mBaseRef);
+ if (parentURLRef) {
+ // If the parent path is longer than file's path then
+ // CFURLCreateCopyDeletingLastPathComponent must have simply added
+ // two dots at the end - in this case indicate that there is no parent.
+ // See bug 332389.
+ CFStringRef path = ::CFURLGetString(mBaseRef);
+ CFStringRef newPath = ::CFURLGetString(parentURLRef);
+ if (::CFStringGetLength(newPath) < ::CFStringGetLength(path)) {
+ rv = NS_ERROR_FAILURE;
+ newFile = new nsLocalFile;
+ if (newFile) {
+ rv = newFile->InitWithCFURL(parentURLRef);
+ if (NS_SUCCEEDED(rv)) {
+ NS_ADDREF(*aParent = newFile);
+ rv = NS_OK;
+ }
+ }
+ }
+ ::CFRelease(parentURLRef);
+ }
+ return rv;
+}
+
+/* readonly attribute nsISimpleEnumerator directoryEntries; */
+NS_IMETHODIMP nsLocalFile::GetDirectoryEntries(nsISimpleEnumerator **aDirectoryEntries)
+{
+ NS_ENSURE_ARG_POINTER(aDirectoryEntries);
+ *aDirectoryEntries = nsnull;
+
+ nsresult rv;
+ PRBool isDir;
+ rv = IsDirectory(&isDir);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!isDir)
+ return NS_ERROR_FILE_NOT_DIRECTORY;
+
+ nsDirEnumerator* dirEnum = new nsDirEnumerator;
+ if (dirEnum == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(dirEnum);
+ rv = dirEnum->Init(this);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(dirEnum);
+ return rv;
+ }
+ *aDirectoryEntries = dirEnum;
+
+ return NS_OK;
+}
+
+
+//*****************************************************************************
+// nsLocalFile::nsILocalFile
+//*****************************************************************************
+#pragma mark -
+#pragma mark [nsILocalFile]
+
+/* void initWithPath (in AString filePath); */
+NS_IMETHODIMP nsLocalFile::InitWithPath(const nsAString& filePath)
+{
+ return InitWithNativePath(NS_ConvertUTF16toUTF8(filePath));
+}
+
+/* [noscript] void initWithNativePath (in ACString filePath); */
+NS_IMETHODIMP nsLocalFile::InitWithNativePath(const nsACString& filePath)
+{
+ nsCAutoString fixedPath;
+ if (Substring(filePath, 0, 2).EqualsLiteral("~/")) {
+ nsCOMPtr<nsIFile> homeDir;
+ nsCAutoString homePath;
+ nsresult rv = NS_GetSpecialDirectory(NS_OS_HOME_DIR,
+ getter_AddRefs(homeDir));
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = homeDir->GetNativePath(homePath);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ fixedPath = homePath + Substring(filePath, 1, filePath.Length() - 1);
+ }
+ else if (filePath.IsEmpty() || filePath.First() != '/')
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+ else
+ fixedPath.Assign(filePath);
+
+ // A path with consecutive '/'s which are not between
+ // nodes crashes CFURLGetFSRef(). Consecutive '/'s which
+ // are between actual nodes are OK. So, convert consecutive
+ // '/'s to a single one.
+ fixedPath.ReplaceSubstring("//", "/");
+
+#if 1 // bird: hack to fix RegistryLocationForSpec issues with /path/to/./components
+ fixedPath.ReplaceSubstring("/./", "/");
+ size_t len = fixedPath.Length();
+ while (len > 2)
+ {
+ size_t choplen = 0;
+ if (!strcmp(fixedPath.get() + len - 2, "/."))
+ choplen = 2;
+ else if (!strcmp(fixedPath.get() + len - 1, "/"))
+ choplen = 1;
+ else
+ break;
+ fixedPath = StringHead(fixedPath, len - choplen);
+ }
+ // bird: another hack for the issue with VirtualBoxVM and symlinks...
+ char tmpBuf[PATH_MAX];
+ if (realpath(fixedPath.get(), tmpBuf))
+ fixedPath = tmpBuf;
+#endif
+
+ // On 10.2, huge paths also crash CFURLGetFSRef()
+ if (fixedPath.Length() > PATH_MAX)
+ return NS_ERROR_FILE_NAME_TOO_LONG;
+
+ CFStringRef pathAsCFString;
+ CFURLRef pathAsCFURL;
+
+ pathAsCFString = ::CFStringCreateWithCString(nsnull, fixedPath.get(), kCFStringEncodingUTF8);
+ if (!pathAsCFString)
+ return NS_ERROR_FAILURE;
+ pathAsCFURL = ::CFURLCreateWithFileSystemPath(nsnull, pathAsCFString, kCFURLPOSIXPathStyle, PR_FALSE);
+ if (!pathAsCFURL) {
+ ::CFRelease(pathAsCFString);
+ return NS_ERROR_FAILURE;
+ }
+ SetBaseRef(pathAsCFURL);
+ ::CFRelease(pathAsCFURL);
+ ::CFRelease(pathAsCFString);
+ return NS_OK;
+}
+
+/* void initWithFile (in nsILocalFile aFile); */
+NS_IMETHODIMP nsLocalFile::InitWithFile(nsILocalFile *aFile)
+{
+ NS_ENSURE_ARG(aFile);
+
+ nsCOMPtr<nsILocalFileMac> aFileMac(do_QueryInterface(aFile));
+ if (!aFileMac)
+ return NS_ERROR_UNEXPECTED;
+ CFURLRef urlRef;
+ nsresult rv = aFileMac->GetCFURL(&urlRef);
+ if (NS_FAILED(rv))
+ return rv;
+ rv = InitWithCFURL(urlRef);
+ ::CFRelease(urlRef);
+ return rv;
+}
+
+/* attribute PRBool followLinks; */
+NS_IMETHODIMP nsLocalFile::GetFollowLinks(PRBool *aFollowLinks)
+{
+ NS_ENSURE_ARG_POINTER(aFollowLinks);
+
+ *aFollowLinks = mFollowLinks;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::SetFollowLinks(PRBool aFollowLinks)
+{
+ if (aFollowLinks != mFollowLinks) {
+ mFollowLinks = aFollowLinks;
+ UpdateTargetRef();
+ }
+ return NS_OK;
+}
+
+/* [noscript] PRFileDescStar openNSPRFileDesc (in long flags, in long mode); */
+NS_IMETHODIMP nsLocalFile::OpenNSPRFileDesc(PRInt32 flags, PRInt32 mode, PRFileDesc **_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ nsCAutoString path;
+ nsresult rv = GetPathInternal(path);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *_retval = PR_Open(path.get(), flags, mode);
+ if (! *_retval)
+ return NS_ErrorAccordingToNSPR();
+
+ return NS_OK;
+}
+
+/* [noscript] FILE openANSIFileDesc (in string mode); */
+NS_IMETHODIMP nsLocalFile::OpenANSIFileDesc(const char *mode, FILE **_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ nsCAutoString path;
+ nsresult rv = GetPathInternal(path);
+ if (NS_FAILED(rv))
+ return rv;
+
+ *_retval = fopen(path.get(), mode);
+ if (! *_retval)
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+/* [noscript] PRLibraryStar load (); */
+NS_IMETHODIMP nsLocalFile::Load(PRLibrary **_retval)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ NS_TIMELINE_START_TIMER("PR_LoadLibrary");
+
+ nsCAutoString path;
+ nsresult rv = GetPathInternal(path);
+ if (NS_FAILED(rv))
+ return rv;
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+ nsTraceRefcntImpl::SetActivityIsLegal(PR_FALSE);
+#endif
+
+ *_retval = PR_LoadLibrary(path.get());
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+ nsTraceRefcntImpl::SetActivityIsLegal(PR_TRUE);
+#endif
+
+ NS_TIMELINE_STOP_TIMER("PR_LoadLibrary");
+ NS_TIMELINE_MARK_TIMER1("PR_LoadLibrary", path.get());
+
+ if (!*_retval)
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+/* readonly attribute PRInt64 diskSpaceAvailable; */
+NS_IMETHODIMP nsLocalFile::GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ NS_ENSURE_ARG_POINTER(aDiskSpaceAvailable);
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ OSErr err;
+ FSCatalogInfo catalogInfo;
+ err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoVolume, &catalogInfo,
+ nsnull, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ FSVolumeInfo volumeInfo;
+ err = ::FSGetVolumeInfo(catalogInfo.volume, 0, nsnull, kFSVolInfoSizes,
+ &volumeInfo, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ *aDiskSpaceAvailable = volumeInfo.freeBytes;
+ return NS_OK;
+}
+
+/* void appendRelativePath (in AString relativeFilePath); */
+NS_IMETHODIMP nsLocalFile::AppendRelativePath(const nsAString& relativeFilePath)
+{
+ return AppendRelativeNativePath(NS_ConvertUTF16toUTF8(relativeFilePath));
+}
+
+/* [noscript] void appendRelativeNativePath (in ACString relativeFilePath); */
+NS_IMETHODIMP nsLocalFile::AppendRelativeNativePath(const nsACString& relativeFilePath)
+{
+ if (relativeFilePath.IsEmpty())
+ return NS_OK;
+ // No leading '/'
+ if (relativeFilePath.First() == '/')
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ // Parse the nodes and call Append() for each
+ nsACString::const_iterator nodeBegin, pathEnd;
+ relativeFilePath.BeginReading(nodeBegin);
+ relativeFilePath.EndReading(pathEnd);
+ nsACString::const_iterator nodeEnd(nodeBegin);
+
+ while (nodeEnd != pathEnd) {
+ FindCharInReadable(kPathSepChar, nodeEnd, pathEnd);
+ nsresult rv = AppendNative(Substring(nodeBegin, nodeEnd));
+ if (NS_FAILED(rv))
+ return rv;
+ if (nodeEnd != pathEnd) // If there's more left in the string, inc over the '/' nodeEnd is on.
+ ++nodeEnd;
+ nodeBegin = nodeEnd;
+ }
+ return NS_OK;
+}
+
+/* attribute ACString persistentDescriptor; */
+NS_IMETHODIMP nsLocalFile::GetPersistentDescriptor(nsACString& aPersistentDescriptor)
+{
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ AliasHandle aliasH;
+ OSErr err = ::FSNewAlias(nsnull, &fsRef, &aliasH);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ PRUint32 bytes = ::GetHandleSize((Handle) aliasH);
+ ::HLock((Handle) aliasH);
+ // Passing nsnull for dest makes NULL-term string
+ char* buf = PL_Base64Encode((const char*)*aliasH, bytes, nsnull);
+ ::DisposeHandle((Handle) aliasH);
+ NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY);
+
+ aPersistentDescriptor = buf;
+ PR_Free(buf);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::SetPersistentDescriptor(const nsACString& aPersistentDescriptor)
+{
+ if (aPersistentDescriptor.IsEmpty())
+ return NS_ERROR_INVALID_ARG;
+
+ // Support pathnames as user-supplied descriptors if they begin with '/'
+ // or '~'. These characters do not collide with the base64 set used for
+ // encoding alias records.
+ char first = aPersistentDescriptor.First();
+ if (first == '/' || first == '~')
+ return InitWithNativePath(aPersistentDescriptor);
+
+ nsresult rv = NS_OK;
+
+ PRUint32 dataSize = aPersistentDescriptor.Length();
+ char* decodedData = PL_Base64Decode(PromiseFlatCString(aPersistentDescriptor).get(), dataSize, nsnull);
+ if (!decodedData) {
+ NS_ERROR("SetPersistentDescriptor was given bad data");
+ return NS_ERROR_FAILURE;
+ }
+
+ // Cast to an alias record and resolve.
+ AliasRecord aliasHeader = *(AliasPtr)decodedData;
+ PRInt32 aliasSize = GetAliasSizeFromRecord(aliasHeader);
+ if (aliasSize > ((PRInt32)dataSize * 3) / 4) { // be paranoid about having too few data
+ PR_Free(decodedData);
+ return NS_ERROR_FAILURE;
+ }
+
+ // Move the now-decoded data into the Handle.
+ // The size of the decoded data is 3/4 the size of the encoded data. See plbase64.h
+ Handle newHandle = nsnull;
+ if (::PtrToHand(decodedData, &newHandle, aliasSize) != noErr)
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ PR_Free(decodedData);
+ if (NS_FAILED(rv))
+ return rv;
+
+ Boolean changed;
+ FSRef resolvedFSRef;
+ OSErr err = ::FSResolveAlias(nsnull, (AliasHandle)newHandle, &resolvedFSRef, &changed);
+
+ rv = MacErrorMapper(err);
+ DisposeHandle(newHandle);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return InitWithFSRef(&resolvedFSRef);
+}
+
+/* void reveal (); */
+NS_IMETHODIMP nsLocalFile::Reveal()
+{
+ FSRef fsRefToReveal;
+ AppleEvent aeEvent = {0, nil};
+ AppleEvent aeReply = {0, nil};
+ StAEDesc aeDirDesc, listElem, myAddressDesc, fileList;
+ OSErr err;
+ ProcessSerialNumber process;
+
+ nsresult rv = GetFSRefInternal(fsRefToReveal);
+ if (NS_FAILED(rv))
+ return rv;
+
+ err = ::FindRunningAppBySignature ('MACS', process);
+ if (err == noErr) {
+ err = ::AECreateDesc(typeProcessSerialNumber, (Ptr)&process, sizeof(process), &myAddressDesc);
+ if (err == noErr) {
+ // Create the FinderEvent
+ err = ::AECreateAppleEvent(kAEMiscStandards, kAEMakeObjectsVisible, &myAddressDesc,
+ kAutoGenerateReturnID, kAnyTransactionID, &aeEvent);
+ if (err == noErr) {
+ // Create the file list
+ err = ::AECreateList(nil, 0, false, &fileList);
+ if (err == noErr) {
+ FSSpec fsSpecToReveal;
+ err = ::FSRefMakeFSSpec(&fsRefToReveal, &fsSpecToReveal);
+ if (err == noErr) {
+ err = ::AEPutPtr(&fileList, 0, typeFSS, &fsSpecToReveal, sizeof(FSSpec));
+ if (err == noErr) {
+ err = ::AEPutParamDesc(&aeEvent, keyDirectObject, &fileList);
+ if (err == noErr) {
+ err = ::AESend(&aeEvent, &aeReply, kAENoReply, kAENormalPriority, kAEDefaultTimeout, nil, nil);
+ if (err == noErr)
+ ::SetFrontProcess(&process);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return NS_OK;
+}
+
+/* void launch (); */
+NS_IMETHODIMP nsLocalFile::Launch()
+{
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ OSErr err = ::LSOpenFSRef(&fsRef, NULL);
+ return MacErrorMapper(err);
+}
+
+
+//*****************************************************************************
+// nsLocalFile::nsILocalFileMac
+//*****************************************************************************
+#pragma mark -
+#pragma mark [nsILocalFileMac]
+
+/* void initWithCFURL (in CFURLRef aCFURL); */
+NS_IMETHODIMP nsLocalFile::InitWithCFURL(CFURLRef aCFURL)
+{
+ NS_ENSURE_ARG(aCFURL);
+
+ SetBaseRef(aCFURL);
+ return NS_OK;
+}
+
+/* void initWithFSRef ([const] in FSRefPtr aFSRef); */
+NS_IMETHODIMP nsLocalFile::InitWithFSRef(const FSRef *aFSRef)
+{
+ NS_ENSURE_ARG(aFSRef);
+ nsresult rv = NS_ERROR_FAILURE;
+
+ CFURLRef newURLRef = ::CFURLCreateFromFSRef(kCFAllocatorDefault, aFSRef);
+ if (newURLRef) {
+ SetBaseRef(newURLRef);
+ ::CFRelease(newURLRef);
+ rv = NS_OK;
+ }
+ return rv;
+}
+
+/* void initWithFSSpec ([const] in FSSpecPtr aFileSpec); */
+NS_IMETHODIMP nsLocalFile::InitWithFSSpec(const FSSpec *aFileSpec)
+{
+ NS_ENSURE_ARG(aFileSpec);
+
+ FSRef fsRef;
+ OSErr err = ::FSpMakeFSRef(aFileSpec, &fsRef);
+ if (err == noErr)
+ return InitWithFSRef(&fsRef);
+ else if (err == fnfErr) {
+ CInfoPBRec pBlock;
+ FSSpec parentDirSpec;
+
+ memset(&pBlock, 0, sizeof(CInfoPBRec));
+ parentDirSpec.name[0] = 0;
+ pBlock.dirInfo.ioVRefNum = aFileSpec->vRefNum;
+ pBlock.dirInfo.ioDrDirID = aFileSpec->parID;
+ pBlock.dirInfo.ioNamePtr = (StringPtr)parentDirSpec.name;
+ pBlock.dirInfo.ioFDirIndex = -1; //get info on parID
+ err = ::PBGetCatInfoSync(&pBlock);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ parentDirSpec.vRefNum = aFileSpec->vRefNum;
+ parentDirSpec.parID = pBlock.dirInfo.ioDrParID;
+ err = ::FSpMakeFSRef(&parentDirSpec, &fsRef);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ HFSUniStr255 unicodeName;
+ err = ::HFSNameGetUnicodeName(aFileSpec->name, kTextEncodingUnknown, &unicodeName);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ nsresult rv = InitWithFSRef(&fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+ return Append(nsDependentString(unicodeName.unicode, unicodeName.length));
+ }
+ return MacErrorMapper(err);
+}
+
+/* void initToAppWithCreatorCode (in OSType aAppCreator); */
+NS_IMETHODIMP nsLocalFile::InitToAppWithCreatorCode(OSType aAppCreator)
+{
+ FSRef fsRef;
+ OSErr err = ::LSFindApplicationForInfo(aAppCreator, nsnull, nsnull, &fsRef, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ return InitWithFSRef(&fsRef);
+}
+
+/* CFURLRef getCFURL (); */
+NS_IMETHODIMP nsLocalFile::GetCFURL(CFURLRef *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ CFURLRef whichURLRef = mFollowLinks ? mTargetRef : mBaseRef;
+ if (whichURLRef)
+ ::CFRetain(whichURLRef);
+ *_retval = whichURLRef;
+ return whichURLRef ? NS_OK : NS_ERROR_FAILURE;
+}
+
+/* FSRef getFSRef (); */
+NS_IMETHODIMP nsLocalFile::GetFSRef(FSRef *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ return GetFSRefInternal(*_retval);
+}
+
+/* FSSpec getFSSpec (); */
+NS_IMETHODIMP nsLocalFile::GetFSSpec(FSSpec *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ OSErr err;
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_SUCCEEDED(rv)) {
+ // If the leaf node exists, things are simple.
+ err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoNone,
+ nsnull, nsnull, _retval, nsnull);
+ return MacErrorMapper(err);
+ }
+ else if (rv == NS_ERROR_FILE_NOT_FOUND) {
+ // If the parent of the leaf exists, make an FSSpec from that.
+ CFURLRef parentURLRef = ::CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, mBaseRef);
+ if (!parentURLRef)
+ return NS_ERROR_FAILURE;
+
+ err = fnfErr;
+ if (::CFURLGetFSRef(parentURLRef, &fsRef)) {
+ FSCatalogInfo catalogInfo;
+ if ((err = ::FSGetCatalogInfo(&fsRef,
+ kFSCatInfoVolume + kFSCatInfoNodeID + kFSCatInfoTextEncoding,
+ &catalogInfo, nsnull, nsnull, nsnull)) == noErr) {
+ nsAutoString leafName;
+ if (NS_SUCCEEDED(GetLeafName(leafName))) {
+ Str31 hfsName;
+ if ((err = ::UnicodeNameGetHFSName(leafName.Length(),
+ leafName.get(),
+ catalogInfo.textEncodingHint,
+ catalogInfo.nodeID == fsRtDirID,
+ hfsName)) == noErr)
+ err = ::FSMakeFSSpec(catalogInfo.volume, catalogInfo.nodeID, hfsName, _retval);
+ }
+ }
+ }
+ ::CFRelease(parentURLRef);
+ rv = MacErrorMapper(err);
+ }
+ return rv;
+}
+
+/* readonly attribute PRInt64 fileSizeWithResFork; */
+NS_IMETHODIMP nsLocalFile::GetFileSizeWithResFork(PRInt64 *aFileSizeWithResFork)
+{
+ NS_ENSURE_ARG_POINTER(aFileSizeWithResFork);
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ FSCatalogInfo catalogInfo;
+ OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoDataSizes + kFSCatInfoRsrcSizes,
+ &catalogInfo, nsnull, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ *aFileSizeWithResFork = catalogInfo.dataLogicalSize + catalogInfo.rsrcLogicalSize;
+ return NS_OK;
+}
+
+/* attribute OSType fileType; */
+NS_IMETHODIMP nsLocalFile::GetFileType(OSType *aFileType)
+{
+ NS_ENSURE_ARG_POINTER(aFileType);
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ FinderInfo fInfo;
+ OSErr err = ::FSGetFinderInfo(&fsRef, &fInfo, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ *aFileType = fInfo.file.fileType;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::SetFileType(OSType aFileType)
+{
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ OSErr err = ::FSChangeCreatorType(&fsRef, 0, aFileType);
+ return MacErrorMapper(err);
+}
+
+/* attribute OSType fileCreator; */
+NS_IMETHODIMP nsLocalFile::GetFileCreator(OSType *aFileCreator)
+{
+ NS_ENSURE_ARG_POINTER(aFileCreator);
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ FinderInfo fInfo;
+ OSErr err = ::FSGetFinderInfo(&fsRef, &fInfo, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ *aFileCreator = fInfo.file.fileCreator;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsLocalFile::SetFileCreator(OSType aFileCreator)
+{
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ OSErr err = ::FSChangeCreatorType(&fsRef, aFileCreator, 0);
+ return MacErrorMapper(err);
+}
+
+/* void setFileTypeAndCreatorFromMIMEType (in string aMIMEType); */
+NS_IMETHODIMP nsLocalFile::SetFileTypeAndCreatorFromMIMEType(const char *aMIMEType)
+{
+ // XXX - This should be cut from the API. Would create an evil dependency.
+ NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void setFileTypeAndCreatorFromExtension (in string aExtension); */
+NS_IMETHODIMP nsLocalFile::SetFileTypeAndCreatorFromExtension(const char *aExtension)
+{
+ // XXX - This should be cut from the API. Would create an evil dependency.
+ NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* void launchWithDoc (in nsILocalFile aDocToLoad, in boolean aLaunchInBackground); */
+NS_IMETHODIMP nsLocalFile::LaunchWithDoc(nsILocalFile *aDocToLoad, PRBool aLaunchInBackground)
+{
+ PRBool isExecutable;
+ nsresult rv = IsExecutable(&isExecutable);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!isExecutable)
+ return NS_ERROR_FILE_EXECUTION_FAILED;
+
+ FSRef appFSRef, docFSRef;
+ rv = GetFSRefInternal(appFSRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (aDocToLoad) {
+ nsCOMPtr<nsILocalFileMac> macDoc = do_QueryInterface(aDocToLoad);
+ rv = macDoc->GetFSRef(&docFSRef);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ LSLaunchFlags theLaunchFlags = kLSLaunchDefaults;
+ LSLaunchFSRefSpec thelaunchSpec;
+
+ if (aLaunchInBackground)
+ theLaunchFlags |= kLSLaunchDontSwitch;
+ memset(&thelaunchSpec, 0, sizeof(LSLaunchFSRefSpec));
+
+ thelaunchSpec.appRef = &appFSRef;
+ if (aDocToLoad) {
+ thelaunchSpec.numDocs = 1;
+ thelaunchSpec.itemRefs = &docFSRef;
+ }
+ thelaunchSpec.launchFlags = theLaunchFlags;
+
+ OSErr err = ::LSOpenFromRefSpec(&thelaunchSpec, NULL);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ return NS_OK;
+}
+
+/* void openDocWithApp (in nsILocalFile aAppToOpenWith, in boolean aLaunchInBackground); */
+NS_IMETHODIMP nsLocalFile::OpenDocWithApp(nsILocalFile *aAppToOpenWith, PRBool aLaunchInBackground)
+{
+ nsresult rv;
+ OSErr err;
+
+ FSRef docFSRef, appFSRef;
+ rv = GetFSRefInternal(docFSRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (aAppToOpenWith) {
+ nsCOMPtr<nsILocalFileMac> appFileMac = do_QueryInterface(aAppToOpenWith, &rv);
+ if (!appFileMac)
+ return rv;
+
+ PRBool isExecutable;
+ rv = appFileMac->IsExecutable(&isExecutable);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!isExecutable)
+ return NS_ERROR_FILE_EXECUTION_FAILED;
+
+ rv = appFileMac->GetFSRef(&appFSRef);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ else {
+ OSType fileCreator;
+ rv = GetFileCreator(&fileCreator);
+ if (NS_FAILED(rv))
+ return rv;
+
+ err = ::LSFindApplicationForInfo(fileCreator, nsnull, nsnull, &appFSRef, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ }
+
+ LSLaunchFlags theLaunchFlags = kLSLaunchDefaults;
+ LSLaunchFSRefSpec thelaunchSpec;
+
+ if (aLaunchInBackground)
+ theLaunchFlags |= kLSLaunchDontSwitch;
+ memset(&thelaunchSpec, 0, sizeof(LSLaunchFSRefSpec));
+
+ thelaunchSpec.appRef = &appFSRef;
+ thelaunchSpec.numDocs = 1;
+ thelaunchSpec.itemRefs = &docFSRef;
+ thelaunchSpec.launchFlags = theLaunchFlags;
+
+ err = ::LSOpenFromRefSpec(&thelaunchSpec, NULL);
+ if (err != noErr)
+ return MacErrorMapper(err);
+
+ return NS_OK;
+}
+
+/* boolean isPackage (); */
+NS_IMETHODIMP nsLocalFile::IsPackage(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ FSRef fsRef;
+ nsresult rv = GetFSRefInternal(fsRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ FSCatalogInfo catalogInfo;
+ OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoNodeFlags + kFSCatInfoFinderInfo,
+ &catalogInfo, nsnull, nsnull, nsnull);
+ if (err != noErr)
+ return MacErrorMapper(err);
+ if ((catalogInfo.nodeFlags & kFSNodeIsDirectoryMask) != 0) {
+ FileInfo *fInfoPtr = (FileInfo *)(catalogInfo.finderInfo);
+ if ((fInfoPtr->finderFlags & kHasBundle) != 0) {
+ *_retval = PR_TRUE;
+ }
+ else {
+ // Folders ending with ".app" are also considered to
+ // be packages, even if the top-level folder doesn't have bundle set
+ nsCAutoString name;
+ if (NS_SUCCEEDED(rv = GetNativeLeafName(name))) {
+ const char *extPtr = strrchr(name.get(), '.');
+ if (extPtr) {
+ if ((nsCRT::strcasecmp(extPtr, ".app") == 0))
+ *_retval = PR_TRUE;
+ }
+ }
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetBundleDisplayName(nsAString& outBundleName)
+{
+ PRBool isPackage = PR_FALSE;
+ nsresult rv = IsPackage(&isPackage);
+ if (NS_FAILED(rv) || !isPackage)
+ return NS_ERROR_FAILURE;
+
+ nsAutoString name;
+ rv = GetLeafName(name);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRInt32 length = name.Length();
+ if (Substring(name, length - 4, length).EqualsLiteral(".app")) {
+ // 4 characters in ".app"
+ outBundleName = Substring(name, 0, length - 4);
+ }
+ else
+ outBundleName = name;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetBundleIdentifier(nsACString& outBundleIdentifier)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+
+ CFURLRef urlRef;
+ if (NS_SUCCEEDED(GetCFURL(&urlRef))) {
+ CFBundleRef bundle = ::CFBundleCreate(NULL, urlRef);
+ if (bundle) {
+ CFStringRef bundleIdentifier = ::CFBundleGetIdentifier(bundle);
+ if (bundleIdentifier)
+ rv = CFStringReftoUTF8(bundleIdentifier, outBundleIdentifier);
+
+ ::CFRelease(bundle);
+ }
+ ::CFRelease(urlRef);
+ }
+
+ return rv;
+}
+
+
+//*****************************************************************************
+// nsLocalFile Methods
+//*****************************************************************************
+#pragma mark -
+#pragma mark [Protected Methods]
+
+nsresult nsLocalFile::SetBaseRef(CFURLRef aCFURLRef)
+{
+ NS_ENSURE_ARG(aCFURLRef);
+
+ ::CFRetain(aCFURLRef);
+ if (mBaseRef)
+ ::CFRelease(mBaseRef);
+ mBaseRef = aCFURLRef;
+
+ mFollowLinksDirty = PR_TRUE;
+ UpdateTargetRef();
+ mCachedFSRefValid = PR_FALSE;
+ return NS_OK;
+}
+
+nsresult nsLocalFile::UpdateTargetRef()
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ if (mFollowLinksDirty) {
+ if (mTargetRef) {
+ ::CFRelease(mTargetRef);
+ mTargetRef = nsnull;
+ }
+ if (mFollowLinks) {
+ mTargetRef = mBaseRef;
+ ::CFRetain(mTargetRef);
+
+ FSRef fsRef;
+ if (::CFURLGetFSRef(mBaseRef, &fsRef)) {
+ Boolean targetIsFolder, wasAliased;
+ if (FSResolveAliasFile(&fsRef, true /*resolveAliasChains*/,
+ &targetIsFolder, &wasAliased) == noErr && wasAliased) {
+ ::CFRelease(mTargetRef);
+ mTargetRef = CFURLCreateFromFSRef(NULL, &fsRef);
+ if (!mTargetRef)
+ return NS_ERROR_FAILURE;
+ }
+ }
+ mFollowLinksDirty = PR_FALSE;
+ }
+ }
+ return NS_OK;
+}
+
+nsresult nsLocalFile::GetFSRefInternal(FSRef& aFSRef, PRBool bForceUpdateCache)
+{
+ if (bForceUpdateCache || !mCachedFSRefValid) {
+ mCachedFSRefValid = PR_FALSE;
+ CFURLRef whichURLRef = mFollowLinks ? mTargetRef : mBaseRef;
+ NS_ENSURE_TRUE(whichURLRef, NS_ERROR_NULL_POINTER);
+ if (::CFURLGetFSRef(whichURLRef, &mCachedFSRef))
+ mCachedFSRefValid = PR_TRUE;
+ }
+ if (mCachedFSRefValid) {
+ aFSRef = mCachedFSRef;
+ return NS_OK;
+ }
+ // CFURLGetFSRef only returns a Boolean for success,
+ // so we have to assume what the error was. This is
+ // the only probable cause.
+ return NS_ERROR_FILE_NOT_FOUND;
+}
+
+nsresult nsLocalFile::GetPathInternal(nsACString& path)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+
+ CFURLRef whichURLRef = mFollowLinks ? mTargetRef : mBaseRef;
+ NS_ENSURE_TRUE(whichURLRef, NS_ERROR_NULL_POINTER);
+
+ CFStringRef pathStrRef = ::CFURLCopyFileSystemPath(whichURLRef, kCFURLPOSIXPathStyle);
+ if (pathStrRef) {
+ rv = CFStringReftoUTF8(pathStrRef, path);
+ ::CFRelease(pathStrRef);
+ }
+ return rv;
+}
+
+nsresult nsLocalFile::CopyInternal(nsIFile* aParentDir,
+ const nsAString& newName,
+ PRBool followLinks)
+{
+ // Check we are correctly initialized.
+ CHECK_mBaseRef();
+
+ StFollowLinksState srcFollowState(*this, followLinks);
+
+ nsresult rv;
+ OSErr err;
+ FSRef srcFSRef, newFSRef;
+
+ rv = GetFSRefInternal(srcFSRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCOMPtr<nsIFile> newParentDir = aParentDir;
+
+ if (!newParentDir) {
+ if (newName.IsEmpty())
+ return NS_ERROR_INVALID_ARG;
+ rv = GetParent(getter_AddRefs(newParentDir));
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ // If newParentDir does not exist, create it
+ PRBool exists;
+ rv = newParentDir->Exists(&exists);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!exists) {
+ rv = newParentDir->Create(nsIFile::DIRECTORY_TYPE, 0777);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ FSRef destFSRef;
+ nsCOMPtr<nsILocalFileMac> newParentDirMac(do_QueryInterface(newParentDir));
+ if (!newParentDirMac)
+ return NS_ERROR_NO_INTERFACE;
+ rv = newParentDirMac->GetFSRef(&destFSRef);
+ if (NS_FAILED(rv))
+ return rv;
+
+ err =
+ ::FSCopyObject(&srcFSRef, &destFSRef, newName.Length(),
+ newName.Length() ? PromiseFlatString(newName).get() : NULL,
+ 0, kFSCatInfoNone, false, false, NULL, NULL, &newFSRef);
+
+ return MacErrorMapper(err);
+}
+
+const PRInt64 kMillisecsPerSec = 1000LL;
+const PRInt64 kUTCDateTimeFractionDivisor = 65535LL;
+
+PRInt64 nsLocalFile::HFSPlustoNSPRTime(const UTCDateTime& utcTime)
+{
+ // Start with seconds since Jan. 1, 1904 GMT
+ PRInt64 result = ((PRInt64)utcTime.highSeconds << 32) + (PRInt64)utcTime.lowSeconds;
+ // Subtract to convert to NSPR epoch of 1970
+ result -= kJanuaryFirst1970Seconds;
+ // Convert to millisecs
+ result *= kMillisecsPerSec;
+ // Convert the fraction to millisecs and add it
+ result += ((PRInt64)utcTime.fraction * kMillisecsPerSec) / kUTCDateTimeFractionDivisor;
+
+ return result;
+}
+
+void nsLocalFile::NSPRtoHFSPlusTime(PRInt64 nsprTime, UTCDateTime& utcTime)
+{
+ PRInt64 fraction = nsprTime % kMillisecsPerSec;
+ PRInt64 seconds = (nsprTime / kMillisecsPerSec) + kJanuaryFirst1970Seconds;
+ utcTime.highSeconds = (UInt16)((PRUint64)seconds >> 32);
+ utcTime.lowSeconds = (UInt32)seconds;
+ utcTime.fraction = (UInt16)((fraction * kUTCDateTimeFractionDivisor) / kMillisecsPerSec);
+}
+
+nsresult nsLocalFile::CFStringReftoUTF8(CFStringRef aInStrRef, nsACString& aOutStr)
+{
+ nsresult rv = NS_ERROR_FAILURE;
+ CFIndex usedBufLen, inStrLen = ::CFStringGetLength(aInStrRef);
+ CFIndex charsConverted = ::CFStringGetBytes(aInStrRef, CFRangeMake(0, inStrLen),
+ kCFStringEncodingUTF8, 0, PR_FALSE, nsnull, 0, &usedBufLen);
+ if (charsConverted == inStrLen) {
+#if 0 /* bird: too new? */
+ aOutStr.SetLength(usedBufLen);
+ if (aOutStr.Length() != (unsigned int)usedBufLen)
+ return NS_ERROR_OUT_OF_MEMORY;
+ UInt8 *buffer = (UInt8*) aOutStr.BeginWriting();
+
+ ::CFStringGetBytes(aInStrRef, CFRangeMake(0, inStrLen),
+ kCFStringEncodingUTF8, 0, false, buffer, usedBufLen, &usedBufLen);
+ rv = NS_OK;
+#else
+ nsAutoBuffer<UInt8, FILENAME_BUFFER_SIZE> buffer;
+ if (buffer.EnsureElemCapacity(usedBufLen + 1)) {
+ ::CFStringGetBytes(aInStrRef, CFRangeMake(0, inStrLen),
+ kCFStringEncodingUTF8, 0, false, buffer.get(), usedBufLen, &usedBufLen);
+ buffer.get()[usedBufLen] = '\0';
+ aOutStr.Assign(nsDependentCString((char*)buffer.get()));
+ rv = NS_OK;
+ }
+#endif
+ }
+ return rv;
+}
+
+// nsIHashable
+
+NS_IMETHODIMP
+nsLocalFile::Equals(nsIHashable* aOther, PRBool *aResult)
+{
+ return EqualsInternal(aOther, PR_FALSE, aResult);
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetHashCode(PRUint32 *aResult)
+{
+ CFStringRef pathStrRef = ::CFURLCopyFileSystemPath(mBaseRef, kCFURLPOSIXPathStyle);
+ nsCAutoString path;
+ CFStringReftoUTF8(pathStrRef, path);
+ ::CFRelease(pathStrRef);
+ *aResult = HashString(path);
+ return NS_OK;
+}
+
+//*****************************************************************************
+// Global Functions
+//*****************************************************************************
+#pragma mark -
+#pragma mark [Global Functions]
+
+void nsLocalFile::GlobalInit()
+{
+}
+
+void nsLocalFile::GlobalShutdown()
+{
+}
+
+nsresult NS_NewLocalFile(const nsAString& path, PRBool followLinks, nsILocalFile* *result)
+{
+ nsLocalFile* file = new nsLocalFile;
+ if (file == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(file);
+
+ file->SetFollowLinks(followLinks);
+
+ if (!path.IsEmpty()) {
+ nsresult rv = file->InitWithPath(path);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(file);
+ return rv;
+ }
+ }
+ *result = file;
+ return NS_OK;
+}
+
+nsresult NS_NewNativeLocalFile(const nsACString& path, PRBool followLinks, nsILocalFile **result)
+{
+ return NS_NewLocalFile(NS_ConvertUTF8toUTF16(path), followLinks, result);
+}
+
+nsresult NS_NewLocalFileWithFSSpec(const FSSpec* inSpec, PRBool followLinks, nsILocalFileMac **result)
+{
+ nsLocalFile* file = new nsLocalFile();
+ if (file == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(file);
+
+ file->SetFollowLinks(followLinks);
+
+ nsresult rv = file->InitWithFSSpec(inSpec);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(file);
+ return rv;
+ }
+ *result = file;
+ return NS_OK;
+}
+
+nsresult NS_NewLocalFileWithFSRef(const FSRef* aFSRef, PRBool aFollowLinks, nsILocalFileMac** result)
+{
+ nsLocalFile* file = new nsLocalFile();
+ if (file == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(file);
+
+ file->SetFollowLinks(aFollowLinks);
+
+ nsresult rv = file->InitWithFSRef(aFSRef);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(file);
+ return rv;
+ }
+ *result = file;
+ return NS_OK;
+}
+
+//*****************************************************************************
+// Static Functions
+//*****************************************************************************
+
+static nsresult MacErrorMapper(OSErr inErr)
+{
+ nsresult outErr;
+
+ switch (inErr)
+ {
+ case noErr:
+ outErr = NS_OK;
+ break;
+
+ case fnfErr:
+ case afpObjectNotFound:
+ case afpDirNotFound:
+ outErr = NS_ERROR_FILE_NOT_FOUND;
+ break;
+
+ case dupFNErr:
+ case afpObjectExists:
+ outErr = NS_ERROR_FILE_ALREADY_EXISTS;
+ break;
+
+ case dskFulErr:
+ case afpDiskFull:
+ outErr = NS_ERROR_FILE_DISK_FULL;
+ break;
+
+ case fLckdErr:
+ case afpVolLocked:
+ outErr = NS_ERROR_FILE_IS_LOCKED;
+ break;
+
+ case afpAccessDenied:
+ outErr = NS_ERROR_FILE_ACCESS_DENIED;
+ break;
+
+ case afpDirNotEmpty:
+ outErr = NS_ERROR_FILE_DIR_NOT_EMPTY;
+ break;
+
+ // Can't find good map for some
+ case bdNamErr:
+ outErr = NS_ERROR_FAILURE;
+ break;
+
+ default:
+ outErr = NS_ERROR_FAILURE;
+ break;
+ }
+ return outErr;
+}
+
+static OSErr FindRunningAppBySignature(OSType aAppSig, ProcessSerialNumber& outPsn)
+{
+ ProcessInfoRec info;
+ OSErr err = noErr;
+
+ outPsn.highLongOfPSN = 0;
+ outPsn.lowLongOfPSN = kNoProcess;
+
+ while (PR_TRUE)
+ {
+ err = ::GetNextProcess(&outPsn);
+ if (err == procNotFound)
+ break;
+ if (err != noErr)
+ return err;
+ info.processInfoLength = sizeof(ProcessInfoRec);
+ info.processName = nil;
+ info.processAppSpec = nil;
+ err = ::GetProcessInformation(&outPsn, &info);
+ if (err != noErr)
+ return err;
+
+ if (info.processSignature == aAppSig)
+ return noErr;
+ }
+ return procNotFound;
+}
+
+// Convert a UTF-8 string to a UTF-16 string while normalizing to
+// Normalization Form C (composed Unicode). We need this because
+// Mac OS X file system uses NFD (Normalization Form D : decomposed Unicode)
+// while most other OS', server-side programs usually expect NFC.
+
+typedef void (*UnicodeNormalizer) (CFMutableStringRef, CFStringNormalizationForm);
+static void CopyUTF8toUTF16NFC(const nsACString& aSrc, nsAString& aResult)
+{
+ static PRBool sChecked = PR_FALSE;
+ static UnicodeNormalizer sUnicodeNormalizer = NULL;
+
+ // CFStringNormalize was not introduced until Mac OS 10.2
+ if (!sChecked) {
+ CFBundleRef carbonBundle =
+ CFBundleGetBundleWithIdentifier(CFSTR("com.apple.Carbon"));
+ if (carbonBundle)
+ sUnicodeNormalizer = (UnicodeNormalizer)
+ ::CFBundleGetFunctionPointerForName(carbonBundle,
+ CFSTR("CFStringNormalize"));
+ sChecked = PR_TRUE;
+ }
+
+ if (!sUnicodeNormalizer) { // OS X 10.2 or earlier
+ CopyUTF8toUTF16(aSrc, aResult);
+ return;
+ }
+
+ const nsAFlatCString &inFlatSrc = PromiseFlatCString(aSrc);
+
+ // The number of 16bit code units in a UTF-16 string will never be
+ // larger than the number of bytes in the corresponding UTF-8 string.
+ CFMutableStringRef inStr =
+ ::CFStringCreateMutable(NULL, inFlatSrc.Length());
+
+ if (!inStr) {
+ CopyUTF8toUTF16(aSrc, aResult);
+ return;
+ }
+
+ ::CFStringAppendCString(inStr, inFlatSrc.get(), kCFStringEncodingUTF8);
+
+ sUnicodeNormalizer(inStr, kCFStringNormalizationFormC);
+
+ CFIndex length = CFStringGetLength(inStr);
+ const UniChar* chars = CFStringGetCharactersPtr(inStr);
+
+ if (chars)
+ aResult.Assign(chars, length);
+ else {
+ nsAutoBuffer<UniChar, FILENAME_BUFFER_SIZE> buffer;
+ if (!buffer.EnsureElemCapacity(length))
+ CopyUTF8toUTF16(aSrc, aResult);
+ else {
+ CFStringGetCharacters(inStr, CFRangeMake(0, length), buffer.get());
+ aResult.Assign(buffer.get(), length);
+ }
+ }
+ CFRelease(inStr);
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFileOSX.h b/src/libs/xpcom18a4/xpcom/io/nsLocalFileOSX.h
new file mode 100644
index 00000000..b6d74521
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFileOSX.h
@@ -0,0 +1,119 @@
+/* -*- 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) 2001, 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Conrad Carlen <ccarlen@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 nsLocalFileMac_h__
+#define nsLocalFileMac_h__
+
+#include "nsILocalFileMac.h"
+#include "nsString.h"
+#include "nsIHashable.h"
+
+class nsDirEnumerator;
+
+//*****************************************************************************
+// nsLocalFile
+//
+// The native charset of this implementation is UTF-8. The Unicode used by the
+// Mac OS file system is decomposed, so "Native" versions of these routines will
+// always use decomposed Unicode (NFD). Their "non-Native" counterparts are
+// intended to be simple wrappers which call the "Native" version and convert
+// between UTF-8 and UTF-16. All the work is done on the "Native" side except
+// for the conversion to NFC (composed Unicode) done in "non-Native" getters.
+//*****************************************************************************
+
+class NS_COM nsLocalFile : public nsILocalFileMac,
+ public nsIHashable
+{
+ friend class nsDirEnumerator;
+
+public:
+ NS_DEFINE_STATIC_CID_ACCESSOR(NS_LOCAL_FILE_CID)
+
+ nsLocalFile();
+
+ static NS_METHOD nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIFILE
+ NS_DECL_NSILOCALFILE
+ NS_DECL_NSILOCALFILEMAC
+ NS_DECL_NSIHASHABLE
+
+public:
+
+ static void GlobalInit();
+ static void GlobalShutdown();
+
+private:
+ ~nsLocalFile();
+
+protected:
+ nsLocalFile(const nsLocalFile& src);
+
+ nsresult SetBaseRef(CFURLRef aCFURLRef); // Does CFRetain on aCFURLRef
+ nsresult UpdateTargetRef();
+
+ nsresult GetFSRefInternal(FSRef& aFSSpec, PRBool bForceUpdateCache = PR_TRUE);
+ nsresult GetPathInternal(nsACString& path); // Returns path WRT mFollowLinks
+ nsresult EqualsInternal(nsISupports* inFile,
+ PRBool aUpdateCache, PRBool *_retval);
+
+ nsresult CopyInternal(nsIFile* newParentDir,
+ const nsAString& newName,
+ PRBool followLinks);
+
+ static PRInt64 HFSPlustoNSPRTime(const UTCDateTime& utcTime);
+ static void NSPRtoHFSPlusTime(PRInt64 nsprTime, UTCDateTime& utcTime);
+ static nsresult CFStringReftoUTF8(CFStringRef aInStrRef, nsACString& aOutStr);
+
+protected:
+ CFURLRef mBaseRef; // The FS object we represent
+ CFURLRef mTargetRef; // If mBaseRef is an alias, its target
+
+ FSRef mCachedFSRef;
+ PRPackedBool mCachedFSRefValid;
+
+ PRPackedBool mFollowLinks;
+ PRPackedBool mFollowLinksDirty;
+
+ static const char kPathSepChar;
+ static const PRUnichar kPathSepUnichar;
+ static const PRInt64 kJanuaryFirst1970Seconds;
+};
+
+#endif // nsLocalFileMac_h__
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFileUnicode.h b/src/libs/xpcom18a4/xpcom/io/nsLocalFileUnicode.h
new file mode 100644
index 00000000..90bc9c07
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFileUnicode.h
@@ -0,0 +1,47 @@
+/* -*- 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) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henry Sobotka <sobotka@axess.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 _NS_LOCALFILEUNICODE_H_
+
+extern void NS_ShutdownLocalFileUnicode();
+
+extern "C" NS_EXPORT nsresult
+NS_NewUnicodeLocalFile(const PRUnichar *, PRBool, nsILocalFile **);
+
+#endif // _NS_LOCALFILEUNICODE_H_
+
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFileUnix.cpp b/src/libs/xpcom18a4/xpcom/io/nsLocalFileUnix.cpp
new file mode 100644
index 00000000..eef17bde
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFileUnix.cpp
@@ -0,0 +1,1724 @@
+/* -*- 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-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike Shaver <shaver@mozilla.org>
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * Jason Eager <jce2@po.cwru.edu>
+ * Stuart Parmenter <pavlov@netscape.com>
+ * Brendan Eich <brendan@mozilla.org>
+ * Pete Collins <petejc@mozdev.org>
+ * Paul Ashford <arougthopher@lizardland.net>
+ *
+ * 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 of nsIFile for ``Unixy'' systems.
+ */
+
+// We're going to need some autoconf loving, I can just tell.
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <utime.h>
+#include <dirent.h>
+#include <ctype.h>
+#include <locale.h>
+#ifdef XP_BEOS
+ #include <Path.h>
+ #include <Entry.h>
+ #include <Roster.h>
+#endif
+#if defined(VMS)
+ #include <fabdef.h>
+#endif
+
+#include "nsDirectoryServiceDefs.h"
+#include "nsCRT.h"
+#include "nsCOMPtr.h"
+#include "nsMemory.h"
+#include "nsIFile.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+#include "nsLocalFile.h"
+#include "nsIComponentManager.h"
+#include "nsXPIDLString.h"
+#include "prproces.h"
+#include "nsISimpleEnumerator.h"
+#include "nsITimelineService.h"
+
+#include "nsNativeCharsetUtils.h"
+
+// On some platforms file/directory name comparisons need to
+// be case-blind.
+#if defined(VMS)
+ #define FILE_STRCMP strcasecmp
+ #define FILE_STRNCMP strncasecmp
+#else
+ #define FILE_STRCMP strcmp
+ #define FILE_STRNCMP strncmp
+#endif
+
+#define VALIDATE_STAT_CACHE() \
+ PR_BEGIN_MACRO \
+ if (!mHaveCachedStat) { \
+ FillStatCache(); \
+ if (!mHaveCachedStat) \
+ return NSRESULT_FOR_ERRNO(); \
+ } \
+ PR_END_MACRO
+
+#define CHECK_mPath() \
+ PR_BEGIN_MACRO \
+ if (mPath.IsEmpty()) \
+ return NS_ERROR_NOT_INITIALIZED; \
+ PR_END_MACRO
+
+/* directory enumerator */
+class NS_COM
+nsDirEnumeratorUnix : public nsISimpleEnumerator
+{
+ public:
+ nsDirEnumeratorUnix();
+
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+
+ // nsISimpleEnumerator interface
+ NS_DECL_NSISIMPLEENUMERATOR
+
+ NS_IMETHOD Init(nsLocalFile *parent, PRBool ignored);
+
+ private:
+ ~nsDirEnumeratorUnix();
+
+ protected:
+ NS_IMETHOD GetNextEntry();
+
+ DIR *mDir;
+ struct dirent *mEntry;
+ nsCString mParentPath;
+};
+
+nsDirEnumeratorUnix::nsDirEnumeratorUnix() :
+ mDir(nsnull),
+ mEntry(nsnull)
+{
+}
+
+nsDirEnumeratorUnix::~nsDirEnumeratorUnix()
+{
+ if (mDir)
+ closedir(mDir);
+}
+
+NS_IMPL_ISUPPORTS1(nsDirEnumeratorUnix, nsISimpleEnumerator)
+
+NS_IMETHODIMP
+nsDirEnumeratorUnix::Init(nsLocalFile *parent, PRBool resolveSymlinks /*ignored*/)
+{
+ nsCAutoString dirPath;
+ if (NS_FAILED(parent->GetNativePath(dirPath)) ||
+ dirPath.IsEmpty()) {
+ return NS_ERROR_FILE_INVALID_PATH;
+ }
+
+ if (NS_FAILED(parent->GetNativePath(mParentPath)))
+ return NS_ERROR_FAILURE;
+
+ mDir = opendir(dirPath.get());
+ if (!mDir)
+ return NSRESULT_FOR_ERRNO();
+ return GetNextEntry();
+}
+
+NS_IMETHODIMP
+nsDirEnumeratorUnix::HasMoreElements(PRBool *result)
+{
+ *result = mDir && mEntry;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDirEnumeratorUnix::GetNext(nsISupports **_retval)
+{
+ nsresult rv;
+ if (!mDir || !mEntry) {
+ *_retval = nsnull;
+ return NS_OK;
+ }
+
+ nsLocalFile* file = new nsLocalFile();
+ if (!file)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (NS_FAILED(rv = file->InitWithNativePath(mParentPath)) ||
+ NS_FAILED(rv = file->AppendNative(nsDependentCString(mEntry->d_name)))) {
+ return rv;
+ }
+ *_retval = NS_STATIC_CAST(nsISupports *, file);
+ NS_ADDREF(*_retval);
+ return GetNextEntry();
+}
+
+NS_IMETHODIMP
+nsDirEnumeratorUnix::GetNextEntry()
+{
+ do {
+ errno = 0;
+ mEntry = readdir(mDir);
+
+ // end of dir or error
+ if (!mEntry)
+ return NSRESULT_FOR_ERRNO();
+
+ // keep going past "." and ".."
+ } while (mEntry->d_name[0] == '.' &&
+ (mEntry->d_name[1] == '\0' || // .\0
+ (mEntry->d_name[1] == '.' &&
+ mEntry->d_name[2] == '\0'))); // ..\0
+ return NS_OK;
+}
+
+nsLocalFile::nsLocalFile() :
+ mHaveCachedStat(PR_FALSE)
+{
+}
+
+nsLocalFile::nsLocalFile(const nsLocalFile& other)
+ : mCachedStat(other.mCachedStat)
+ , mPath(other.mPath)
+ , mHaveCachedStat(other.mHaveCachedStat)
+{
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsLocalFile,
+ nsIFile,
+ nsILocalFile)
+
+nsresult
+nsLocalFile::nsLocalFileConstructor(nsISupports *outer,
+ const nsIID &aIID,
+ void **aInstancePtr)
+{
+ NS_ENSURE_ARG_POINTER(aInstancePtr);
+ NS_ENSURE_NO_AGGREGATION(outer);
+
+ *aInstancePtr = nsnull;
+
+ nsCOMPtr<nsIFile> inst = new nsLocalFile();
+ if (!inst)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return inst->QueryInterface(aIID, aInstancePtr);
+}
+
+nsresult
+nsLocalFile::FillStatCache() {
+ if (stat(mPath.get(), &mCachedStat) == -1) {
+ // try lstat it may be a symlink
+ if (lstat(mPath.get(), &mCachedStat) == -1) {
+ return NSRESULT_FOR_ERRNO();
+ }
+ }
+ mHaveCachedStat = PR_TRUE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Clone(nsIFile **file)
+{
+ // Just copy-construct ourselves
+ *file = new nsLocalFile(*this);
+ if (!*file)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(*file);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::InitWithNativePath(const nsACString &filePath)
+{
+ if (Substring(filePath, 0, 2).EqualsLiteral("~/")) {
+ nsCOMPtr<nsIFile> homeDir;
+ nsCAutoString homePath;
+ if (NS_FAILED(NS_GetSpecialDirectory(NS_OS_HOME_DIR,
+ getter_AddRefs(homeDir))) ||
+ NS_FAILED(homeDir->GetNativePath(homePath))) {
+ return NS_ERROR_FAILURE;
+ }
+
+ mPath = homePath + Substring(filePath, 1, filePath.Length() - 1);
+ } else if (filePath.IsEmpty() || filePath.First() != '/') {
+ NS_ERROR("Relative paths not allowed");
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+ } else {
+ mPath = filePath;
+ }
+
+ // trim off trailing slashes
+ ssize_t len = mPath.Length();
+ while ((len > 1) && (mPath[len - 1] == '/'))
+ --len;
+ mPath.SetLength(len);
+
+ InvalidateCache();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::CreateAllAncestors(PRUint32 permissions)
+{
+ // <jband> I promise to play nice
+ char *buffer = mPath.BeginWriting(),
+ *slashp = buffer;
+
+#ifdef DEBUG_NSIFILE
+ fprintf(stderr, "nsIFile: before: %s\n", buffer);
+#endif
+
+ while ((slashp = strchr(slashp + 1, '/'))) {
+ /*
+ * Sequences of '/' are equivalent to a single '/'.
+ */
+ if (slashp[1] == '/')
+ continue;
+
+ /*
+ * If the path has a trailing slash, don't make the last component,
+ * because we'll get EEXIST in Create when we try to build the final
+ * component again, and it's easier to condition the logic here than
+ * there.
+ */
+ if (slashp[1] == '\0')
+ break;
+
+ /* Temporarily NUL-terminate here */
+ *slashp = '\0';
+#ifdef DEBUG_NSIFILE
+ fprintf(stderr, "nsIFile: mkdir(\"%s\")\n", buffer);
+#endif
+ int mkdir_result = mkdir(buffer, permissions);
+ int mkdir_errno = errno;
+ if (mkdir_result == -1) {
+ /*
+ * Always set |errno| to EEXIST if the dir already exists
+ * (we have to do this here since the errno value is not consistent
+ * in all cases - various reasons like different platform,
+ * automounter-controlled dir, etc. can affect it (see bug 125489
+ * for details)).
+ */
+ if (access(buffer, F_OK) == 0) {
+ mkdir_errno = EEXIST;
+ }
+ }
+
+ /* Put the / back before we (maybe) return */
+ *slashp = '/';
+
+ /*
+ * We could get EEXIST for an existing file -- not directory --
+ * with the name of one of our ancestors, but that's OK: we'll get
+ * ENOTDIR when we try to make the next component in the path,
+ * either here on back in Create, and error out appropriately.
+ */
+ if (mkdir_result == -1 && mkdir_errno != EEXIST)
+ return nsresultForErrno(mkdir_errno);
+ }
+
+#ifdef DEBUG_NSIFILE
+ fprintf(stderr, "nsIFile: after: %s\n", buffer);
+#endif
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::OpenNSPRFileDesc(PRInt32 flags, PRInt32 mode, PRFileDesc **_retval)
+{
+ *_retval = PR_Open(mPath.get(), flags, mode);
+ if (! *_retval)
+ return NS_ErrorAccordingToNSPR();
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::OpenANSIFileDesc(const char *mode, FILE **_retval)
+{
+ *_retval = fopen(mPath.get(), mode);
+ if (! *_retval)
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+static int
+do_create(const char *path, PRIntn flags, mode_t mode, PRFileDesc **_retval)
+{
+ *_retval = PR_Open(path, flags, mode);
+ return *_retval ? 0 : -1;
+}
+
+static int
+do_mkdir(const char *path, PRIntn flags, mode_t mode, PRFileDesc **_retval)
+{
+ *_retval = nsnull;
+ return mkdir(path, mode);
+}
+
+nsresult
+nsLocalFile::CreateAndKeepOpen(PRUint32 type, PRIntn flags,
+ PRUint32 permissions, PRFileDesc **_retval)
+{
+ if (type != NORMAL_FILE_TYPE && type != DIRECTORY_TYPE)
+ return NS_ERROR_FILE_UNKNOWN_TYPE;
+
+ int result;
+ int (*createFunc)(const char *, PRIntn, mode_t, PRFileDesc **) =
+ (type == NORMAL_FILE_TYPE) ? do_create : do_mkdir;
+
+ result = createFunc(mPath.get(), flags, permissions, _retval);
+ if (result == -1 && errno == ENOENT) {
+ /*
+ * If we failed because of missing ancestor components, try to create
+ * them and then retry the original creation.
+ *
+ * Ancestor directories get the same permissions as the file we're
+ * creating, with the X bit set for each of (user,group,other) with
+ * an R bit in the original permissions. If you want to do anything
+ * fancy like setgid or sticky bits, do it by hand.
+ */
+ int dirperm = permissions;
+ if (permissions & S_IRUSR)
+ dirperm |= S_IXUSR;
+ if (permissions & S_IRGRP)
+ dirperm |= S_IXGRP;
+ if (permissions & S_IROTH)
+ dirperm |= S_IXOTH;
+
+#ifdef DEBUG_NSIFILE
+ fprintf(stderr, "nsIFile: perm = %o, dirperm = %o\n", permissions,
+ dirperm);
+#endif
+
+ if (NS_FAILED(CreateAllAncestors(dirperm)))
+ return NS_ERROR_FAILURE;
+
+#ifdef DEBUG_NSIFILE
+ fprintf(stderr, "nsIFile: Create(\"%s\") again\n", mPath.get());
+#endif
+ result = createFunc(mPath.get(), flags, permissions, _retval);
+ }
+
+ return NSRESULT_FOR_RETURN(result);
+}
+
+NS_IMETHODIMP
+nsLocalFile::Create(PRUint32 type, PRUint32 permissions)
+{
+ PRFileDesc *junk = nsnull;
+ nsresult rv = CreateAndKeepOpen(type,
+ PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE |
+ PR_EXCL,
+ permissions,
+ &junk);
+ if (junk)
+ PR_Close(junk);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::AppendNative(const nsACString &fragment)
+{
+ if (fragment.IsEmpty())
+ return NS_OK;
+
+ // only one component of path can be appended
+ nsACString::const_iterator begin, end;
+ if (FindCharInReadable('/', fragment.BeginReading(begin),
+ fragment.EndReading(end)))
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ return AppendRelativeNativePath(fragment);
+}
+
+NS_IMETHODIMP
+nsLocalFile::AppendRelativeNativePath(const nsACString &fragment)
+{
+ if (fragment.IsEmpty())
+ return NS_OK;
+
+ // No leading '/'
+ if (fragment.First() == '/')
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ if (mPath.EqualsLiteral("/"))
+ mPath.Append(fragment);
+ else
+ mPath.Append(NS_LITERAL_CSTRING("/") + fragment);
+
+ InvalidateCache();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Normalize()
+{
+ char resolved_path[PATH_MAX] = "";
+ char *resolved_path_ptr = nsnull;
+
+#ifdef XP_BEOS
+ BEntry be_e(mPath.get(), true);
+ BPath be_p;
+ status_t err;
+ if ((err = be_e.GetPath(&be_p)) == B_OK) {
+ resolved_path_ptr = (char *)be_p.Path();
+ PL_strncpyz(resolved_path, resolved_path_ptr, PATH_MAX - 1);
+ }
+#else
+ resolved_path_ptr = realpath(mPath.get(), resolved_path);
+#endif
+ // if there is an error, the return is null.
+ if (!resolved_path_ptr)
+ return NSRESULT_FOR_ERRNO();
+
+ mPath = resolved_path;
+ return NS_OK;
+}
+
+void
+nsLocalFile::LocateNativeLeafName(nsACString::const_iterator &begin,
+ nsACString::const_iterator &end)
+{
+ // XXX perhaps we should cache this??
+
+ mPath.BeginReading(begin);
+ mPath.EndReading(end);
+
+ nsACString::const_iterator it = end;
+ nsACString::const_iterator stop = begin;
+ --stop;
+ while (--it != stop) {
+ if (*it == '/') {
+ begin = ++it;
+ return;
+ }
+ }
+ // else, the entire path is the leaf name (which means this
+ // isn't an absolute path... unexpected??)
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetNativeLeafName(nsACString &aLeafName)
+{
+ nsACString::const_iterator begin, end;
+ LocateNativeLeafName(begin, end);
+ aLeafName = Substring(begin, end);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetNativeLeafName(const nsACString &aLeafName)
+{
+ nsACString::const_iterator begin, end;
+ LocateNativeLeafName(begin, end);
+ mPath.Replace(begin.get() - mPath.get(), Distance(begin, end), aLeafName);
+ InvalidateCache();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetNativePath(nsACString &_retval)
+{
+ _retval = mPath;
+ return NS_OK;
+}
+
+nsresult
+nsLocalFile::GetNativeTargetPathName(nsIFile *newParent,
+ const nsACString &newName,
+ nsACString &_retval)
+{
+ nsresult rv;
+ nsCOMPtr<nsIFile> oldParent;
+
+ if (!newParent) {
+ if (NS_FAILED(rv = GetParent(getter_AddRefs(oldParent))))
+ return rv;
+ newParent = oldParent.get();
+ } else {
+ // check to see if our target directory exists
+ PRBool targetExists;
+ if (NS_FAILED(rv = newParent->Exists(&targetExists)))
+ return rv;
+
+ if (!targetExists) {
+ // XXX create the new directory with some permissions
+ rv = newParent->Create(DIRECTORY_TYPE, 0700);
+ if (NS_FAILED(rv))
+ return rv;
+ } else {
+ // make sure that the target is actually a directory
+ PRBool targetIsDirectory;
+ if (NS_FAILED(rv = newParent->IsDirectory(&targetIsDirectory)))
+ return rv;
+ if (!targetIsDirectory)
+ return NS_ERROR_FILE_DESTINATION_NOT_DIR;
+ }
+ }
+
+ nsACString::const_iterator nameBegin, nameEnd;
+ if (!newName.IsEmpty()) {
+ newName.BeginReading(nameBegin);
+ newName.EndReading(nameEnd);
+ }
+ else
+ LocateNativeLeafName(nameBegin, nameEnd);
+
+ nsCAutoString dirName;
+ if (NS_FAILED(rv = newParent->GetNativePath(dirName)))
+ return rv;
+
+ _retval = dirName
+ + NS_LITERAL_CSTRING("/")
+ + Substring(nameBegin, nameEnd);
+ return NS_OK;
+}
+
+nsresult
+nsLocalFile::CopyDirectoryTo(nsIFile *newParent)
+{
+ nsresult rv;
+ /*
+ * dirCheck is used for various boolean test results such as from Equals,
+ * Exists, isDir, etc.
+ */
+ PRBool dirCheck, isSymlink;
+ PRUint32 oldPerms;
+
+ if (NS_FAILED((rv = IsDirectory(&dirCheck))))
+ return rv;
+ if (!dirCheck)
+ return CopyToNative(newParent, EmptyCString());
+
+ if (NS_FAILED(rv = Equals(newParent, &dirCheck)))
+ return rv;
+ if (dirCheck) {
+ // can't copy dir to itself
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ if (NS_FAILED(rv = newParent->Exists(&dirCheck)))
+ return rv;
+ // get the dirs old permissions
+ if (NS_FAILED(rv = GetPermissions(&oldPerms)))
+ return rv;
+ if (!dirCheck) {
+ if (NS_FAILED(rv = newParent->Create(DIRECTORY_TYPE, oldPerms)))
+ return rv;
+ } else { // dir exists lets try to use leaf
+ nsCAutoString leafName;
+ if (NS_FAILED(rv = GetNativeLeafName(leafName)))
+ return rv;
+ if (NS_FAILED(rv = newParent->AppendNative(leafName)))
+ return rv;
+ if (NS_FAILED(rv = newParent->Exists(&dirCheck)))
+ return rv;
+ if (dirCheck)
+ return NS_ERROR_FILE_ALREADY_EXISTS; // dest exists
+ if (NS_FAILED(rv = newParent->Create(DIRECTORY_TYPE, oldPerms)))
+ return rv;
+ }
+
+ nsCOMPtr<nsISimpleEnumerator> dirIterator;
+ if (NS_FAILED(rv = GetDirectoryEntries(getter_AddRefs(dirIterator))))
+ return rv;
+
+ PRBool hasMore = PR_FALSE;
+ while (dirIterator->HasMoreElements(&hasMore), hasMore) {
+ nsCOMPtr<nsIFile> entry;
+ rv = dirIterator->GetNext((nsISupports**)getter_AddRefs(entry));
+ if (NS_FAILED(rv))
+ continue;
+ if (NS_FAILED(rv = entry->IsSymlink(&isSymlink)))
+ return rv;
+ if (NS_FAILED(rv = entry->IsDirectory(&dirCheck)))
+ return rv;
+ if (dirCheck && !isSymlink) {
+ nsCOMPtr<nsIFile> destClone;
+ rv = newParent->Clone(getter_AddRefs(destClone));
+ if (NS_SUCCEEDED(rv)) {
+ nsCOMPtr<nsILocalFile> newDir(do_QueryInterface(destClone));
+ if (NS_FAILED(rv = entry->CopyToNative(newDir, EmptyCString()))) {
+#ifdef DEBUG
+ nsresult rv2;
+ nsCAutoString pathName;
+ if (NS_FAILED(rv2 = entry->GetNativePath(pathName)))
+ return rv2;
+ printf("Operation not supported: %s\n", pathName.get());
+#endif
+ if (rv == NS_ERROR_OUT_OF_MEMORY)
+ return rv;
+ continue;
+ }
+ }
+ } else {
+ if (NS_FAILED(rv = entry->CopyToNative(newParent, EmptyCString()))) {
+#ifdef DEBUG
+ nsresult rv2;
+ nsCAutoString pathName;
+ if (NS_FAILED(rv2 = entry->GetNativePath(pathName)))
+ return rv2;
+ printf("Operation not supported: %s\n", pathName.get());
+#endif
+ if (rv == NS_ERROR_OUT_OF_MEMORY)
+ return rv;
+ continue;
+ }
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::CopyToNative(nsIFile *newParent, const nsACString &newName)
+{
+ nsresult rv;
+ // check to make sure that this has been initialized properly
+ CHECK_mPath();
+
+ // we copy the parent here so 'newParent' remains immutable
+ nsCOMPtr <nsIFile> workParent;
+ if (newParent) {
+ if (NS_FAILED(rv = newParent->Clone(getter_AddRefs(workParent))))
+ return rv;
+ } else {
+ if (NS_FAILED(rv = GetParent(getter_AddRefs(workParent))))
+ return rv;
+ }
+
+ // check to see if we are a directory or if we are a file
+ PRBool isDirectory;
+ if (NS_FAILED(rv = IsDirectory(&isDirectory)))
+ return rv;
+
+ nsCAutoString newPathName;
+ if (isDirectory) {
+ if (!newName.IsEmpty()) {
+ if (NS_FAILED(rv = workParent->AppendNative(newName)))
+ return rv;
+ } else {
+ if (NS_FAILED(rv = GetNativeLeafName(newPathName)))
+ return rv;
+ if (NS_FAILED(rv = workParent->AppendNative(newPathName)))
+ return rv;
+ }
+ if (NS_FAILED(rv = CopyDirectoryTo(workParent)))
+ return rv;
+ } else {
+ rv = GetNativeTargetPathName(workParent, newName, newPathName);
+ if (NS_FAILED(rv))
+ return rv;
+
+#ifdef DEBUG_blizzard
+ printf("nsLocalFile::CopyTo() %s -> %s\n", mPath.get(), newPathName.get());
+#endif
+
+ // actually create the file.
+ nsLocalFile *newFile = new nsLocalFile();
+ if (!newFile)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsCOMPtr<nsILocalFile> fileRef(newFile); // release on exit
+
+ rv = newFile->InitWithNativePath(newPathName);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // get the old permissions
+ PRUint32 myPerms;
+ GetPermissions(&myPerms);
+
+ // Create the new file with the old file's permissions, even if write
+ // permission is missing. We can't create with write permission and
+ // then change back to myPerm on all filesystems (FAT on Linux, e.g.).
+ // But we can write to a read-only file on all Unix filesystems if we
+ // open it successfully for writing.
+
+ PRFileDesc *newFD;
+ rv = newFile->CreateAndKeepOpen(NORMAL_FILE_TYPE,
+ PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE,
+ myPerms,
+ &newFD);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // open the old file, too
+ PRBool specialFile;
+ if (NS_FAILED(rv = IsSpecial(&specialFile))) {
+ PR_Close(newFD);
+ return rv;
+ }
+ if (specialFile) {
+#ifdef DEBUG
+ printf("Operation not supported: %s\n", mPath.get());
+#endif
+ // make sure to clean up properly
+ PR_Close(newFD);
+ return NS_OK;
+ }
+
+ PRFileDesc *oldFD;
+ rv = OpenNSPRFileDesc(PR_RDONLY, myPerms, &oldFD);
+ if (NS_FAILED(rv)) {
+ // make sure to clean up properly
+ PR_Close(newFD);
+ return rv;
+ }
+
+#ifdef DEBUG_blizzard
+ PRInt32 totalRead = 0;
+ PRInt32 totalWritten = 0;
+#endif
+ char buf[BUFSIZ];
+ PRInt32 bytesRead;
+
+ while ((bytesRead = PR_Read(oldFD, buf, BUFSIZ)) > 0) {
+#ifdef DEBUG_blizzard
+ totalRead += bytesRead;
+#endif
+
+ // PR_Write promises never to do a short write
+ PRInt32 bytesWritten = PR_Write(newFD, buf, bytesRead);
+ if (bytesWritten < 0) {
+ bytesRead = -1;
+ break;
+ }
+ NS_ASSERTION(bytesWritten == bytesRead, "short PR_Write?");
+
+#ifdef DEBUG_blizzard
+ totalWritten += bytesWritten;
+#endif
+ }
+
+#ifdef DEBUG_blizzard
+ printf("read %d bytes, wrote %d bytes\n",
+ totalRead, totalWritten);
+#endif
+
+ // close the files
+ PR_Close(newFD);
+ PR_Close(oldFD);
+
+ // check for read (or write) error after cleaning up
+ if (bytesRead < 0)
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::CopyToFollowingLinksNative(nsIFile *newParent, const nsACString &newName)
+{
+ return CopyToNative(newParent, newName);
+}
+
+NS_IMETHODIMP
+nsLocalFile::MoveToNative(nsIFile *newParent, const nsACString &newName)
+{
+ nsresult rv;
+
+ // check to make sure that this has been initialized properly
+ CHECK_mPath();
+
+ // check to make sure that we have a new parent
+ nsCAutoString newPathName;
+ rv = GetNativeTargetPathName(newParent, newName, newPathName);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // try for atomic rename, falling back to copy/delete
+ if (rename(mPath.get(), newPathName.get()) < 0) {
+#ifdef VMS
+ if (errno == EXDEV || errno == ENXIO) {
+#else
+ if (errno == EXDEV) {
+#endif
+ rv = CopyToNative(newParent, newName);
+ if (NS_SUCCEEDED(rv))
+ rv = Remove(PR_TRUE);
+ } else {
+ rv = NSRESULT_FOR_ERRNO();
+ }
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Remove(PRBool recursive)
+{
+ CHECK_mPath();
+
+ VALIDATE_STAT_CACHE();
+ PRBool isSymLink, isDir;
+
+ nsresult rv = IsSymlink(&isSymLink);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (!recursive && isSymLink)
+ return NSRESULT_FOR_RETURN(unlink(mPath.get()));
+
+ isDir = S_ISDIR(mCachedStat.st_mode);
+ InvalidateCache();
+ if (isDir) {
+ if (recursive) {
+ nsDirEnumeratorUnix *dir = new nsDirEnumeratorUnix();
+ if (!dir)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsCOMPtr<nsISimpleEnumerator> dirRef(dir); // release on exit
+
+ rv = dir->Init(this, PR_FALSE);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRBool more;
+ while (dir->HasMoreElements(&more), more) {
+ nsCOMPtr<nsISupports> item;
+ rv = dir->GetNext(getter_AddRefs(item));
+ if (NS_FAILED(rv))
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIFile> file = do_QueryInterface(item, &rv);
+ if (NS_FAILED(rv))
+ return NS_ERROR_FAILURE;
+ if (NS_FAILED(rv = file->Remove(recursive)))
+ return rv;
+ }
+ }
+
+ if (rmdir(mPath.get()) == -1)
+ return NSRESULT_FOR_ERRNO();
+ } else {
+ if (unlink(mPath.get()) == -1)
+ return NSRESULT_FOR_ERRNO();
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetLastModifiedTime(PRInt64 *aLastModTime)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG(aLastModTime);
+
+ PRFileInfo64 info;
+ if (PR_GetFileInfo64(mPath.get(), &info) != PR_SUCCESS)
+ return NSRESULT_FOR_ERRNO();
+
+ // PRTime is a 64 bit value
+ // microseconds -> milliseconds
+ PRInt64 usecPerMsec;
+ LL_I2L(usecPerMsec, PR_USEC_PER_MSEC);
+ LL_DIV(*aLastModTime, info.modifyTime, usecPerMsec);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetLastModifiedTime(PRInt64 aLastModTime)
+{
+ CHECK_mPath();
+
+ int result;
+ if (! LL_IS_ZERO(aLastModTime)) {
+ VALIDATE_STAT_CACHE();
+ struct utimbuf ut;
+ ut.actime = mCachedStat.st_atime;
+
+ // convert milliseconds to seconds since the unix epoch
+ double dTime;
+ LL_L2D(dTime, aLastModTime);
+ ut.modtime = (time_t) (dTime / PR_MSEC_PER_SEC);
+ result = utime(mPath.get(), &ut);
+ } else {
+ result = utime(mPath.get(), nsnull);
+ }
+ InvalidateCache();
+ return NSRESULT_FOR_RETURN(result);
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetLastModifiedTimeOfLink(PRInt64 *aLastModTimeOfLink)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG(aLastModTimeOfLink);
+
+ struct stat sbuf;
+ if (lstat(mPath.get(), &sbuf) == -1)
+ return NSRESULT_FOR_ERRNO();
+ LL_I2L(*aLastModTimeOfLink, (PRInt32)sbuf.st_mtime);
+
+ // lstat returns st_mtime in seconds
+ PRInt64 msecPerSec;
+ LL_I2L(msecPerSec, PR_MSEC_PER_SEC);
+ LL_MUL(*aLastModTimeOfLink, *aLastModTimeOfLink, msecPerSec);
+
+ return NS_OK;
+}
+
+/*
+ * utime(2) may or may not dereference symlinks, joy.
+ */
+NS_IMETHODIMP
+nsLocalFile::SetLastModifiedTimeOfLink(PRInt64 aLastModTimeOfLink)
+{
+ return SetLastModifiedTime(aLastModTimeOfLink);
+}
+
+/*
+ * Only send back permissions bits: maybe we want to send back the whole
+ * mode_t to permit checks against other file types?
+ */
+
+#define NORMALIZE_PERMS(mode) ((mode)& (S_IRWXU | S_IRWXG | S_IRWXO))
+
+NS_IMETHODIMP
+nsLocalFile::GetPermissions(PRUint32 *aPermissions)
+{
+ NS_ENSURE_ARG(aPermissions);
+ VALIDATE_STAT_CACHE();
+ *aPermissions = NORMALIZE_PERMS(mCachedStat.st_mode);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPermissionsOfLink(PRUint32 *aPermissionsOfLink)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG(aPermissionsOfLink);
+
+ struct stat sbuf;
+ if (lstat(mPath.get(), &sbuf) == -1)
+ return NSRESULT_FOR_ERRNO();
+ *aPermissionsOfLink = NORMALIZE_PERMS(sbuf.st_mode);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetPermissions(PRUint32 aPermissions)
+{
+ CHECK_mPath();
+
+ InvalidateCache();
+
+ /*
+ * Race condition here: we should use fchmod instead, there's no way to
+ * guarantee the name still refers to the same file.
+ */
+ if (chmod(mPath.get(), aPermissions) < 0)
+ return NSRESULT_FOR_ERRNO();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetPermissionsOfLink(PRUint32 aPermissions)
+{
+ return SetPermissions(aPermissions);
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetFileSize(PRInt64 *aFileSize)
+{
+ NS_ENSURE_ARG_POINTER(aFileSize);
+ *aFileSize = LL_ZERO;
+ VALIDATE_STAT_CACHE();
+
+#if defined(VMS)
+ /* Only two record formats can report correct file content size */
+ if ((mCachedStat.st_fab_rfm != FAB$C_STMLF) &&
+ (mCachedStat.st_fab_rfm != FAB$C_STMCR)) {
+ return NS_ERROR_FAILURE;
+ }
+#endif
+
+ /* XXX autoconf for and use stat64 if available */
+ if (!S_ISDIR(mCachedStat.st_mode)) {
+ LL_UI2L(*aFileSize, (PRUint32)mCachedStat.st_size);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetFileSize(PRInt64 aFileSize)
+{
+ CHECK_mPath();
+
+ PRInt32 size;
+ LL_L2I(size, aFileSize);
+ /* XXX truncate64? */
+ InvalidateCache();
+ if (truncate(mPath.get(), (off_t)size) == -1)
+ return NSRESULT_FOR_ERRNO();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetFileSizeOfLink(PRInt64 *aFileSize)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG(aFileSize);
+
+ struct stat sbuf;
+ if (lstat(mPath.get(), &sbuf) == -1)
+ return NSRESULT_FOR_ERRNO();
+ /* XXX autoconf for and use lstat64 if available */
+ LL_UI2L(*aFileSize, (PRUint32)sbuf.st_size);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable)
+{
+ NS_ENSURE_ARG_POINTER(aDiskSpaceAvailable);
+
+ // These systems have the operations necessary to check disk space.
+
+#if defined(HAVE_SYS_STATFS_H) || defined(HAVE_SYS_STATVFS_H)
+
+ // check to make sure that mPath is properly initialized
+ CHECK_mPath();
+
+ struct STATFS fs_buf;
+
+ /*
+ * Members of the STATFS struct that you should know about:
+ * f_bsize = block size on disk.
+ * f_bavail = number of free blocks available to a non-superuser.
+ * f_bfree = number of total free blocks in file system.
+ */
+
+ if (STATFS(mPath.get(), &fs_buf) < 0) {
+ // The call to STATFS failed.
+#ifdef DEBUG
+ printf("ERROR: GetDiskSpaceAvailable: STATFS call FAILED. \n");
+#endif
+ return NS_ERROR_FAILURE;
+ }
+#ifdef DEBUG_DISK_SPACE
+ printf("DiskSpaceAvailable: %d bytes\n",
+ fs_buf.f_bsize * (fs_buf.f_bavail - 1));
+#endif
+
+ /*
+ * The number of bytes free == The number of free blocks available to
+ * a non-superuser, minus one as a fudge factor, multiplied by the size
+ * of the aforementioned blocks.
+ */
+ PRInt64 bsize, bavail;
+
+ LL_I2L(bsize, fs_buf.f_bsize);
+ LL_I2L(bavail, fs_buf.f_bavail - 1);
+ LL_MUL(*aDiskSpaceAvailable, bsize, bavail);
+ return NS_OK;
+
+#else
+ /*
+ * This platform doesn't have statfs or statvfs. I'm sure that there's
+ * a way to check for free disk space on platforms that don't have statfs
+ * (I'm SURE they have df, for example).
+ *
+ * Until we figure out how to do that, lets be honest and say that this
+ * command isn't implemented properly for these platforms yet.
+ */
+#ifdef DEBUG
+ printf("ERROR: GetDiskSpaceAvailable: Not implemented for plaforms without statfs.\n");
+#endif
+ return NS_ERROR_NOT_IMPLEMENTED;
+
+#endif /* HAVE_SYS_STATFS_H or HAVE_SYS_STATVFS_H */
+
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetParent(nsIFile **aParent)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG_POINTER(aParent);
+ *aParent = nsnull;
+
+ // if '/' we are at the top of the volume, return null
+ if (mPath.Equals("/"))
+ return NS_OK;
+
+ // <brendan, after jband> I promise to play nice
+ char *buffer = mPath.BeginWriting(),
+ *slashp = buffer;
+
+ // find the last significant slash in buffer
+ slashp = strrchr(buffer, '/');
+ NS_ASSERTION(slashp, "non-canonical mPath?");
+ if (!slashp)
+ return NS_ERROR_FILE_INVALID_PATH;
+
+ // for the case where we are at '/'
+ if (slashp == buffer)
+ slashp++;
+
+ // temporarily terminate buffer at the last significant slash
+ char c = *slashp;
+ *slashp = '\0';
+
+ nsCOMPtr<nsILocalFile> localFile;
+ nsresult rv = NS_NewNativeLocalFile(nsDependentCString(buffer), PR_TRUE,
+ getter_AddRefs(localFile));
+
+ // make buffer whole again
+ *slashp = c;
+
+ if (NS_SUCCEEDED(rv) && localFile)
+ rv = CallQueryInterface(localFile, aParent);
+ return rv;
+}
+
+/*
+ * The results of Exists, isWritable and isReadable are not cached.
+ */
+
+NS_IMETHODIMP
+nsLocalFile::Exists(PRBool *_retval)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ *_retval = (access(mPath.get(), F_OK) == 0);
+ return NS_OK;
+}
+
+#ifdef XP_BEOS
+// access() is buggy in BeOS POSIX implementation, at least for BFS, using stat() instead
+NS_IMETHODIMP
+nsLocalFile::IsWritable(PRBool *_retval)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG_POINTER(_retval);
+ struct stat buf;
+ *_retval = (stat(mPath.get(), &buf) == 0);
+ *_retval = *_retval && (buf.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH ));
+ if (*_retval || errno == EACCES)
+ return NS_OK;
+ return NSRESULT_FOR_ERRNO();
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsReadable(PRBool *_retval)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG_POINTER(_retval);
+ struct stat buf;
+ *_retval = (stat(mPath.get(), &buf) == 0);
+ *_retval = *_retval && (buf.st_mode & (S_IRUSR | S_IRGRP | S_IROTH ));
+ if (*_retval || errno == EACCES)
+ return NS_OK;
+ return NSRESULT_FOR_ERRNO();
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsExecutable(PRBool *_retval)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG_POINTER(_retval);
+ struct stat buf;
+ *_retval = (stat(mPath.get(), &buf) == 0);
+ *_retval = *_retval && (buf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH ));
+ if (*_retval || errno == EACCES)
+ return NS_OK;
+ return NSRESULT_FOR_ERRNO();
+}
+#else
+NS_IMETHODIMP
+nsLocalFile::IsWritable(PRBool *_retval)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ *_retval = (access(mPath.get(), W_OK) == 0);
+ if (*_retval || errno == EACCES)
+ return NS_OK;
+ return NSRESULT_FOR_ERRNO();
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsReadable(PRBool *_retval)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ *_retval = (access(mPath.get(), R_OK) == 0);
+ if (*_retval || errno == EACCES)
+ return NS_OK;
+ return NSRESULT_FOR_ERRNO();
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsExecutable(PRBool *_retval)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ *_retval = (access(mPath.get(), X_OK) == 0);
+ if (*_retval || errno == EACCES)
+ return NS_OK;
+ return NSRESULT_FOR_ERRNO();
+}
+#endif
+NS_IMETHODIMP
+nsLocalFile::IsDirectory(PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = PR_FALSE;
+ VALIDATE_STAT_CACHE();
+ *_retval = S_ISDIR(mCachedStat.st_mode);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsFile(PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = PR_FALSE;
+ VALIDATE_STAT_CACHE();
+ *_retval = S_ISREG(mCachedStat.st_mode);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsHidden(PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ nsACString::const_iterator begin, end;
+ LocateNativeLeafName(begin, end);
+ *_retval = (*begin == '.');
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsSymlink(PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ CHECK_mPath();
+
+ struct stat symStat;
+ lstat(mPath.get(), &symStat);
+ *_retval=S_ISLNK(symStat.st_mode);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsSpecial(PRBool *_retval)
+{
+ NS_ENSURE_ARG_POINTER(_retval);
+ VALIDATE_STAT_CACHE();
+ *_retval = S_ISCHR(mCachedStat.st_mode) ||
+ S_ISBLK(mCachedStat.st_mode) ||
+#ifdef S_ISSOCK
+ S_ISSOCK(mCachedStat.st_mode) ||
+#endif
+ S_ISFIFO(mCachedStat.st_mode);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Equals(nsIFile *inFile, PRBool *_retval)
+{
+ NS_ENSURE_ARG(inFile);
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv;
+ nsCAutoString inPath;
+
+ if (NS_FAILED(rv = inFile->GetNativePath(inPath)))
+ return rv;
+
+ *_retval = !FILE_STRCMP(inPath.get(), mPath.get());
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Contains(nsIFile *inFile, PRBool recur, PRBool *_retval)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG(inFile);
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ nsCAutoString inPath;
+ nsresult rv;
+
+ if (NS_FAILED(rv = inFile->GetNativePath(inPath)))
+ return rv;
+
+ *_retval = PR_FALSE;
+
+ ssize_t len = mPath.Length();
+ if (FILE_STRNCMP(mPath.get(), inPath.get(), len) == 0) {
+ // Now make sure that the |inFile|'s path has a separator at len,
+ // which implies that it has more components after len.
+ if (inPath[len] == '/')
+ *_retval = PR_TRUE;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetNativeTarget(nsACString &_retval)
+{
+ CHECK_mPath();
+ _retval.Truncate();
+
+ struct stat symStat;
+ lstat(mPath.get(), &symStat);
+ if (!S_ISLNK(symStat.st_mode))
+ return NS_ERROR_FILE_INVALID_PATH;
+
+ PRInt64 targetSize64;
+ if (NS_FAILED(GetFileSizeOfLink(&targetSize64)))
+ return NS_ERROR_FAILURE;
+
+ PRInt32 size;
+ LL_L2I(size, targetSize64);
+ char *target = (char *)nsMemory::Alloc(size + 1);
+ if (!target)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (readlink(mPath.get(), target, (size_t)size) < 0) {
+ nsMemory::Free(target);
+ return NSRESULT_FOR_ERRNO();
+ }
+ target[size] = '\0';
+
+ nsresult rv;
+ PRBool isSymlink;
+ nsCOMPtr<nsIFile> self(this);
+ nsCOMPtr<nsIFile> parent;
+ while (NS_SUCCEEDED(rv = self->GetParent(getter_AddRefs(parent)))) {
+ NS_ASSERTION(parent != nsnull, "no parent?!");
+
+ if (target[0] != '/') {
+ nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(parent, &rv));
+ if (NS_FAILED(rv))
+ break;
+ if (NS_FAILED(rv = localFile->AppendRelativeNativePath(nsDependentCString(target))))
+ break;
+ if (NS_FAILED(rv = localFile->GetNativePath(_retval)))
+ break;
+ if (NS_FAILED(rv = parent->IsSymlink(&isSymlink)))
+ break;
+ self = parent;
+ } else {
+ nsCOMPtr<nsILocalFile> localFile;
+ rv = NS_NewNativeLocalFile(nsDependentCString(target), PR_TRUE,
+ getter_AddRefs(localFile));
+ if (NS_FAILED(rv))
+ break;
+ if (NS_FAILED(rv = localFile->IsSymlink(&isSymlink)))
+ break;
+ _retval = target; // XXX can we avoid this buffer copy?
+ self = do_QueryInterface(localFile);
+ }
+ if (NS_FAILED(rv) || !isSymlink)
+ break;
+
+ const nsPromiseFlatCString &flatRetval = PromiseFlatCString(_retval);
+
+ // strip off any and all trailing '/'
+ PRInt32 len = strlen(target);
+ while (target[len-1] == '/' && len > 1)
+ target[--len] = '\0';
+ if (lstat(flatRetval.get(), &symStat) < 0) {
+ rv = NSRESULT_FOR_ERRNO();
+ break;
+ }
+ if (!S_ISLNK(symStat.st_mode)) {
+ rv = NS_ERROR_FILE_INVALID_PATH;
+ break;
+ }
+ size = symStat.st_size;
+ if (readlink(flatRetval.get(), target, size) < 0) {
+ rv = NSRESULT_FOR_ERRNO();
+ break;
+ }
+ target[size] = '\0';
+
+ _retval.Truncate();
+ }
+
+ nsMemory::Free(target);
+
+ if (NS_FAILED(rv))
+ _retval.Truncate();
+ return rv;
+}
+
+/* attribute PRBool followLinks; */
+NS_IMETHODIMP
+nsLocalFile::GetFollowLinks(PRBool *aFollowLinks)
+{
+ *aFollowLinks = PR_TRUE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetFollowLinks(PRBool aFollowLinks)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetDirectoryEntries(nsISimpleEnumerator **entries)
+{
+ nsDirEnumeratorUnix *dir = new nsDirEnumeratorUnix();
+ if (!dir)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(dir);
+ nsresult rv = dir->Init(this, PR_FALSE);
+ if (NS_FAILED(rv)) {
+ *entries = nsnull;
+ NS_RELEASE(dir);
+ } else {
+ *entries = dir; // transfer reference
+ }
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Load(PRLibrary **_retval)
+{
+ CHECK_mPath();
+ NS_ENSURE_ARG_POINTER(_retval);
+
+ NS_TIMELINE_START_TIMER("PR_LoadLibrary");
+
+ *_retval = PR_LoadLibrary(mPath.get());
+
+ NS_TIMELINE_STOP_TIMER("PR_LoadLibrary");
+ NS_TIMELINE_MARK_TIMER1("PR_LoadLibrary", mPath.get());
+
+ if (!*_retval)
+ return NS_ERROR_FAILURE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPersistentDescriptor(nsACString &aPersistentDescriptor)
+{
+ return GetNativePath(aPersistentDescriptor);
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetPersistentDescriptor(const nsACString &aPersistentDescriptor)
+{
+ return InitWithNativePath(aPersistentDescriptor);
+}
+
+#ifdef XP_BEOS
+NS_IMETHODIMP
+nsLocalFile::Reveal()
+{
+ BPath bPath(mPath.get());
+ bPath.GetParent(&bPath);
+ entry_ref ref;
+ get_ref_for_path(bPath.Path(),&ref);
+ BMessage message(B_REFS_RECEIVED);
+ message.AddRef("refs",&ref);
+ BMessenger messenger("application/x-vnd.Be-TRAK");
+ messenger.SendMessage(&message);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Launch()
+{
+ entry_ref ref;
+ get_ref_for_path (mPath.get(), &ref);
+ be_roster->Launch (&ref);
+
+ return NS_OK;
+}
+#else
+NS_IMETHODIMP
+nsLocalFile::Reveal()
+{
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Launch()
+{
+ return NS_ERROR_FAILURE;
+}
+#endif
+
+nsresult
+NS_NewNativeLocalFile(const nsACString &path, PRBool followSymlinks, nsILocalFile **result)
+{
+ nsLocalFile *file = new nsLocalFile();
+ if (!file)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(file);
+
+ if (!path.IsEmpty()) {
+ nsresult rv = file->InitWithNativePath(path);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(file);
+ return rv;
+ }
+ }
+ *result = file;
+ return NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+// unicode support
+//-----------------------------------------------------------------------------
+
+#define SET_UCS(func, ucsArg) \
+ { \
+ nsCAutoString buf; \
+ nsresult rv = NS_CopyUnicodeToNative(ucsArg, buf); \
+ if (NS_FAILED(rv)) \
+ return rv; \
+ return (func)(buf); \
+ }
+
+#define GET_UCS(func, ucsArg) \
+ { \
+ nsCAutoString buf; \
+ nsresult rv = (func)(buf); \
+ if (NS_FAILED(rv)) return rv; \
+ return NS_CopyNativeToUnicode(buf, ucsArg); \
+ }
+
+#define SET_UCS_2ARGS_2(func, opaqueArg, ucsArg) \
+ { \
+ nsCAutoString buf; \
+ nsresult rv = NS_CopyUnicodeToNative(ucsArg, buf); \
+ if (NS_FAILED(rv)) \
+ return rv; \
+ return (func)(opaqueArg, buf); \
+ }
+
+// Unicode interface Wrapper
+nsresult
+nsLocalFile::InitWithPath(const nsAString &filePath)
+{
+ SET_UCS(InitWithNativePath, filePath);
+}
+nsresult
+nsLocalFile::Append(const nsAString &node)
+{
+ SET_UCS(AppendNative, node);
+}
+nsresult
+nsLocalFile::AppendRelativePath(const nsAString &node)
+{
+ SET_UCS(AppendRelativeNativePath, node);
+}
+nsresult
+nsLocalFile::GetLeafName(nsAString &aLeafName)
+{
+ GET_UCS(GetNativeLeafName, aLeafName);
+}
+nsresult
+nsLocalFile::SetLeafName(const nsAString &aLeafName)
+{
+ SET_UCS(SetNativeLeafName, aLeafName);
+}
+nsresult
+nsLocalFile::GetPath(nsAString &_retval)
+{
+ return NS_CopyNativeToUnicode(mPath, _retval);
+}
+nsresult
+nsLocalFile::CopyTo(nsIFile *newParentDir, const nsAString &newName)
+{
+ SET_UCS_2ARGS_2(CopyToNative , newParentDir, newName);
+}
+nsresult
+nsLocalFile::CopyToFollowingLinks(nsIFile *newParentDir, const nsAString &newName)
+{
+ SET_UCS_2ARGS_2(CopyToFollowingLinksNative , newParentDir, newName);
+}
+nsresult
+nsLocalFile::MoveTo(nsIFile *newParentDir, const nsAString &newName)
+{
+ SET_UCS_2ARGS_2(MoveToNative, newParentDir, newName);
+}
+nsresult
+nsLocalFile::GetTarget(nsAString &_retval)
+{
+ GET_UCS(GetNativeTarget, _retval);
+}
+nsresult
+NS_NewLocalFile(const nsAString &path, PRBool followLinks, nsILocalFile* *result)
+{
+ nsCAutoString buf;
+ nsresult rv = NS_CopyUnicodeToNative(path, buf);
+ if (NS_FAILED(rv))
+ return rv;
+ return NS_NewNativeLocalFile(buf, followLinks, result);
+}
+
+//-----------------------------------------------------------------------------
+// global init/shutdown
+//-----------------------------------------------------------------------------
+
+void
+nsLocalFile::GlobalInit()
+{
+}
+
+void
+nsLocalFile::GlobalShutdown()
+{
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFileUnix.h b/src/libs/xpcom18a4/xpcom/io/nsLocalFileUnix.h
new file mode 100644
index 00000000..a994e1a1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFileUnix.h
@@ -0,0 +1,132 @@
+/* -*- 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 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):
+ * Mike Shaver <shaver@mozilla.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 ***** */
+
+/*
+ * Implementation of nsIFile for ``Unixy'' systems.
+ */
+
+#ifndef _nsLocalFileUNIX_H_
+#define _nsLocalFileUNIX_H_
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "nscore.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+
+/**
+ * we need these for statfs()
+ */
+#ifdef HAVE_SYS_STATVFS_H
+ #if defined(__osf__) && defined(__DECCXX)
+ extern "C" int statvfs(const char *, struct statvfs *);
+ #endif
+ #include <sys/statvfs.h>
+#endif
+
+#ifdef HAVE_SYS_STATFS_H
+ #include <sys/statfs.h>
+#endif
+
+#ifdef HAVE_STATVFS
+ #define STATFS statvfs
+#else
+ #define STATFS statfs
+#endif
+
+// so we can statfs on freebsd
+#if defined(__FreeBSD__)
+ #define HAVE_SYS_STATFS_H
+ #define STATFS statfs
+ #include <sys/param.h>
+ #include <sys/mount.h>
+#endif
+
+class NS_COM nsLocalFile : public nsILocalFile
+{
+public:
+ NS_DEFINE_STATIC_CID_ACCESSOR(NS_LOCAL_FILE_CID)
+
+ nsLocalFile();
+
+ static NS_METHOD nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+ // nsISupports
+ NS_DECL_ISUPPORTS
+
+ // nsIFile
+ NS_DECL_NSIFILE
+
+ // nsILocalFile
+ NS_DECL_NSILOCALFILE
+
+public:
+ static void GlobalInit();
+ static void GlobalShutdown();
+
+private:
+ nsLocalFile(const nsLocalFile& other);
+ ~nsLocalFile() {}
+
+protected:
+ struct stat mCachedStat;
+ nsCString mPath;
+ PRPackedBool mHaveCachedStat;
+
+ void LocateNativeLeafName(nsACString::const_iterator &,
+ nsACString::const_iterator &);
+
+ nsresult CopyDirectoryTo(nsIFile *newParent);
+ nsresult CreateAllAncestors(PRUint32 permissions);
+ nsresult GetNativeTargetPathName(nsIFile *newParent,
+ const nsACString &newName,
+ nsACString &_retval);
+
+ void InvalidateCache() {
+ mHaveCachedStat = PR_FALSE;
+ }
+ nsresult FillStatCache();
+
+ nsresult CreateAndKeepOpen(PRUint32 type, PRIntn flags,
+ PRUint32 permissions, PRFileDesc **_retval);
+};
+
+#endif /* _nsLocalFileUNIX_H_ */
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFileWin.cpp b/src/libs/xpcom18a4/xpcom/io/nsLocalFileWin.cpp
new file mode 100644
index 00000000..63414fc3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFileWin.cpp
@@ -0,0 +1,2440 @@
+/* -*- 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-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Doug Turner <dougt@netscape.com>
+ * Dean Tessman <dean_tessman@hotmail.com>
+ * Brodie Thiesfield <brofield@jellycan.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 "nsCOMPtr.h"
+#include "nsMemory.h"
+
+#include "nsLocalFile.h"
+#include "nsNativeCharsetUtils.h"
+
+#include "nsISimpleEnumerator.h"
+#include "nsIComponentManager.h"
+#include "prtypes.h"
+#include "prio.h"
+
+#include "nsXPIDLString.h"
+#include "nsReadableUtils.h"
+
+#include <direct.h>
+#include <windows.h>
+
+#include "shellapi.h"
+#include "shlguid.h"
+
+#include <io.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <mbstring.h>
+
+#include "nsXPIDLString.h"
+#include "prproces.h"
+#include "nsITimelineService.h"
+
+#include "nsAutoLock.h"
+#include "SpecialSystemDirectory.h"
+
+// _mbsstr isn't declared in w32api headers but it's there in the libs
+#ifdef __MINGW32__
+extern "C" {
+unsigned char *_mbsstr( const unsigned char *str,
+ const unsigned char *substr );
+}
+#endif
+
+class nsDriveEnumerator : public nsISimpleEnumerator
+{
+public:
+ nsDriveEnumerator();
+ virtual ~nsDriveEnumerator();
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISIMPLEENUMERATOR
+ nsresult Init();
+private:
+ /* mDrives and mLetter share data
+ * Init sets them.
+ * HasMoreElements reads mLetter.
+ * GetNext advances mLetter.
+ */
+ nsCString mDrives;
+ const char *mLetter;
+};
+
+//----------------------------------------------------------------------------
+// short cut resolver
+//----------------------------------------------------------------------------
+
+class ShortcutResolver
+{
+public:
+ ShortcutResolver();
+ // nonvirtual since we're not subclassed
+ ~ShortcutResolver();
+
+ nsresult Init();
+ nsresult Resolve(const WCHAR* in, char* out);
+
+private:
+ PRLock* mLock;
+ IPersistFile* mPersistFile;
+ IShellLink* mShellLink;
+};
+
+ShortcutResolver::ShortcutResolver()
+{
+ mLock = nsnull;
+ mPersistFile = nsnull;
+ mShellLink = nsnull;
+}
+
+ShortcutResolver::~ShortcutResolver()
+{
+ if (mLock)
+ PR_DestroyLock(mLock);
+
+ // Release the pointer to the IPersistFile interface.
+ if (mPersistFile)
+ mPersistFile->Release();
+
+ // Release the pointer to the IShellLink interface.
+ if(mShellLink)
+ mShellLink->Release();
+
+ CoUninitialize();
+}
+
+nsresult
+ShortcutResolver::Init()
+{
+ CoInitialize(NULL); // FIX: we should probably move somewhere higher up during startup
+
+ mLock = PR_NewLock();
+ if (!mLock)
+ return NS_ERROR_FAILURE;
+
+ HRESULT hres = CoCreateInstance(CLSID_ShellLink,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_IShellLink,
+ (void**)&mShellLink);
+ if (SUCCEEDED(hres))
+ {
+ // Get a pointer to the IPersistFile interface.
+ hres = mShellLink->QueryInterface(IID_IPersistFile, (void**)&mPersistFile);
+ }
+
+ if (mPersistFile == nsnull || mShellLink == nsnull)
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+// |out| must be an allocated buffer of size MAX_PATH
+nsresult
+ShortcutResolver::Resolve(const WCHAR* in, char* out)
+{
+ nsAutoLock lock(mLock);
+
+ // see if we can Load the path.
+ HRESULT hres = mPersistFile->Load(in, STGM_READ);
+
+ if (FAILED(hres))
+ return NS_ERROR_FAILURE;
+
+ // Resolve the link.
+ hres = mShellLink->Resolve(nsnull, SLR_NO_UI );
+
+ if (FAILED(hres))
+ return NS_ERROR_FAILURE;
+
+ WIN32_FIND_DATA wfd;
+ // Get the path to the link target.
+ hres = mShellLink->GetPath( out, MAX_PATH, &wfd, SLGP_UNCPRIORITY );
+ if (FAILED(hres))
+ return NS_ERROR_FAILURE;
+ return NS_OK;
+}
+
+static ShortcutResolver * gResolver = nsnull;
+
+static nsresult NS_CreateShortcutResolver()
+{
+ gResolver = new ShortcutResolver();
+ if (!gResolver)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return gResolver->Init();
+}
+
+static void NS_DestroyShortcutResolver()
+{
+ delete gResolver;
+ gResolver = nsnull;
+}
+
+
+//-----------------------------------------------------------------------------
+// static helper functions
+//-----------------------------------------------------------------------------
+
+// certainly not all the error that can be
+// encountered, but many of them common ones
+static nsresult ConvertWinError(DWORD winErr)
+{
+ nsresult rv;
+
+ switch (winErr)
+ {
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_PATH_NOT_FOUND:
+ case ERROR_INVALID_DRIVE:
+ rv = NS_ERROR_FILE_NOT_FOUND;
+ break;
+ case ERROR_ACCESS_DENIED:
+ case ERROR_NOT_SAME_DEVICE:
+ rv = NS_ERROR_FILE_ACCESS_DENIED;
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ case ERROR_INVALID_BLOCK:
+ case ERROR_INVALID_HANDLE:
+ case ERROR_ARENA_TRASHED:
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+ case ERROR_CURRENT_DIRECTORY:
+ rv = NS_ERROR_FILE_DIR_NOT_EMPTY;
+ break;
+ case ERROR_WRITE_PROTECT:
+ rv = NS_ERROR_FILE_READ_ONLY;
+ break;
+ case ERROR_HANDLE_DISK_FULL:
+ rv = NS_ERROR_FILE_TOO_BIG;
+ break;
+ case ERROR_FILE_EXISTS:
+ case ERROR_ALREADY_EXISTS:
+ case ERROR_CANNOT_MAKE:
+ rv = NS_ERROR_FILE_ALREADY_EXISTS;
+ break;
+ case 0:
+ rv = NS_OK;
+ break;
+ default:
+ rv = NS_ERROR_FAILURE;
+ break;
+ }
+ return rv;
+}
+
+// definition of INVALID_SET_FILE_POINTER from VC.NET header files
+// it doesn't appear to be defined by VC6
+#ifndef INVALID_SET_FILE_POINTER
+# define INVALID_SET_FILE_POINTER ((DWORD)-1)
+#endif
+// same goes for INVALID_FILE_ATTRIBUTES
+#ifndef INVALID_FILE_ATTRIBUTES
+# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
+#endif
+
+// as suggested in the MSDN documentation on SetFilePointer
+static __int64
+MyFileSeek64(HANDLE aHandle, __int64 aDistance, DWORD aMoveMethod)
+{
+ LARGE_INTEGER li;
+
+ li.QuadPart = aDistance;
+ li.LowPart = SetFilePointer(aHandle, li.LowPart, &li.HighPart, aMoveMethod);
+ if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
+ {
+ li.QuadPart = -1;
+ }
+
+ return li.QuadPart;
+}
+
+static PRBool
+IsShortcutPath(const char *path)
+{
+ // Under Windows, the shortcuts are just files with a ".lnk" extension.
+ // Note also that we don't resolve links in the middle of paths.
+ // i.e. "c:\foo.lnk\bar.txt" is invalid.
+ NS_ABORT_IF_FALSE(path, "don't pass nulls");
+ const char * ext = (const char *) _mbsrchr((const unsigned char *)path, '.');
+ if (!ext || 0 != stricmp(ext + 1, "lnk"))
+ return PR_FALSE;
+ return PR_TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// nsDirEnumerator
+//-----------------------------------------------------------------------------
+
+class nsDirEnumerator : public nsISimpleEnumerator
+{
+ public:
+
+ NS_DECL_ISUPPORTS
+
+ nsDirEnumerator() : mDir(nsnull)
+ {
+ }
+
+ nsresult Init(nsILocalFile* parent)
+ {
+ nsCAutoString filepath;
+ parent->GetNativeTarget(filepath);
+
+ if (filepath.IsEmpty())
+ {
+ parent->GetNativePath(filepath);
+ }
+
+ if (filepath.IsEmpty())
+ {
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ mDir = PR_OpenDir(filepath.get());
+ if (mDir == nsnull) // not a directory?
+ return NS_ERROR_FAILURE;
+
+ mParent = parent;
+ return NS_OK;
+ }
+
+ NS_IMETHOD HasMoreElements(PRBool *result)
+ {
+ nsresult rv;
+ if (mNext == nsnull && mDir)
+ {
+ PRDirEntry* entry = PR_ReadDir(mDir, PR_SKIP_BOTH);
+ if (entry == nsnull)
+ {
+ // end of dir entries
+
+ PRStatus status = PR_CloseDir(mDir);
+ if (status != PR_SUCCESS)
+ return NS_ERROR_FAILURE;
+ mDir = nsnull;
+
+ *result = PR_FALSE;
+ return NS_OK;
+ }
+
+ nsCOMPtr<nsIFile> file;
+ rv = mParent->Clone(getter_AddRefs(file));
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = file->AppendNative(nsDependentCString(entry->name));
+ if (NS_FAILED(rv))
+ return rv;
+
+ // make sure the thing exists. If it does, try the next one.
+ PRBool exists;
+ rv = file->Exists(&exists);
+ if (NS_FAILED(rv) || !exists)
+ {
+ return HasMoreElements(result);
+ }
+
+ mNext = do_QueryInterface(file);
+ }
+ *result = mNext != nsnull;
+ return NS_OK;
+ }
+
+ NS_IMETHOD GetNext(nsISupports **result)
+ {
+ nsresult rv;
+ PRBool hasMore;
+ rv = HasMoreElements(&hasMore);
+ if (NS_FAILED(rv)) return rv;
+
+ *result = mNext; // might return nsnull
+ NS_IF_ADDREF(*result);
+
+ mNext = nsnull;
+ return NS_OK;
+ }
+
+ // dtor can be non-virtual since there are no subclasses, but must be
+ // public to use the class on the stack.
+ ~nsDirEnumerator()
+ {
+ if (mDir)
+ {
+ PRStatus status = PR_CloseDir(mDir);
+ NS_ASSERTION(status == PR_SUCCESS, "close failed");
+ }
+ }
+
+ protected:
+ PRDir* mDir;
+ nsCOMPtr<nsILocalFile> mParent;
+ nsCOMPtr<nsILocalFile> mNext;
+};
+
+NS_IMPL_ISUPPORTS1(nsDirEnumerator, nsISimpleEnumerator)
+
+
+//-----------------------------------------------------------------------------
+// nsLocalFile <public>
+//-----------------------------------------------------------------------------
+
+nsLocalFile::nsLocalFile()
+ : mFollowSymlinks(PR_FALSE)
+{
+ MakeDirty();
+ memset(&mFileInfo64, 0, sizeof(mFileInfo64));
+}
+
+NS_METHOD
+nsLocalFile::nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
+{
+ NS_ENSURE_ARG_POINTER(aInstancePtr);
+ NS_ENSURE_NO_AGGREGATION(outer);
+
+ nsLocalFile* inst = new nsLocalFile();
+ if (inst == NULL)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = inst->QueryInterface(aIID, aInstancePtr);
+ if (NS_FAILED(rv))
+ {
+ delete inst;
+ return rv;
+ }
+ return NS_OK;
+}
+
+
+//-----------------------------------------------------------------------------
+// nsLocalFile::nsISupports
+//-----------------------------------------------------------------------------
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsLocalFile, nsILocalFile, nsIFile)
+
+
+//-----------------------------------------------------------------------------
+// nsLocalFile <private>
+//-----------------------------------------------------------------------------
+
+nsLocalFile::nsLocalFile(const nsLocalFile& other)
+ : mDirty(other.mDirty)
+ , mFollowSymlinks(other.mFollowSymlinks)
+ , mWorkingPath(other.mWorkingPath)
+ , mResolvedPath(other.mResolvedPath)
+ , mFileInfo64(other.mFileInfo64)
+{
+}
+
+// Resolve the shortcut file from mWorkingPath and write the path
+// it points to into mResolvedPath.
+nsresult
+nsLocalFile::ResolveShortcut()
+{
+ // we can't do anything without the resolver
+ if (!gResolver)
+ return NS_ERROR_FAILURE;
+
+ // allocate the memory for the result of the resolution
+ nsAutoString ucsBuf;
+ NS_CopyNativeToUnicode(mWorkingPath, ucsBuf);
+
+ mResolvedPath.SetLength(MAX_PATH);
+ char *resolvedPath = mResolvedPath.BeginWriting();
+
+ // resolve this shortcut
+ nsresult rv = gResolver->Resolve(ucsBuf.get(), resolvedPath);
+
+ size_t len = NS_FAILED(rv) ? 0 : strlen(resolvedPath);
+ mResolvedPath.SetLength(len);
+
+ return rv;
+}
+
+// Resolve any shortcuts and stat the resolved path. After a successful return
+// the path is guaranteed valid and the members of mFileInfo64 can be used.
+nsresult
+nsLocalFile::ResolveAndStat()
+{
+ // if we aren't dirty then we are already done
+ if (!mDirty)
+ return NS_OK;
+
+ // we can't resolve/stat anything that isn't a valid NSPR addressable path
+ if (mWorkingPath.IsEmpty())
+ return NS_ERROR_FILE_INVALID_PATH;
+
+ // this is usually correct
+ mResolvedPath.Assign(mWorkingPath);
+
+ // slutty hack designed to work around bug 134796 until it is fixed
+ char temp[4];
+ const char *nsprPath = mWorkingPath.get();
+ if (mWorkingPath.Length() == 2 && mWorkingPath.CharAt(1) == ':')
+ {
+ temp[0] = mWorkingPath[0];
+ temp[1] = mWorkingPath[1];
+ temp[2] = '\\';
+ temp[3] = '\0';
+ nsprPath = temp;
+ }
+
+ // first we will see if the working path exists. If it doesn't then
+ // there is nothing more that can be done
+ PRStatus status = PR_GetFileInfo64(nsprPath, &mFileInfo64);
+ if (status != PR_SUCCESS)
+ return NS_ERROR_FILE_NOT_FOUND;
+
+ // if this isn't a shortcut file or we aren't following symlinks then we're done
+ if (!mFollowSymlinks
+ || mFileInfo64.type != PR_FILE_FILE
+ || !IsShortcutPath(mWorkingPath.get()))
+ {
+ mDirty = PR_FALSE;
+ return NS_OK;
+ }
+
+ // we need to resolve this shortcut to what it points to, this will
+ // set mResolvedPath. Even if it fails we need to have the resolved
+ // path equal to working path for those functions that always use
+ // the resolved path.
+ nsresult rv = ResolveShortcut();
+ if (NS_FAILED(rv))
+ {
+ mResolvedPath.Assign(mWorkingPath);
+ return rv;
+ }
+
+ // get the details of the resolved path
+ status = PR_GetFileInfo64(mResolvedPath.get(), &mFileInfo64);
+ if (status != PR_SUCCESS)
+ return NS_ERROR_FILE_NOT_FOUND;
+
+ mDirty = PR_FALSE;
+ return NS_OK;
+}
+
+
+//-----------------------------------------------------------------------------
+// nsLocalFile::nsIFile,nsILocalFile
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+nsLocalFile::Clone(nsIFile **file)
+{
+ // Just copy-construct ourselves
+ *file = new nsLocalFile(*this);
+ if (!*file)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(*file);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::InitWithNativePath(const nsACString &filePath)
+{
+ MakeDirty();
+
+ nsACString::const_iterator begin, end;
+ filePath.BeginReading(begin);
+ filePath.EndReading(end);
+
+ // input string must not be empty
+ if (begin == end)
+ return NS_ERROR_FAILURE;
+
+ char firstChar = *begin;
+ char secondChar = *(++begin);
+
+ // just do a sanity check. if it has any forward slashes, it is not a Native path
+ // on windows. Also, it must have a colon at after the first char.
+
+ char *path = nsnull;
+ PRInt32 pathLen = 0;
+
+ if ( ( (secondChar == ':') && !FindCharInReadable('/', begin, end) ) || // normal path
+ ( (firstChar == '\\') && (secondChar == '\\') ) ) // network path
+ {
+ // This is a native path
+ path = ToNewCString(filePath);
+ pathLen = filePath.Length();
+ }
+
+ if (path == nsnull)
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ // kill any trailing '\' provided it isn't the second char of DBCS
+ PRInt32 len = pathLen - 1;
+ if (path[len] == '\\' &&
+ (!::IsDBCSLeadByte(path[len-1]) ||
+ _mbsrchr((const unsigned char *)path, '\\') == (const unsigned char *)path+len))
+ {
+ path[len] = '\0';
+ pathLen = len;
+ }
+
+ mWorkingPath.Adopt(path, pathLen);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::OpenNSPRFileDesc(PRInt32 flags, PRInt32 mode, PRFileDesc **_retval)
+{
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
+ return rv;
+
+ *_retval = PR_Open(mResolvedPath.get(), flags, mode);
+ if (*_retval)
+ return NS_OK;
+
+ return NS_ErrorAccordingToNSPR();
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::OpenANSIFileDesc(const char *mode, FILE * *_retval)
+{
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
+ return rv;
+
+ *_retval = fopen(mResolvedPath.get(), mode);
+ if (*_retval)
+ return NS_OK;
+
+ return NS_ERROR_FAILURE;
+}
+
+
+
+NS_IMETHODIMP
+nsLocalFile::Create(PRUint32 type, PRUint32 attributes)
+{
+ if (type != NORMAL_FILE_TYPE && type != DIRECTORY_TYPE)
+ return NS_ERROR_FILE_UNKNOWN_TYPE;
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
+ return rv;
+
+ // create directories to target
+ //
+ // A given local file can be either one of these forms:
+ //
+ // - normal: X:\some\path\on\this\drive
+ // ^--- start here
+ //
+ // - UNC path: \\machine\volume\some\path\on\this\drive
+ // ^--- start here
+ //
+ // Skip the first 'X:\' for the first form, and skip the first full
+ // '\\machine\volume\' segment for the second form.
+
+ const unsigned char* path = (const unsigned char*) mResolvedPath.get();
+ if (path[0] == '\\' && path[1] == '\\')
+ {
+ // dealing with a UNC path here; skip past '\\machine\'
+ path = _mbschr(path + 2, '\\');
+ if (!path)
+ return NS_ERROR_FILE_INVALID_PATH;
+ ++path;
+ }
+
+ // search for first slash after the drive (or volume) name
+ unsigned char* slash = _mbschr(path, '\\');
+
+ if (slash)
+ {
+ // skip the first '\\'
+ ++slash;
+ slash = _mbschr(slash, '\\');
+
+ while (slash)
+ {
+ *slash = '\0';
+
+ if (!CreateDirectoryA(mResolvedPath.get(), NULL)) {
+ rv = ConvertWinError(GetLastError());
+ // perhaps the base path already exists, or perhaps we don't have
+ // permissions to create the directory. NOTE: access denied could
+ // occur on a parent directory even though it exists.
+ if (rv != NS_ERROR_FILE_ALREADY_EXISTS &&
+ rv != NS_ERROR_FILE_ACCESS_DENIED)
+ return rv;
+ }
+ *slash = '\\';
+ ++slash;
+ slash = _mbschr(slash, '\\');
+ }
+ }
+
+ if (type == NORMAL_FILE_TYPE)
+ {
+ PRFileDesc* file = PR_Open(mResolvedPath.get(), PR_RDONLY | PR_CREATE_FILE | PR_APPEND | PR_EXCL, attributes);
+ if (!file) return NS_ERROR_FILE_ALREADY_EXISTS;
+
+ PR_Close(file);
+ return NS_OK;
+ }
+
+ if (type == DIRECTORY_TYPE)
+ {
+ if (!CreateDirectoryA(mResolvedPath.get(), NULL))
+ return ConvertWinError(GetLastError());
+ else
+ return NS_OK;
+ }
+
+ return NS_ERROR_FILE_UNKNOWN_TYPE;
+}
+
+NS_IMETHODIMP
+nsLocalFile::AppendNative(const nsACString &node)
+{
+ // append this path, multiple components are not permitted
+ return AppendNativeInternal(PromiseFlatCString(node), PR_FALSE);
+}
+
+NS_IMETHODIMP
+nsLocalFile::AppendRelativeNativePath(const nsACString &node)
+{
+ // append this path, multiple components are permitted
+ return AppendNativeInternal(PromiseFlatCString(node), PR_TRUE);
+}
+
+nsresult
+nsLocalFile::AppendNativeInternal(const nsAFlatCString &node, PRBool multipleComponents)
+{
+ if (node.IsEmpty())
+ return NS_OK;
+
+ // check the relative path for validity
+ const unsigned char * nodePath = (const unsigned char *) node.get();
+ if (*nodePath == '\\' // can't start with an '\'
+ || _mbschr(nodePath, '/') // can't contain /
+ || node.Equals("..")) // can't be ..
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ if (multipleComponents)
+ {
+ // can't contain .. as a path component. Ensure that the valid components
+ // "foo..foo", "..foo", and "foo.." are not falsely detected, but the invalid
+ // paths "..\", "foo\..", "foo\..\foo", "..\foo", etc are.
+ unsigned char * doubleDot = _mbsstr(nodePath, (unsigned char *)"\\..");
+ while (doubleDot)
+ {
+ doubleDot += 3;
+ if (*doubleDot == '\0' || *doubleDot == '\\')
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+ doubleDot = _mbsstr(doubleDot, (unsigned char *)"\\..");
+ }
+ if (0 == _mbsncmp(nodePath, (unsigned char *)"..\\", 3)) // catches the remaining cases of prefixes
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+ }
+ else if (_mbschr(nodePath, '\\')) // single components can't contain '\'
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ MakeDirty();
+
+ mWorkingPath.Append(NS_LITERAL_CSTRING("\\") + node);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Normalize()
+{
+ // XXX See bug 187957 comment 18 for possible problems with this implementation.
+
+ if (mWorkingPath.IsEmpty())
+ return NS_OK;
+
+ // work in unicode for ease
+ nsAutoString path;
+ NS_CopyNativeToUnicode(mWorkingPath, path);
+
+ // find the index of the root backslash for the path. Everything before
+ // this is considered fully normalized and cannot be ascended beyond
+ // using ".." For a local drive this is the first slash (e.g. "c:\").
+ // For a UNC path it is the slash following the share name
+ // (e.g. "\\server\share\").
+ PRInt32 rootIdx = 2; // default to local drive
+ if (path.First() == '\\') // if a share then calculate the rootIdx
+ {
+ rootIdx = path.FindChar('\\', 2); // skip \\ in front of the server
+ if (rootIdx == kNotFound)
+ return NS_OK; // already normalized
+ rootIdx = path.FindChar('\\', rootIdx+1);
+ if (rootIdx == kNotFound)
+ return NS_OK; // already normalized
+ }
+ else if (path.CharAt(rootIdx) != '\\')
+ {
+ // The path has been specified relative to the current working directory
+ // for that drive. To normalize it, the current working directory for
+ // that drive needs to be inserted before the supplied relative path
+ // which will provide an absolute path (and the rootIdx will still be 2).
+ char cwd[MAX_PATH];
+ char * pcwd = cwd;
+ int drive = toupper(path.First()) - 'A' + 1;
+ if (!_getdcwd(drive, pcwd, MAX_PATH))
+ pcwd = _getdcwd(drive, 0, 0);
+ if (!pcwd)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsAutoString currentDir;
+ NS_CopyNativeToUnicode(nsDependentCString(pcwd), currentDir);
+ if (pcwd != cwd)
+ free(pcwd);
+
+ if (currentDir.Last() == '\\')
+ path.Replace(0, 2, currentDir);
+ else
+ path.Replace(0, 2, currentDir + NS_LITERAL_STRING("\\"));
+ }
+ NS_POSTCONDITION(0 < rootIdx && rootIdx < (PRInt32)path.Length(), "rootIdx is invalid");
+ NS_POSTCONDITION(path.CharAt(rootIdx) == '\\', "rootIdx is invalid");
+
+ // if there is nothing following the root path then it is already normalized
+ if (rootIdx + 1 == (PRInt32)path.Length())
+ return NS_OK;
+
+ // assign the root
+ nsAutoString normal;
+ const PRUnichar * pathBuffer = path.get(); // simplify access to the buffer
+ normal.SetCapacity(path.Length()); // it won't ever grow longer
+ normal.Assign(pathBuffer, rootIdx);
+
+ // Normalize the path components. The actions taken are:
+ //
+ // "\\" condense to single backslash
+ // "." remove from path
+ // ".." up a directory
+ // "..." remove from path (any number of dots > 2)
+ //
+ // The last form is something that Windows 95 and 98 supported and
+ // is a shortcut for changing up multiple directories. Windows XP
+ // and ilk ignore it in a path, as is done here.
+ PRInt32 len, begin, end = rootIdx;
+ while (end < (PRInt32)path.Length())
+ {
+ // find the current segment (text between the backslashes) to
+ // be examined, this will set the following variables:
+ // begin == index of first char in segment
+ // end == index 1 char after last char in segment
+ // len == length of segment
+ begin = end + 1;
+ end = path.FindChar('\\', begin);
+ if (end == kNotFound)
+ end = path.Length();
+ len = end - begin;
+
+ // ignore double backslashes
+ if (len == 0)
+ continue;
+
+ // len != 0, and interesting paths always begin with a dot
+ if (pathBuffer[begin] == '.')
+ {
+ // ignore single dots
+ if (len == 1)
+ continue;
+
+ // handle multiple dots
+ if (len >= 2 && pathBuffer[begin+1] == '.')
+ {
+ // back up a path component on double dot
+ if (len == 2)
+ {
+ PRInt32 prev = normal.RFindChar('\\');
+ if (prev >= rootIdx)
+ normal.Truncate(prev);
+ continue;
+ }
+
+ // length is > 2 and the first two characters are dots.
+ // if the rest of the string is dots, then ignore it.
+ int idx = len - 1;
+ for (; idx >= 2; --idx)
+ {
+ if (pathBuffer[begin+idx] != '.')
+ break;
+ }
+
+ // this is true if the loop above didn't break
+ // and all characters in this segment are dots.
+ if (idx < 2)
+ continue;
+ }
+ }
+
+ // add the current component to the path, including the preceding backslash
+ normal.Append(pathBuffer + begin - 1, len + 1);
+ }
+
+ NS_CopyUnicodeToNative(normal, mWorkingPath);
+ MakeDirty();
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetNativeLeafName(nsACString &aLeafName)
+{
+ aLeafName.Truncate();
+
+ const char* temp = mWorkingPath.get();
+ if(temp == nsnull)
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ const char* leaf = (const char*) _mbsrchr((const unsigned char*) temp, '\\');
+
+ // if the working path is just a node without any lashes.
+ if (leaf == nsnull)
+ leaf = temp;
+ else
+ leaf++;
+
+ aLeafName.Assign(leaf);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetNativeLeafName(const nsACString &aLeafName)
+{
+ MakeDirty();
+
+ const unsigned char* temp = (const unsigned char*) mWorkingPath.get();
+ if(temp == nsnull)
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ // cannot use nsCString::RFindChar() due to 0x5c problem
+ PRInt32 offset = (PRInt32) (_mbsrchr(temp, '\\') - temp);
+ if (offset)
+ {
+ mWorkingPath.Truncate(offset+1);
+ }
+ mWorkingPath.Append(aLeafName);
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::GetNativePath(nsACString &_retval)
+{
+ _retval = mWorkingPath;
+ return NS_OK;
+}
+
+nsresult
+nsLocalFile::CopySingleFile(nsIFile *sourceFile, nsIFile *destParent, const nsACString &newName,
+ PRBool followSymlinks, PRBool move)
+{
+ nsresult rv;
+ nsCAutoString filePath;
+
+ // get the path that we are going to copy to.
+ // Since windows does not know how to auto
+ // resolve shortcuts, we must work with the
+ // target.
+ nsCAutoString destPath;
+ destParent->GetNativeTarget(destPath);
+
+ destPath.Append("\\");
+
+ if (newName.IsEmpty())
+ {
+ nsCAutoString aFileName;
+ sourceFile->GetNativeLeafName(aFileName);
+ destPath.Append(aFileName);
+ }
+ else
+ {
+ destPath.Append(newName);
+ }
+
+
+ if (followSymlinks)
+ {
+ rv = sourceFile->GetNativeTarget(filePath);
+ if (filePath.IsEmpty())
+ rv = sourceFile->GetNativePath(filePath);
+ }
+ else
+ {
+ rv = sourceFile->GetNativePath(filePath);
+ }
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ int copyOK;
+
+ if (!move)
+ copyOK = CopyFile(filePath.get(), destPath.get(), PR_TRUE);
+ else
+ {
+ // What we have to do is check to see if the destPath exists. If it
+ // does, we have to move it out of the say so that MoveFile will
+ // succeed. However, we don't want to just remove it since MoveFile
+ // can fail leaving us without a file.
+
+ nsCAutoString backup;
+ PRFileInfo64 fileInfo64;
+ PRStatus status = PR_GetFileInfo64(destPath.get(), &fileInfo64);
+ if (status == PR_SUCCESS)
+ {
+
+ // the file exists. Check to make sure it is not a directory,
+ // then move it out of the way.
+ if (fileInfo64.type == PR_FILE_FILE)
+ {
+ backup.Append(destPath);
+ backup.Append(".moztmp");
+
+ // remove any existing backup file that we may already have.
+ // maybe we should be doing some kind of unique naming here,
+ // but why bother.
+ remove(backup.get());
+
+ // move destination file to backup file
+ copyOK = MoveFile(destPath.get(), backup.get());
+ if (!copyOK)
+ {
+ // I guess we can't do the backup copy, so return.
+ rv = ConvertWinError(GetLastError());
+ return rv;
+ }
+ }
+ }
+ // move source file to destination file
+ copyOK = MoveFile(filePath.get(), destPath.get());
+
+ if (!backup.IsEmpty())
+ {
+ if (copyOK)
+ {
+ // remove the backup copy.
+ remove(backup.get());
+ }
+ else
+ {
+ // restore backup
+ int backupOk = MoveFile(backup.get(), destPath.get());
+ NS_ASSERTION(backupOk, "move backup failed");
+ }
+ }
+ }
+ if (!copyOK) // CopyFile and MoveFile returns non-zero if succeeds (backward if you ask me).
+ rv = ConvertWinError(GetLastError());
+
+ return rv;
+}
+
+
+nsresult
+nsLocalFile::CopyMove(nsIFile *aParentDir, const nsACString &newName, PRBool followSymlinks, PRBool move)
+{
+ nsCOMPtr<nsIFile> newParentDir = aParentDir;
+ // check to see if this exists, otherwise return an error.
+ // we will check this by resolving. If the user wants us
+ // to follow links, then we are talking about the target,
+ // hence we can use the |followSymlinks| parameter.
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (!newParentDir)
+ {
+ // no parent was specified. We must rename.
+
+ if (newName.IsEmpty())
+ return NS_ERROR_INVALID_ARG;
+
+ rv = GetParent(getter_AddRefs(newParentDir));
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ if (!newParentDir)
+ return NS_ERROR_FILE_DESTINATION_NOT_DIR;
+
+ // make sure it exists and is a directory. Create it if not there.
+ PRBool exists;
+ newParentDir->Exists(&exists);
+ if (!exists)
+ {
+ rv = newParentDir->Create(DIRECTORY_TYPE, 0644); // TODO, what permissions should we use
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ else
+ {
+ PRBool isDir;
+ newParentDir->IsDirectory(&isDir);
+ if (isDir == PR_FALSE)
+ {
+ if (followSymlinks)
+ {
+ PRBool isLink;
+ newParentDir->IsSymlink(&isLink);
+ if (isLink)
+ {
+ nsCAutoString target;
+ newParentDir->GetNativeTarget(target);
+
+ nsCOMPtr<nsILocalFile> realDest = new nsLocalFile();
+ if (realDest == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ rv = realDest->InitWithNativePath(target);
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ return CopyMove(realDest, newName, followSymlinks, move);
+ }
+ }
+ else
+ {
+ return NS_ERROR_FILE_DESTINATION_NOT_DIR;
+ }
+ }
+ }
+
+ // check to see if we are a directory, if so enumerate it.
+
+ PRBool isDir;
+ IsDirectory(&isDir);
+ PRBool isSymlink;
+ IsSymlink(&isSymlink);
+
+ if (!isDir || (isSymlink && !followSymlinks))
+ {
+ rv = CopySingleFile(this, newParentDir, newName, followSymlinks, move);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ else
+ {
+ // create a new target destination in the new parentDir;
+ nsCOMPtr<nsIFile> target;
+ rv = newParentDir->Clone(getter_AddRefs(target));
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCAutoString allocatedNewName;
+ if (newName.IsEmpty())
+ {
+ PRBool isLink;
+ IsSymlink(&isLink);
+ if (isLink)
+ {
+ nsCAutoString temp;
+ GetNativeTarget(temp);
+ const char* leaf = (const char*) _mbsrchr((const unsigned char*) temp.get(), '\\');
+ if (leaf[0] == '\\')
+ leaf++;
+ allocatedNewName = leaf;
+ }
+ else
+ {
+ GetNativeLeafName(allocatedNewName);// this should be the leaf name of the
+ }
+ }
+ else
+ {
+ allocatedNewName = newName;
+ }
+
+ rv = target->AppendNative(allocatedNewName);
+ if (NS_FAILED(rv))
+ return rv;
+
+ allocatedNewName.Truncate();
+
+ // check if the destination directory already exists
+ target->Exists(&exists);
+ if (!exists)
+ {
+ // if the destination directory cannot be created, return an error
+ rv = target->Create(DIRECTORY_TYPE, 0644); // TODO, what permissions should we use
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ else
+ {
+ // check if the destination directory is writable and empty
+ PRBool isWritable;
+
+ target->IsWritable(&isWritable);
+ if (!isWritable)
+ return NS_ERROR_FILE_ACCESS_DENIED;
+
+ nsCOMPtr<nsISimpleEnumerator> targetIterator;
+ rv = target->GetDirectoryEntries(getter_AddRefs(targetIterator));
+
+ PRBool more;
+ targetIterator->HasMoreElements(&more);
+ // return error if target directory is not empty
+ if (more)
+ return NS_ERROR_FILE_DIR_NOT_EMPTY;
+ }
+
+ nsDirEnumerator dirEnum;
+
+ rv = dirEnum.Init(this);
+ if (NS_FAILED(rv)) {
+ NS_WARNING("dirEnum initalization failed");
+ return rv;
+ }
+
+ PRBool more;
+ while (NS_SUCCEEDED(dirEnum.HasMoreElements(&more)) && more)
+ {
+ nsCOMPtr<nsISupports> item;
+ nsCOMPtr<nsIFile> file;
+ dirEnum.GetNext(getter_AddRefs(item));
+ file = do_QueryInterface(item);
+ if (file)
+ {
+ PRBool isDir, isLink;
+
+ file->IsDirectory(&isDir);
+ file->IsSymlink(&isLink);
+
+ if (move)
+ {
+ if (followSymlinks)
+ return NS_ERROR_FAILURE;
+
+ rv = file->MoveToNative(target, nsCString());
+ NS_ENSURE_SUCCESS(rv,rv);
+ }
+ else
+ {
+ if (followSymlinks)
+ rv = file->CopyToFollowingLinksNative(target, nsCString());
+ else
+ rv = file->CopyToNative(target, nsCString());
+ NS_ENSURE_SUCCESS(rv,rv);
+ }
+ }
+ }
+ // we've finished moving all the children of this directory
+ // in the new directory. so now delete the directory
+ // note, we don't need to do a recursive delete.
+ // MoveTo() is recursive. At this point,
+ // we've already moved the children of the current folder
+ // to the new location. nothing should be left in the folder.
+ if (move)
+ {
+ rv = Remove(PR_FALSE /* recursive */);
+ NS_ENSURE_SUCCESS(rv,rv);
+ }
+ }
+
+
+ // If we moved, we want to adjust this.
+ if (move)
+ {
+ MakeDirty();
+
+ nsCAutoString newParentPath;
+ newParentDir->GetNativePath(newParentPath);
+
+ if (newParentPath.IsEmpty())
+ return NS_ERROR_FAILURE;
+
+ if (newName.IsEmpty())
+ {
+ nsCAutoString aFileName;
+ GetNativeLeafName(aFileName);
+
+ InitWithNativePath(newParentPath);
+ AppendNative(aFileName);
+ }
+ else
+ {
+ InitWithNativePath(newParentPath);
+ AppendNative(newName);
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::CopyToNative(nsIFile *newParentDir, const nsACString &newName)
+{
+ return CopyMove(newParentDir, newName, PR_FALSE, PR_FALSE);
+}
+
+NS_IMETHODIMP
+nsLocalFile::CopyToFollowingLinksNative(nsIFile *newParentDir, const nsACString &newName)
+{
+ return CopyMove(newParentDir, newName, PR_TRUE, PR_FALSE);
+}
+
+NS_IMETHODIMP
+nsLocalFile::MoveToNative(nsIFile *newParentDir, const nsACString &newName)
+{
+ return CopyMove(newParentDir, newName, PR_FALSE, PR_TRUE);
+}
+
+NS_IMETHODIMP
+nsLocalFile::Load(PRLibrary * *_retval)
+{
+ PRBool isFile;
+ nsresult rv = IsFile(&isFile);
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (! isFile)
+ return NS_ERROR_FILE_IS_DIRECTORY;
+
+ NS_TIMELINE_START_TIMER("PR_LoadLibrary");
+ *_retval = PR_LoadLibrary(mResolvedPath.get());
+ NS_TIMELINE_STOP_TIMER("PR_LoadLibrary");
+ NS_TIMELINE_MARK_TIMER1("PR_LoadLibrary", mResolvedPath.get());
+
+ if (*_retval)
+ return NS_OK;
+
+ return NS_ERROR_NULL_POINTER;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Remove(PRBool recursive)
+{
+ // NOTE:
+ //
+ // if the working path points to a shortcut, then we will only
+ // delete the shortcut itself. even if the shortcut points to
+ // a directory, we will not recurse into that directory or
+ // delete that directory itself. likewise, if the shortcut
+ // points to a normal file, we will not delete the real file.
+ // this is done to be consistent with the other platforms that
+ // behave this way. we do this even if the followLinks attribute
+ // is set to true. this helps protect against misuse that could
+ // lead to security bugs (e.g., bug 210588).
+ //
+ // Since shortcut files are no longer permitted to be used as unix-like
+ // symlinks interspersed in the path (e.g. "c:/file.lnk/foo/bar.txt")
+ // this processing is a lot simpler. Even if the shortcut file is
+ // pointing to a directory, only the mWorkingPath value is used and so
+ // only the shortcut file will be deleted.
+
+ PRBool isDir, isLink;
+ nsresult rv;
+
+ isDir = PR_FALSE;
+ rv = IsSymlink(&isLink);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // only check to see if we have a directory if it isn't a link
+ if (!isLink)
+ {
+ rv = IsDirectory(&isDir);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ if (isDir)
+ {
+ if (recursive)
+ {
+ nsDirEnumerator dirEnum;
+
+ rv = dirEnum.Init(this);
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRBool more;
+ while (NS_SUCCEEDED(dirEnum.HasMoreElements(&more)) && more)
+ {
+ nsCOMPtr<nsISupports> item;
+ dirEnum.GetNext(getter_AddRefs(item));
+ nsCOMPtr<nsIFile> file = do_QueryInterface(item);
+ if (file)
+ file->Remove(recursive);
+ }
+ }
+ rv = rmdir(mWorkingPath.get());
+ }
+ else
+ {
+ rv = remove(mWorkingPath.get());
+ }
+
+ // fixup error code if necessary...
+ if (rv == (nsresult)-1)
+ rv = NSRESULT_FOR_ERRNO();
+
+ MakeDirty();
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetLastModifiedTime(PRInt64 *aLastModifiedTime)
+{
+ NS_ENSURE_ARG(aLastModifiedTime);
+
+ // get the modified time of the target as determined by mFollowSymlinks
+ // If PR_TRUE, then this will be for the target of the shortcut file,
+ // otherwise it will be for the shortcut file itself (i.e. the same
+ // results as GetLastModifiedTimeOfLink)
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ // microseconds -> milliseconds
+ PRInt64 usecPerMsec;
+ LL_I2L(usecPerMsec, PR_USEC_PER_MSEC);
+ LL_DIV(*aLastModifiedTime, mFileInfo64.modifyTime, usecPerMsec);
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::GetLastModifiedTimeOfLink(PRInt64 *aLastModifiedTime)
+{
+ NS_ENSURE_ARG(aLastModifiedTime);
+
+ // The caller is assumed to have already called IsSymlink
+ // and to have found that this file is a link.
+
+ PRFileInfo64 info;
+ if (PR_GetFileInfo64(mWorkingPath.get(), &info) != PR_SUCCESS)
+ return NSRESULT_FOR_ERRNO();
+
+ // microseconds -> milliseconds
+ PRInt64 usecPerMsec;
+ LL_I2L(usecPerMsec, PR_USEC_PER_MSEC);
+ LL_DIV(*aLastModifiedTime, info.modifyTime, usecPerMsec);
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::SetLastModifiedTime(PRInt64 aLastModifiedTime)
+{
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ // set the modified time of the target as determined by mFollowSymlinks
+ // If PR_TRUE, then this will be for the target of the shortcut file,
+ // otherwise it will be for the shortcut file itself (i.e. the same
+ // results as SetLastModifiedTimeOfLink)
+
+ rv = SetModDate(aLastModifiedTime, mResolvedPath.get());
+ if (NS_SUCCEEDED(rv))
+ MakeDirty();
+
+ return rv;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::SetLastModifiedTimeOfLink(PRInt64 aLastModifiedTime)
+{
+ // The caller is assumed to have already called IsSymlink
+ // and to have found that this file is a link.
+
+ nsresult rv = SetModDate(aLastModifiedTime, mWorkingPath.get());
+ if (NS_SUCCEEDED(rv))
+ MakeDirty();
+
+ return rv;
+}
+
+nsresult
+nsLocalFile::SetModDate(PRInt64 aLastModifiedTime, const char *filePath)
+{
+ HANDLE file = CreateFile(filePath, // pointer to name of the file
+ GENERIC_WRITE, // access (write) mode
+ 0, // share mode
+ NULL, // pointer to security attributes
+ OPEN_EXISTING, // how to create
+ 0, // file attributes
+ NULL);
+ if (file == INVALID_HANDLE_VALUE)
+ {
+ return ConvertWinError(GetLastError());
+ }
+
+ FILETIME lft, ft;
+ SYSTEMTIME st;
+ PRExplodedTime pret;
+
+ // PR_ExplodeTime expects usecs...
+ PR_ExplodeTime(aLastModifiedTime * PR_USEC_PER_MSEC, PR_LocalTimeParameters, &pret);
+ st.wYear = pret.tm_year;
+ st.wMonth = pret.tm_month + 1; // Convert start offset -- Win32: Jan=1; NSPR: Jan=0
+ st.wDayOfWeek = pret.tm_wday;
+ st.wDay = pret.tm_mday;
+ st.wHour = pret.tm_hour;
+ st.wMinute = pret.tm_min;
+ st.wSecond = pret.tm_sec;
+ st.wMilliseconds = pret.tm_usec/1000;
+
+ nsresult rv = NS_OK;
+ if ( 0 != SystemTimeToFileTime(&st, &lft)
+ || 0 != LocalFileTimeToFileTime(&lft, &ft)
+ || 0 != SetFileTime(file, NULL, &ft, &ft) )
+ {
+ rv = ConvertWinError(GetLastError());
+ }
+
+ CloseHandle(file);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPermissions(PRUint32 *aPermissions)
+{
+ NS_ENSURE_ARG(aPermissions);
+
+ // get the permissions of the target as determined by mFollowSymlinks
+ // If PR_TRUE, then this will be for the target of the shortcut file,
+ // otherwise it will be for the shortcut file itself (i.e. the same
+ // results as GetPermissionsOfLink)
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRBool isWritable, isExecutable;
+ IsWritable(&isWritable);
+ IsExecutable(&isExecutable);
+
+ *aPermissions = PR_IRUSR|PR_IRGRP|PR_IROTH; // all read
+ if (isWritable)
+ *aPermissions |= PR_IWUSR|PR_IWGRP|PR_IWOTH; // all write
+ if (isExecutable)
+ *aPermissions |= PR_IXUSR|PR_IXGRP|PR_IXOTH; // all execute
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPermissionsOfLink(PRUint32 *aPermissions)
+{
+ NS_ENSURE_ARG(aPermissions);
+
+ // The caller is assumed to have already called IsSymlink
+ // and to have found that this file is a link. It is not
+ // possible for a link file to be executable.
+
+ DWORD word = GetFileAttributes(mWorkingPath.get());
+ if (word == INVALID_FILE_ATTRIBUTES)
+ return NS_ERROR_FILE_INVALID_PATH;
+
+ PRBool isWritable = !(word & FILE_ATTRIBUTE_READONLY);
+ *aPermissions = PR_IRUSR|PR_IRGRP|PR_IROTH; // all read
+ if (isWritable)
+ *aPermissions |= PR_IWUSR|PR_IWGRP|PR_IWOTH; // all write
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::SetPermissions(PRUint32 aPermissions)
+{
+ // set the permissions of the target as determined by mFollowSymlinks
+ // If PR_TRUE, then this will be for the target of the shortcut file,
+ // otherwise it will be for the shortcut file itself (i.e. the same
+ // results as SetPermissionsOfLink)
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ // windows only knows about the following permissions
+ int mode = 0;
+ if (aPermissions & (PR_IRUSR|PR_IRGRP|PR_IROTH)) // any read
+ mode |= _S_IREAD;
+ if (aPermissions & (PR_IWUSR|PR_IWGRP|PR_IWOTH)) // any write
+ mode |= _S_IWRITE;
+
+ if (chmod(mResolvedPath.get(), mode) == -1)
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetPermissionsOfLink(PRUint32 aPermissions)
+{
+ // The caller is assumed to have already called IsSymlink
+ // and to have found that this file is a link.
+
+ // windows only knows about the following permissions
+ int mode = 0;
+ if (aPermissions & (PR_IRUSR|PR_IRGRP|PR_IROTH)) // any read
+ mode |= _S_IREAD;
+ if (aPermissions & (PR_IWUSR|PR_IWGRP|PR_IWOTH)) // any write
+ mode |= _S_IWRITE;
+
+ if (chmod(mWorkingPath.get(), mode) == -1)
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::GetFileSize(PRInt64 *aFileSize)
+{
+ NS_ENSURE_ARG(aFileSize);
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ *aFileSize = mFileInfo64.size;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::GetFileSizeOfLink(PRInt64 *aFileSize)
+{
+ NS_ENSURE_ARG(aFileSize);
+
+ // The caller is assumed to have already called IsSymlink
+ // and to have found that this file is a link.
+
+ PRFileInfo64 info;
+ if (!PR_GetFileInfo64(mWorkingPath.get(), &info))
+ return NS_ERROR_FILE_INVALID_PATH;
+
+ *aFileSize = info.size;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetFileSize(PRInt64 aFileSize)
+{
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ HANDLE hFile = CreateFile(mResolvedPath.get(), // pointer to name of the file
+ GENERIC_WRITE, // access (write) mode
+ FILE_SHARE_READ, // share mode
+ NULL, // pointer to security attributes
+ OPEN_EXISTING, // how to create
+ FILE_ATTRIBUTE_NORMAL, // file attributes
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ return ConvertWinError(GetLastError());
+ }
+
+ // seek the file pointer to the new, desired end of file
+ // and then truncate the file at that position
+ rv = NS_ERROR_FAILURE;
+ aFileSize = MyFileSeek64(hFile, aFileSize, FILE_BEGIN);
+ if (aFileSize != -1 && SetEndOfFile(hFile))
+ {
+ MakeDirty();
+ rv = NS_OK;
+ }
+
+ CloseHandle(hFile);
+ return rv;
+}
+
+typedef BOOL (WINAPI *fpGetDiskFreeSpaceExA)(LPCTSTR lpDirectoryName,
+ PULARGE_INTEGER lpFreeBytesAvailableToCaller,
+ PULARGE_INTEGER lpTotalNumberOfBytes,
+ PULARGE_INTEGER lpTotalNumberOfFreeBytes);
+
+NS_IMETHODIMP
+nsLocalFile::GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable)
+{
+ NS_ENSURE_ARG(aDiskSpaceAvailable);
+
+ ResolveAndStat();
+
+ // Attempt to check disk space using the GetDiskFreeSpaceExA function.
+ // --- FROM MSDN ---
+ // The GetDiskFreeSpaceEx function is available beginning with Windows 95 OEM Service
+ // Release 2 (OSR2). To determine whether GetDiskFreeSpaceEx is available, call
+ // GetModuleHandle to get the handle to Kernel32.dll. Then you can call GetProcAddress.
+ // It is not necessary to call LoadLibrary on Kernel32.dll because it is already loaded
+ // into every process address space.
+ fpGetDiskFreeSpaceExA pGetDiskFreeSpaceExA = (fpGetDiskFreeSpaceExA)
+ GetProcAddress(GetModuleHandle("kernel32.dll"), "GetDiskFreeSpaceExA");
+ if (pGetDiskFreeSpaceExA)
+ {
+ ULARGE_INTEGER liFreeBytesAvailableToCaller, liTotalNumberOfBytes;
+ if (pGetDiskFreeSpaceExA(mResolvedPath.get(), &liFreeBytesAvailableToCaller,
+ &liTotalNumberOfBytes, NULL))
+ {
+ *aDiskSpaceAvailable = liFreeBytesAvailableToCaller.QuadPart;
+ return NS_OK;
+ }
+ }
+
+ // use the old method of getting available disk space
+ char aDrive[_MAX_DRIVE + 2];
+ _splitpath( mResolvedPath.get(), aDrive, NULL, NULL, NULL);
+ strcat(aDrive, "\\");
+
+ DWORD dwSecPerClus, dwBytesPerSec, dwFreeClus, dwTotalClus;
+ if (GetDiskFreeSpace(aDrive, &dwSecPerClus, &dwBytesPerSec, &dwFreeClus, &dwTotalClus))
+ {
+ __int64 bytes = dwFreeClus;
+ bytes *= dwSecPerClus;
+ bytes *= dwBytesPerSec;
+
+ *aDiskSpaceAvailable = bytes;
+ return NS_OK;
+ }
+
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetParent(nsIFile * *aParent)
+{
+ NS_ENSURE_ARG_POINTER(aParent);
+
+ nsCAutoString parentPath(mWorkingPath);
+
+ // cannot use nsCString::RFindChar() due to 0x5c problem
+ PRInt32 offset = (PRInt32) (_mbsrchr((const unsigned char *) parentPath.get(), '\\')
+ - (const unsigned char *) parentPath.get());
+ // adding this offset check that was removed in bug 241708 fixes mail
+ // directories that aren't relative to/underneath the profile dir.
+ // e.g., on a different drive. Before you remove them, please make
+ // sure local mail directories that aren't underneath the profile dir work.
+ if (offset < 0)
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+
+ if (offset == 1 && parentPath[0] == '\\') {
+ aParent = nsnull;
+ return NS_OK;
+ }
+ if (offset > 0)
+ parentPath.Truncate(offset);
+ else
+ parentPath.AssignLiteral("\\\\.");
+
+ nsCOMPtr<nsILocalFile> localFile;
+ nsresult rv = NS_NewNativeLocalFile(parentPath, mFollowSymlinks, getter_AddRefs(localFile));
+
+ if(NS_SUCCEEDED(rv) && localFile)
+ {
+ return CallQueryInterface(localFile, aParent);
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Exists(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ MakeDirty();
+ nsresult rv = ResolveAndStat();
+ *_retval = NS_SUCCEEDED(rv);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsWritable(PRBool *aIsWritable)
+{
+ //TODO: extend to support NTFS file permissions
+
+ // The read-only attribute on a FAT directory only means that it can't
+ // be deleted. It is still possible to modify the contents of the directory.
+ nsresult rv = IsDirectory(aIsWritable);
+ if (NS_FAILED(rv))
+ return rv;
+ if (*aIsWritable)
+ return NS_OK;
+
+ // writable if the file doesn't have the readonly attribute
+ rv = HasFileAttribute(FILE_ATTRIBUTE_READONLY, aIsWritable);
+ if (NS_FAILED(rv))
+ return rv;
+ *aIsWritable = !*aIsWritable;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsReadable(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ *_retval = PR_TRUE;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::IsExecutable(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+ *_retval = PR_FALSE;
+
+ nsresult rv;
+
+ // only files can be executables
+ PRBool isFile;
+ rv = IsFile(&isFile);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!isFile)
+ return NS_OK;
+
+ //TODO: shouldn't we be checking mFollowSymlinks here?
+ PRBool symLink;
+ rv = IsSymlink(&symLink);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCAutoString path;
+ if (symLink)
+ GetNativeTarget(path);
+ else
+ GetNativePath(path);
+
+ // Get extension.
+ char * ext = (char *) _mbsrchr((unsigned char *)path.BeginWriting(), '.');
+ if ( ext ) {
+ // Convert extension to lower case.
+ for( unsigned char *p = (unsigned char *)ext; *p; p++ )
+ *p = _mbctolower( *p );
+
+ // Search for any of the set of executable extensions.
+ const char * const executableExts[] = {
+ ".ad",
+ ".adp",
+ ".asp",
+ ".bas",
+ ".bat",
+ ".chm",
+ ".cmd",
+ ".com",
+ ".cpl",
+ ".crt",
+ ".exe",
+ ".hlp",
+ ".hta",
+ ".inf",
+ ".ins",
+ ".isp",
+ ".js",
+ ".jse",
+ ".lnk",
+ ".mdb",
+ ".mde",
+ ".msc",
+ ".msi",
+ ".msp",
+ ".mst",
+ ".pcd",
+ ".pif",
+ ".reg",
+ ".scr",
+ ".sct",
+ ".shb",
+ ".shs",
+ ".url",
+ ".vb",
+ ".vbe",
+ ".vbs",
+ ".vsd",
+ ".vss",
+ ".vst",
+ ".vsw",
+ ".ws",
+ ".wsc",
+ ".wsf",
+ ".wsh",
+ 0 };
+ for ( int i = 0; executableExts[i]; i++ ) {
+ if ( ::strcmp( executableExts[i], ext ) == 0 ) {
+ // Found a match. Set result and quit.
+ *_retval = PR_TRUE;
+ break;
+ }
+ }
+ }
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::IsDirectory(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ *_retval = (mFileInfo64.type == PR_FILE_DIRECTORY);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsFile(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ *_retval = (mFileInfo64.type == PR_FILE_FILE);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsHidden(PRBool *_retval)
+{
+ return HasFileAttribute(FILE_ATTRIBUTE_HIDDEN, _retval);
+}
+
+nsresult
+nsLocalFile::HasFileAttribute(DWORD fileAttrib, PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ // get the file attributes for the correct item depending on following symlinks
+ const char *filePath = mFollowSymlinks ? mResolvedPath.get() : mWorkingPath.get();
+ DWORD word = GetFileAttributes(filePath);
+
+ *_retval = ((word & fileAttrib) != 0);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsSymlink(PRBool *_retval)
+{
+ NS_ENSURE_ARG(_retval);
+
+ // unless it is a valid shortcut path it's not a symlink
+ if (!IsShortcutPath(mWorkingPath.get()))
+ {
+ *_retval = PR_FALSE;
+ return NS_OK;
+ }
+
+ // we need to know if this is a file or directory
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv))
+ return rv;
+
+ // it's only a shortcut if it is a file
+ *_retval = (mFileInfo64.type == PR_FILE_FILE);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::IsSpecial(PRBool *_retval)
+{
+ return HasFileAttribute(FILE_ATTRIBUTE_SYSTEM, _retval);
+}
+
+NS_IMETHODIMP
+nsLocalFile::Equals(nsIFile *inFile, PRBool *_retval)
+{
+ NS_ENSURE_ARG(inFile);
+ NS_ENSURE_ARG(_retval);
+
+ nsCAutoString inFilePath;
+ inFile->GetNativePath(inFilePath);
+
+ *_retval = inFilePath.Equals(mWorkingPath);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::Contains(nsIFile *inFile, PRBool recur, PRBool *_retval)
+{
+ *_retval = PR_FALSE;
+
+ nsCAutoString myFilePath;
+ if ( NS_FAILED(GetNativeTarget(myFilePath)))
+ GetNativePath(myFilePath);
+
+ PRInt32 myFilePathLen = myFilePath.Length();
+
+ nsCAutoString inFilePath;
+ if ( NS_FAILED(inFile->GetNativeTarget(inFilePath)))
+ inFile->GetNativePath(inFilePath);
+
+ if ( strnicmp( myFilePath.get(), inFilePath.get(), myFilePathLen) == 0)
+ {
+ // now make sure that the |inFile|'s path has a trailing
+ // separator.
+
+ if (inFilePath[myFilePathLen] == '\\')
+ {
+ *_retval = PR_TRUE;
+ }
+
+ }
+
+ return NS_OK;
+}
+
+
+
+NS_IMETHODIMP
+nsLocalFile::GetNativeTarget(nsACString &_retval)
+{
+ _retval.Truncate();
+#if STRICT_FAKE_SYMLINKS
+ PRBool symLink;
+
+ nsresult rv = IsSymlink(&symLink);
+ if (NS_FAILED(rv))
+ return rv;
+
+ if (!symLink)
+ {
+ return NS_ERROR_FILE_INVALID_PATH;
+ }
+#endif
+ ResolveAndStat();
+
+ _retval = mResolvedPath;
+ return NS_OK;
+}
+
+
+/* attribute PRBool followLinks; */
+NS_IMETHODIMP
+nsLocalFile::GetFollowLinks(PRBool *aFollowLinks)
+{
+ *aFollowLinks = mFollowSymlinks;
+ return NS_OK;
+}
+NS_IMETHODIMP
+nsLocalFile::SetFollowLinks(PRBool aFollowLinks)
+{
+ MakeDirty();
+ mFollowSymlinks = aFollowLinks;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::GetDirectoryEntries(nsISimpleEnumerator * *entries)
+{
+ nsresult rv;
+
+ *entries = nsnull;
+ if (mWorkingPath.EqualsLiteral("\\\\.")) {
+ nsDriveEnumerator *drives = new nsDriveEnumerator;
+ if (!drives)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(drives);
+ rv = drives->Init();
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(drives);
+ return rv;
+ }
+ *entries = drives;
+ return NS_OK;
+ }
+
+ PRBool isDir;
+ rv = IsDirectory(&isDir);
+ if (NS_FAILED(rv))
+ return rv;
+ if (!isDir)
+ return NS_ERROR_FILE_NOT_DIRECTORY;
+
+ nsDirEnumerator* dirEnum = new nsDirEnumerator();
+ if (dirEnum == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(dirEnum);
+ rv = dirEnum->Init(this);
+ if (NS_FAILED(rv))
+ {
+ NS_RELEASE(dirEnum);
+ return rv;
+ }
+
+ *entries = dirEnum;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsLocalFile::GetPersistentDescriptor(nsACString &aPersistentDescriptor)
+{
+ return GetNativePath(aPersistentDescriptor);
+}
+
+NS_IMETHODIMP
+nsLocalFile::SetPersistentDescriptor(const nsACString &aPersistentDescriptor)
+{
+ return InitWithNativePath(aPersistentDescriptor);
+}
+
+NS_IMETHODIMP
+nsLocalFile::Reveal()
+{
+ // make sure mResolvedPath is set
+ nsresult rv = ResolveAndStat();
+ if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
+ return rv;
+
+ // use the full path to explorer for security
+ nsCOMPtr<nsILocalFile> winDir;
+ rv = GetSpecialSystemDirectory(Win_WindowsDirectory, getter_AddRefs(winDir));
+ NS_ENSURE_SUCCESS(rv, rv);
+ nsCAutoString explorerPath;
+ rv = winDir->GetNativePath(explorerPath);
+ NS_ENSURE_SUCCESS(rv, rv);
+ explorerPath.Append("\\explorer.exe");
+
+ // Always open a new window for files because Win2K doesn't appear to select
+ // the file if a window showing that folder was already open. If the resolved
+ // path is a directory then instead of opening the parent and selecting it,
+ // we open the directory itself.
+ nsCAutoString explorerParams;
+ if (mFileInfo64.type != PR_FILE_DIRECTORY) // valid because we ResolveAndStat above
+ explorerParams.Append("/n,/select,");
+ explorerParams.Append('\"');
+ explorerParams.Append(mResolvedPath);
+ explorerParams.Append('\"');
+
+ if (::ShellExecute(NULL, "open", explorerPath.get(), explorerParams.get(),
+ NULL, SW_SHOWNORMAL) <= (HINSTANCE) 32)
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsLocalFile::Launch()
+{
+ const nsCString &path = mWorkingPath;
+
+ // use the app registry name to launch a shell execute....
+ LONG r = (LONG) ::ShellExecute( NULL, NULL, path.get(), NULL, NULL, SW_SHOWNORMAL);
+
+ // if the file has no association, we launch windows' "what do you want to do" dialog
+ if (r == SE_ERR_NOASSOC) {
+ nsCAutoString shellArg;
+ shellArg.Assign(NS_LITERAL_CSTRING("shell32.dll,OpenAs_RunDLL ") + path);
+ r = (LONG) ::ShellExecute(NULL, NULL, "RUNDLL32.EXE", shellArg.get(),
+ NULL, SW_SHOWNORMAL);
+ }
+ if (r < 32) {
+ switch (r) {
+ case 0:
+ case SE_ERR_OOM:
+ return NS_ERROR_OUT_OF_MEMORY;
+ case ERROR_FILE_NOT_FOUND:
+ return NS_ERROR_FILE_NOT_FOUND;
+ case ERROR_PATH_NOT_FOUND:
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+ case ERROR_BAD_FORMAT:
+ return NS_ERROR_FILE_CORRUPTED;
+ case SE_ERR_ACCESSDENIED:
+ return NS_ERROR_FILE_ACCESS_DENIED;
+ case SE_ERR_ASSOCINCOMPLETE:
+ case SE_ERR_NOASSOC:
+ return NS_ERROR_UNEXPECTED;
+ case SE_ERR_DDEBUSY:
+ case SE_ERR_DDEFAIL:
+ case SE_ERR_DDETIMEOUT:
+ return NS_ERROR_NOT_AVAILABLE;
+ case SE_ERR_DLLNOTFOUND:
+ return NS_ERROR_FAILURE;
+ case SE_ERR_SHARE:
+ return NS_ERROR_FILE_IS_LOCKED;
+ default:
+ return NS_ERROR_FILE_EXECUTION_FAILED;
+ }
+ }
+ return NS_OK;
+}
+
+nsresult
+NS_NewNativeLocalFile(const nsACString &path, PRBool followLinks, nsILocalFile* *result)
+{
+ nsLocalFile* file = new nsLocalFile();
+ if (file == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(file);
+
+ file->SetFollowLinks(followLinks);
+
+ if (!path.IsEmpty()) {
+ nsresult rv = file->InitWithNativePath(path);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(file);
+ return rv;
+ }
+ }
+
+ *result = file;
+ return NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+// UCS2 interface
+//-----------------------------------------------------------------------------
+
+nsresult
+nsLocalFile::InitWithPath(const nsAString &filePath)
+{
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(filePath, tmp);
+ if (NS_SUCCEEDED(rv))
+ return InitWithNativePath(tmp);
+
+ return rv;
+}
+
+nsresult
+nsLocalFile::Append(const nsAString &node)
+{
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(node, tmp);
+ if (NS_SUCCEEDED(rv))
+ return AppendNative(tmp);
+
+ return rv;
+}
+
+nsresult
+nsLocalFile::AppendRelativePath(const nsAString &node)
+{
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(node, tmp);
+ if (NS_SUCCEEDED(rv))
+ return AppendRelativeNativePath(tmp);
+ return rv;
+}
+
+nsresult
+nsLocalFile::GetLeafName(nsAString &aLeafName)
+{
+ nsCAutoString tmp;
+ nsresult rv = GetNativeLeafName(tmp);
+ if (NS_SUCCEEDED(rv))
+ rv = NS_CopyNativeToUnicode(tmp, aLeafName);
+
+ return rv;
+}
+
+nsresult
+nsLocalFile::SetLeafName(const nsAString &aLeafName)
+{
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(aLeafName, tmp);
+ if (NS_SUCCEEDED(rv))
+ return SetNativeLeafName(tmp);
+
+ return rv;
+}
+
+nsresult
+nsLocalFile::GetPath(nsAString &_retval)
+{
+ return NS_CopyNativeToUnicode(mWorkingPath, _retval);
+}
+
+nsresult
+nsLocalFile::CopyTo(nsIFile *newParentDir, const nsAString &newName)
+{
+ if (newName.IsEmpty())
+ return CopyToNative(newParentDir, nsCString());
+
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(newName, tmp);
+ if (NS_SUCCEEDED(rv))
+ return CopyToNative(newParentDir, tmp);
+
+ return rv;
+}
+
+nsresult
+nsLocalFile::CopyToFollowingLinks(nsIFile *newParentDir, const nsAString &newName)
+{
+ if (newName.IsEmpty())
+ return CopyToFollowingLinksNative(newParentDir, nsCString());
+
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(newName, tmp);
+ if (NS_SUCCEEDED(rv))
+ return CopyToFollowingLinksNative(newParentDir, tmp);
+
+ return rv;
+}
+
+nsresult
+nsLocalFile::MoveTo(nsIFile *newParentDir, const nsAString &newName)
+{
+ if (newName.IsEmpty())
+ return MoveToNative(newParentDir, nsCString());
+
+ nsCAutoString tmp;
+ nsresult rv = NS_CopyUnicodeToNative(newName, tmp);
+ if (NS_SUCCEEDED(rv))
+ return MoveToNative(newParentDir, tmp);
+
+ return rv;
+}
+
+nsresult
+nsLocalFile::GetTarget(nsAString &_retval)
+{
+ nsCAutoString tmp;
+ nsresult rv = GetNativeTarget(tmp);
+ if (NS_SUCCEEDED(rv))
+ rv = NS_CopyNativeToUnicode(tmp, _retval);
+
+ return rv;
+}
+
+nsresult
+NS_NewLocalFile(const nsAString &path, PRBool followLinks, nsILocalFile* *result)
+{
+ nsCAutoString buf;
+ nsresult rv = NS_CopyUnicodeToNative(path, buf);
+ if (NS_FAILED(rv)) {
+ *result = nsnull;
+ return rv;
+ }
+ return NS_NewNativeLocalFile(buf, followLinks, result);
+}
+
+//-----------------------------------------------------------------------------
+// nsLocalFile <static members>
+//-----------------------------------------------------------------------------
+
+void
+nsLocalFile::GlobalInit()
+{
+ nsresult rv = NS_CreateShortcutResolver();
+ NS_ASSERTION(NS_SUCCEEDED(rv), "Shortcut resolver could not be created");
+}
+
+void
+nsLocalFile::GlobalShutdown()
+{
+ NS_DestroyShortcutResolver();
+}
+
+NS_IMPL_ISUPPORTS1(nsDriveEnumerator, nsISimpleEnumerator)
+
+nsDriveEnumerator::nsDriveEnumerator()
+ : mLetter(0)
+{
+}
+
+nsDriveEnumerator::~nsDriveEnumerator()
+{
+}
+
+nsresult nsDriveEnumerator::Init()
+{
+ /* If the length passed to GetLogicalDriveStrings is smaller
+ * than the length of the string it would return, it returns
+ * the length required for the string. */
+ DWORD length = GetLogicalDriveStrings(0, 0);
+ /* The string is null terminated */
+ mDrives.SetLength(length+1);
+ if (!GetLogicalDriveStrings(length, mDrives.BeginWriting()))
+ return NS_ERROR_FAILURE;
+ mLetter = mDrives.get();
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsDriveEnumerator::HasMoreElements(PRBool *aHasMore)
+{
+ *aHasMore = *mLetter != '\0';
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsDriveEnumerator::GetNext(nsISupports **aNext)
+{
+ /* GetLogicalDrives stored in mLetter is a concatenation
+ * of null terminated strings, followed by a null terminator. */
+ if (!*mLetter) {
+ *aNext = nsnull;
+ return NS_OK;
+ }
+ const char *drive = mLetter;
+ mLetter += strlen(drive) + 1;
+ nsILocalFile *file;
+ nsresult rv =
+ NS_NewNativeLocalFile(nsDependentCString(drive), PR_FALSE, &file);
+
+ *aNext = file;
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsLocalFileWin.h b/src/libs/xpcom18a4/xpcom/io/nsLocalFileWin.h
new file mode 100644
index 00000000..0ef1d9f0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsLocalFileWin.h
@@ -0,0 +1,113 @@
+/* -*- 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):
+ * Doug Turner <dougt@netscape.com>
+ * Brodie Thiesfield <brofield@jellycan.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 _nsLocalFileWIN_H_
+#define _nsLocalFileWIN_H_
+
+#include "nscore.h"
+#include "nsError.h"
+#include "nsString.h"
+#include "nsCRT.h"
+#include "nsIFile.h"
+#include "nsIFactory.h"
+
+#include "windows.h"
+
+// For older version (<6.0) of the VC Compiler
+#if (_MSC_VER == 1100)
+#include <objbase.h>
+DEFINE_OLEGUID(IID_IPersistFile, 0x0000010BL, 0, 0);
+#endif
+
+#include "shlobj.h"
+
+#include <sys/stat.h>
+
+class nsLocalFile : public nsILocalFile
+{
+public:
+ NS_DEFINE_STATIC_CID_ACCESSOR(NS_LOCAL_FILE_CID)
+
+ nsLocalFile();
+
+ static NS_METHOD nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+
+ // nsIFile interface
+ NS_DECL_NSIFILE
+
+ // nsILocalFile interface
+ NS_DECL_NSILOCALFILE
+
+public:
+ static void GlobalInit();
+ static void GlobalShutdown();
+
+private:
+ nsLocalFile(const nsLocalFile& other);
+ ~nsLocalFile() {}
+
+ PRPackedBool mDirty; // cached information can only be used when this is PR_FALSE
+ PRPackedBool mFollowSymlinks; // should we follow symlinks when working on this file
+
+ // this string will always be in native format!
+ nsCString mWorkingPath;
+
+ // this will be the resolved path of shortcuts, it will *NEVER* be returned to the user
+ nsCString mResolvedPath;
+
+ PRFileInfo64 mFileInfo64;
+
+ void MakeDirty() { mDirty = PR_TRUE; }
+
+ nsresult ResolveAndStat();
+ nsresult ResolveShortcut();
+
+ nsresult CopyMove(nsIFile *newParentDir, const nsACString &newName, PRBool followSymlinks, PRBool move);
+ nsresult CopySingleFile(nsIFile *source, nsIFile* dest, const nsACString &newName, PRBool followSymlinks, PRBool move);
+
+ nsresult SetModDate(PRInt64 aLastModifiedTime, const char *filePath);
+ nsresult HasFileAttribute(DWORD fileAttrib, PRBool *_retval);
+ nsresult AppendNativeInternal(const nsAFlatCString &node, PRBool multipleComponents);
+};
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/io/nsMultiplexInputStream.cpp b/src/libs/xpcom18a4/xpcom/io/nsMultiplexInputStream.cpp
new file mode 100644
index 00000000..ba04a842
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsMultiplexInputStream.cpp
@@ -0,0 +1,389 @@
+/* -*- 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 frightening to behold.
+ *
+ * The Initial Developer of the Original Code is
+ * Jonas Sicking.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Jonas Sicking <sicking@bigfoot.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 ***** */
+
+/**
+ * The multiplex stream concatenates a list of input streams into a single
+ * stream.
+ */
+
+#include "nsMultiplexInputStream.h"
+#include "nsIMultiplexInputStream.h"
+#include "nsISeekableStream.h"
+#include "nsSupportsArray.h"
+#include "nsInt64.h"
+
+class nsMultiplexInputStream : public nsIMultiplexInputStream,
+ public nsISeekableStream
+{
+public:
+ nsMultiplexInputStream();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIINPUTSTREAM
+ NS_DECL_NSIMULTIPLEXINPUTSTREAM
+ NS_DECL_NSISEEKABLESTREAM
+
+ static NS_METHOD Create(nsISupports *outer, REFNSIID iid, void **result);
+
+private:
+ ~nsMultiplexInputStream() {}
+
+
+ struct ReadSegmentsState {
+ nsIInputStream* mThisStream;
+ PRUint32 mOffset;
+ nsWriteSegmentFun mWriter;
+ void* mClosure;
+ PRBool mDone;
+ };
+
+ static NS_METHOD ReadSegCb(nsIInputStream* aIn, void* aClosure,
+ const char* aFromRawSegment, PRUint32 aToOffset,
+ PRUint32 aCount, PRUint32 *aWriteCount);
+
+ nsSupportsArray mStreams;
+ PRUint32 mCurrentStream;
+ PRBool mStartedReadingCurrent;
+};
+
+
+NS_IMPL_THREADSAFE_ISUPPORTS3(nsMultiplexInputStream,
+ nsIMultiplexInputStream,
+ nsIInputStream,
+ nsISeekableStream)
+
+nsMultiplexInputStream::nsMultiplexInputStream()
+ : mCurrentStream(0),
+ mStartedReadingCurrent(PR_FALSE)
+{
+}
+
+/* readonly attribute unsigned long count; */
+NS_IMETHODIMP
+nsMultiplexInputStream::GetCount(PRUint32 *aCount)
+{
+ mStreams.Count(aCount);
+ return NS_OK;
+}
+
+/* void appendStream (in nsIInputStream stream); */
+NS_IMETHODIMP
+nsMultiplexInputStream::AppendStream(nsIInputStream *aStream)
+{
+ return mStreams.AppendElement(aStream);
+}
+
+/* void insertStream (in nsIInputStream stream, in unsigned long index); */
+NS_IMETHODIMP
+nsMultiplexInputStream::InsertStream(nsIInputStream *aStream, PRUint32 aIndex)
+{
+ nsresult rv = mStreams.InsertElementAt(aStream, aIndex);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (mCurrentStream > aIndex ||
+ (mCurrentStream == aIndex && mStartedReadingCurrent))
+ ++mCurrentStream;
+ return rv;
+}
+
+/* void removeStream (in unsigned long index); */
+NS_IMETHODIMP
+nsMultiplexInputStream::RemoveStream(PRUint32 aIndex)
+{
+ nsresult rv = mStreams.RemoveElementAt(aIndex);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (mCurrentStream > aIndex)
+ --mCurrentStream;
+ else if (mCurrentStream == aIndex)
+ mStartedReadingCurrent = PR_FALSE;
+
+ return rv;
+}
+
+/* nsIInputStream getStream (in unsigned long index); */
+NS_IMETHODIMP
+nsMultiplexInputStream::GetStream(PRUint32 aIndex, nsIInputStream **_retval)
+{
+ return mStreams.QueryElementAt(aIndex,
+ NS_GET_IID(nsIInputStream),
+ (void**)_retval);
+}
+
+/* void close (); */
+NS_IMETHODIMP
+nsMultiplexInputStream::Close()
+{
+ PRUint32 len, i;
+ nsresult rv = NS_OK;
+
+ mStreams.Count(&len);
+ for (i = 0; i < len; ++i) {
+ nsCOMPtr<nsIInputStream> stream(do_QueryElementAt(&mStreams, i));
+ nsresult rv2 = stream->Close();
+ // We still want to close all streams, but we should return an error
+ if (NS_FAILED(rv2))
+ rv = rv2;
+ }
+ return rv;
+}
+
+/* unsigned long available (); */
+NS_IMETHODIMP
+nsMultiplexInputStream::Available(PRUint32 *_retval)
+{
+ nsresult rv;
+ PRUint32 i, len, avail = 0;
+
+ mStreams.Count(&len);
+ for (i = mCurrentStream; i < len; i++) {
+ nsCOMPtr<nsIInputStream> stream(do_QueryElementAt(&mStreams, i));
+
+ PRUint32 streamAvail;
+ rv = stream->Available(&streamAvail);
+ NS_ENSURE_SUCCESS(rv, rv);
+ avail += streamAvail;
+ }
+ *_retval = avail;
+ return NS_OK;
+}
+
+/* [noscript] unsigned long read (in charPtr buf, in unsigned long count); */
+NS_IMETHODIMP
+nsMultiplexInputStream::Read(char * aBuf, PRUint32 aCount, PRUint32 *_retval)
+{
+ nsresult rv = NS_OK;
+ PRUint32 len, read;
+
+ *_retval = 0;
+
+ mStreams.Count(&len);
+ while (mCurrentStream < len && aCount) {
+ nsCOMPtr<nsIInputStream> stream(do_QueryElementAt(&mStreams,
+ mCurrentStream));
+ rv = stream->Read(aBuf, aCount, &read);
+
+ // XXX some streams return NS_BASE_STREAM_CLOSED to indicate EOF.
+ if (rv == NS_BASE_STREAM_CLOSED) {
+ rv = NS_OK;
+ read = 0;
+ }
+ else if (NS_FAILED(rv))
+ break;
+
+ if (read == 0) {
+ ++mCurrentStream;
+ mStartedReadingCurrent = PR_FALSE;
+ }
+ else {
+ NS_ASSERTION(aCount >= read, "Read more than requested");
+ *_retval += read;
+ aCount -= read;
+ aBuf += read;
+ mStartedReadingCurrent = PR_TRUE;
+ }
+ }
+ return *_retval ? NS_OK : rv;
+}
+
+/* [noscript] unsigned long readSegments (in nsWriteSegmentFun writer,
+ * in voidPtr closure,
+ * in unsigned long count); */
+NS_IMETHODIMP
+nsMultiplexInputStream::ReadSegments(nsWriteSegmentFun aWriter, void *aClosure,
+ PRUint32 aCount, PRUint32 *_retval)
+{
+ NS_ASSERTION(aWriter, "missing aWriter");
+
+ nsresult rv = NS_OK;
+ ReadSegmentsState state;
+ state.mThisStream = this;
+ state.mOffset = 0;
+ state.mWriter = aWriter;
+ state.mClosure = aClosure;
+ state.mDone = PR_FALSE;
+
+ PRUint32 len;
+ mStreams.Count(&len);
+ while (mCurrentStream < len && aCount) {
+ nsCOMPtr<nsIInputStream> stream(do_QueryElementAt(&mStreams,
+ mCurrentStream));
+ PRUint32 read;
+ rv = stream->ReadSegments(ReadSegCb, &state, aCount, &read);
+
+ // XXX some streams return NS_BASE_STREAM_CLOSED to indicate EOF.
+ if (rv == NS_BASE_STREAM_CLOSED) {
+ rv = NS_OK;
+ read = 0;
+ }
+
+ // if |aWriter| decided to stop reading segments...
+ if (state.mDone || NS_FAILED(rv))
+ break;
+
+ // if stream is empty, then advance to the next stream.
+ if (read == 0) {
+ ++mCurrentStream;
+ mStartedReadingCurrent = PR_FALSE;
+ }
+ else {
+ NS_ASSERTION(aCount >= read, "Read more than requested");
+ state.mOffset += read;
+ aCount -= read;
+ mStartedReadingCurrent = PR_TRUE;
+ }
+ }
+
+ // if we successfully read some data, then this call succeeded.
+ *_retval = state.mOffset;
+ return state.mOffset ? NS_OK : rv;
+}
+
+NS_METHOD
+nsMultiplexInputStream::ReadSegCb(nsIInputStream* aIn, void* aClosure,
+ const char* aFromRawSegment,
+ PRUint32 aToOffset, PRUint32 aCount,
+ PRUint32 *aWriteCount)
+{
+ nsresult rv;
+ ReadSegmentsState* state = (ReadSegmentsState*)aClosure;
+ rv = (state->mWriter)(state->mThisStream,
+ state->mClosure,
+ aFromRawSegment,
+ aToOffset + state->mOffset,
+ aCount,
+ aWriteCount);
+ if (NS_FAILED(rv))
+ state->mDone = PR_TRUE;
+ return rv;
+}
+
+/* readonly attribute boolean nonBlocking; */
+NS_IMETHODIMP
+nsMultiplexInputStream::IsNonBlocking(PRBool *aNonBlocking)
+{
+ nsresult rv;
+ PRUint32 i, len;
+
+ mStreams.Count(&len);
+ for (i = 0; i < len; ++i) {
+ nsCOMPtr<nsIInputStream> stream(do_QueryElementAt(&mStreams, i));
+ rv = stream->IsNonBlocking(aNonBlocking);
+ NS_ENSURE_SUCCESS(rv, rv);
+ // If one is non-blocking the entire stream becomes non-blocking
+ if (*aNonBlocking)
+ return NS_OK;
+ }
+ return NS_OK;
+}
+
+/* void seek (in PRInt32 whence, in PRInt32 offset); */
+NS_IMETHODIMP
+nsMultiplexInputStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
+{
+ nsresult rv;
+
+ // rewinding to start is easy, and should be the most common case
+ if (aWhence == NS_SEEK_SET && aOffset == 0)
+ {
+ PRUint32 i, last;
+ last = mStartedReadingCurrent ? mCurrentStream+1 : mCurrentStream;
+ for (i = 0; i < last; ++i) {
+ nsCOMPtr<nsISeekableStream> stream(do_QueryElementAt(&mStreams, i));
+ NS_ENSURE_TRUE(stream, NS_ERROR_NO_INTERFACE);
+
+ rv = stream->Seek(NS_SEEK_SET, 0);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ mCurrentStream = 0;
+ mStartedReadingCurrent = PR_FALSE;
+ return NS_OK;
+ }
+
+ // other Seeks not implemented yet
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* PRUint32 tell (); */
+NS_IMETHODIMP
+nsMultiplexInputStream::Tell(PRInt64 *_retval)
+{
+ nsresult rv;
+ nsInt64 ret64 = 0;
+ PRUint32 i, last;
+ last = mStartedReadingCurrent ? mCurrentStream+1 : mCurrentStream;
+ for (i = 0; i < last; ++i) {
+ nsCOMPtr<nsISeekableStream> stream(do_QueryElementAt(&mStreams, i));
+ NS_ENSURE_TRUE(stream, NS_ERROR_NO_INTERFACE);
+
+ PRInt64 pos;
+ rv = stream->Tell(&pos);
+ NS_ENSURE_SUCCESS(rv, rv);
+ ret64 += pos;
+ }
+ *_retval = ret64;
+
+ return NS_OK;
+}
+
+/* void setEOF (); */
+NS_IMETHODIMP
+nsMultiplexInputStream::SetEOF()
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_METHOD
+nsMultiplexInputStreamConstructor(nsISupports *outer,
+ REFNSIID iid,
+ void **result)
+{
+ *result = nsnull;
+
+ if (outer)
+ return NS_ERROR_NO_AGGREGATION;
+
+ nsMultiplexInputStream *inst;
+ NS_NEWXPCOM(inst, nsMultiplexInputStream);
+ if (!inst)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(inst);
+ nsresult rv = inst->QueryInterface(iid, result);
+ NS_RELEASE(inst);
+
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsMultiplexInputStream.h b/src/libs/xpcom18a4/xpcom/io/nsMultiplexInputStream.h
new file mode 100644
index 00000000..32d3026d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsMultiplexInputStream.h
@@ -0,0 +1,63 @@
+/* -*- 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 frightening to behold.
+ *
+ * The Initial Developer of the Original Code is
+ * Jonas Sicking.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Jonas Sicking <sicking@bigfoot.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 ***** */
+
+/**
+ * The multiplex stream concatinates a list of input streams into a single
+ * stream.
+ */
+
+#ifndef _nsMultiplexInputStream_h_
+#define _nsMultiplexInputStream_h_
+
+#include "nsIMultiplexInputStream.h"
+
+#define NS_MULTIPLEXINPUTSTREAM_CLASSNAME "nsMultiplexInputStream"
+#define NS_MULTIPLEXINPUTSTREAM_CONTRACTID "@mozilla.org/io/multiplex-input-stream;1"
+#define NS_MULTIPLEXINPUTSTREAM_CID \
+{ /* 565e3a2c-1dd2-11b2-8da1-b4cef17e568d */ \
+ 0x565e3a2c, \
+ 0x1dd2, \
+ 0x11b2, \
+ {0x8d, 0xa1, 0xb4, 0xce, 0xf1, 0x7e, 0x56, 0x8d} \
+}
+
+extern NS_METHOD nsMultiplexInputStreamConstructor(nsISupports *outer,
+ REFNSIID iid,
+ void **result);
+
+#endif // _nsMultiplexInputStream_h_
diff --git a/src/libs/xpcom18a4/xpcom/io/nsNativeCharsetUtils.cpp b/src/libs/xpcom18a4/xpcom/io/nsNativeCharsetUtils.cpp
new file mode 100644
index 00000000..55b5c63c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsNativeCharsetUtils.cpp
@@ -0,0 +1,1280 @@
+/* ***** 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.
+ *
+ * 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):
+ * Darin Fisher <darin@netscape.com>
+ * Brian Stell <bstell@ix.netcom.com>
+ * Frank Tang <ftang@netscape.com>
+ * Brendan Eich <brendan@mozilla.org>
+ * Sergei Dolgov <sergei_d@fi.fi.tartu.ee>
+ *
+ * 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 "xpcom-private.h"
+
+//-----------------------------------------------------------------------------
+// XP_UNIX
+//-----------------------------------------------------------------------------
+#if defined(XP_UNIX)
+
+#include <stdlib.h> // mbtowc, wctomb
+#include <locale.h> // setlocale
+#include "nscore.h"
+#include "prlock.h"
+#include "nsAString.h"
+#include "nsReadableUtils.h"
+
+//
+// choose a conversion library. we used to use mbrtowc/wcrtomb under Linux,
+// but that doesn't work for non-BMP characters whether we use '-fshort-wchar'
+// or not (see bug 206811 and
+// news://news.mozilla.org:119/bajml3$fvr1@ripley.netscape.com). we now use
+// iconv for all platforms where nltypes.h and nllanginfo.h are present
+// along with iconv.
+//
+#if defined(HAVE_ICONV) && defined(HAVE_NL_TYPES_H) && defined(HAVE_LANGINFO_CODESET)
+#define USE_ICONV 1
+#else
+#define USE_STDCONV 1
+#endif
+
+static void
+isolatin1_to_utf16(const char **input, PRUint32 *inputLeft, PRUnichar **output, PRUint32 *outputLeft)
+{
+ while (*inputLeft && *outputLeft) {
+ **output = (unsigned char) **input;
+ (*input)++;
+ (*inputLeft)--;
+ (*output)++;
+ (*outputLeft)--;
+ }
+}
+
+static void
+utf16_to_isolatin1(const PRUnichar **input, PRUint32 *inputLeft, char **output, PRUint32 *outputLeft)
+{
+ while (*inputLeft && *outputLeft) {
+ **output = (unsigned char) **input;
+ (*input)++;
+ (*inputLeft)--;
+ (*output)++;
+ (*outputLeft)--;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// conversion using iconv
+//-----------------------------------------------------------------------------
+#if defined(USE_ICONV)
+#include <nl_types.h> // CODESET
+#include <langinfo.h> // nl_langinfo
+#include <iconv.h> // iconv_open, iconv, iconv_close
+#include <errno.h>
+
+#if defined(HAVE_ICONV_WITH_CONST_INPUT)
+#define ICONV_INPUT(x) (x)
+#else
+#define ICONV_INPUT(x) ((char **)x)
+#endif
+
+// solaris definitely needs this, but we'll enable it by default
+// just in case... but we know for sure that iconv(3) in glibc
+// doesn't need this.
+#if !defined(__GLIBC__)
+#define ENABLE_UTF8_FALLBACK_SUPPORT
+#endif
+
+#define INVALID_ICONV_T ((iconv_t) -1)
+
+static inline size_t
+xp_iconv(iconv_t converter,
+ const char **input,
+ size_t *inputLeft,
+ char **output,
+ size_t *outputLeft)
+{
+ size_t res, outputAvail = outputLeft ? *outputLeft : 0;
+ res = iconv(converter, ICONV_INPUT(input), inputLeft, output, outputLeft);
+ if (res == (size_t) -1) {
+ // on some platforms (e.g., linux) iconv will fail with
+ // E2BIG if it cannot convert _all_ of its input. it'll
+ // still adjust all of the in/out params correctly, so we
+ // can ignore this error. the assumption is that we will
+ // be called again to complete the conversion.
+ if ((errno == E2BIG) && (*outputLeft < outputAvail))
+ res = 0;
+ }
+ return res;
+}
+
+static inline void
+xp_iconv_reset(iconv_t converter)
+{
+ // NOTE: the man pages on Solaris claim that you can pass NULL
+ // for all parameter to reset the converter, but beware the
+ // evil Solaris crash if you go down this route >:-)
+
+ const char *zero_char_in_ptr = NULL;
+ char *zero_char_out_ptr = NULL;
+ size_t zero_size_in = 0,
+ zero_size_out = 0;
+
+ xp_iconv(converter, &zero_char_in_ptr,
+ &zero_size_in,
+ &zero_char_out_ptr,
+ &zero_size_out);
+}
+
+static inline iconv_t
+xp_iconv_open(const char **to_list, const char **from_list)
+{
+ iconv_t res;
+ const char **from_name;
+ const char **to_name;
+
+ // try all possible combinations to locate a converter.
+ to_name = to_list;
+ while (*to_name) {
+ if (**to_name) {
+ from_name = from_list;
+ while (*from_name) {
+ if (**from_name) {
+ res = iconv_open(*to_name, *from_name);
+ if (res != INVALID_ICONV_T)
+ return res;
+ }
+ from_name++;
+ }
+ }
+ to_name++;
+ }
+
+ return INVALID_ICONV_T;
+}
+
+/*
+ * PRUnichar[] is NOT a UCS-2 array BUT a UTF-16 string. Therefore, we
+ * have to use UTF-16 with iconv(3) on platforms where it's supported.
+ * However, the way UTF-16 and UCS-2 are interpreted varies across platforms
+ * and implementations of iconv(3). On Tru64, it also depends on the environment
+ * variable. To avoid the trouble arising from byte-swapping
+ * (bug 208809), we have to try UTF-16LE/BE and UCS-2LE/BE before falling
+ * back to UTF-16 and UCS-2 and variants. We assume that UTF-16 and UCS-2
+ * on systems without UTF-16LE/BE and UCS-2LE/BE have the native endianness,
+ * which isn't the case of glibc 2.1.x, for which we use 'UNICODELITTLE'
+ * and 'UNICODEBIG'. It's also not true of Tru64 V4 when the environment
+ * variable ICONV_BYTEORDER is set to 'big-endian', about which not much
+ * can be done other than adding a note in the release notes. (bug 206811)
+ */
+static const char *UTF_16_NAMES[] = {
+#if defined(IS_LITTLE_ENDIAN)
+ "UTF-16LE",
+#if defined(__GLIBC__)
+ "UNICODELITTLE",
+#endif
+ "UCS-2LE",
+#else
+ "UTF-16BE",
+#if defined(__GLIBC__)
+ "UNICODEBIG",
+#endif
+ "UCS-2BE",
+#endif
+ "UTF-16",
+ "UCS-2",
+ "UCS2",
+ "UCS_2",
+ "ucs-2",
+ "ucs2",
+ "ucs_2",
+ NULL
+};
+
+#if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
+static const char *UTF_8_NAMES[] = {
+ "UTF-8",
+ "UTF8",
+ "UTF_8",
+ "utf-8",
+ "utf8",
+ "utf_8",
+ NULL
+};
+#endif
+
+static const char *ISO_8859_1_NAMES[] = {
+ "ISO-8859-1",
+#if !defined(__GLIBC__)
+ "ISO8859-1",
+ "ISO88591",
+ "ISO_8859_1",
+ "ISO8859_1",
+ "iso-8859-1",
+ "iso8859-1",
+ "iso88591",
+ "iso_8859_1",
+ "iso8859_1",
+#endif
+ NULL
+};
+
+class nsNativeCharsetConverter
+{
+public:
+ nsNativeCharsetConverter();
+ ~nsNativeCharsetConverter();
+
+ nsresult NativeToUnicode(const char **input , PRUint32 *inputLeft,
+ PRUnichar **output, PRUint32 *outputLeft);
+ nsresult UnicodeToNative(const PRUnichar **input , PRUint32 *inputLeft,
+ char **output, PRUint32 *outputLeft);
+
+ static void GlobalInit();
+ static void GlobalShutdown();
+
+private:
+ static iconv_t gNativeToUnicode;
+ static iconv_t gUnicodeToNative;
+#if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
+ static iconv_t gNativeToUTF8;
+ static iconv_t gUTF8ToNative;
+ static iconv_t gUnicodeToUTF8;
+ static iconv_t gUTF8ToUnicode;
+#endif
+ static PRLock *gLock;
+ static PRBool gInitialized;
+
+ static void LazyInit();
+
+ static void Lock() { if (gLock) PR_Lock(gLock); }
+ static void Unlock() { if (gLock) PR_Unlock(gLock); }
+};
+
+iconv_t nsNativeCharsetConverter::gNativeToUnicode = INVALID_ICONV_T;
+iconv_t nsNativeCharsetConverter::gUnicodeToNative = INVALID_ICONV_T;
+#if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
+iconv_t nsNativeCharsetConverter::gNativeToUTF8 = INVALID_ICONV_T;
+iconv_t nsNativeCharsetConverter::gUTF8ToNative = INVALID_ICONV_T;
+iconv_t nsNativeCharsetConverter::gUnicodeToUTF8 = INVALID_ICONV_T;
+iconv_t nsNativeCharsetConverter::gUTF8ToUnicode = INVALID_ICONV_T;
+#endif
+PRLock *nsNativeCharsetConverter::gLock = nsnull;
+PRBool nsNativeCharsetConverter::gInitialized = PR_FALSE;
+
+void
+nsNativeCharsetConverter::LazyInit()
+{
+ const char *blank_list[] = { "", NULL };
+ const char **native_charset_list = blank_list;
+ const char *native_charset = nl_langinfo(CODESET);
+ if (native_charset == nsnull) {
+ NS_ERROR("native charset is unknown");
+ // fallback to ISO-8859-1
+ native_charset_list = ISO_8859_1_NAMES;
+ }
+ else
+ native_charset_list[0] = native_charset;
+
+ gNativeToUnicode = xp_iconv_open(UTF_16_NAMES, native_charset_list);
+ gUnicodeToNative = xp_iconv_open(native_charset_list, UTF_16_NAMES);
+
+#if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
+ if (gNativeToUnicode == INVALID_ICONV_T) {
+ gNativeToUTF8 = xp_iconv_open(UTF_8_NAMES, native_charset_list);
+ gUTF8ToUnicode = xp_iconv_open(UTF_16_NAMES, UTF_8_NAMES);
+ NS_ASSERTION(gNativeToUTF8 != INVALID_ICONV_T, "no native to utf-8 converter");
+ NS_ASSERTION(gUTF8ToUnicode != INVALID_ICONV_T, "no utf-8 to utf-16 converter");
+ }
+ if (gUnicodeToNative == INVALID_ICONV_T) {
+ gUnicodeToUTF8 = xp_iconv_open(UTF_8_NAMES, UTF_16_NAMES);
+ gUTF8ToNative = xp_iconv_open(native_charset_list, UTF_8_NAMES);
+ NS_ASSERTION(gUnicodeToUTF8 != INVALID_ICONV_T, "no utf-16 to utf-8 converter");
+ NS_ASSERTION(gUTF8ToNative != INVALID_ICONV_T, "no utf-8 to native converter");
+ }
+#else
+ NS_ASSERTION(gNativeToUnicode != INVALID_ICONV_T, "no native to utf-16 converter");
+ NS_ASSERTION(gUnicodeToNative != INVALID_ICONV_T, "no utf-16 to native converter");
+#endif
+
+ /*
+ * On Solaris 8 (and newer?), the iconv modules converting to UCS-2
+ * prepend a byte order mark unicode character (BOM, u+FEFF) during
+ * the first use of the iconv converter. The same is the case of
+ * glibc 2.2.9x and Tru64 V5 (see bug 208809) when 'UTF-16' is used.
+ * However, we use 'UTF-16LE/BE' in both cases, instead so that we
+ * should be safe. But just in case...
+ *
+ * This dummy conversion gets rid of the BOMs and fixes bug 153562.
+ */
+ char dummy_input[1] = { ' ' };
+ char dummy_output[4];
+
+ if (gNativeToUnicode != INVALID_ICONV_T) {
+ const char *input = dummy_input;
+ size_t input_left = sizeof(dummy_input);
+ char *output = dummy_output;
+ size_t output_left = sizeof(dummy_output);
+
+ xp_iconv(gNativeToUnicode, &input, &input_left, &output, &output_left);
+ }
+#if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
+ if (gUTF8ToUnicode != INVALID_ICONV_T) {
+ const char *input = dummy_input;
+ size_t input_left = sizeof(dummy_input);
+ char *output = dummy_output;
+ size_t output_left = sizeof(dummy_output);
+
+ xp_iconv(gUTF8ToUnicode, &input, &input_left, &output, &output_left);
+ }
+#endif
+
+ gInitialized = PR_TRUE;
+}
+
+void
+nsNativeCharsetConverter::GlobalInit()
+{
+ gLock = PR_NewLock();
+ NS_ASSERTION(gLock, "lock creation failed");
+}
+
+void
+nsNativeCharsetConverter::GlobalShutdown()
+{
+ if (gLock) {
+ PR_DestroyLock(gLock);
+ gLock = nsnull;
+ }
+
+ if (gNativeToUnicode != INVALID_ICONV_T) {
+ iconv_close(gNativeToUnicode);
+ gNativeToUnicode = INVALID_ICONV_T;
+ }
+
+ if (gUnicodeToNative != INVALID_ICONV_T) {
+ iconv_close(gUnicodeToNative);
+ gUnicodeToNative = INVALID_ICONV_T;
+ }
+
+#if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
+ if (gNativeToUTF8 != INVALID_ICONV_T) {
+ iconv_close(gNativeToUTF8);
+ gNativeToUTF8 = INVALID_ICONV_T;
+ }
+ if (gUTF8ToNative != INVALID_ICONV_T) {
+ iconv_close(gUTF8ToNative);
+ gUTF8ToNative = INVALID_ICONV_T;
+ }
+ if (gUnicodeToUTF8 != INVALID_ICONV_T) {
+ iconv_close(gUnicodeToUTF8);
+ gUnicodeToUTF8 = INVALID_ICONV_T;
+ }
+ if (gUTF8ToUnicode != INVALID_ICONV_T) {
+ iconv_close(gUTF8ToUnicode);
+ gUTF8ToUnicode = INVALID_ICONV_T;
+ }
+#endif
+
+ gInitialized = PR_FALSE;
+}
+
+nsNativeCharsetConverter::nsNativeCharsetConverter()
+{
+ Lock();
+ if (!gInitialized)
+ LazyInit();
+}
+
+nsNativeCharsetConverter::~nsNativeCharsetConverter()
+{
+ // reset converters for next time
+ if (gNativeToUnicode != INVALID_ICONV_T)
+ xp_iconv_reset(gNativeToUnicode);
+ if (gUnicodeToNative != INVALID_ICONV_T)
+ xp_iconv_reset(gUnicodeToNative);
+#if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
+ if (gNativeToUTF8 != INVALID_ICONV_T)
+ xp_iconv_reset(gNativeToUTF8);
+ if (gUTF8ToNative != INVALID_ICONV_T)
+ xp_iconv_reset(gUTF8ToNative);
+ if (gUnicodeToUTF8 != INVALID_ICONV_T)
+ xp_iconv_reset(gUnicodeToUTF8);
+ if (gUTF8ToUnicode != INVALID_ICONV_T)
+ xp_iconv_reset(gUTF8ToUnicode);
+#endif
+ Unlock();
+}
+
+nsresult
+nsNativeCharsetConverter::NativeToUnicode(const char **input,
+ PRUint32 *inputLeft,
+ PRUnichar **output,
+ PRUint32 *outputLeft)
+{
+ size_t res = 0;
+ size_t inLeft = (size_t) *inputLeft;
+ size_t outLeft = (size_t) *outputLeft * 2;
+
+ if (gNativeToUnicode != INVALID_ICONV_T) {
+
+ res = xp_iconv(gNativeToUnicode, input, &inLeft, (char **) output, &outLeft);
+
+ *inputLeft = inLeft;
+ *outputLeft = outLeft / 2;
+ if (res != (size_t) -1)
+ return NS_OK;
+
+ NS_WARNING("conversion from native to utf-16 failed");
+
+ // reset converter
+ xp_iconv_reset(gNativeToUnicode);
+ }
+#if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
+ else if ((gNativeToUTF8 != INVALID_ICONV_T) &&
+ (gUTF8ToUnicode != INVALID_ICONV_T)) {
+ // convert first to UTF8, then from UTF8 to UCS2
+ const char *in = *input;
+
+ char ubuf[1024];
+
+ // we assume we're always called with enough space in |output|,
+ // so convert many chars at a time...
+ while (inLeft) {
+ char *p = ubuf;
+ size_t n = sizeof(ubuf);
+ res = xp_iconv(gNativeToUTF8, &in, &inLeft, &p, &n);
+ if (res == (size_t) -1) {
+ NS_ERROR("conversion from native to utf-8 failed");
+ break;
+ }
+ NS_ASSERTION(outLeft > 0, "bad assumption");
+ p = ubuf;
+ n = sizeof(ubuf) - n;
+ res = xp_iconv(gUTF8ToUnicode, (const char **) &p, &n, (char **) output, &outLeft);
+ if (res == (size_t) -1) {
+ NS_ERROR("conversion from utf-8 to utf-16 failed");
+ break;
+ }
+ }
+
+ (*input) += (*inputLeft - inLeft);
+ *inputLeft = inLeft;
+ *outputLeft = outLeft / 2;
+
+ if (res != (size_t) -1)
+ return NS_OK;
+
+ // reset converters
+ xp_iconv_reset(gNativeToUTF8);
+ xp_iconv_reset(gUTF8ToUnicode);
+ }
+#endif
+
+ // fallback: zero-pad and hope for the best
+ // XXX This is lame and we have to do better.
+ isolatin1_to_utf16(input, inputLeft, output, outputLeft);
+
+ return NS_OK;
+}
+
+nsresult
+nsNativeCharsetConverter::UnicodeToNative(const PRUnichar **input,
+ PRUint32 *inputLeft,
+ char **output,
+ PRUint32 *outputLeft)
+{
+ size_t res = 0;
+ size_t inLeft = (size_t) *inputLeft * 2;
+ size_t outLeft = (size_t) *outputLeft;
+
+ if (gUnicodeToNative != INVALID_ICONV_T) {
+ res = xp_iconv(gUnicodeToNative, (const char **) input, &inLeft, output, &outLeft);
+
+ if (res != (size_t) -1) {
+ *inputLeft = inLeft / 2;
+ *outputLeft = outLeft;
+ return NS_OK;
+ }
+
+ NS_ERROR("iconv failed");
+
+ // reset converter
+ xp_iconv_reset(gUnicodeToNative);
+ }
+#if defined(ENABLE_UTF8_FALLBACK_SUPPORT)
+ else if ((gUnicodeToUTF8 != INVALID_ICONV_T) &&
+ (gUTF8ToNative != INVALID_ICONV_T)) {
+ const char *in = (const char *) *input;
+
+ char ubuf[6]; // max utf-8 char length (really only needs to be 4 bytes)
+
+ // convert one uchar at a time...
+ while (inLeft && outLeft) {
+ char *p = ubuf;
+ size_t n = sizeof(ubuf), one_uchar = sizeof(PRUnichar);
+ res = xp_iconv(gUnicodeToUTF8, &in, &one_uchar, &p, &n);
+ if (res == (size_t) -1) {
+ NS_ERROR("conversion from utf-16 to utf-8 failed");
+ break;
+ }
+ p = ubuf;
+ n = sizeof(ubuf) - n;
+ res = xp_iconv(gUTF8ToNative, (const char **) &p, &n, output, &outLeft);
+ if (res == (size_t) -1) {
+ if (errno == E2BIG) {
+ // not enough room for last uchar... back up and return.
+ in -= sizeof(PRUnichar);
+ res = 0;
+ }
+ else
+ NS_ERROR("conversion from utf-8 to native failed");
+ break;
+ }
+ inLeft -= sizeof(PRUnichar);
+ }
+
+ if (res != (size_t) -1) {
+ (*input) += (*inputLeft - inLeft/2);
+ *inputLeft = inLeft/2;
+ *outputLeft = outLeft;
+ return NS_OK;
+ }
+
+ // reset converters
+ xp_iconv_reset(gUnicodeToUTF8);
+ xp_iconv_reset(gUTF8ToNative);
+ }
+#endif
+
+ // fallback: truncate and hope for the best
+ utf16_to_isolatin1(input, inputLeft, output, outputLeft);
+
+ return NS_OK;
+}
+
+#endif // USE_ICONV
+
+//-----------------------------------------------------------------------------
+// conversion using mb[r]towc/wc[r]tomb
+//-----------------------------------------------------------------------------
+#if defined(USE_STDCONV)
+#if defined(HAVE_WCRTOMB) || defined(HAVE_MBRTOWC)
+#include <wchar.h> // mbrtowc, wcrtomb
+#endif
+
+class nsNativeCharsetConverter
+{
+public:
+ nsNativeCharsetConverter();
+
+ nsresult NativeToUnicode(const char **input , PRUint32 *inputLeft,
+ PRUnichar **output, PRUint32 *outputLeft);
+ nsresult UnicodeToNative(const PRUnichar **input , PRUint32 *inputLeft,
+ char **output, PRUint32 *outputLeft);
+
+ static void GlobalInit();
+ static void GlobalShutdown() { }
+
+private:
+ static PRBool gWCharIsUnicode;
+
+#if defined(HAVE_WCRTOMB) || defined(HAVE_MBRTOWC)
+ mbstate_t ps;
+#endif
+};
+
+PRBool nsNativeCharsetConverter::gWCharIsUnicode = PR_FALSE;
+
+nsNativeCharsetConverter::nsNativeCharsetConverter()
+{
+#if defined(HAVE_WCRTOMB) || defined(HAVE_MBRTOWC)
+ memset(&ps, 0, sizeof(ps));
+#endif
+}
+
+void
+nsNativeCharsetConverter::GlobalInit()
+{
+ // verify that wchar_t for the current locale is actually unicode.
+ // if it is not, then we should avoid calling mbtowc/wctomb and
+ // just fallback on zero-pad/truncation conversion.
+ //
+ // this test cannot be done at build time because the encoding of
+ // wchar_t may depend on the runtime locale. sad, but true!!
+ //
+ // so, if wchar_t is unicode then converting an ASCII character
+ // to wchar_t should not change its numeric value. we'll just
+ // check what happens with the ASCII 'a' character.
+ //
+ // this test is not perfect... obviously, it could yield false
+ // positives, but then at least ASCII text would be converted
+ // properly (or maybe just the 'a' character) -- oh well :(
+
+ char a = 'a';
+ unsigned int w = 0;
+
+ int res = mbtowc((wchar_t *) &w, &a, 1);
+
+ gWCharIsUnicode = (res != -1 && w == 'a');
+
+#ifdef DEBUG
+ if (!gWCharIsUnicode)
+ NS_WARNING("wchar_t is not unicode (unicode conversion will be lossy)");
+#endif
+}
+
+nsresult
+nsNativeCharsetConverter::NativeToUnicode(const char **input,
+ PRUint32 *inputLeft,
+ PRUnichar **output,
+ PRUint32 *outputLeft)
+{
+ if (gWCharIsUnicode) {
+ int incr;
+
+ // cannot use wchar_t here since it may have been redefined (e.g.,
+ // via -fshort-wchar). hopefully, sizeof(tmp) is sufficient XP.
+ unsigned int tmp = 0;
+ while (*inputLeft && *outputLeft) {
+#ifdef HAVE_MBRTOWC
+ incr = (int) mbrtowc((wchar_t *) &tmp, *input, *inputLeft, &ps);
+#else
+ // XXX is this thread-safe?
+ incr = (int) mbtowc((wchar_t *) &tmp, *input, *inputLeft);
+#endif
+ if (incr < 0) {
+ NS_WARNING("mbtowc failed: possible charset mismatch");
+ // zero-pad and hope for the best
+ tmp = (unsigned char) **input;
+ incr = 1;
+ }
+ **output = (PRUnichar) tmp;
+ (*input) += incr;
+ (*inputLeft) -= incr;
+ (*output)++;
+ (*outputLeft)--;
+ }
+ }
+ else {
+ // wchar_t isn't unicode, so the best we can do is treat the
+ // input as if it is isolatin1 :(
+ isolatin1_to_utf16(input, inputLeft, output, outputLeft);
+ }
+
+ return NS_OK;
+}
+
+nsresult
+nsNativeCharsetConverter::UnicodeToNative(const PRUnichar **input,
+ PRUint32 *inputLeft,
+ char **output,
+ PRUint32 *outputLeft)
+{
+ if (gWCharIsUnicode) {
+ int incr;
+
+ while (*inputLeft && *outputLeft >= MB_CUR_MAX) {
+#ifdef HAVE_WCRTOMB
+ incr = (int) wcrtomb(*output, (wchar_t) **input, &ps);
+#else
+ // XXX is this thread-safe?
+ incr = (int) wctomb(*output, (wchar_t) **input);
+#endif
+ if (incr < 0) {
+ NS_WARNING("mbtowc failed: possible charset mismatch");
+ **output = (unsigned char) **input; // truncate
+ incr = 1;
+ }
+ // most likely we're dead anyways if this assertion should fire
+ NS_ASSERTION(PRUint32(incr) <= *outputLeft, "wrote beyond end of string");
+ (*output) += incr;
+ (*outputLeft) -= incr;
+ (*input)++;
+ (*inputLeft)--;
+ }
+ }
+ else {
+ // wchar_t isn't unicode, so the best we can do is treat the
+ // input as if it is isolatin1 :(
+ utf16_to_isolatin1(input, inputLeft, output, outputLeft);
+ }
+
+ return NS_OK;
+}
+
+#endif // USE_STDCONV
+
+//-----------------------------------------------------------------------------
+// API implementation
+//-----------------------------------------------------------------------------
+
+NS_COM nsresult
+NS_CopyNativeToUnicode(const nsACString &input, nsAString &output)
+{
+ output.Truncate();
+
+ PRUint32 inputLen = input.Length();
+
+ nsACString::const_iterator iter;
+ input.BeginReading(iter);
+
+ //
+ // OPTIMIZATION: preallocate space for largest possible result; convert
+ // directly into the result buffer to avoid intermediate buffer copy.
+ //
+ // this will generally result in a larger allocation, but that seems
+ // better than an extra buffer copy.
+ //
+ output.SetLength(inputLen);
+ nsAString::iterator out_iter;
+ output.BeginWriting(out_iter);
+
+ PRUnichar *result = out_iter.get();
+ PRUint32 resultLeft = inputLen;
+
+ const char *buf = iter.get();
+ PRUint32 bufLeft = inputLen;
+
+ nsNativeCharsetConverter conv;
+ nsresult rv = conv.NativeToUnicode(&buf, &bufLeft, &result, &resultLeft);
+ if (NS_SUCCEEDED(rv)) {
+ NS_ASSERTION(bufLeft == 0, "did not consume entire input buffer");
+ output.SetLength(inputLen - resultLeft);
+ }
+ return rv;
+}
+
+NS_COM nsresult
+NS_CopyUnicodeToNative(const nsAString &input, nsACString &output)
+{
+ output.Truncate();
+
+ nsAString::const_iterator iter, end;
+ input.BeginReading(iter);
+ input.EndReading(end);
+
+ // cannot easily avoid intermediate buffer copy.
+ char temp[4096];
+
+ nsNativeCharsetConverter conv;
+
+ const PRUnichar *buf = iter.get();
+ PRUint32 bufLeft = Distance(iter, end);
+ while (bufLeft) {
+ char *p = temp;
+ PRUint32 tempLeft = sizeof(temp);
+
+ nsresult rv = conv.UnicodeToNative(&buf, &bufLeft, &p, &tempLeft);
+ if (NS_FAILED(rv)) return rv;
+
+ if (tempLeft < sizeof(temp))
+ output.Append(temp, sizeof(temp) - tempLeft);
+ }
+ return NS_OK;
+}
+
+void
+NS_StartupNativeCharsetUtils()
+{
+ //
+ // need to initialize the locale or else charset conversion will fail.
+ // better not delay this in case some other component alters the locale
+ // settings.
+ //
+ // XXX we assume that we are called early enough that we should
+ // always be the first to care about the locale's charset.
+ //
+ setlocale(LC_CTYPE, "");
+
+ nsNativeCharsetConverter::GlobalInit();
+}
+
+void
+NS_ShutdownNativeCharsetUtils()
+{
+ nsNativeCharsetConverter::GlobalShutdown();
+}
+
+//-----------------------------------------------------------------------------
+// XP_BEOS
+//-----------------------------------------------------------------------------
+#elif defined(XP_BEOS)
+
+#include "nsAString.h"
+#include "nsReadableUtils.h"
+#include "nsString.h"
+
+NS_COM nsresult
+NS_CopyNativeToUnicode(const nsACString &input, nsAString &output)
+{
+ CopyUTF8toUTF16(input, output);
+ return NS_OK;
+}
+
+NS_COM nsresult
+NS_CopyUnicodeToNative(const nsAString &input, nsACString &output)
+{
+ CopyUTF16toUTF8(input, output);
+ return NS_OK;
+}
+
+void
+NS_StartupNativeCharsetUtils()
+{
+}
+
+void
+NS_ShutdownNativeCharsetUtils()
+{
+}
+
+//-----------------------------------------------------------------------------
+// XP_WIN
+//-----------------------------------------------------------------------------
+#elif defined(XP_WIN)
+
+#include <windows.h>
+#include "nsAString.h"
+
+NS_COM nsresult
+NS_CopyNativeToUnicode(const nsACString &input, nsAString &output)
+{
+ PRUint32 inputLen = input.Length();
+
+ nsACString::const_iterator iter;
+ input.BeginReading(iter);
+
+ const char *buf = iter.get();
+
+ // determine length of result
+ PRUint32 resultLen = 0;
+ int n = ::MultiByteToWideChar(CP_ACP, 0, buf, inputLen, NULL, 0);
+ if (n > 0)
+ resultLen += n;
+
+ // allocate sufficient space
+ output.SetLength(resultLen);
+ if (resultLen > 0) {
+ nsAString::iterator out_iter;
+ output.BeginWriting(out_iter);
+
+ PRUnichar *result = out_iter.get();
+
+ ::MultiByteToWideChar(CP_ACP, 0, buf, inputLen, result, resultLen);
+ }
+ return NS_OK;
+}
+
+NS_COM nsresult
+NS_CopyUnicodeToNative(const nsAString &input, nsACString &output)
+{
+ PRUint32 inputLen = input.Length();
+
+ nsAString::const_iterator iter;
+ input.BeginReading(iter);
+
+ const PRUnichar *buf = iter.get();
+
+ // determine length of result
+ PRUint32 resultLen = 0;
+
+ int n = ::WideCharToMultiByte(CP_ACP, 0, buf, inputLen, NULL, 0, NULL, NULL);
+ if (n > 0)
+ resultLen += n;
+
+ // allocate sufficient space
+ output.SetLength(resultLen);
+ if (resultLen > 0) {
+ nsACString::iterator out_iter;
+ output.BeginWriting(out_iter);
+
+ // default "defaultChar" is '?', which is an illegal character on windows
+ // file system. That will cause file uncreatable. Change it to '_'
+ const char defaultChar = '_';
+
+ char *result = out_iter.get();
+
+ ::WideCharToMultiByte(CP_ACP, 0, buf, inputLen, result, resultLen,
+ &defaultChar, NULL);
+ }
+ return NS_OK;
+}
+
+void
+NS_StartupNativeCharsetUtils()
+{
+}
+
+void
+NS_ShutdownNativeCharsetUtils()
+{
+}
+
+//-----------------------------------------------------------------------------
+// XP_OS2
+//-----------------------------------------------------------------------------
+#elif defined(XP_OS2)
+
+#define INCL_DOS
+#include <os2.h>
+#include <uconv.h>
+#include "nsAString.h"
+#include <ulserrno.h>
+#include "nsNativeCharsetUtils.h"
+
+static UconvObject UnicodeConverter = NULL;
+
+NS_COM nsresult
+NS_CopyNativeToUnicode(const nsACString &input, nsAString &output)
+{
+ PRUint32 inputLen = input.Length();
+
+ nsACString::const_iterator iter;
+ input.BeginReading(iter);
+ const char *inputStr = iter.get();
+
+ // determine length of result
+ PRUint32 resultLen = inputLen;
+ output.SetLength(resultLen);
+
+ nsAString::iterator out_iter;
+ output.BeginWriting(out_iter);
+ UniChar *result = (UniChar*)out_iter.get();
+
+ size_t cSubs = 0;
+ size_t resultLeft = resultLen;
+
+ if (!UnicodeConverter)
+ NS_StartupNativeCharsetUtils();
+
+ int unirc = ::UniUconvToUcs(UnicodeConverter, (void**)&inputStr, &inputLen,
+ &result, &resultLeft, &cSubs);
+
+ NS_ASSERTION(unirc != UCONV_E2BIG, "Path too big");
+
+ if (unirc != ULS_SUCCESS) {
+ output.Truncate();
+ return NS_ERROR_FAILURE;
+ }
+
+ // Need to update string length to reflect how many bytes were actually
+ // written.
+ output.Truncate(resultLen - resultLeft);
+ return NS_OK;
+}
+
+NS_COM nsresult
+NS_CopyUnicodeToNative(const nsAString &input, nsACString &output)
+{
+ size_t inputLen = input.Length();
+
+ nsAString::const_iterator iter;
+ input.BeginReading(iter);
+ UniChar* inputStr = (UniChar*) NS_CONST_CAST(PRUnichar*, iter.get());
+
+ // maximum length of unicode string of length x converted to native
+ // codepage is x*2
+ size_t resultLen = inputLen * 2;
+ output.SetLength(resultLen);
+
+ nsACString::iterator out_iter;
+ output.BeginWriting(out_iter);
+ char *result = out_iter.get();
+
+ size_t cSubs = 0;
+ size_t resultLeft = resultLen;
+
+ if (!UnicodeConverter)
+ NS_StartupNativeCharsetUtils();
+
+ int unirc = ::UniUconvFromUcs(UnicodeConverter, &inputStr, &inputLen,
+ (void**)&result, &resultLeft, &cSubs);
+
+ NS_ASSERTION(unirc != UCONV_E2BIG, "Path too big");
+
+ if (unirc != ULS_SUCCESS) {
+ output.Truncate();
+ return NS_ERROR_FAILURE;
+ }
+
+ // Need to update string length to reflect how many bytes were actually
+ // written.
+ output.Truncate(resultLen - resultLeft);
+ return NS_OK;
+}
+
+void
+NS_StartupNativeCharsetUtils()
+{
+ ULONG ulLength;
+ ULONG ulCodePage;
+ DosQueryCp(sizeof(ULONG), &ulCodePage, &ulLength);
+
+ UniChar codepage[20];
+ int unirc = ::UniMapCpToUcsCp(ulCodePage, codepage, 20);
+ if (unirc == ULS_SUCCESS) {
+ unirc = ::UniCreateUconvObject(codepage, &UnicodeConverter);
+ if (unirc == ULS_SUCCESS) {
+ uconv_attribute_t attr;
+ ::UniQueryUconvObject(UnicodeConverter, &attr, sizeof(uconv_attribute_t),
+ NULL, NULL, NULL);
+ attr.options = UCONV_OPTION_SUBSTITUTE_BOTH;
+ attr.subchar_len=1;
+ attr.subchar[0]='_';
+ ::UniSetUconvObject(UnicodeConverter, &attr);
+ }
+ }
+}
+
+void
+NS_ShutdownNativeCharsetUtils()
+{
+ ::UniFreeUconvObject(UnicodeConverter);
+}
+
+//-----------------------------------------------------------------------------
+// XP_MAC
+//-----------------------------------------------------------------------------
+#elif defined(XP_MAC)
+
+#include <UnicodeConverter.h>
+#include <TextCommon.h>
+#include <Script.h>
+#include <MacErrors.h>
+#include "nsAString.h"
+
+class nsFSStringConversionMac {
+public:
+ static nsresult UCSToFS(const nsAString& aIn, nsACString& aOut);
+ static nsresult FSToUCS(const nsACString& ain, nsAString& aOut);
+
+ static void CleanUp();
+
+private:
+ static TextEncoding GetSystemEncoding();
+ static nsresult PrepareEncoder();
+ static nsresult PrepareDecoder();
+
+ static UnicodeToTextInfo sEncoderInfo;
+ static TextToUnicodeInfo sDecoderInfo;
+};
+
+UnicodeToTextInfo nsFSStringConversionMac::sEncoderInfo = nsnull;
+TextToUnicodeInfo nsFSStringConversionMac::sDecoderInfo = nsnull;
+
+nsresult nsFSStringConversionMac::UCSToFS(const nsAString& aIn, nsACString& aOut)
+{
+ nsresult rv = PrepareEncoder();
+ if (NS_FAILED(rv)) return rv;
+
+ OSStatus err = noErr;
+ char stackBuffer[512];
+
+ aOut.Truncate();
+
+ // for each chunk of |aIn|...
+ nsReadingIterator<PRUnichar> iter;
+ aIn.BeginReading(iter);
+
+ PRUint32 fragmentLength = PRUint32(iter.size_forward());
+ UInt32 bytesLeft = fragmentLength * sizeof(UniChar);
+
+ do {
+ UInt32 bytesRead = 0, bytesWritten = 0;
+ err = ::ConvertFromUnicodeToText(sEncoderInfo,
+ bytesLeft,
+ (const UniChar*)iter.get(),
+ kUnicodeUseFallbacksMask | kUnicodeLooseMappingsMask,
+ 0, nsnull, nsnull, nsnull,
+ sizeof(stackBuffer),
+ &bytesRead,
+ &bytesWritten,
+ stackBuffer);
+ if (err == kTECUsedFallbacksStatus)
+ err = noErr;
+ else if (err == kTECOutputBufferFullStatus) {
+ bytesLeft -= bytesRead;
+ iter.advance(bytesRead / sizeof(UniChar));
+ }
+ aOut.Append(stackBuffer, bytesWritten);
+ }
+ while (err == kTECOutputBufferFullStatus);
+
+ return (err == noErr) ? NS_OK : NS_ERROR_FAILURE;
+}
+
+nsresult nsFSStringConversionMac::FSToUCS(const nsACString& aIn, nsAString& aOut)
+{
+ nsresult rv = PrepareDecoder();
+ if (NS_FAILED(rv)) return rv;
+
+ OSStatus err = noErr;
+ UniChar stackBuffer[512];
+
+ aOut.Truncate(0);
+
+ // for each chunk of |aIn|...
+ nsReadingIterator<char> iter;
+ aIn.BeginReading(iter);
+
+ PRUint32 fragmentLength = PRUint32(iter.size_forward());
+ UInt32 bytesLeft = fragmentLength;
+
+ do {
+ UInt32 bytesRead = 0, bytesWritten = 0;
+ err = ::ConvertFromTextToUnicode(sDecoderInfo,
+ bytesLeft,
+ iter.get(),
+ kUnicodeUseFallbacksMask | kUnicodeLooseMappingsMask,
+ 0, nsnull, nsnull, nsnull,
+ sizeof(stackBuffer),
+ &bytesRead,
+ &bytesWritten,
+ stackBuffer);
+ if (err == kTECUsedFallbacksStatus)
+ err = noErr;
+ else if (err == kTECOutputBufferFullStatus) {
+ bytesLeft -= bytesRead;
+ iter.advance(bytesRead);
+ }
+ aOut.Append((PRUnichar *)stackBuffer, bytesWritten / sizeof(PRUnichar));
+ }
+ while (err == kTECOutputBufferFullStatus);
+
+ return (err == noErr) ? NS_OK : NS_ERROR_FAILURE;
+}
+
+void nsFSStringConversionMac::CleanUp()
+{
+ if (sDecoderInfo) {
+ ::DisposeTextToUnicodeInfo(&sDecoderInfo);
+ sDecoderInfo = nsnull;
+ }
+ if (sEncoderInfo) {
+ ::DisposeUnicodeToTextInfo(&sEncoderInfo);
+ sEncoderInfo = nsnull;
+ }
+}
+
+TextEncoding nsFSStringConversionMac::GetSystemEncoding()
+{
+ OSStatus err;
+ TextEncoding theEncoding;
+
+ err = ::UpgradeScriptInfoToTextEncoding(smSystemScript, kTextLanguageDontCare,
+ kTextRegionDontCare, NULL, &theEncoding);
+
+ if (err != noErr)
+ theEncoding = kTextEncodingMacRoman;
+
+ return theEncoding;
+}
+
+nsresult nsFSStringConversionMac::PrepareEncoder()
+{
+ nsresult rv = NS_OK;
+ if (!sEncoderInfo) {
+ OSStatus err;
+ err = ::CreateUnicodeToTextInfoByEncoding(GetSystemEncoding(), &sEncoderInfo);
+ if (err)
+ rv = NS_ERROR_FAILURE;
+ }
+ return rv;
+}
+
+nsresult nsFSStringConversionMac::PrepareDecoder()
+{
+ nsresult rv = NS_OK;
+ if (!sDecoderInfo) {
+ OSStatus err;
+ err = ::CreateTextToUnicodeInfoByEncoding(GetSystemEncoding(), &sDecoderInfo);
+ if (err)
+ rv = NS_ERROR_FAILURE;
+ }
+ return rv;
+}
+
+NS_COM nsresult
+NS_CopyNativeToUnicode(const nsACString &input, nsAString &output)
+{
+ return nsFSStringConversionMac::FSToUCS(input, output);
+}
+
+NS_COM nsresult
+NS_CopyUnicodeToNative(const nsAString &input, nsACString &output)
+{
+ return nsFSStringConversionMac::UCSToFS(input, output);
+}
+
+void
+NS_StartupNativeCharsetUtils()
+{
+}
+
+void
+NS_ShutdownNativeCharsetUtils()
+{
+ nsFSStringConversionMac::CleanUp();
+}
+
+//-----------------------------------------------------------------------------
+// default : truncate/zeropad
+//-----------------------------------------------------------------------------
+#else
+
+#include "nsReadableUtils.h"
+
+NS_COM nsresult
+NS_CopyNativeToUnicode(const nsACString &input, nsAString &output)
+{
+ CopyASCIItoUCS2(input, output);
+ return NS_OK;
+}
+
+NS_COM nsresult
+NS_CopyUnicodeToNative(const nsAString &input, nsACString &output)
+{
+ CopyUCS2toASCII(input, output);
+ return NS_OK;
+}
+
+void
+NS_StartupNativeCharsetUtils()
+{
+}
+
+void
+NS_ShutdownNativeCharsetUtils()
+{
+}
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/io/nsNativeCharsetUtils.h b/src/libs/xpcom18a4/xpcom/io/nsNativeCharsetUtils.h
new file mode 100644
index 00000000..539fa37f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsNativeCharsetUtils.h
@@ -0,0 +1,66 @@
+/* ***** 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.
+ *
+ * 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):
+ * Darin Fisher <darin@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 nsNativeCharsetUtils_h__
+#define nsNativeCharsetUtils_h__
+
+
+/*****************************************************************************\
+ * *
+ * **** NOTICE **** *
+ * *
+ * *** THESE ARE NOT GENERAL PURPOSE CONVERTERS *** *
+ * *
+ * NS_CopyNativeToUnicode / NS_CopyUnicodeToNative should only be used *
+ * for converting *FILENAMES* between native and unicode. They are not *
+ * designed or tested for general encoding converter use. *
+ * *
+\*****************************************************************************/
+
+/**
+ * thread-safe conversion routines that do not depend on uconv libraries.
+ */
+NS_COM nsresult NS_CopyNativeToUnicode(const nsACString &input, nsAString &output);
+NS_COM nsresult NS_CopyUnicodeToNative(const nsAString &input, nsACString &output);
+
+/**
+ * internal
+ */
+void NS_StartupNativeCharsetUtils();
+void NS_ShutdownNativeCharsetUtils();
+
+#endif // nsNativeCharsetUtils_h__
diff --git a/src/libs/xpcom18a4/xpcom/io/nsPipe3.cpp b/src/libs/xpcom18a4/xpcom/io/nsPipe3.cpp
new file mode 100644
index 00000000..be06179f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsPipe3.cpp
@@ -0,0 +1,1276 @@
+/* ***** 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.
+ *
+ * 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):
+ * Darin Fisher <darin@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 "nsIPipe.h"
+#include "nsIEventTarget.h"
+#include "nsISeekableStream.h"
+#include "nsSegmentedBuffer.h"
+#include "nsStreamUtils.h"
+#include "nsAutoLock.h"
+#include "nsCOMPtr.h"
+#include "nsCRT.h"
+#include "prlog.h"
+#include "nsInt64.h"
+
+#if defined(PR_LOGGING)
+//
+// set NSPR_LOG_MODULES=nsPipe:5
+//
+static PRLogModuleInfo *gPipeLog = nsnull;
+#define LOG(args) PR_LOG(gPipeLog, PR_LOG_DEBUG, args)
+#else
+#define LOG(args)
+#endif
+
+#define DEFAULT_SEGMENT_SIZE 4096
+#define DEFAULT_SEGMENT_COUNT 16
+
+class nsPipe;
+class nsPipeEvents;
+class nsPipeInputStream;
+class nsPipeOutputStream;
+
+//-----------------------------------------------------------------------------
+
+// this class is used to delay notifications until the end of a particular
+// scope. it helps avoid the complexity of issuing callbacks while inside
+// a critical section.
+class nsPipeEvents
+{
+public:
+ nsPipeEvents() { }
+ ~nsPipeEvents();
+
+ inline void NotifyInputReady(nsIAsyncInputStream *stream,
+ nsIInputStreamCallback *callback)
+ {
+ NS_ASSERTION(!mInputCallback, "already have an input event");
+ mInputStream = stream;
+ mInputCallback = callback;
+ }
+
+ inline void NotifyOutputReady(nsIAsyncOutputStream *stream,
+ nsIOutputStreamCallback *callback)
+ {
+ NS_ASSERTION(!mOutputCallback, "already have an output event");
+ mOutputStream = stream;
+ mOutputCallback = callback;
+ }
+
+private:
+ nsCOMPtr<nsIAsyncInputStream> mInputStream;
+ nsCOMPtr<nsIInputStreamCallback> mInputCallback;
+ nsCOMPtr<nsIAsyncOutputStream> mOutputStream;
+ nsCOMPtr<nsIOutputStreamCallback> mOutputCallback;
+};
+
+//-----------------------------------------------------------------------------
+
+// the input end of a pipe (allocated as a member of the pipe).
+class nsPipeInputStream : public nsIAsyncInputStream
+ , public nsISeekableStream
+ , public nsISearchableInputStream
+{
+public:
+ // since this class will be allocated as a member of the pipe, we do not
+ // need our own ref count. instead, we share the lifetime (the ref count)
+ // of the entire pipe. this macro is just convenience since it does not
+ // declare a mRefCount variable; however, don't let the name fool you...
+ // we are not inheriting from nsPipe ;-)
+ NS_DECL_ISUPPORTS_INHERITED
+
+ NS_DECL_NSIINPUTSTREAM
+ NS_DECL_NSIASYNCINPUTSTREAM
+ NS_DECL_NSISEEKABLESTREAM
+ NS_DECL_NSISEARCHABLEINPUTSTREAM
+
+ nsPipeInputStream(nsPipe *pipe)
+ : mPipe(pipe)
+ , mReaderRefCnt(0)
+ , mLogicalOffset(0)
+ , mBlocking(PR_TRUE)
+ , mBlocked(PR_FALSE)
+ , mAvailable(0)
+ , mCallbackFlags(0)
+ { }
+
+ nsresult Fill();
+ void SetNonBlocking(PRBool aNonBlocking) { mBlocking = !aNonBlocking; }
+
+ PRUint32 Available() { return mAvailable; }
+ void ReduceAvailable(PRUint32 avail) { mAvailable -= avail; }
+
+ // synchronously wait for the pipe to become readable.
+ nsresult Wait();
+
+ // these functions return true to indicate that the pipe's monitor should
+ // be notified, to wake up a blocked reader if any.
+ PRBool OnInputReadable(PRUint32 bytesWritten, nsPipeEvents &);
+ PRBool OnInputException(nsresult, nsPipeEvents &);
+
+private:
+ nsPipe *mPipe;
+
+ // separate refcnt so that we know when to close the consumer
+ nsrefcnt mReaderRefCnt;
+ nsInt64 mLogicalOffset;
+ PRPackedBool mBlocking;
+
+ // these variables can only be accessed while inside the pipe's monitor
+ PRPackedBool mBlocked;
+ PRUint32 mAvailable;
+ nsCOMPtr<nsIInputStreamCallback> mCallback;
+ PRUint32 mCallbackFlags;
+};
+
+//-----------------------------------------------------------------------------
+
+// the output end of a pipe (allocated as a member of the pipe).
+class nsPipeOutputStream : public nsIAsyncOutputStream
+ , public nsISeekableStream
+{
+public:
+ // since this class will be allocated as a member of the pipe, we do not
+ // need our own ref count. instead, we share the lifetime (the ref count)
+ // of the entire pipe. this macro is just convenience since it does not
+ // declare a mRefCount variable; however, don't let the name fool you...
+ // we are not inheriting from nsPipe ;-)
+ NS_DECL_ISUPPORTS_INHERITED
+
+ NS_DECL_NSIOUTPUTSTREAM
+ NS_DECL_NSIASYNCOUTPUTSTREAM
+ NS_DECL_NSISEEKABLESTREAM
+
+ nsPipeOutputStream(nsPipe *pipe)
+ : mPipe(pipe)
+ , mWriterRefCnt(0)
+ , mLogicalOffset(0)
+ , mBlocking(PR_TRUE)
+ , mBlocked(PR_FALSE)
+ , mWritable(PR_TRUE)
+ , mCallbackFlags(0)
+ { }
+
+ void SetNonBlocking(PRBool aNonBlocking) { mBlocking = !aNonBlocking; }
+ void SetWritable(PRBool writable) { mWritable = writable; }
+
+ // synchronously wait for the pipe to become writable.
+ nsresult Wait();
+
+ // these functions return true to indicate that the pipe's monitor should
+ // be notified, to wake up a blocked writer if any.
+ PRBool OnOutputWritable(nsPipeEvents &);
+ PRBool OnOutputException(nsresult, nsPipeEvents &);
+
+private:
+ nsPipe *mPipe;
+
+ // separate refcnt so that we know when to close the producer
+ nsrefcnt mWriterRefCnt;
+ nsInt64 mLogicalOffset;
+ PRPackedBool mBlocking;
+
+ // these variables can only be accessed while inside the pipe's monitor
+ PRPackedBool mBlocked;
+ PRPackedBool mWritable;
+ nsCOMPtr<nsIOutputStreamCallback> mCallback;
+ PRUint32 mCallbackFlags;
+};
+
+//-----------------------------------------------------------------------------
+
+class nsPipe : public nsIPipe
+{
+public:
+ friend class nsPipeInputStream;
+ friend class nsPipeOutputStream;
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPIPE
+
+ // nsPipe methods:
+ nsPipe();
+
+private:
+ ~nsPipe();
+
+public:
+ //
+ // methods below may only be called while inside the pipe's monitor
+ //
+
+ void PeekSegment(PRUint32 n, char *&cursor, char *&limit);
+
+ //
+ // methods below may be called while outside the pipe's monitor
+ //
+
+ nsresult GetReadSegment(const char *&segment, PRUint32 &segmentLen);
+ void AdvanceReadCursor(PRUint32 count);
+
+ nsresult GetWriteSegment(char *&segment, PRUint32 &segmentLen);
+ void AdvanceWriteCursor(PRUint32 count);
+
+ void OnPipeException(nsresult reason, PRBool outputOnly = PR_FALSE);
+
+protected:
+ // We can't inherit from both nsIInputStream and nsIOutputStream
+ // because they collide on their Close method. Consequently we nest their
+ // implementations to avoid the extra object allocation.
+ nsPipeInputStream mInput;
+ nsPipeOutputStream mOutput;
+
+ PRMonitor* mMonitor;
+ nsSegmentedBuffer mBuffer;
+
+ char* mReadCursor;
+ char* mReadLimit;
+
+ PRInt32 mWriteSegment;
+ char* mWriteCursor;
+ char* mWriteLimit;
+
+ nsresult mStatus;
+};
+
+//
+// NOTES on buffer architecture:
+//
+// +-----------------+ - - mBuffer.GetSegment(0)
+// | |
+// + - - - - - - - - + - - mReadCursor
+// |/////////////////|
+// |/////////////////|
+// |/////////////////|
+// |/////////////////|
+// +-----------------+ - - mReadLimit
+// |
+// +-----------------+
+// |/////////////////|
+// |/////////////////|
+// |/////////////////|
+// |/////////////////|
+// |/////////////////|
+// |/////////////////|
+// +-----------------+
+// |
+// +-----------------+ - - mBuffer.GetSegment(mWriteSegment)
+// |/////////////////|
+// |/////////////////|
+// |/////////////////|
+// + - - - - - - - - + - - mWriteCursor
+// | |
+// | |
+// +-----------------+ - - mWriteLimit
+//
+// (shaded region contains data)
+//
+// NOTE: on some systems (notably OS/2), the heap allocator uses an arena for
+// small allocations (e.g., 64 byte allocations). this means that buffers may
+// be allocated back-to-back. in the diagram above, for example, mReadLimit
+// would actually be pointing at the beginning of the next segment. when
+// making changes to this file, please keep this fact in mind.
+//
+
+//-----------------------------------------------------------------------------
+// nsPipe methods:
+//-----------------------------------------------------------------------------
+
+nsPipe::nsPipe()
+ : mInput(this)
+ , mOutput(this)
+ , mMonitor(nsnull)
+ , mReadCursor(nsnull)
+ , mReadLimit(nsnull)
+ , mWriteSegment(-1)
+ , mWriteCursor(nsnull)
+ , mWriteLimit(nsnull)
+ , mStatus(NS_OK)
+{
+}
+
+nsPipe::~nsPipe()
+{
+ if (mMonitor)
+ PR_DestroyMonitor(mMonitor);
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsPipe, nsIPipe)
+
+NS_IMETHODIMP
+nsPipe::Init(PRBool nonBlockingIn,
+ PRBool nonBlockingOut,
+ PRUint32 segmentSize,
+ PRUint32 segmentCount,
+ nsIMemory *segmentAlloc)
+{
+ mMonitor = PR_NewMonitor();
+ if (!mMonitor)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (segmentSize == 0)
+ segmentSize = DEFAULT_SEGMENT_SIZE;
+ if (segmentCount == 0)
+ segmentCount = DEFAULT_SEGMENT_COUNT;
+
+ // protect against overflow
+ PRUint32 maxCount = PRUint32(-1) / segmentSize;
+ if (segmentCount > maxCount)
+ segmentCount = maxCount;
+
+ nsresult rv = mBuffer.Init(segmentSize, segmentSize * segmentCount, segmentAlloc);
+ if (NS_FAILED(rv))
+ return rv;
+
+ mInput.SetNonBlocking(nonBlockingIn);
+ mOutput.SetNonBlocking(nonBlockingOut);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipe::GetInputStream(nsIAsyncInputStream **aInputStream)
+{
+ NS_ADDREF(*aInputStream = &mInput);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipe::GetOutputStream(nsIAsyncOutputStream **aOutputStream)
+{
+ NS_ADDREF(*aOutputStream = &mOutput);
+ return NS_OK;
+}
+
+void
+nsPipe::PeekSegment(PRUint32 index, char *&cursor, char *&limit)
+{
+ if (index == 0) {
+ NS_ASSERTION(!mReadCursor || mBuffer.GetSegmentCount(), "unexpected state");
+ cursor = mReadCursor;
+ limit = mReadLimit;
+ }
+ else {
+ PRUint32 numSegments = mBuffer.GetSegmentCount();
+ if (index >= numSegments)
+ cursor = limit = nsnull;
+ else {
+ cursor = mBuffer.GetSegment(index);
+ if (mWriteSegment == (PRInt32) index)
+ limit = mWriteCursor;
+ else
+ limit = cursor + mBuffer.GetSegmentSize();
+ }
+ }
+}
+
+nsresult
+nsPipe::GetReadSegment(const char *&segment, PRUint32 &segmentLen)
+{
+ nsAutoMonitor mon(mMonitor);
+
+ if (mReadCursor == mReadLimit)
+ return NS_FAILED(mStatus) ? mStatus : NS_BASE_STREAM_WOULD_BLOCK;
+
+ segment = mReadCursor;
+ segmentLen = mReadLimit - mReadCursor;
+ return NS_OK;
+}
+
+void
+nsPipe::AdvanceReadCursor(PRUint32 bytesRead)
+{
+ NS_ASSERTION(bytesRead, "dont call if no bytes read");
+
+ nsPipeEvents events;
+ {
+ nsAutoMonitor mon(mMonitor);
+
+ LOG(("III advancing read cursor by %u\n", bytesRead));
+ NS_ASSERTION(bytesRead <= mBuffer.GetSegmentSize(), "read too much");
+
+ mReadCursor += bytesRead;
+ NS_ASSERTION(mReadCursor <= mReadLimit, "read cursor exceeds limit");
+
+ mInput.ReduceAvailable(bytesRead);
+
+ if (mReadCursor == mReadLimit) {
+ // we've reached the limit of how much we can read from this segment.
+ // if at the end of this segment, then we must discard this segment.
+
+ // if still writing in this segment then bail because we're not done
+ // with the segment and have to wait for now...
+ if (mWriteSegment == 0 && mWriteLimit > mWriteCursor) {
+ NS_ASSERTION(mReadLimit == mWriteCursor, "unexpected state");
+ return;
+ }
+
+ // shift write segment index (-1 indicates an empty buffer).
+ --mWriteSegment;
+
+ // done with this segment
+ mBuffer.DeleteFirstSegment();
+ LOG(("III deleting first segment\n"));
+
+ if (mWriteSegment == -1) {
+ // buffer is completely empty
+ mReadCursor = nsnull;
+ mReadLimit = nsnull;
+ mWriteCursor = nsnull;
+ mWriteLimit = nsnull;
+ }
+ else {
+ // advance read cursor and limit to next buffer segment
+ mReadCursor = mBuffer.GetSegment(0);
+ if (mWriteSegment == 0)
+ mReadLimit = mWriteCursor;
+ else
+ mReadLimit = mReadCursor + mBuffer.GetSegmentSize();
+ }
+
+ // we've free'd up a segment, so notify output stream that pipe has
+ // room for a new segment.
+ if (mOutput.OnOutputWritable(events))
+ mon.Notify();
+ }
+ }
+}
+
+nsresult
+nsPipe::GetWriteSegment(char *&segment, PRUint32 &segmentLen)
+{
+ nsAutoMonitor mon(mMonitor);
+
+ if (NS_FAILED(mStatus))
+ return mStatus;
+
+ // write cursor and limit may both be null indicating an empty buffer.
+ if (mWriteCursor == mWriteLimit) {
+ char *seg = mBuffer.AppendNewSegment();
+ // pipe is full
+ if (seg == nsnull)
+ return NS_BASE_STREAM_WOULD_BLOCK;
+ LOG(("OOO appended new segment\n"));
+ mWriteCursor = seg;
+ mWriteLimit = mWriteCursor + mBuffer.GetSegmentSize();
+ ++mWriteSegment;
+ }
+
+ // make sure read cursor is initialized
+ if (mReadCursor == nsnull) {
+ NS_ASSERTION(mWriteSegment == 0, "unexpected null read cursor");
+ mReadCursor = mReadLimit = mWriteCursor;
+ }
+
+ // check to see if we can roll-back our read and write cursors to the
+ // beginning of the current/first segment. this is purely an optimization.
+ if (mReadCursor == mWriteCursor && mWriteSegment == 0) {
+ char *head = mBuffer.GetSegment(0);
+ LOG(("OOO rolling back write cursor %u bytes\n", mWriteCursor - head));
+ mWriteCursor = mReadCursor = mReadLimit = head;
+ }
+
+ segment = mWriteCursor;
+ segmentLen = mWriteLimit - mWriteCursor;
+ return NS_OK;
+}
+
+void
+nsPipe::AdvanceWriteCursor(PRUint32 bytesWritten)
+{
+ NS_ASSERTION(bytesWritten, "dont call if no bytes written");
+
+ nsPipeEvents events;
+ {
+ nsAutoMonitor mon(mMonitor);
+
+ LOG(("OOO advancing write cursor by %u\n", bytesWritten));
+
+ char *newWriteCursor = mWriteCursor + bytesWritten;
+ NS_ASSERTION(newWriteCursor <= mWriteLimit, "write cursor exceeds limit");
+
+ // update read limit if reading in the same segment
+ if (mWriteSegment == 0 && mReadLimit == mWriteCursor)
+ mReadLimit = newWriteCursor;
+
+ mWriteCursor = newWriteCursor;
+
+ NS_ASSERTION(mReadCursor != mWriteCursor, "read cursor is bad");
+
+ // update the writable flag on the output stream
+ if (mWriteCursor == mWriteLimit) {
+ if (mBuffer.GetSize() >= mBuffer.GetMaxSize())
+ mOutput.SetWritable(PR_FALSE);
+ }
+
+ // notify input stream that pipe now contains additional data
+ if (mInput.OnInputReadable(bytesWritten, events))
+ mon.Notify();
+ }
+}
+
+void
+nsPipe::OnPipeException(nsresult reason, PRBool outputOnly)
+{
+ LOG(("PPP nsPipe::OnPipeException [reason=%x output-only=%d]\n",
+ reason, outputOnly));
+
+ nsPipeEvents events;
+ {
+ nsAutoMonitor mon(mMonitor);
+
+ // if we've already hit an exception, then ignore this one.
+ if (NS_FAILED(mStatus))
+ return;
+
+ mStatus = reason;
+
+ // an output-only exception applies to the input end if the pipe has
+ // zero bytes available.
+ if (outputOnly && !mInput.Available())
+ outputOnly = PR_FALSE;
+
+ if (!outputOnly)
+ if (mInput.OnInputException(reason, events))
+ mon.Notify();
+
+ if (mOutput.OnOutputException(reason, events))
+ mon.Notify();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// nsPipeEvents methods:
+//-----------------------------------------------------------------------------
+
+nsPipeEvents::~nsPipeEvents()
+{
+ // dispatch any pending events
+
+ if (mInputCallback) {
+ mInputCallback->OnInputStreamReady(mInputStream);
+ mInputCallback = 0;
+ mInputStream = 0;
+ }
+ if (mOutputCallback) {
+ mOutputCallback->OnOutputStreamReady(mOutputStream);
+ mOutputCallback = 0;
+ mOutputStream = 0;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// nsPipeInputStream methods:
+//-----------------------------------------------------------------------------
+
+nsresult
+nsPipeInputStream::Wait()
+{
+ NS_ASSERTION(mBlocking, "wait on non-blocking pipe input stream");
+
+ nsAutoMonitor mon(mPipe->mMonitor);
+
+ while (NS_SUCCEEDED(mPipe->mStatus) && (mAvailable == 0)) {
+ LOG(("III pipe input: waiting for data\n"));
+
+ mBlocked = PR_TRUE;
+ mon.Wait();
+ mBlocked = PR_FALSE;
+
+ LOG(("III pipe input: woke up [pipe-status=%x available=%u]\n",
+ mPipe->mStatus, mAvailable));
+ }
+
+ return mPipe->mStatus == NS_BASE_STREAM_CLOSED ? NS_OK : mPipe->mStatus;
+}
+
+PRBool
+nsPipeInputStream::OnInputReadable(PRUint32 bytesWritten, nsPipeEvents &events)
+{
+ PRBool result = PR_FALSE;
+
+ mAvailable += bytesWritten;
+
+ if (mCallback && !(mCallbackFlags & WAIT_CLOSURE_ONLY)) {
+ events.NotifyInputReady(this, mCallback);
+ mCallback = 0;
+ mCallbackFlags = 0;
+ }
+ else if (mBlocked)
+ result = PR_TRUE;
+
+ return result;
+}
+
+PRBool
+nsPipeInputStream::OnInputException(nsresult reason, nsPipeEvents &events)
+{
+ LOG(("nsPipeInputStream::OnInputException [this=%x reason=%x]\n",
+ this, reason));
+
+ PRBool result = PR_FALSE;
+
+ NS_ASSERTION(NS_FAILED(reason), "huh? successful exception");
+
+ // force count of available bytes to zero.
+ mAvailable = 0;
+
+ if (mCallback) {
+ events.NotifyInputReady(this, mCallback);
+ mCallback = 0;
+ mCallbackFlags = 0;
+ }
+ else if (mBlocked)
+ result = PR_TRUE;
+
+ return result;
+}
+
+NS_IMETHODIMP_(nsrefcnt)
+nsPipeInputStream::AddRef(void)
+{
+ ++mReaderRefCnt;
+ return mPipe->AddRef();
+}
+
+NS_IMETHODIMP_(nsrefcnt)
+nsPipeInputStream::Release(void)
+{
+ if (--mReaderRefCnt == 0)
+ Close();
+ return mPipe->Release();
+}
+
+NS_IMPL_QUERY_INTERFACE4(nsPipeInputStream,
+ nsIInputStream,
+ nsIAsyncInputStream,
+ nsISeekableStream,
+ nsISearchableInputStream)
+
+NS_IMETHODIMP
+nsPipeInputStream::CloseWithStatus(nsresult reason)
+{
+ LOG(("III CloseWithStatus [this=%x reason=%x]\n", this, reason));
+
+ if (NS_SUCCEEDED(reason))
+ reason = NS_BASE_STREAM_CLOSED;
+
+ mPipe->OnPipeException(reason);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipeInputStream::Close()
+{
+ return CloseWithStatus(NS_BASE_STREAM_CLOSED);
+}
+
+NS_IMETHODIMP
+nsPipeInputStream::Available(PRUint32 *result)
+{
+ nsAutoMonitor mon(mPipe->mMonitor);
+
+ // return error if pipe closed
+ if (!mAvailable && NS_FAILED(mPipe->mStatus))
+ return mPipe->mStatus;
+
+ *result = mAvailable;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipeInputStream::ReadSegments(nsWriteSegmentFun writer,
+ void *closure,
+ PRUint32 count,
+ PRUint32 *readCount)
+{
+ LOG(("III ReadSegments [this=%x count=%u]\n", this, count));
+
+ nsresult rv = NS_OK;
+
+ const char *segment;
+ PRUint32 segmentLen;
+
+ *readCount = 0;
+ while (count) {
+ rv = mPipe->GetReadSegment(segment, segmentLen);
+ if (NS_FAILED(rv)) {
+ // ignore this error if we've already read something.
+ if (*readCount > 0) {
+ rv = NS_OK;
+ break;
+ }
+ if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
+ // pipe is empty
+ if (!mBlocking)
+ break;
+ // wait for some data to be written to the pipe
+ rv = Wait();
+ if (NS_SUCCEEDED(rv))
+ continue;
+ }
+ // ignore this error, just return.
+ if (rv == NS_BASE_STREAM_CLOSED) {
+ rv = NS_OK;
+ break;
+ }
+ mPipe->OnPipeException(rv);
+ break;
+ }
+
+ // read no more than count
+ if (segmentLen > count)
+ segmentLen = count;
+
+ PRUint32 writeCount, originalLen = segmentLen;
+ while (segmentLen) {
+ writeCount = 0;
+
+ rv = writer(this, closure, segment, *readCount, segmentLen, &writeCount);
+
+ if (NS_FAILED(rv) || writeCount == 0) {
+ count = 0;
+ // any errors returned from the writer end here: do not
+ // propogate to the caller of ReadSegments.
+ rv = NS_OK;
+ break;
+ }
+
+ NS_ASSERTION(writeCount <= segmentLen, "wrote more than expected");
+ segment += writeCount;
+ segmentLen -= writeCount;
+ count -= writeCount;
+ *readCount += writeCount;
+ mLogicalOffset += writeCount;
+ }
+
+ if (segmentLen < originalLen)
+ mPipe->AdvanceReadCursor(originalLen - segmentLen);
+ }
+
+ return rv;
+}
+
+static NS_METHOD
+nsWriteToRawBuffer(nsIInputStream* inStr,
+ void *closure,
+ const char *fromRawSegment,
+ PRUint32 offset,
+ PRUint32 count,
+ PRUint32 *writeCount)
+{
+ char *toBuf = (char*)closure;
+ memcpy(&toBuf[offset], fromRawSegment, count);
+ *writeCount = count;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipeInputStream::Read(char* toBuf, PRUint32 bufLen, PRUint32 *readCount)
+{
+ return ReadSegments(nsWriteToRawBuffer, toBuf, bufLen, readCount);
+}
+
+NS_IMETHODIMP
+nsPipeInputStream::IsNonBlocking(PRBool *aNonBlocking)
+{
+ *aNonBlocking = !mBlocking;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipeInputStream::AsyncWait(nsIInputStreamCallback *callback,
+ PRUint32 flags,
+ PRUint32 requestedCount,
+ nsIEventTarget *target)
+{
+ LOG(("III AsyncWait [this=%x]\n", this));
+
+ nsPipeEvents pipeEvents;
+ {
+ nsAutoMonitor mon(mPipe->mMonitor);
+
+ // replace a pending callback
+ mCallback = 0;
+ mCallbackFlags = 0;
+
+ nsCOMPtr<nsIInputStreamCallback> proxy;
+ if (target) {
+ nsresult rv = NS_NewInputStreamReadyEvent(getter_AddRefs(proxy),
+ callback, target);
+ if (NS_FAILED(rv)) return rv;
+ callback = proxy;
+ }
+
+ if (NS_FAILED(mPipe->mStatus) ||
+ (mAvailable && !(flags & WAIT_CLOSURE_ONLY))) {
+ // stream is already closed or readable; post event.
+ pipeEvents.NotifyInputReady(this, callback);
+ }
+ else {
+ // queue up callback object to be notified when data becomes available
+ mCallback = callback;
+ mCallbackFlags = flags;
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipeInputStream::Seek(PRInt32 whence, PRInt64 offset)
+{
+ NS_NOTREACHED("nsPipeInputStream::Seek");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsPipeInputStream::Tell(PRInt64 *offset)
+{
+ *offset = mLogicalOffset;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipeInputStream::SetEOF()
+{
+ NS_NOTREACHED("nsPipeInputStream::SetEOF");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+#define COMPARE(s1, s2, i) \
+ (ignoreCase \
+ ? nsCRT::strncasecmp((const char *)s1, (const char *)s2, (PRUint32)i) \
+ : nsCRT::strncmp((const char *)s1, (const char *)s2, (PRUint32)i))
+
+NS_IMETHODIMP
+nsPipeInputStream::Search(const char *forString,
+ PRBool ignoreCase,
+ PRBool *found,
+ PRUint32 *offsetSearchedTo)
+{
+ LOG(("III Search [for=%s ic=%u]\n", forString, ignoreCase));
+
+ nsAutoMonitor mon(mPipe->mMonitor);
+
+ char *cursor1, *limit1;
+ PRUint32 index = 0, offset = 0;
+ PRUint32 strLen = strlen(forString);
+
+ mPipe->PeekSegment(0, cursor1, limit1);
+ if (cursor1 == limit1) {
+ *found = PR_FALSE;
+ *offsetSearchedTo = 0;
+ LOG((" result [found=%u offset=%u]\n", *found, *offsetSearchedTo));
+ return NS_OK;
+ }
+
+ while (PR_TRUE) {
+ PRUint32 i, len1 = limit1 - cursor1;
+
+ // check if the string is in the buffer segment
+ for (i = 0; i < len1 - strLen + 1; i++) {
+ if (COMPARE(&cursor1[i], forString, strLen) == 0) {
+ *found = PR_TRUE;
+ *offsetSearchedTo = offset + i;
+ LOG((" result [found=%u offset=%u]\n", *found, *offsetSearchedTo));
+ return NS_OK;
+ }
+ }
+
+ // get the next segment
+ char *cursor2, *limit2;
+ PRUint32 len2;
+
+ index++;
+ offset += len1;
+
+ mPipe->PeekSegment(index, cursor2, limit2);
+ if (cursor2 == limit2) {
+ *found = PR_FALSE;
+ *offsetSearchedTo = offset - strLen + 1;
+ LOG((" result [found=%u offset=%u]\n", *found, *offsetSearchedTo));
+ return NS_OK;
+ }
+ len2 = limit2 - cursor2;
+
+ // check if the string is straddling the next buffer segment
+ PRUint32 lim = PR_MIN(strLen, len2 + 1);
+ for (i = 0; i < lim; ++i) {
+ PRUint32 strPart1Len = strLen - i - 1;
+ PRUint32 strPart2Len = strLen - strPart1Len;
+ const char* strPart2 = &forString[strLen - strPart2Len];
+ PRUint32 bufSeg1Offset = len1 - strPart1Len;
+ if (COMPARE(&cursor1[bufSeg1Offset], forString, strPart1Len) == 0 &&
+ COMPARE(cursor2, strPart2, strPart2Len) == 0) {
+ *found = PR_TRUE;
+ *offsetSearchedTo = offset - strPart1Len;
+ LOG((" result [found=%u offset=%u]\n", *found, *offsetSearchedTo));
+ return NS_OK;
+ }
+ }
+
+ // finally continue with the next buffer
+ cursor1 = cursor2;
+ limit1 = limit2;
+ }
+
+ NS_NOTREACHED("can't get here");
+ return NS_ERROR_UNEXPECTED; // keep compiler happy
+}
+
+//-----------------------------------------------------------------------------
+// nsPipeOutputStream methods:
+//-----------------------------------------------------------------------------
+
+nsresult
+nsPipeOutputStream::Wait()
+{
+ NS_ASSERTION(mBlocking, "wait on non-blocking pipe output stream");
+
+ nsAutoMonitor mon(mPipe->mMonitor);
+
+ if (NS_SUCCEEDED(mPipe->mStatus) && !mWritable) {
+ LOG(("OOO pipe output: waiting for space\n"));
+ mBlocked = PR_TRUE;
+ mon.Wait();
+ mBlocked = PR_FALSE;
+ LOG(("OOO pipe output: woke up [pipe-status=%x writable=%u]\n",
+ mPipe->mStatus, mWritable == PR_TRUE));
+ }
+
+ return mPipe->mStatus == NS_BASE_STREAM_CLOSED ? NS_OK : mPipe->mStatus;
+}
+
+PRBool
+nsPipeOutputStream::OnOutputWritable(nsPipeEvents &events)
+{
+ PRBool result = PR_FALSE;
+
+ mWritable = PR_TRUE;
+
+ if (mCallback && !(mCallbackFlags & WAIT_CLOSURE_ONLY)) {
+ events.NotifyOutputReady(this, mCallback);
+ mCallback = 0;
+ mCallbackFlags = 0;
+ }
+ else if (mBlocked)
+ result = PR_TRUE;
+
+ return result;
+}
+
+PRBool
+nsPipeOutputStream::OnOutputException(nsresult reason, nsPipeEvents &events)
+{
+ LOG(("nsPipeOutputStream::OnOutputException [this=%x reason=%x]\n",
+ this, reason));
+
+ nsresult result = PR_FALSE;
+
+ NS_ASSERTION(NS_FAILED(reason), "huh? successful exception");
+ mWritable = PR_FALSE;
+
+ if (mCallback) {
+ events.NotifyOutputReady(this, mCallback);
+ mCallback = 0;
+ mCallbackFlags = 0;
+ }
+ else if (mBlocked)
+ result = PR_TRUE;
+
+ return result;
+}
+
+
+NS_IMETHODIMP_(nsrefcnt)
+nsPipeOutputStream::AddRef()
+{
+ mWriterRefCnt++;
+ return mPipe->AddRef();
+}
+
+NS_IMETHODIMP_(nsrefcnt)
+nsPipeOutputStream::Release()
+{
+ if (--mWriterRefCnt == 0)
+ Close();
+ return mPipe->Release();
+}
+
+NS_IMPL_QUERY_INTERFACE2(nsPipeOutputStream,
+ nsIOutputStream,
+ nsIAsyncOutputStream)
+
+NS_IMETHODIMP
+nsPipeOutputStream::CloseWithStatus(nsresult reason)
+{
+ LOG(("OOO CloseWithStatus [this=%x reason=%x]\n", this, reason));
+
+ if (NS_SUCCEEDED(reason))
+ reason = NS_BASE_STREAM_CLOSED;
+
+ // input stream may remain open
+ mPipe->OnPipeException(reason, PR_TRUE);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipeOutputStream::Close()
+{
+ return CloseWithStatus(NS_BASE_STREAM_CLOSED);
+}
+
+NS_IMETHODIMP
+nsPipeOutputStream::WriteSegments(nsReadSegmentFun reader,
+ void* closure,
+ PRUint32 count,
+ PRUint32 *writeCount)
+{
+ LOG(("OOO WriteSegments [this=%x count=%u]\n", this, count));
+
+ nsresult rv = NS_OK;
+
+ char *segment;
+ PRUint32 segmentLen;
+
+ *writeCount = 0;
+ while (count) {
+ rv = mPipe->GetWriteSegment(segment, segmentLen);
+ if (NS_FAILED(rv)) {
+ if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
+ // pipe is full
+ if (!mBlocking) {
+ // ignore this error if we've already written something
+ if (*writeCount > 0)
+ rv = NS_OK;
+ break;
+ }
+ // wait for the pipe to have an empty segment.
+ rv = Wait();
+ if (NS_SUCCEEDED(rv))
+ continue;
+ }
+ mPipe->OnPipeException(rv);
+ break;
+ }
+
+ // write no more than count
+ if (segmentLen > count)
+ segmentLen = count;
+
+ PRUint32 readCount, originalLen = segmentLen;
+ while (segmentLen) {
+ readCount = 0;
+
+ rv = reader(this, closure, segment, *writeCount, segmentLen, &readCount);
+
+ if (NS_FAILED(rv) || readCount == 0) {
+ count = 0;
+ // any errors returned from the reader end here: do not
+ // propogate to the caller of WriteSegments.
+ rv = NS_OK;
+ break;
+ }
+
+ NS_ASSERTION(readCount <= segmentLen, "read more than expected");
+ segment += readCount;
+ segmentLen -= readCount;
+ count -= readCount;
+ *writeCount += readCount;
+ mLogicalOffset += readCount;
+ }
+
+ if (segmentLen < originalLen)
+ mPipe->AdvanceWriteCursor(originalLen - segmentLen);
+ }
+
+ return rv;
+}
+
+static NS_METHOD
+nsReadFromRawBuffer(nsIOutputStream* outStr,
+ void* closure,
+ char* toRawSegment,
+ PRUint32 offset,
+ PRUint32 count,
+ PRUint32 *readCount)
+{
+ const char* fromBuf = (const char*)closure;
+ memcpy(toRawSegment, &fromBuf[offset], count);
+ *readCount = count;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipeOutputStream::Write(const char* fromBuf,
+ PRUint32 bufLen,
+ PRUint32 *writeCount)
+{
+ return WriteSegments(nsReadFromRawBuffer, (void*)fromBuf, bufLen, writeCount);
+}
+
+NS_IMETHODIMP
+nsPipeOutputStream::Flush(void)
+{
+ // nothing to do
+ return NS_OK;
+}
+
+static NS_METHOD
+nsReadFromInputStream(nsIOutputStream* outStr,
+ void* closure,
+ char* toRawSegment,
+ PRUint32 offset,
+ PRUint32 count,
+ PRUint32 *readCount)
+{
+ nsIInputStream* fromStream = (nsIInputStream*)closure;
+ return fromStream->Read(toRawSegment, count, readCount);
+}
+
+NS_IMETHODIMP
+nsPipeOutputStream::WriteFrom(nsIInputStream* fromStream,
+ PRUint32 count,
+ PRUint32 *writeCount)
+{
+ return WriteSegments(nsReadFromInputStream, fromStream, count, writeCount);
+}
+
+NS_IMETHODIMP
+nsPipeOutputStream::IsNonBlocking(PRBool *aNonBlocking)
+{
+ *aNonBlocking = !mBlocking;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipeOutputStream::AsyncWait(nsIOutputStreamCallback *callback,
+ PRUint32 flags,
+ PRUint32 requestedCount,
+ nsIEventTarget *target)
+{
+ LOG(("OOO AsyncWait [this=%x]\n", this));
+
+ nsPipeEvents pipeEvents;
+ {
+ nsAutoMonitor mon(mPipe->mMonitor);
+
+ // replace a pending callback
+ mCallback = 0;
+ mCallbackFlags = 0;
+
+ nsCOMPtr<nsIOutputStreamCallback> proxy;
+ if (target) {
+ nsresult rv = NS_NewOutputStreamReadyEvent(getter_AddRefs(proxy),
+ callback, target);
+ if (NS_FAILED(rv)) return rv;
+ callback = proxy;
+ }
+
+ if (NS_FAILED(mPipe->mStatus) ||
+ (mWritable && !(flags & WAIT_CLOSURE_ONLY))) {
+ // stream is already closed or writable; post event.
+ pipeEvents.NotifyOutputReady(this, callback);
+ }
+ else {
+ // queue up callback object to be notified when data becomes available
+ mCallback = callback;
+ mCallbackFlags = flags;
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipeOutputStream::Seek(PRInt32 whence, PRInt64 offset)
+{
+ NS_NOTREACHED("nsPipeOutputStream::Seek");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsPipeOutputStream::Tell(PRInt64 *offset)
+{
+ *offset = mLogicalOffset;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPipeOutputStream::SetEOF()
+{
+ NS_NOTREACHED("nsPipeOutputStream::SetEOF");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+NS_COM nsresult
+NS_NewPipe2(nsIAsyncInputStream **pipeIn,
+ nsIAsyncOutputStream **pipeOut,
+ PRBool nonBlockingInput,
+ PRBool nonBlockingOutput,
+ PRUint32 segmentSize,
+ PRUint32 segmentCount,
+ nsIMemory *segmentAlloc)
+{
+ nsresult rv;
+
+#if defined(PR_LOGGING)
+ if (!gPipeLog)
+ gPipeLog = PR_NewLogModule("nsPipe");
+#endif
+
+ nsPipe *pipe = new nsPipe();
+ if (!pipe)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ rv = pipe->Init(nonBlockingInput,
+ nonBlockingOutput,
+ segmentSize,
+ segmentCount,
+ segmentAlloc);
+ if (NS_FAILED(rv)) {
+ NS_ADDREF(pipe);
+ NS_RELEASE(pipe);
+ return rv;
+ }
+
+ pipe->GetInputStream(pipeIn);
+ pipe->GetOutputStream(pipeOut);
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libs/xpcom18a4/xpcom/io/nsScriptableInputStream.cpp b/src/libs/xpcom18a4/xpcom/io/nsScriptableInputStream.cpp
new file mode 100644
index 00000000..5458b1b7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsScriptableInputStream.cpp
@@ -0,0 +1,102 @@
+/* -*- 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 "nsScriptableInputStream.h"
+#include "nsMemory.h"
+
+NS_IMPL_ISUPPORTS1(nsScriptableInputStream, nsIScriptableInputStream)
+
+// nsIBaseStream methods
+NS_IMETHODIMP
+nsScriptableInputStream::Close(void) {
+ if (!mInputStream) return NS_ERROR_NOT_INITIALIZED;
+ return mInputStream->Close();
+}
+
+// nsIScriptableInputStream methods
+NS_IMETHODIMP
+nsScriptableInputStream::Init(nsIInputStream *aInputStream) {
+ if (!aInputStream) return NS_ERROR_NULL_POINTER;
+ mInputStream = aInputStream;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScriptableInputStream::Available(PRUint32 *_retval) {
+ if (!mInputStream) return NS_ERROR_NOT_INITIALIZED;
+ return mInputStream->Available(_retval);
+}
+
+NS_IMETHODIMP
+nsScriptableInputStream::Read(PRUint32 aCount, char **_retval) {
+ nsresult rv = NS_OK;
+ PRUint32 count = 0;
+ char *buffer = nsnull;
+
+ if (!mInputStream) return NS_ERROR_NOT_INITIALIZED;
+
+ rv = mInputStream->Available(&count);
+ if (NS_FAILED(rv)) return rv;
+
+ count = PR_MIN(count, aCount);
+ buffer = (char*)nsMemory::Alloc(count+1); // make room for '\0'
+ if (!buffer) return NS_ERROR_OUT_OF_MEMORY;
+
+ PRUint32 amtRead = 0;
+ rv = mInputStream->Read(buffer, count, &amtRead);
+ if (NS_FAILED(rv)) {
+ nsMemory::Free(buffer);
+ return rv;
+ }
+
+ buffer[amtRead] = '\0';
+ *_retval = buffer;
+ return NS_OK;
+}
+
+NS_METHOD
+nsScriptableInputStream::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) {
+ if (aOuter) return NS_ERROR_NO_AGGREGATION;
+
+ nsScriptableInputStream *sis = new nsScriptableInputStream();
+ if (!sis) return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(sis);
+ nsresult rv = sis->QueryInterface(aIID, aResult);
+ NS_RELEASE(sis);
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsScriptableInputStream.h b/src/libs/xpcom18a4/xpcom/io/nsScriptableInputStream.h
new file mode 100644
index 00000000..b9976176
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsScriptableInputStream.h
@@ -0,0 +1,71 @@
+/* -*- 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 ***** */
+
+#ifndef ___nsscriptableinputstream___h_
+#define ___nsscriptableinputstream___h_
+
+#include "nsIScriptableInputStream.h"
+#include "nsIInputStream.h"
+#include "nsCOMPtr.h"
+
+#define NS_SCRIPTABLEINPUTSTREAM_CID \
+{ 0x7225c040, 0xa9bf, 0x11d3, { 0xa1, 0x97, 0x0, 0x50, 0x4, 0x1c, 0xaf, 0x44 } }
+
+#define NS_SCRIPTABLEINPUTSTREAM_CONTRACTID "@mozilla.org/scriptableinputstream;1"
+#define NS_SCRIPTABLEINPUTSTREAM_CLASSNAME "Scriptable Input Stream"
+
+class nsScriptableInputStream : public nsIScriptableInputStream {
+public:
+ // nsISupports methods
+ NS_DECL_ISUPPORTS
+
+ // nsIScriptableInputStream methods
+ NS_DECL_NSISCRIPTABLEINPUTSTREAM
+
+ // nsScriptableInputStream methods
+ nsScriptableInputStream() {};
+
+ static NS_METHOD
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+private:
+ ~nsScriptableInputStream() {};
+
+ nsCOMPtr<nsIInputStream> mInputStream;
+};
+
+#endif // ___nsscriptableinputstream___h_
diff --git a/src/libs/xpcom18a4/xpcom/io/nsSegmentedBuffer.cpp b/src/libs/xpcom18a4/xpcom/io/nsSegmentedBuffer.cpp
new file mode 100644
index 00000000..f6a1c15d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsSegmentedBuffer.cpp
@@ -0,0 +1,207 @@
+/* -*- 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 "nsSegmentedBuffer.h"
+#include "nsCRT.h"
+
+nsresult
+nsSegmentedBuffer::Init(PRUint32 segmentSize, PRUint32 maxSize,
+ nsIMemory* allocator)
+{
+ if (mSegmentArrayCount != 0)
+ return NS_ERROR_FAILURE; // initialized more than once
+ mSegmentSize = segmentSize;
+ mMaxSize = maxSize;
+ mSegAllocator = allocator;
+ if (mSegAllocator == nsnull) {
+ mSegAllocator = nsMemory::GetGlobalMemoryService();
+ }
+ else {
+ NS_ADDREF(mSegAllocator);
+ }
+#if 0 // testing...
+ mSegmentArrayCount = 2;
+#else
+ mSegmentArrayCount = NS_SEGMENTARRAY_INITIAL_COUNT;
+#endif
+ return NS_OK;
+}
+
+char*
+nsSegmentedBuffer::AppendNewSegment()
+{
+ if (GetSize() >= mMaxSize)
+ return nsnull;
+
+ if (mSegmentArray == nsnull) {
+ PRUint32 bytes = mSegmentArrayCount * sizeof(char*);
+ mSegmentArray = (char**)nsMemory::Alloc(bytes);
+ if (mSegmentArray == nsnull)
+ return nsnull;
+ memset(mSegmentArray, 0, bytes);
+ }
+
+ if (IsFull()) {
+ PRUint32 newArraySize = mSegmentArrayCount * 2;
+ PRUint32 bytes = newArraySize * sizeof(char*);
+ char** newSegArray = (char**)nsMemory::Realloc(mSegmentArray, bytes);
+ if (newSegArray == nsnull)
+ return nsnull;
+ mSegmentArray = newSegArray;
+ // copy wrapped content to new extension
+ if (mFirstSegmentIndex > mLastSegmentIndex) {
+ // deal with wrap around case
+ memcpy(&mSegmentArray[mSegmentArrayCount],
+ mSegmentArray,
+ mLastSegmentIndex * sizeof(char*));
+ memset(mSegmentArray, 0, mLastSegmentIndex * sizeof(char*));
+ mLastSegmentIndex += mSegmentArrayCount;
+ memset(&mSegmentArray[mLastSegmentIndex], 0,
+ (newArraySize - mLastSegmentIndex) * sizeof(char*));
+ }
+ else {
+ memset(&mSegmentArray[mLastSegmentIndex], 0,
+ (newArraySize - mLastSegmentIndex) * sizeof(char*));
+ }
+ mSegmentArrayCount = newArraySize;
+ }
+
+ char* seg = (char*)mSegAllocator->Alloc(mSegmentSize);
+ if (seg == nsnull) {
+ return nsnull;
+ }
+ mSegmentArray[mLastSegmentIndex] = seg;
+ mLastSegmentIndex = ModSegArraySize(mLastSegmentIndex + 1);
+ return seg;
+}
+
+PRBool
+nsSegmentedBuffer::DeleteFirstSegment()
+{
+ NS_ASSERTION(mSegmentArray[mFirstSegmentIndex] != nsnull, "deleting bad segment");
+ (void)mSegAllocator->Free(mSegmentArray[mFirstSegmentIndex]);
+ mSegmentArray[mFirstSegmentIndex] = nsnull;
+ PRInt32 last = ModSegArraySize(mLastSegmentIndex - 1);
+ if (mFirstSegmentIndex == last) {
+ mLastSegmentIndex = last;
+ return PR_TRUE;
+ }
+ else {
+ mFirstSegmentIndex = ModSegArraySize(mFirstSegmentIndex + 1);
+ return PR_FALSE;
+ }
+}
+
+PRBool
+nsSegmentedBuffer::DeleteLastSegment()
+{
+ PRInt32 last = ModSegArraySize(mLastSegmentIndex - 1);
+ NS_ASSERTION(mSegmentArray[last] != nsnull, "deleting bad segment");
+ (void)mSegAllocator->Free(mSegmentArray[last]);
+ mSegmentArray[last] = nsnull;
+ mLastSegmentIndex = last;
+ return (PRBool)(mLastSegmentIndex == mFirstSegmentIndex);
+}
+
+PRBool
+nsSegmentedBuffer::ReallocLastSegment(size_t newSize)
+{
+ PRInt32 last = ModSegArraySize(mLastSegmentIndex - 1);
+ NS_ASSERTION(mSegmentArray[last] != nsnull, "realloc'ing bad segment");
+ char *newSegment =
+ (char*)mSegAllocator->Realloc(mSegmentArray[last], newSize);
+ if (newSegment) {
+ mSegmentArray[last] = newSegment;
+ return PR_TRUE;
+ } else {
+ return PR_FALSE;
+ }
+}
+
+void
+nsSegmentedBuffer::Empty()
+{
+ if (mSegmentArray) {
+ for (PRUint32 i = 0; i < mSegmentArrayCount; i++) {
+ if (mSegmentArray[i])
+ mSegAllocator->Free(mSegmentArray[i]);
+ }
+ nsMemory::Free(mSegmentArray);
+ mSegmentArray = nsnull;
+ }
+ mSegmentArrayCount = NS_SEGMENTARRAY_INITIAL_COUNT;
+ mFirstSegmentIndex = mLastSegmentIndex = 0;
+}
+
+#ifdef DEBUG
+NS_COM void
+TestSegmentedBuffer()
+{
+ nsSegmentedBuffer* buf = new nsSegmentedBuffer();
+ NS_ASSERTION(buf, "out of memory");
+ buf->Init(4, 16);
+ char* seg;
+ PRBool empty;
+ seg = buf->AppendNewSegment();
+ NS_ASSERTION(seg, "AppendNewSegment failed");
+ seg = buf->AppendNewSegment();
+ NS_ASSERTION(seg, "AppendNewSegment failed");
+ seg = buf->AppendNewSegment();
+ NS_ASSERTION(seg, "AppendNewSegment failed");
+ empty = buf->DeleteFirstSegment();
+ NS_ASSERTION(!empty, "DeleteFirstSegment failed");
+ empty = buf->DeleteFirstSegment();
+ NS_ASSERTION(!empty, "DeleteFirstSegment failed");
+ seg = buf->AppendNewSegment();
+ NS_ASSERTION(seg, "AppendNewSegment failed");
+ seg = buf->AppendNewSegment();
+ NS_ASSERTION(seg, "AppendNewSegment failed");
+ seg = buf->AppendNewSegment();
+ NS_ASSERTION(seg, "AppendNewSegment failed");
+ empty = buf->DeleteFirstSegment();
+ NS_ASSERTION(!empty, "DeleteFirstSegment failed");
+ empty = buf->DeleteFirstSegment();
+ NS_ASSERTION(!empty, "DeleteFirstSegment failed");
+ empty = buf->DeleteFirstSegment();
+ NS_ASSERTION(!empty, "DeleteFirstSegment failed");
+ empty = buf->DeleteFirstSegment();
+ NS_ASSERTION(empty, "DeleteFirstSegment failed");
+ delete buf;
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libs/xpcom18a4/xpcom/io/nsSegmentedBuffer.h b/src/libs/xpcom18a4/xpcom/io/nsSegmentedBuffer.h
new file mode 100644
index 00000000..43620632
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsSegmentedBuffer.h
@@ -0,0 +1,125 @@
+/* -*- 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 ***** */
+
+#ifndef nsSegmentedBuffer_h__
+#define nsSegmentedBuffer_h__
+
+#include "nsMemory.h"
+#include "prclist.h"
+
+class nsSegmentedBuffer
+{
+public:
+ nsSegmentedBuffer()
+ : mSegmentSize(0), mMaxSize(0),
+ mSegAllocator(nsnull), mSegmentArray(nsnull),
+ mSegmentArrayCount(0),
+ mFirstSegmentIndex(0), mLastSegmentIndex(0) {}
+
+ ~nsSegmentedBuffer() {
+ Empty();
+ NS_IF_RELEASE(mSegAllocator);
+ }
+
+
+ NS_COM nsresult Init(PRUint32 segmentSize, PRUint32 maxSize,
+ nsIMemory* allocator = nsnull);
+
+ NS_COM char* AppendNewSegment(); // pushes at end
+
+ // returns true if no more segments remain:
+ PRBool DeleteFirstSegment(); // pops from beginning
+
+ // returns true if no more segments remain:
+ PRBool DeleteLastSegment(); // pops from beginning
+
+ // Call Realloc() on last segment. This is used to reduce memory
+ // consumption when data is not an exact multiple of segment size.
+ PRBool ReallocLastSegment(size_t newSize);
+
+ NS_COM void Empty(); // frees all segments
+
+ inline PRUint32 GetSegmentCount() {
+ if (mFirstSegmentIndex <= mLastSegmentIndex)
+ return mLastSegmentIndex - mFirstSegmentIndex;
+ else
+ return mSegmentArrayCount + mLastSegmentIndex - mFirstSegmentIndex;
+ }
+
+ inline PRUint32 GetSegmentSize() { return mSegmentSize; }
+ inline PRUint32 GetMaxSize() { return mMaxSize; }
+ inline PRUint32 GetSize() { return GetSegmentCount() * mSegmentSize; }
+
+ inline char* GetSegment(PRUint32 indx) {
+ NS_ASSERTION(indx < GetSegmentCount(), "index out of bounds");
+ PRInt32 i = ModSegArraySize(mFirstSegmentIndex + (PRInt32)indx);
+ return mSegmentArray[i];
+ }
+
+protected:
+ inline PRInt32 ModSegArraySize(PRInt32 n) {
+ PRUint32 result = n & (mSegmentArrayCount - 1);
+ NS_ASSERTION(result == n % mSegmentArrayCount,
+ "non-power-of-2 mSegmentArrayCount");
+ return result;
+ }
+
+ inline PRBool IsFull() {
+ return ModSegArraySize(mLastSegmentIndex + 1) == mFirstSegmentIndex;
+ }
+
+protected:
+ PRUint32 mSegmentSize;
+ PRUint32 mMaxSize;
+ nsIMemory* mSegAllocator;
+ char** mSegmentArray;
+ PRUint32 mSegmentArrayCount;
+ PRInt32 mFirstSegmentIndex;
+ PRInt32 mLastSegmentIndex;
+};
+
+// NS_SEGMENTARRAY_INITIAL_SIZE: This number needs to start out as a
+// power of 2 given how it gets used. We double the segment array
+// when we overflow it, and use that fact that it's a power of 2
+// to compute a fast modulus operation in IsFull.
+//
+// 32 segment array entries can accommodate 128k of data if segments
+// are 4k in size. That seems like a reasonable amount that will avoid
+// needing to grow the segment array.
+#define NS_SEGMENTARRAY_INITIAL_COUNT 32
+
+#endif // nsSegmentedBuffer_h__
diff --git a/src/libs/xpcom18a4/xpcom/io/nsStorageStream.cpp b/src/libs/xpcom18a4/xpcom/io/nsStorageStream.cpp
new file mode 100644
index 00000000..2a6b0166
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsStorageStream.cpp
@@ -0,0 +1,563 @@
+/* -*- 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-1999
+ * 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 ***** */
+
+/*
+ * The storage stream provides an internal buffer that can be filled by a
+ * client using a single output stream. One or more independent input streams
+ * can be created to read the data out non-destructively. The implementation
+ * uses a segmented buffer internally to avoid realloc'ing of large buffers,
+ * with the attendant performance loss and heap fragmentation.
+ */
+
+#include "nsStorageStream.h"
+#include "nsSegmentedBuffer.h"
+#include "nsCOMPtr.h"
+#include "prbit.h"
+#include "nsIInputStream.h"
+#include "nsISeekableStream.h"
+#include "prlog.h"
+#include "nsInt64.h"
+#if defined(PR_LOGGING)
+//
+// Log module for StorageStream logging...
+//
+// To enable logging (see prlog.h for full details):
+//
+// set NSPR_LOG_MODULES=StorageStreamLog:5
+// set NSPR_LOG_FILE=nspr.log
+//
+// this enables PR_LOG_DEBUG level information and places all output in
+// the file nspr.log
+//
+PRLogModuleInfo* StorageStreamLog = nsnull;
+
+#endif /* PR_LOGGING */
+
+nsStorageStream::nsStorageStream()
+ : mSegmentedBuffer(0), mSegmentSize(0), mWriteInProgress(PR_FALSE),
+ mLastSegmentNum(-1), mWriteCursor(0), mSegmentEnd(0), mLogicalLength(0)
+{
+#if defined(PR_LOGGING)
+ //
+ // Initialize the global PRLogModule for socket transport logging
+ // if necessary...
+ //
+ if (nsnull == StorageStreamLog) {
+ StorageStreamLog = PR_NewLogModule("StorageStreamLog");
+ }
+#endif /* PR_LOGGING */
+
+ PR_LOG(StorageStreamLog, PR_LOG_DEBUG,
+ ("Creating nsStorageStream [%x].\n", this));
+}
+
+nsStorageStream::~nsStorageStream()
+{
+ if (mSegmentedBuffer)
+ delete mSegmentedBuffer;
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsStorageStream,
+ nsIStorageStream,
+ nsIOutputStream)
+
+NS_IMETHODIMP
+nsStorageStream::Init(PRUint32 segmentSize, PRUint32 maxSize,
+ nsIMemory *segmentAllocator)
+{
+ mSegmentedBuffer = new nsSegmentedBuffer();
+ if (!mSegmentedBuffer)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ mSegmentSize = segmentSize;
+ mSegmentSizeLog2 = PR_FloorLog2(segmentSize);
+
+ // Segment size must be a power of two
+ if (mSegmentSize != ((PRUint32)1 << mSegmentSizeLog2))
+ return NS_ERROR_INVALID_ARG;
+
+ return mSegmentedBuffer->Init(segmentSize, maxSize, segmentAllocator);
+}
+
+NS_IMETHODIMP
+nsStorageStream::GetOutputStream(PRInt32 aStartingOffset,
+ nsIOutputStream * *aOutputStream)
+{
+ NS_ENSURE_ARG(aOutputStream);
+ if (mWriteInProgress)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ nsresult rv = Seek(aStartingOffset);
+ if (NS_FAILED(rv)) return rv;
+
+ // Enlarge the last segment in the buffer so that it is the same size as
+ // all the other segments in the buffer. (It may have been realloc'ed
+ // smaller in the Close() method.)
+ if (mLastSegmentNum >= 0)
+ mSegmentedBuffer->ReallocLastSegment(mSegmentSize);
+
+ // Need to re-Seek, since realloc might have changed segment base pointer
+ rv = Seek(aStartingOffset);
+ if (NS_FAILED(rv)) return rv;
+
+ NS_ADDREF(this);
+ *aOutputStream = NS_STATIC_CAST(nsIOutputStream*, this);
+ mWriteInProgress = PR_TRUE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStorageStream::Close()
+{
+ mWriteInProgress = PR_FALSE;
+
+ PRInt32 segmentOffset = SegOffset(mLogicalLength);
+
+ // Shrink the final segment in the segmented buffer to the minimum size
+ // needed to contain the data, so as to conserve memory.
+ if (segmentOffset)
+ mSegmentedBuffer->ReallocLastSegment(segmentOffset);
+
+ mWriteCursor = 0;
+ mSegmentEnd = 0;
+
+ PR_LOG(StorageStreamLog, PR_LOG_DEBUG,
+ ("nsStorageStream [%x] Close mWriteCursor=%x mSegmentEnd=%x\n",
+ this, mWriteCursor, mSegmentEnd));
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStorageStream::Flush()
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStorageStream::Write(const char *aBuffer, PRUint32 aCount, PRUint32 *aNumWritten)
+{
+ const char* readCursor;
+ PRUint32 count, availableInSegment, remaining;
+ nsresult rv = NS_OK;
+
+ NS_ENSURE_ARG_POINTER(aNumWritten);
+ NS_ENSURE_ARG(aBuffer);
+
+ PR_LOG(StorageStreamLog, PR_LOG_DEBUG,
+ ("nsStorageStream [%x] Write mWriteCursor=%x mSegmentEnd=%x aCount=%d\n",
+ this, mWriteCursor, mSegmentEnd, aCount));
+
+ remaining = aCount;
+ readCursor = aBuffer;
+ while (remaining) {
+ availableInSegment = mSegmentEnd - mWriteCursor;
+ if (!availableInSegment) {
+ mWriteCursor = mSegmentedBuffer->AppendNewSegment();
+ if (!mWriteCursor) {
+ mSegmentEnd = 0;
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+ mLastSegmentNum++;
+ mSegmentEnd = mWriteCursor + mSegmentSize;
+ availableInSegment = mSegmentEnd - mWriteCursor;
+ PR_LOG(StorageStreamLog, PR_LOG_DEBUG,
+ ("nsStorageStream [%x] Write (new seg) mWriteCursor=%x mSegmentEnd=%x\n",
+ this, mWriteCursor, mSegmentEnd));
+ }
+
+ count = PR_MIN(availableInSegment, remaining);
+ memcpy(mWriteCursor, readCursor, count);
+ remaining -= count;
+ readCursor += count;
+ mWriteCursor += count;
+ PR_LOG(StorageStreamLog, PR_LOG_DEBUG,
+ ("nsStorageStream [%x] Writing mWriteCursor=%x mSegmentEnd=%x count=%d\n",
+ this, mWriteCursor, mSegmentEnd, count));
+ };
+
+ out:
+ *aNumWritten = aCount - remaining;
+ mLogicalLength += *aNumWritten;
+
+ PR_LOG(StorageStreamLog, PR_LOG_DEBUG,
+ ("nsStorageStream [%x] Wrote mWriteCursor=%x mSegmentEnd=%x numWritten=%d\n",
+ this, mWriteCursor, mSegmentEnd, *aNumWritten));
+ return rv;
+}
+
+NS_IMETHODIMP
+nsStorageStream::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval)
+{
+ NS_NOTREACHED("WriteFrom");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsStorageStream::WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval)
+{
+ NS_NOTREACHED("WriteSegments");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsStorageStream::IsNonBlocking(PRBool *aNonBlocking)
+{
+ *aNonBlocking = PR_TRUE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStorageStream::GetLength(PRUint32 *aLength)
+{
+ NS_ENSURE_ARG(aLength);
+ *aLength = mLogicalLength;
+ return NS_OK;
+}
+
+// Truncate the buffer by deleting the end segments
+NS_IMETHODIMP
+nsStorageStream::SetLength(PRUint32 aLength)
+{
+ if (mWriteInProgress)
+ return NS_ERROR_NOT_AVAILABLE;
+
+ if (aLength > mLogicalLength)
+ return NS_ERROR_INVALID_ARG;
+
+ PRInt32 newLastSegmentNum = SegNum(aLength);
+ PRInt32 segmentOffset = SegOffset(aLength);
+ if (segmentOffset == 0)
+ newLastSegmentNum--;
+
+ while (newLastSegmentNum < mLastSegmentNum) {
+ mSegmentedBuffer->DeleteLastSegment();
+ mLastSegmentNum--;
+ }
+
+ mLogicalLength = aLength;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStorageStream::GetWriteInProgress(PRBool *aWriteInProgress)
+{
+ NS_ENSURE_ARG(aWriteInProgress);
+
+ *aWriteInProgress = mWriteInProgress;
+ return NS_OK;
+}
+
+NS_METHOD
+nsStorageStream::Seek(PRInt32 aPosition)
+{
+ // An argument of -1 means "seek to end of stream"
+ if (aPosition == -1)
+ aPosition = mLogicalLength;
+
+ // Seeking beyond the buffer end is illegal
+ if ((PRUint32)aPosition > mLogicalLength)
+ return NS_ERROR_INVALID_ARG;
+
+ // Seeking backwards in the write stream results in truncation
+ SetLength(aPosition);
+
+ // Special handling for seek to start-of-buffer
+ if (aPosition == 0) {
+ mWriteCursor = 0;
+ mSegmentEnd = 0;
+ PR_LOG(StorageStreamLog, PR_LOG_DEBUG,
+ ("nsStorageStream [%x] Seek mWriteCursor=%x mSegmentEnd=%x\n",
+ this, mWriteCursor, mSegmentEnd));
+ return NS_OK;
+ }
+
+ // Segment may have changed, so reset pointers
+ mWriteCursor = mSegmentedBuffer->GetSegment(mLastSegmentNum);
+ NS_ASSERTION(mWriteCursor, "null mWriteCursor");
+ mSegmentEnd = mWriteCursor + mSegmentSize;
+ PRInt32 segmentOffset = SegOffset(aPosition);
+ mWriteCursor += segmentOffset;
+
+ PR_LOG(StorageStreamLog, PR_LOG_DEBUG,
+ ("nsStorageStream [%x] Seek mWriteCursor=%x mSegmentEnd=%x\n",
+ this, mWriteCursor, mSegmentEnd));
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+// There can be many nsStorageInputStreams for a single nsStorageStream
+class nsStorageInputStream : public nsIInputStream
+ , public nsISeekableStream
+{
+public:
+ nsStorageInputStream(nsStorageStream *aStorageStream, PRUint32 aSegmentSize)
+ : mStorageStream(aStorageStream), mReadCursor(0),
+ mSegmentEnd(0), mSegmentNum(0),
+ mSegmentSize(aSegmentSize), mLogicalCursor(0)
+ {
+ NS_ADDREF(mStorageStream);
+ }
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIINPUTSTREAM
+ NS_DECL_NSISEEKABLESTREAM
+
+private:
+ ~nsStorageInputStream()
+ {
+ NS_IF_RELEASE(mStorageStream);
+ }
+
+protected:
+ NS_METHOD Seek(PRUint32 aPosition);
+
+ friend class nsStorageStream;
+
+private:
+ nsStorageStream* mStorageStream;
+ const char* mReadCursor; // Next memory location to read byte, or NULL
+ const char* mSegmentEnd; // One byte past end of current buffer segment
+ PRUint32 mSegmentNum; // Segment number containing read cursor
+ PRUint32 mSegmentSize; // All segments, except the last, are of this size
+ PRUint32 mLogicalCursor; // Logical offset into stream
+
+ PRUint32 SegNum(PRUint32 aPosition) {return aPosition >> mStorageStream->mSegmentSizeLog2;}
+ PRUint32 SegOffset(PRUint32 aPosition) {return aPosition & (mSegmentSize - 1);}
+};
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsStorageInputStream,
+ nsIInputStream,
+ nsISeekableStream)
+
+NS_IMETHODIMP
+nsStorageStream::NewInputStream(PRInt32 aStartingOffset, nsIInputStream* *aInputStream)
+{
+ nsStorageInputStream *inputStream = new nsStorageInputStream(this, mSegmentSize);
+ if (!inputStream)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(inputStream);
+
+ nsresult rv = inputStream->Seek(aStartingOffset);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(inputStream);
+ return rv;
+ }
+
+ *aInputStream = inputStream;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStorageInputStream::Close()
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStorageInputStream::Available(PRUint32 *aAvailable)
+{
+ *aAvailable = mStorageStream->mLogicalLength - mLogicalCursor;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStorageInputStream::Read(char* aBuffer, PRUint32 aCount, PRUint32 *aNumRead)
+{
+ char* writeCursor;
+ PRUint32 count, availableInSegment, remainingCapacity;
+
+ remainingCapacity = aCount;
+ writeCursor = aBuffer;
+ while (remainingCapacity) {
+ availableInSegment = mSegmentEnd - mReadCursor;
+ if (!availableInSegment) {
+ PRUint32 available = mStorageStream->mLogicalLength - mLogicalCursor;
+ if (!available)
+ goto out;
+
+ mReadCursor = mStorageStream->mSegmentedBuffer->GetSegment(++mSegmentNum);
+ mSegmentEnd = mReadCursor + PR_MIN(mSegmentSize, available);
+ }
+
+ count = PR_MIN(availableInSegment, remainingCapacity);
+ memcpy(writeCursor, mReadCursor, count);
+ remainingCapacity -= count;
+ mReadCursor += count;
+ writeCursor += count;
+ mLogicalCursor += count;
+ };
+
+ out:
+ *aNumRead = aCount - remainingCapacity;
+
+ PRBool isWriteInProgress = PR_FALSE;
+ if (NS_FAILED(mStorageStream->GetWriteInProgress(&isWriteInProgress)))
+ isWriteInProgress = PR_FALSE;
+
+ if (*aNumRead == 0 && isWriteInProgress)
+ return NS_BASE_STREAM_WOULD_BLOCK;
+ else
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStorageInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 aCount, PRUint32 *aNumRead)
+{
+ PRUint32 count, availableInSegment, remainingCapacity, bytesConsumed;
+ nsresult rv;
+
+ remainingCapacity = aCount;
+ while (remainingCapacity) {
+ availableInSegment = mSegmentEnd - mReadCursor;
+ if (!availableInSegment) {
+ PRUint32 available = mStorageStream->mLogicalLength - mLogicalCursor;
+ if (!available)
+ goto out;
+
+ mReadCursor = mStorageStream->mSegmentedBuffer->GetSegment(++mSegmentNum);
+ mSegmentEnd = mReadCursor + PR_MIN(mSegmentSize, available);
+ availableInSegment = mSegmentEnd - mReadCursor;
+ }
+
+ count = PR_MIN(availableInSegment, remainingCapacity);
+ rv = writer(this, closure, mReadCursor, mLogicalCursor, count, &bytesConsumed);
+ if (NS_FAILED(rv) || (bytesConsumed == 0))
+ break;
+ remainingCapacity -= bytesConsumed;
+ mReadCursor += bytesConsumed;
+ mLogicalCursor += bytesConsumed;
+ };
+
+ out:
+ *aNumRead = aCount - remainingCapacity;
+
+ PRBool isWriteInProgress = PR_FALSE;
+ if (NS_FAILED(mStorageStream->GetWriteInProgress(&isWriteInProgress)))
+ isWriteInProgress = PR_FALSE;
+
+ if (*aNumRead == 0 && isWriteInProgress)
+ return NS_BASE_STREAM_WOULD_BLOCK;
+ else
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStorageInputStream::IsNonBlocking(PRBool *aNonBlocking)
+{
+ *aNonBlocking = PR_TRUE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStorageInputStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
+{
+ nsInt64 pos = aOffset;
+
+ switch (aWhence) {
+ case NS_SEEK_SET:
+ break;
+ case NS_SEEK_CUR:
+ pos += mLogicalCursor;
+ break;
+ case NS_SEEK_END:
+ pos += mStorageStream->mLogicalLength;
+ break;
+ default:
+ NS_NOTREACHED("unexpected whence value");
+ return NS_ERROR_UNEXPECTED;
+ }
+ nsInt64 logicalCursor(mLogicalCursor);
+ if (pos == logicalCursor)
+ return NS_OK;
+
+ return Seek(pos);
+}
+
+NS_IMETHODIMP
+nsStorageInputStream::Tell(PRInt64 *aResult)
+{
+ LL_UI2L(*aResult, mLogicalCursor);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStorageInputStream::SetEOF()
+{
+ NS_NOTREACHED("nsStorageInputStream::SetEOF");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_METHOD
+nsStorageInputStream::Seek(PRUint32 aPosition)
+{
+ PRUint32 length = mStorageStream->mLogicalLength;
+ if (aPosition >= length)
+ return NS_ERROR_INVALID_ARG;
+
+ mSegmentNum = SegNum(aPosition);
+ PRUint32 segmentOffset = SegOffset(aPosition);
+ mReadCursor = mStorageStream->mSegmentedBuffer->GetSegment(mSegmentNum) +
+ segmentOffset;
+ PRUint32 available = length - aPosition;
+ mSegmentEnd = mReadCursor + PR_MIN(mSegmentSize - segmentOffset, available);
+ mLogicalCursor = aPosition;
+ return NS_OK;
+}
+
+NS_COM nsresult
+NS_NewStorageStream(PRUint32 segmentSize, PRUint32 maxSize, nsIStorageStream **result)
+{
+ NS_ENSURE_ARG(result);
+
+ nsStorageStream* storageStream = new nsStorageStream();
+ if (!storageStream) return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(storageStream);
+ nsresult rv = storageStream->Init(segmentSize, maxSize, nsnull);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(storageStream);
+ return rv;
+ }
+ *result = storageStream;
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsStorageStream.h b/src/libs/xpcom18a4/xpcom/io/nsStorageStream.h
new file mode 100644
index 00000000..0729c01c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsStorageStream.h
@@ -0,0 +1,98 @@
+/* -*- 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-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 ***** */
+
+/*
+ * The storage stream provides an internal buffer that can be filled by a
+ * client using a single output stream. One or more independent input streams
+ * can be created to read the data out non-destructively. The implementation
+ * uses a segmented buffer internally to avoid realloc'ing of large buffers,
+ * with the attendant performance loss and heap fragmentation.
+ */
+
+#ifndef _nsStorageStream_h_
+#define _nsStorageStream_h_
+
+#include "nsIStorageStream.h"
+#include "nsIOutputStream.h"
+#include "nsMemory.h"
+
+#define NS_STORAGESTREAM_CID \
+{ /* 669a9795-6ff7-4ed4-9150-c34ce2971b63 */ \
+ 0x669a9795, \
+ 0x6ff7, \
+ 0x4ed4, \
+ {0x91, 0x50, 0xc3, 0x4c, 0xe2, 0x97, 0x1b, 0x63} \
+}
+
+#define NS_STORAGESTREAM_CONTRACTID "@mozilla.org/storagestream;1"
+#define NS_STORAGESTREAM_CLASSNAME "Storage Stream"
+
+class nsSegmentedBuffer;
+
+class nsStorageStream : public nsIStorageStream,
+ public nsIOutputStream
+{
+public:
+ nsStorageStream();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISTORAGESTREAM
+ NS_DECL_NSIOUTPUTSTREAM
+
+ friend class nsStorageInputStream;
+
+private:
+ ~nsStorageStream();
+
+ nsSegmentedBuffer* mSegmentedBuffer;
+ PRUint32 mSegmentSize; // All segments, except possibly the last, are of this size
+ // Must be power-of-2
+ PRUint32 mSegmentSizeLog2; // log2(mSegmentSize)
+ PRBool mWriteInProgress; // true, if an un-Close'ed output stream exists
+ PRInt32 mLastSegmentNum; // Last segment # in use, -1 initially
+ char* mWriteCursor; // Pointer to next byte to be written
+ char* mSegmentEnd; // Pointer to one byte after end of segment
+ // containing the write cursor
+ PRUint32 mLogicalLength; // Number of bytes written to stream
+
+ NS_METHOD Seek(PRInt32 aPosition);
+ PRUint32 SegNum(PRUint32 aPosition) {return aPosition >> mSegmentSizeLog2;}
+ PRUint32 SegOffset(PRUint32 aPosition) {return aPosition & (mSegmentSize - 1);}
+};
+
+#endif // _nsStorageStream_h_
diff --git a/src/libs/xpcom18a4/xpcom/io/nsStreamUtils.cpp b/src/libs/xpcom18a4/xpcom/io/nsStreamUtils.cpp
new file mode 100644
index 00000000..aeb52b2a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsStreamUtils.cpp
@@ -0,0 +1,583 @@
+/* ***** 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.
+ *
+ * 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):
+ * Darin Fisher <darin@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 "nsStreamUtils.h"
+#include "nsCOMPtr.h"
+#include "nsIPipe.h"
+#include "nsIEventTarget.h"
+#include "nsAutoLock.h"
+
+//-----------------------------------------------------------------------------
+
+class nsInputStreamReadyEvent : public PLEvent
+ , public nsIInputStreamCallback
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ nsInputStreamReadyEvent(nsIInputStreamCallback *callback,
+ nsIEventTarget *target)
+ : mCallback(callback)
+ , mTarget(target)
+ {
+ }
+
+private:
+ ~nsInputStreamReadyEvent()
+ {
+ if (mCallback) {
+ nsresult rv;
+ //
+ // whoa!! looks like we never posted this event. take care to
+ // release mCallback on the correct thread. if mTarget lives on the
+ // calling thread, then we are ok. otherwise, we have to try to
+ // proxy the Release over the right thread. if that thread is dead,
+ // then there's nothing we can do... better to leak than crash.
+ //
+ PRBool val;
+ rv = mTarget->IsOnCurrentThread(&val);
+ if (NS_FAILED(rv) || !val) {
+ nsCOMPtr<nsIInputStreamCallback> event;
+ NS_NewInputStreamReadyEvent(getter_AddRefs(event), mCallback, mTarget);
+ mCallback = 0;
+ if (event) {
+ rv = event->OnInputStreamReady(nsnull);
+ if (NS_FAILED(rv)) {
+ NS_NOTREACHED("leaking stream event");
+ nsISupports *sup = event;
+ NS_ADDREF(sup);
+ }
+ }
+ }
+ }
+ }
+
+public:
+ NS_IMETHOD OnInputStreamReady(nsIAsyncInputStream *stream)
+ {
+ mStream = stream;
+
+ // will be released when event is handled
+ NS_ADDREF_THIS();
+
+ PL_InitEvent(this, nsnull, EventHandler, EventCleanup);
+
+ if (NS_FAILED(mTarget->PostEvent(this))) {
+ NS_WARNING("PostEvent failed");
+ NS_RELEASE_THIS();
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+ }
+
+private:
+ nsCOMPtr<nsIAsyncInputStream> mStream;
+ nsCOMPtr<nsIInputStreamCallback> mCallback;
+ nsCOMPtr<nsIEventTarget> mTarget;
+
+ PR_STATIC_CALLBACK(void *) EventHandler(PLEvent *plevent)
+ {
+ nsInputStreamReadyEvent *ev = (nsInputStreamReadyEvent *) plevent;
+ // bypass event delivery if this is a cleanup event...
+ if (ev->mCallback)
+ ev->mCallback->OnInputStreamReady(ev->mStream);
+ ev->mCallback = 0;
+ return NULL;
+ }
+
+ PR_STATIC_CALLBACK(void) EventCleanup(PLEvent *plevent)
+ {
+ nsInputStreamReadyEvent *ev = (nsInputStreamReadyEvent *) plevent;
+ NS_RELEASE(ev);
+ }
+};
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsInputStreamReadyEvent,
+ nsIInputStreamCallback)
+
+//-----------------------------------------------------------------------------
+
+class nsOutputStreamReadyEvent : public PLEvent
+ , public nsIOutputStreamCallback
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ nsOutputStreamReadyEvent(nsIOutputStreamCallback *callback,
+ nsIEventTarget *target)
+ : mCallback(callback)
+ , mTarget(target)
+ {
+ }
+
+private:
+ ~nsOutputStreamReadyEvent()
+ {
+ if (mCallback) {
+ nsresult rv;
+ //
+ // whoa!! looks like we never posted this event. take care to
+ // release mCallback on the correct thread. if mTarget lives on the
+ // calling thread, then we are ok. otherwise, we have to try to
+ // proxy the Release over the right thread. if that thread is dead,
+ // then there's nothing we can do... better to leak than crash.
+ //
+ PRBool val;
+ rv = mTarget->IsOnCurrentThread(&val);
+ if (NS_FAILED(rv) || !val) {
+ nsCOMPtr<nsIOutputStreamCallback> event;
+ NS_NewOutputStreamReadyEvent(getter_AddRefs(event), mCallback, mTarget);
+ mCallback = 0;
+ if (event) {
+ rv = event->OnOutputStreamReady(nsnull);
+ if (NS_FAILED(rv)) {
+ NS_NOTREACHED("leaking stream event");
+ nsISupports *sup = event;
+ NS_ADDREF(sup);
+ }
+ }
+ }
+ }
+ }
+
+public:
+ void Init(nsIOutputStreamCallback *callback, nsIEventTarget *target)
+ {
+ mCallback = callback;
+ mTarget = target;
+
+ PL_InitEvent(this, nsnull, EventHandler, EventCleanup);
+ }
+
+ NS_IMETHOD OnOutputStreamReady(nsIAsyncOutputStream *stream)
+ {
+ mStream = stream;
+
+ // this will be released when the event is handled
+ NS_ADDREF_THIS();
+
+ PL_InitEvent(this, nsnull, EventHandler, EventCleanup);
+
+ if (NS_FAILED(mTarget->PostEvent(this))) {
+ NS_WARNING("PostEvent failed");
+ NS_RELEASE_THIS();
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+ }
+
+private:
+ nsCOMPtr<nsIAsyncOutputStream> mStream;
+ nsCOMPtr<nsIOutputStreamCallback> mCallback;
+ nsCOMPtr<nsIEventTarget> mTarget;
+
+ PR_STATIC_CALLBACK(void *) EventHandler(PLEvent *plevent)
+ {
+ nsOutputStreamReadyEvent *ev = (nsOutputStreamReadyEvent *) plevent;
+ if (ev->mCallback)
+ ev->mCallback->OnOutputStreamReady(ev->mStream);
+ ev->mCallback = 0;
+ return NULL;
+ }
+
+ PR_STATIC_CALLBACK(void) EventCleanup(PLEvent *ev)
+ {
+ nsOutputStreamReadyEvent *event = (nsOutputStreamReadyEvent *) ev;
+ NS_RELEASE(event);
+ }
+};
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsOutputStreamReadyEvent,
+ nsIOutputStreamCallback)
+
+//-----------------------------------------------------------------------------
+
+NS_COM nsresult
+NS_NewInputStreamReadyEvent(nsIInputStreamCallback **event,
+ nsIInputStreamCallback *callback,
+ nsIEventTarget *target)
+{
+ nsInputStreamReadyEvent *ev = new nsInputStreamReadyEvent(callback, target);
+ if (!ev)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(*event = ev);
+ return NS_OK;
+}
+
+NS_COM nsresult
+NS_NewOutputStreamReadyEvent(nsIOutputStreamCallback **event,
+ nsIOutputStreamCallback *callback,
+ nsIEventTarget *target)
+{
+ nsOutputStreamReadyEvent *ev = new nsOutputStreamReadyEvent(callback, target);
+ if (!ev)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(*event = ev);
+ return NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+// NS_AsyncCopy implementation
+
+// abstract stream copier...
+class nsAStreamCopier : public nsIInputStreamCallback
+ , public nsIOutputStreamCallback
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ nsAStreamCopier()
+ : mLock(nsnull)
+ , mCallback(nsnull)
+ , mClosure(nsnull)
+ , mChunkSize(0)
+ , mEventInProcess(PR_FALSE)
+ , mEventIsPending(PR_FALSE)
+ {
+ }
+
+ // virtual since subclasses call superclass Release()
+ virtual ~nsAStreamCopier()
+ {
+ if (mLock)
+ PR_DestroyLock(mLock);
+ }
+
+ // kick off the async copy...
+ nsresult Start(nsIInputStream *source,
+ nsIOutputStream *sink,
+ nsIEventTarget *target,
+ nsAsyncCopyCallbackFun callback,
+ void *closure,
+ PRUint32 chunksize)
+ {
+ mSource = source;
+ mSink = sink;
+ mTarget = target;
+ mCallback = callback;
+ mClosure = closure;
+ mChunkSize = chunksize;
+
+ mLock = PR_NewLock();
+ if (!mLock)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ mAsyncSource = do_QueryInterface(mSource);
+ mAsyncSink = do_QueryInterface(mSink);
+
+ return PostContinuationEvent();
+ }
+
+ // implemented by subclasses, returns number of bytes copied and
+ // sets source and sink condition before returning.
+ virtual PRUint32 DoCopy(nsresult *sourceCondition, nsresult *sinkCondition) = 0;
+
+ void Process()
+ {
+ if (!mSource || !mSink)
+ return;
+
+ nsresult sourceCondition, sinkCondition;
+
+ // ok, copy data from source to sink.
+ for (;;) {
+ PRUint32 n = DoCopy(&sourceCondition, &sinkCondition);
+ if (NS_FAILED(sourceCondition) || NS_FAILED(sinkCondition) || n == 0) {
+ if (sourceCondition == NS_BASE_STREAM_WOULD_BLOCK && mAsyncSource) {
+ // need to wait for more data from source. while waiting for
+ // more source data, be sure to observe failures on output end.
+ mAsyncSource->AsyncWait(this, 0, 0, nsnull);
+
+ if (mAsyncSink)
+ mAsyncSink->AsyncWait(this,
+ nsIAsyncOutputStream::WAIT_CLOSURE_ONLY,
+ 0, nsnull);
+ }
+ else if (sinkCondition == NS_BASE_STREAM_WOULD_BLOCK && mAsyncSink) {
+ // need to wait for more room in the sink. while waiting for
+ // more room in the sink, be sure to observer failures on the
+ // input end.
+ mAsyncSink->AsyncWait(this, 0, 0, nsnull);
+
+ if (mAsyncSource)
+ mAsyncSource->AsyncWait(this,
+ nsIAsyncInputStream::WAIT_CLOSURE_ONLY,
+ 0, nsnull);
+ }
+ else {
+ // close source
+ if (mAsyncSource)
+ mAsyncSource->CloseWithStatus(sinkCondition);
+ else
+ mSource->Close();
+ mAsyncSource = nsnull;
+ mSource = nsnull;
+
+ // close sink
+ if (mAsyncSink)
+ mAsyncSink->CloseWithStatus(sourceCondition);
+ else
+ mSink->Close();
+ mAsyncSink = nsnull;
+ mSink = nsnull;
+
+ // notify state complete...
+ if (mCallback) {
+ nsresult status = sourceCondition;
+ if (NS_SUCCEEDED(status))
+ status = sinkCondition;
+ if (status == NS_BASE_STREAM_CLOSED)
+ status = NS_OK;
+ mCallback(mClosure, status);
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ NS_IMETHOD OnInputStreamReady(nsIAsyncInputStream *source)
+ {
+ PostContinuationEvent();
+ return NS_OK;
+ }
+
+ NS_IMETHOD OnOutputStreamReady(nsIAsyncOutputStream *sink)
+ {
+ PostContinuationEvent();
+ return NS_OK;
+ }
+
+ PR_STATIC_CALLBACK(void*) HandleContinuationEvent(PLEvent *event)
+ {
+ nsAStreamCopier *self = (nsAStreamCopier *) event->owner;
+ self->Process();
+
+ // clear "in process" flag and post any pending continuation event
+ nsAutoLock lock(self->mLock);
+ self->mEventInProcess = PR_FALSE;
+ if (self->mEventIsPending) {
+ self->mEventIsPending = PR_FALSE;
+ self->PostContinuationEvent_Locked();
+ }
+ return nsnull;
+ }
+
+ PR_STATIC_CALLBACK(void) DestroyContinuationEvent(PLEvent *event)
+ {
+ nsAStreamCopier *self = (nsAStreamCopier *) event->owner;
+ NS_RELEASE(self);
+ delete event;
+ }
+
+ nsresult PostContinuationEvent()
+ {
+ // we cannot post a continuation event if there is currently
+ // an event in process. doing so could result in Process being
+ // run simultaneously on multiple threads, so we mark the event
+ // as pending, and if an event is already in process then we
+ // just let that existing event take care of posting the real
+ // continuation event.
+
+ nsAutoLock lock(mLock);
+ return PostContinuationEvent_Locked();
+ }
+
+ nsresult PostContinuationEvent_Locked()
+ {
+ nsresult rv = NS_OK;
+ if (mEventInProcess)
+ mEventIsPending = PR_TRUE;
+ else {
+ PLEvent *event = new PLEvent;
+ if (!event)
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ else {
+ NS_ADDREF_THIS();
+ PL_InitEvent(event, this,
+ HandleContinuationEvent,
+ DestroyContinuationEvent);
+
+ rv = mTarget->PostEvent(event);
+ if (NS_SUCCEEDED(rv))
+ mEventInProcess = PR_TRUE;
+ else {
+ NS_ERROR("unable to post continuation event");
+ PL_DestroyEvent(event);
+ }
+ }
+ }
+ return rv;
+ }
+
+protected:
+ nsCOMPtr<nsIInputStream> mSource;
+ nsCOMPtr<nsIOutputStream> mSink;
+ nsCOMPtr<nsIAsyncInputStream> mAsyncSource;
+ nsCOMPtr<nsIAsyncOutputStream> mAsyncSink;
+ nsCOMPtr<nsIEventTarget> mTarget;
+ PRLock *mLock;
+ nsAsyncCopyCallbackFun mCallback;
+ void *mClosure;
+ PRUint32 mChunkSize;
+ PRPackedBool mEventInProcess;
+ PRPackedBool mEventIsPending;
+};
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsAStreamCopier,
+ nsIInputStreamCallback,
+ nsIOutputStreamCallback)
+
+class nsStreamCopierIB : public nsAStreamCopier
+{
+public:
+ nsStreamCopierIB() : nsAStreamCopier() {}
+ virtual ~nsStreamCopierIB() {}
+
+ struct ReadSegmentsState {
+ nsIOutputStream *mSink;
+ nsresult mSinkCondition;
+ };
+
+ static NS_METHOD ConsumeInputBuffer(nsIInputStream *inStr,
+ void *closure,
+ const char *buffer,
+ PRUint32 offset,
+ PRUint32 count,
+ PRUint32 *countWritten)
+ {
+ ReadSegmentsState *state = (ReadSegmentsState *) closure;
+
+ nsresult rv = state->mSink->Write(buffer, count, countWritten);
+ if (NS_FAILED(rv))
+ state->mSinkCondition = rv;
+ else if (*countWritten == 0)
+ state->mSinkCondition = NS_BASE_STREAM_CLOSED;
+
+ return state->mSinkCondition;
+ }
+
+ PRUint32 DoCopy(nsresult *sourceCondition, nsresult *sinkCondition)
+ {
+ ReadSegmentsState state;
+ state.mSink = mSink;
+ state.mSinkCondition = NS_OK;
+
+ PRUint32 n;
+ *sourceCondition =
+ mSource->ReadSegments(ConsumeInputBuffer, &state, mChunkSize, &n);
+ *sinkCondition = state.mSinkCondition;
+ return n;
+ }
+};
+
+class nsStreamCopierOB : public nsAStreamCopier
+{
+public:
+ nsStreamCopierOB() : nsAStreamCopier() {}
+ virtual ~nsStreamCopierOB() {}
+
+ struct WriteSegmentsState {
+ nsIInputStream *mSource;
+ nsresult mSourceCondition;
+ };
+
+ static NS_METHOD FillOutputBuffer(nsIOutputStream *outStr,
+ void *closure,
+ char *buffer,
+ PRUint32 offset,
+ PRUint32 count,
+ PRUint32 *countRead)
+ {
+ WriteSegmentsState *state = (WriteSegmentsState *) closure;
+
+ nsresult rv = state->mSource->Read(buffer, count, countRead);
+ if (NS_FAILED(rv))
+ state->mSourceCondition = rv;
+ else if (*countRead == 0)
+ state->mSourceCondition = NS_BASE_STREAM_CLOSED;
+
+ return state->mSourceCondition;
+ }
+
+ PRUint32 DoCopy(nsresult *sourceCondition, nsresult *sinkCondition)
+ {
+ WriteSegmentsState state;
+ state.mSource = mSource;
+ state.mSourceCondition = NS_OK;
+
+ PRUint32 n;
+ *sinkCondition =
+ mSink->WriteSegments(FillOutputBuffer, &state, mChunkSize, &n);
+ *sourceCondition = state.mSourceCondition;
+ return n;
+ }
+};
+
+//-----------------------------------------------------------------------------
+
+NS_COM nsresult
+NS_AsyncCopy(nsIInputStream *source,
+ nsIOutputStream *sink,
+ nsIEventTarget *target,
+ nsAsyncCopyMode mode,
+ PRUint32 chunkSize,
+ nsAsyncCopyCallbackFun callback,
+ void *closure)
+{
+ NS_ASSERTION(target, "non-null target required");
+
+ nsresult rv;
+ nsAStreamCopier *copier;
+
+ if (mode == NS_ASYNCCOPY_VIA_READSEGMENTS)
+ copier = new nsStreamCopierIB();
+ else
+ copier = new nsStreamCopierOB();
+
+ if (!copier)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Start() takes an owning ref to the copier...
+ NS_ADDREF(copier);
+ rv = copier->Start(source, sink, target, callback, closure, chunkSize);
+ NS_RELEASE(copier);
+
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsStreamUtils.h b/src/libs/xpcom18a4/xpcom/io/nsStreamUtils.h
new file mode 100644
index 00000000..3d33f1c1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsStreamUtils.h
@@ -0,0 +1,111 @@
+/* ***** 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.
+ *
+ * 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):
+ * Darin Fisher <darin@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 nsStreamUtils_h__
+#define nsStreamUtils_h__
+
+#include "nscore.h"
+
+class nsIInputStream;
+class nsIOutputStream;
+class nsIInputStreamCallback;
+class nsIOutputStreamCallback;
+class nsIEventTarget;
+
+/**
+ * A "one-shot" proxy of the OnInputStreamReady callback. The resulting
+ * proxy object's OnInputStreamReady function may only be called once! The
+ * proxy object ensures that the real notify object will be free'd on the
+ * thread corresponding to the given event target regardless of what thread
+ * the proxy object is destroyed on.
+ *
+ * This function is designed to be used to implement AsyncWait when the
+ * aEventTarget parameter is non-null.
+ */
+extern NS_COM nsresult
+NS_NewInputStreamReadyEvent(nsIInputStreamCallback **aEvent,
+ nsIInputStreamCallback *aNotify,
+ nsIEventTarget *aEventTarget);
+
+/**
+ * A "one-shot" proxy of the OnOutputStreamReady callback. The resulting
+ * proxy object's OnOutputStreamReady function may only be called once! The
+ * proxy object ensures that the real notify object will be free'd on the
+ * thread corresponding to the given event target regardless of what thread
+ * the proxy object is destroyed on.
+ *
+ * This function is designed to be used to implement AsyncWait when the
+ * aEventTarget parameter is non-null.
+ */
+extern NS_COM nsresult
+NS_NewOutputStreamReadyEvent(nsIOutputStreamCallback **aEvent,
+ nsIOutputStreamCallback *aNotify,
+ nsIEventTarget *aEventTarget);
+
+/* ------------------------------------------------------------------------- */
+
+enum nsAsyncCopyMode {
+ NS_ASYNCCOPY_VIA_READSEGMENTS,
+ NS_ASYNCCOPY_VIA_WRITESEGMENTS
+};
+
+/**
+ * This function is called when the async copy process completes. The reported
+ * status is NS_OK on success and some error code on failure.
+ */
+typedef void (* nsAsyncCopyCallbackFun)(void *closure, nsresult status);
+
+/**
+ * This function asynchronously copies data from the source to the sink. All
+ * data transfer occurs on the thread corresponding to the given event target.
+ * A null event target is not permitted.
+ *
+ * The copier handles blocking or non-blocking streams transparently. If a
+ * stream operation returns NS_BASE_STREAM_WOULD_BLOCK, then the stream will
+ * be QI'd to nsIAsync{In,Out}putStream and its AsyncWait method will be used
+ * to determine when to resume copying.
+ */
+extern NS_COM nsresult
+NS_AsyncCopy(nsIInputStream *aSource,
+ nsIOutputStream *aSink,
+ nsIEventTarget *aEventTarget,
+ nsAsyncCopyMode aMode = NS_ASYNCCOPY_VIA_READSEGMENTS,
+ PRUint32 aChunkSize = 4096,
+ nsAsyncCopyCallbackFun aCallbackFun = nsnull,
+ void *aCallbackClosure = nsnull);
+
+#endif // !nsStreamUtils_h__
diff --git a/src/libs/xpcom18a4/xpcom/io/nsStringIO.h b/src/libs/xpcom18a4/xpcom/io/nsStringIO.h
new file mode 100644
index 00000000..beca1d19
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsStringIO.h
@@ -0,0 +1,86 @@
+/* -*- 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):
+ * Scott Collins <scc@mozilla.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 ***** */
+
+#ifndef nsStringIO_h___
+#define nsStringIO_h___
+
+#include "nsAString.h"
+#include <stdio.h>
+
+
+template <class CharT>
+class nsFileCharSink
+ {
+ public:
+ typedef CharT value_type;
+
+ public:
+ nsFileCharSink( FILE* aOutputFile ) : mOutputFile(aOutputFile) { }
+
+ PRUint32
+ write( const value_type* s, PRUint32 n )
+ {
+ return fwrite(s, sizeof(CharT), n, mOutputFile);
+ }
+
+ private:
+ FILE* mOutputFile;
+ };
+
+
+template <class CharT>
+inline
+void
+fprint_string( FILE* aFile, const basic_nsAString<CharT>& aString )
+ {
+ nsReadingIterator<CharT> fromBegin, fromEnd;
+ nsFileCharSink<CharT> toBegin(aFile);
+ copy_string(aString.BeginReading(fromBegin), aString.EndReading(fromEnd), toBegin);
+ }
+
+
+template <class CharT>
+inline
+void
+print_string( const basic_nsAString<CharT>& aString )
+ {
+ fprint_string(stdout, aString);
+ }
+
+
+#endif // !defined(nsStringIO_h___)
diff --git a/src/libs/xpcom18a4/xpcom/io/nsStringStream.cpp b/src/libs/xpcom18a4/xpcom/io/nsStringStream.cpp
new file mode 100644
index 00000000..536eab11
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsStringStream.cpp
@@ -0,0 +1,457 @@
+/* -*- 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):
+ * mcmullen@netscape.com (original author)
+ * warren@netscape.com
+ * alecf@netscape.com
+ * scc@mozilla.org
+ * david.gardiner@unisa.edu.au
+ * fur@netscape.com
+ * norris@netscape.com
+ * pinkerton@netscape.com
+ * davidm@netscape.com
+ * sfraser@netscape.com
+ * darin@netscape.com
+ * bzbarsky@mit.edu
+ *
+ * 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 ***** */
+
+/**
+ * Based on original code from nsIStringStream.cpp
+ */
+
+#include "nsStringStream.h"
+
+#include "prerror.h"
+#include "plstr.h"
+#include "nsReadableUtils.h"
+#include "nsCRT.h"
+#include "nsISeekableStream.h"
+#include "nsInt64.h"
+
+#define NS_FILE_RESULT(x) ns_file_convert_result((PRInt32)x)
+#define NS_FILE_FAILURE NS_FILE_RESULT(-1)
+
+static nsresult ns_file_convert_result(PRInt32 nativeErr)
+{
+ return nativeErr ?
+ NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES,((nativeErr)&0xFFFF))
+ : NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+// nsIStringInputStream implementation
+//-----------------------------------------------------------------------------
+
+class nsStringInputStream : public nsIStringInputStream
+ , public nsIRandomAccessStore
+
+{
+public:
+ nsStringInputStream()
+ : mOffset(0)
+ , mLastResult(NS_OK)
+ , mEOF(PR_FALSE)
+ , mOwned(PR_FALSE)
+ , mConstString(nsnull)
+ , mLength(0)
+ {}
+
+private:
+ ~nsStringInputStream()
+ {
+ if (mOwned)
+ nsMemory::Free((char*)mConstString);
+ }
+
+public:
+ NS_DECL_ISUPPORTS
+
+ NS_DECL_NSISTRINGINPUTSTREAM
+ NS_DECL_NSIINPUTSTREAM
+
+ // nsIRandomAccessStore interface
+ NS_IMETHOD GetAtEOF(PRBool* outAtEOF);
+ NS_IMETHOD SetAtEOF(PRBool inAtEOF);
+
+ NS_DECL_NSISEEKABLESTREAM
+
+protected:
+ PRInt32 LengthRemaining() const
+ {
+ return mLength - mOffset;
+ }
+
+ void Clear()
+ {
+ NS_ASSERTION(mConstString || !mOwned,
+ "Can't have mOwned set and have a null string!");
+ if (mOwned)
+ nsMemory::Free((char*)mConstString);
+
+ // We're about to get a new string; clear the members that
+ // would no longer have valid values.
+ mOffset = 0;
+ mLastResult = NS_OK;
+ mEOF = PR_FALSE;
+ }
+
+ PRInt32 mOffset;
+ nsresult mLastResult;
+ PRPackedBool mEOF;
+ PRPackedBool mOwned;
+ const char* mConstString;
+ PRInt32 mLength;
+};
+
+NS_IMPL_THREADSAFE_ISUPPORTS4(nsStringInputStream,
+ nsIStringInputStream,
+ nsIInputStream,
+ nsIRandomAccessStore,
+ nsISeekableStream)
+
+/////////
+// nsIStringInputStream implementation
+/////////
+NS_IMETHODIMP
+nsStringInputStream::SetData(const char *data, PRInt32 dataLen)
+{
+ if (dataLen < 0)
+ dataLen = strlen(data);
+
+ return AdoptData(nsCRT::strndup(data, dataLen), dataLen);
+}
+
+NS_IMETHODIMP
+nsStringInputStream::AdoptData(char *data, PRInt32 dataLen)
+{
+ NS_ENSURE_ARG_POINTER(data);
+
+ if (dataLen < 0)
+ dataLen = strlen(data);
+
+ Clear();
+
+ mConstString = (const char *) data;
+ mLength = dataLen;
+ mOwned = PR_TRUE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStringInputStream::ShareData(const char *data, PRInt32 dataLen)
+{
+ NS_ENSURE_ARG_POINTER(data);
+
+ if (dataLen < 0)
+ dataLen = strlen(data);
+
+ Clear();
+
+ mConstString = data;
+ mLength = dataLen;
+ mOwned = PR_FALSE;
+ return NS_OK;
+}
+
+/////////
+// nsIInputStream implementation
+/////////
+NS_IMETHODIMP nsStringInputStream::Close()
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsStringInputStream::Available(PRUint32 *aLength)
+{
+ NS_PRECONDITION(aLength != nsnull, "null ptr");
+ if (!aLength)
+ return NS_ERROR_NULL_POINTER;
+ *aLength = LengthRemaining();
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsStringInputStream::Read(char* aBuf, PRUint32 aCount,
+ PRUint32 *aReadCount)
+{
+ NS_PRECONDITION(aBuf != nsnull, "null ptr");
+ if (!aBuf)
+ return NS_ERROR_NULL_POINTER;
+ NS_PRECONDITION(aReadCount != nsnull, "null ptr");
+ if (!aReadCount)
+ return NS_ERROR_NULL_POINTER;
+ if (NS_FAILED(mLastResult))
+ return mLastResult;
+
+ PRInt32 bytesRead;
+ PRInt32 maxCount = mLength - mOffset;
+ if ((PRInt32)aCount > maxCount)
+ bytesRead = maxCount;
+ else
+ bytesRead = aCount;
+
+ memcpy(aBuf, mConstString + mOffset, bytesRead);
+ mOffset += bytesRead;
+
+ *aReadCount = bytesRead;
+ if (bytesRead < (PRInt32)aCount)
+ SetAtEOF(PR_TRUE);
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsStringInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure,
+ PRUint32 aCount, PRUint32 * result)
+{
+ nsresult rv;
+ PRInt32 maxCount = mLength - mOffset;
+ if (maxCount == 0) {
+ *result = 0;
+ return NS_OK;
+ }
+ if ((PRInt32)aCount > maxCount)
+ aCount = maxCount;
+ rv = writer(this, closure, mConstString + mOffset,
+ 0, aCount, result);
+ if (NS_SUCCEEDED(rv))
+ mOffset += *result;
+ // errors returned from the writer end here!
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStringInputStream::IsNonBlocking(PRBool *aNonBlocking)
+{
+ *aNonBlocking = PR_TRUE;
+ return NS_OK;
+}
+
+
+/////////
+// nsISeekableStream implementation
+/////////
+NS_IMETHODIMP nsStringInputStream::Seek(PRInt32 whence, PRInt64 offset)
+{
+ mLastResult = NS_OK; // reset on a seek.
+ const nsInt64 maxUint32 = PR_UINT32_MAX;
+ nsInt64 offset64(offset);
+ PRInt32 offset32;
+ LL_L2I(offset32, offset);
+
+ NS_ASSERTION(maxUint32 > offset64, "string streams only support 32 bit offsets");
+ mEOF = PR_FALSE; // reset on a seek.
+ PRInt32 fileSize = LengthRemaining();
+ PRInt32 newPosition=-1;
+ switch (whence)
+ {
+ case NS_SEEK_CUR: newPosition = mOffset + offset32; break;
+ case NS_SEEK_SET: newPosition = offset32; break;
+ case NS_SEEK_END: newPosition = fileSize + offset32; break;
+ }
+ if (newPosition < 0)
+ {
+ newPosition = 0;
+ mLastResult = NS_FILE_RESULT(PR_FILE_SEEK_ERROR);
+ }
+ if (newPosition >= fileSize)
+ {
+ newPosition = fileSize;
+ mEOF = PR_TRUE;
+ }
+ mOffset = newPosition;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP nsStringInputStream::Tell(PRInt64* outWhere)
+{
+ *outWhere = mOffset;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsStringInputStream::SetEOF()
+{
+ NS_NOTYETIMPLEMENTED("nsStringInputStream::SetEOF");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/////////
+// nsIRandomAccessStore implementation
+/////////
+NS_IMETHODIMP nsStringInputStream::GetAtEOF(PRBool* outAtEOF)
+{
+ *outAtEOF = mEOF;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsStringInputStream::SetAtEOF(PRBool inAtEOF)
+{
+ mEOF = inAtEOF;
+ return NS_OK;
+}
+
+// Factory method to get an nsInputStream from an nsAString. Result will
+// implement nsIStringInputStream and nsIRandomAccessStore
+extern "C" NS_COM nsresult
+NS_NewStringInputStream(nsIInputStream** aStreamResult,
+ const nsAString& aStringToRead)
+{
+ NS_PRECONDITION(aStreamResult, "null out ptr");
+
+ char* data = ToNewCString(aStringToRead);
+ if (!data)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsStringInputStream* stream = new nsStringInputStream();
+ if (! stream) {
+ nsMemory::Free(data);
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ NS_ADDREF(stream);
+
+ nsresult rv = stream->AdoptData(data, aStringToRead.Length());
+ if (NS_FAILED(rv)) {
+ nsMemory::Free(data);
+ NS_RELEASE(stream);
+ return rv;
+ }
+
+ *aStreamResult = stream;
+ return NS_OK;
+}
+
+// Factory method to get an nsInputStream from an nsACString. Result will
+// implement nsIStringInputStream and nsIRandomAccessStore
+extern "C" NS_COM nsresult
+NS_NewCStringInputStream(nsIInputStream** aStreamResult,
+ const nsACString& aStringToRead)
+{
+ NS_PRECONDITION(aStreamResult, "null out ptr");
+
+ char* data = ToNewCString(aStringToRead);
+ if (!data)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsStringInputStream* stream = new nsStringInputStream();
+ if (! stream) {
+ nsMemory::Free(data);
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ NS_ADDREF(stream);
+
+ nsresult rv = stream->AdoptData(data, aStringToRead.Length());
+ if (NS_FAILED(rv)) {
+ nsMemory::Free(data);
+ NS_RELEASE(stream);
+ return rv;
+ }
+
+ *aStreamResult = stream;
+ return NS_OK;
+}
+
+// Factory method to get an nsInputStream from a C string. Result will
+// implement nsIStringInputStream and nsIRandomAccessStore
+extern "C" NS_COM nsresult
+NS_NewCharInputStream(nsIInputStream** aStreamResult,
+ const char* aStringToRead)
+{
+ NS_PRECONDITION(aStreamResult, "null out ptr");
+
+ nsStringInputStream* stream = new nsStringInputStream();
+ if (! stream)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(stream);
+
+ nsresult rv = stream->ShareData(aStringToRead, -1);
+
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(stream);
+ return rv;
+ }
+
+ *aStreamResult = stream;
+ return NS_OK;
+}
+
+// Factory method to get an nsInputStream from a byte array. Result will
+// implement nsIStringInputStream and nsIRandomAccessStore
+extern "C" NS_COM nsresult
+NS_NewByteInputStream(nsIInputStream** aStreamResult,
+ const char* aStringToRead,
+ PRInt32 aLength)
+{
+ NS_PRECONDITION(aStreamResult, "null out ptr");
+
+ nsStringInputStream* stream = new nsStringInputStream();
+ if (! stream)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(stream);
+
+ nsresult rv = stream->ShareData(aStringToRead, aLength);
+
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(stream);
+ return rv;
+ }
+
+ *aStreamResult = stream;
+ return NS_OK;
+}
+
+// factory method for constructing a nsStringInputStream object
+NS_METHOD
+nsStringInputStreamConstructor(nsISupports *outer, REFNSIID iid, void **result)
+{
+ *result = nsnull;
+
+ if (outer)
+ return NS_ERROR_NO_AGGREGATION;
+
+ nsStringInputStream *inst;
+ NS_NEWXPCOM(inst, nsStringInputStream);
+ if (!inst)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(inst);
+ nsresult rv = inst->QueryInterface(iid, result);
+ NS_RELEASE(inst);
+
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/io/nsStringStream.h b/src/libs/xpcom18a4/xpcom/io/nsStringStream.h
new file mode 100644
index 00000000..6f2f7f20
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsStringStream.h
@@ -0,0 +1,84 @@
+/* -*- 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):
+ * darin@netscape.com (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 nsStringStream_h__
+#define nsStringStream_h__
+
+#include "nsISeekableStream.h"
+
+/* a6cf90e8-15b3-11d2-932e-00805f8add32 */
+#define NS_IRANDOMACCESS_IID \
+{ 0xa6cf90eb, 0x15b3, 0x11d2, \
+ {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} }
+
+//========================================================================================
+class nsIRandomAccessStore
+// Supports Seek, Tell etc.
+//========================================================================================
+: public nsISeekableStream
+{
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IRANDOMACCESS_IID)
+
+/* "PROTECTED" */
+ NS_IMETHOD GetAtEOF(PRBool* outAtEOF) = 0;
+ NS_IMETHOD SetAtEOF(PRBool inAtEOF) = 0;
+}; // class nsIRandomAccessStore
+
+#include "nsIStringStream.h"
+
+/**
+ * nsStringInputStream : nsIStringInputStream
+ * , nsIInputStream
+ * , nsISeekableStream
+ * , nsIRandomAccessStore
+ */
+#define NS_STRINGINPUTSTREAM_CLASSNAME "nsStringInputStream"
+#define NS_STRINGINPUTSTREAM_CONTRACTID "@mozilla.org/io/string-input-stream;1"
+#define NS_STRINGINPUTSTREAM_CID \
+{ /* 0abb0835-5000-4790-af28-61b3ba17c295 */ \
+ 0x0abb0835, \
+ 0x5000, \
+ 0x4790, \
+ {0xaf, 0x28, 0x61, 0xb3, 0xba, 0x17, 0xc2, 0x95} \
+}
+extern NS_METHOD nsStringInputStreamConstructor(nsISupports *, REFNSIID, void **);
+
+
+
+#endif // nsStringStream_h__
diff --git a/src/libs/xpcom18a4/xpcom/io/nsUnicharInputStream.cpp b/src/libs/xpcom18a4/xpcom/io/nsUnicharInputStream.cpp
new file mode 100644
index 00000000..99e9364a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/io/nsUnicharInputStream.cpp
@@ -0,0 +1,415 @@
+/* -*- 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 "nsIUnicharInputStream.h"
+#include "nsIByteBuffer.h"
+#include "nsIUnicharBuffer.h"
+#include "nsIServiceManager.h"
+#include "nsString.h"
+#include "nsCRT.h"
+#include "nsUTF8Utils.h"
+#include <fcntl.h>
+#if defined(NS_WIN32)
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+class StringUnicharInputStream : public nsIUnicharInputStream {
+public:
+ StringUnicharInputStream(nsString* aString);
+
+ NS_DECL_ISUPPORTS
+
+ NS_IMETHOD Read(PRUnichar* aBuf,
+ PRUint32 aCount,
+ PRUint32 *aReadCount);
+ NS_IMETHOD ReadSegments(nsWriteUnicharSegmentFun aWriter,
+ void* aClosure,
+ PRUint32 aCount, PRUint32* aReadCount);
+ NS_IMETHOD Close();
+
+ nsString* mString;
+ PRUint32 mPos;
+ PRUint32 mLen;
+
+private:
+ ~StringUnicharInputStream();
+};
+
+StringUnicharInputStream::StringUnicharInputStream(nsString* aString)
+{
+ mString = aString;
+ mPos = 0;
+ mLen = aString->Length();
+}
+
+StringUnicharInputStream::~StringUnicharInputStream()
+{
+ if (nsnull != mString) {
+ delete mString;
+ }
+}
+
+NS_IMETHODIMP
+StringUnicharInputStream::Read(PRUnichar* aBuf,
+ PRUint32 aCount,
+ PRUint32 *aReadCount)
+{
+ if (mPos >= mLen) {
+ *aReadCount = 0;
+ return NS_OK;
+ }
+ const PRUnichar* us = mString->get();
+ NS_ASSERTION(mLen >= mPos, "unsigned madness");
+ PRUint32 amount = mLen - mPos;
+ if (amount > aCount) {
+ amount = aCount;
+ }
+ memcpy(aBuf, us + mPos, sizeof(PRUnichar) * amount);
+ mPos += amount;
+ *aReadCount = amount;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+StringUnicharInputStream::ReadSegments(nsWriteUnicharSegmentFun aWriter,
+ void* aClosure,
+ PRUint32 aCount, PRUint32 *aReadCount)
+{
+ PRUint32 bytesWritten;
+ PRUint32 totalBytesWritten = 0;
+
+ nsresult rv;
+ aCount = PR_MIN(mString->Length() - mPos, aCount);
+
+ while (aCount) {
+ rv = aWriter(this, aClosure, mString->get() + mPos,
+ totalBytesWritten, aCount, &bytesWritten);
+
+ if (NS_FAILED(rv)) {
+ // don't propagate errors to the caller
+ break;
+ }
+
+ aCount -= bytesWritten;
+ totalBytesWritten += bytesWritten;
+ mPos += bytesWritten;
+ }
+
+ *aReadCount = totalBytesWritten;
+
+ return NS_OK;
+}
+
+nsresult StringUnicharInputStream::Close()
+{
+ mPos = mLen;
+ if (nsnull != mString) {
+ delete mString;
+ mString = 0;
+ }
+ return NS_OK;
+}
+
+NS_IMPL_ISUPPORTS1(StringUnicharInputStream, nsIUnicharInputStream)
+
+NS_COM nsresult
+NS_NewStringUnicharInputStream(nsIUnicharInputStream** aInstancePtrResult,
+ nsString* aString)
+{
+ NS_PRECONDITION(nsnull != aString, "null ptr");
+ NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
+ if ((nsnull == aString) || (nsnull == aInstancePtrResult)) {
+ return NS_ERROR_NULL_POINTER;
+ }
+
+ StringUnicharInputStream* it = new StringUnicharInputStream(aString);
+ if (nsnull == it) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ return it->QueryInterface(NS_GET_IID(nsIUnicharInputStream),
+ (void**) aInstancePtrResult);
+}
+
+//----------------------------------------------------------------------
+
+class UTF8InputStream : public nsIUnicharInputStream {
+public:
+ UTF8InputStream();
+ nsresult Init(nsIInputStream* aStream, PRUint32 aBufSize);
+
+ NS_DECL_ISUPPORTS
+ NS_IMETHOD Read(PRUnichar* aBuf,
+ PRUint32 aCount,
+ PRUint32 *aReadCount);
+ NS_IMETHOD ReadSegments(nsWriteUnicharSegmentFun aWriter,
+ void* aClosure,
+ PRUint32 aCount,
+ PRUint32 *aReadCount);
+ NS_IMETHOD Close();
+
+private:
+ ~UTF8InputStream();
+
+protected:
+ PRInt32 Fill(nsresult * aErrorCode);
+
+ static void CountValidUTF8Bytes(const char *aBuf, PRUint32 aMaxBytes, PRUint32& aValidUTF8bytes, PRUint32& aValidUCS2bytes);
+
+ nsCOMPtr<nsIInputStream> mInput;
+ nsCOMPtr<nsIByteBuffer> mByteData;
+ nsCOMPtr<nsIUnicharBuffer> mUnicharData;
+
+ PRUint32 mByteDataOffset;
+ PRUint32 mUnicharDataOffset;
+ PRUint32 mUnicharDataLength;
+};
+
+UTF8InputStream::UTF8InputStream() :
+ mByteDataOffset(0),
+ mUnicharDataOffset(0),
+ mUnicharDataLength(0)
+{
+}
+
+nsresult
+UTF8InputStream::Init(nsIInputStream* aStream, PRUint32 aBufferSize)
+{
+ if (aBufferSize == 0) {
+ aBufferSize = 8192;
+ }
+
+ nsresult rv = NS_NewByteBuffer(getter_AddRefs(mByteData), nsnull, aBufferSize);
+ if (NS_FAILED(rv)) return rv;
+ rv = NS_NewUnicharBuffer(getter_AddRefs(mUnicharData), nsnull, aBufferSize);
+ if (NS_FAILED(rv)) return rv;
+
+ mInput = aStream;
+
+ return NS_OK;
+}
+
+NS_IMPL_ISUPPORTS1(UTF8InputStream,nsIUnicharInputStream)
+
+UTF8InputStream::~UTF8InputStream()
+{
+ Close();
+}
+
+nsresult UTF8InputStream::Close()
+{
+ mInput = nsnull;
+ mByteData = nsnull;
+ mUnicharData = nsnull;
+
+ return NS_OK;
+}
+
+nsresult UTF8InputStream::Read(PRUnichar* aBuf,
+ PRUint32 aCount,
+ PRUint32 *aReadCount)
+{
+ NS_ASSERTION(mUnicharDataLength >= mUnicharDataOffset, "unsigned madness");
+ PRUint32 rv = mUnicharDataLength - mUnicharDataOffset;
+ nsresult errorCode;
+ if (0 == rv) {
+ // Fill the unichar buffer
+ rv = Fill(&errorCode);
+ if (rv <= 0) {
+ *aReadCount = 0;
+ return errorCode;
+ }
+ }
+ if (rv > aCount) {
+ rv = aCount;
+ }
+ memcpy(aBuf, mUnicharData->GetBuffer() + mUnicharDataOffset,
+ rv * sizeof(PRUnichar));
+ mUnicharDataOffset += rv;
+ *aReadCount = rv;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+UTF8InputStream::ReadSegments(nsWriteUnicharSegmentFun aWriter,
+ void* aClosure,
+ PRUint32 aCount, PRUint32 *aReadCount)
+{
+ NS_ASSERTION(mUnicharDataLength >= mUnicharDataOffset, "unsigned madness");
+ PRUint32 bytesToWrite = mUnicharDataLength - mUnicharDataOffset;
+ nsresult rv = NS_OK;
+ if (0 == bytesToWrite) {
+ // Fill the unichar buffer
+ bytesToWrite = Fill(&rv);
+ if (bytesToWrite <= 0) {
+ *aReadCount = 0;
+ return rv;
+ }
+ }
+
+ if (bytesToWrite > aCount)
+ bytesToWrite = aCount;
+
+ PRUint32 bytesWritten;
+ PRUint32 totalBytesWritten = 0;
+
+ while (bytesToWrite) {
+ rv = aWriter(this, aClosure,
+ mUnicharData->GetBuffer() + mUnicharDataOffset,
+ totalBytesWritten, bytesToWrite, &bytesWritten);
+
+ if (NS_FAILED(rv)) {
+ // don't propagate errors to the caller
+ break;
+ }
+
+ bytesToWrite -= bytesWritten;
+ totalBytesWritten += bytesWritten;
+ mUnicharDataOffset += bytesWritten;
+ }
+
+ *aReadCount = totalBytesWritten;
+
+ return NS_OK;
+}
+
+PRInt32 UTF8InputStream::Fill(nsresult * aErrorCode)
+{
+ if (nsnull == mInput) {
+ // We already closed the stream!
+ *aErrorCode = NS_BASE_STREAM_CLOSED;
+ return -1;
+ }
+
+ NS_ASSERTION(mByteData->GetLength() >= mByteDataOffset, "unsigned madness");
+ PRUint32 remainder = mByteData->GetLength() - mByteDataOffset;
+ mByteDataOffset = remainder;
+ PRInt32 nb = mByteData->Fill(aErrorCode, mInput, remainder);
+ if (nb <= 0) {
+ // Because we assume a many to one conversion, the lingering data
+ // in the byte buffer must be a partial conversion
+ // fragment. Because we know that we have recieved no more new
+ // data to add to it, we can't convert it. Therefore, we discard
+ // it.
+ return nb;
+ }
+ NS_ASSERTION(remainder + nb == mByteData->GetLength(), "bad nb");
+
+ // Now convert as much of the byte buffer to unicode as possible
+ PRUint32 srcLen, dstLen;
+ CountValidUTF8Bytes(mByteData->GetBuffer(),remainder + nb, srcLen, dstLen);
+
+ // the number of UCS2 characters should always be <= the number of
+ // UTF8 chars
+ NS_ASSERTION( (remainder+nb >= srcLen), "cannot be longer than out buffer");
+ NS_ASSERTION(PRInt32(dstLen) <= mUnicharData->GetBufferSize(),
+ "Ouch. I would overflow my buffer if I wasn't so careful.");
+ if (PRInt32(dstLen) > mUnicharData->GetBufferSize()) return 0;
+
+ ConvertUTF8toUTF16 converter(mUnicharData->GetBuffer());
+
+ nsASingleFragmentCString::const_char_iterator start = mByteData->GetBuffer();
+ nsASingleFragmentCString::const_char_iterator end = mByteData->GetBuffer() + srcLen;
+
+ copy_string(start, end, converter);
+ NS_ASSERTION(converter.Length() == dstLen, "length mismatch");
+
+ mUnicharDataOffset = 0;
+ mUnicharDataLength = dstLen;
+ mByteDataOffset = srcLen;
+
+ return dstLen;
+}
+
+void
+UTF8InputStream::CountValidUTF8Bytes(const char* aBuffer, PRUint32 aMaxBytes, PRUint32& aValidUTF8bytes, PRUint32& aValidUCS2chars)
+{
+ const char *c = aBuffer;
+ const char *end = aBuffer + aMaxBytes;
+ const char *lastchar = c; // pre-initialize in case of 0-length buffer
+ PRUint32 ucs2bytes = 0;
+ while (c < end && *c) {
+ lastchar = c;
+ ucs2bytes++;
+
+ if (UTF8traits::isASCII(*c))
+ c++;
+ else if (UTF8traits::is2byte(*c))
+ c += 2;
+ else if (UTF8traits::is3byte(*c))
+ c += 3;
+ else if (UTF8traits::is4byte(*c))
+ c += 4;
+ else if (UTF8traits::is5byte(*c))
+ c += 5;
+ else if (UTF8traits::is6byte(*c))
+ c += 6;
+ else {
+ NS_WARNING("Unrecognized UTF8 string in UTF8InputStream::CountValidUTF8Bytes()");
+ break; // Otherwise we go into an infinite loop. But what happens now?
+ }
+ }
+ if (c > end) {
+ c = lastchar;
+ ucs2bytes--;
+ }
+
+ aValidUTF8bytes = c - aBuffer;
+ aValidUCS2chars = ucs2bytes;
+}
+
+NS_COM nsresult
+NS_NewUTF8ConverterStream(nsIUnicharInputStream** aInstancePtrResult,
+ nsIInputStream* aStreamToWrap,
+ PRInt32 aBufferSize)
+{
+ // Create converter input stream
+ UTF8InputStream* it = new UTF8InputStream();
+ if (nsnull == it) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ nsresult rv = it->Init(aStreamToWrap, aBufferSize);
+ if (NS_FAILED(rv))
+ return rv;
+
+ return it->QueryInterface(NS_GET_IID(nsIUnicharInputStream),
+ (void **) aInstancePtrResult);
+}
diff --git a/src/libs/xpcom18a4/xpcom/libxpt/xptcall/porting.html b/src/libs/xpcom18a4/xpcom/libxpt/xptcall/porting.html
new file mode 100644
index 00000000..38cadb40
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/libxpt/xptcall/porting.html
@@ -0,0 +1,13 @@
+<html>
+<head>
+<title>Document Moved!</title>
+</head>
+<body bgcolor = "white">
+<center>The xptcall porting document has been moved to:
+<P>
+<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/porting.html">http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/porting.html</a>
+<P>
+Please update your links.
+</center>
+</body>
+</html> \ No newline at end of file
diff --git a/src/libs/xpcom18a4/xpcom/libxpt/xptcall/status.html b/src/libs/xpcom18a4/xpcom/libxpt/xptcall/status.html
new file mode 100644
index 00000000..22532119
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/libxpt/xptcall/status.html
@@ -0,0 +1,13 @@
+<html>
+<head>
+<title>Document Moved!</title>
+</head>
+<body bgcolor = "white">
+<center>The xptcall status document has been moved to:
+<P>
+<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/status.html">http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/status.html</a>
+<P>
+Please update your links.
+</center>
+</body>
+</html>
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/Makefile.in b/src/libs/xpcom18a4/xpcom/obsolete/Makefile.in
new file mode 100644
index 00000000..5f8cd041
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/Makefile.in
@@ -0,0 +1,130 @@
+#
+# ***** 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_obsolete
+LIBRARY_NAME = xpcom_compat
+ifneq ($(OS_ARCH),WINNT)
+SHORT_LIBNAME = xpcomct
+endif
+
+GRE_MODULE = 1
+PACKAGE_FILE = xpcomobsolete.pkg
+
+DIRS = component
+
+REQUIRES = xpcom \
+ string \
+ $(NULL)
+
+# pull in MoreFiles for MacOSX
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+REQUIRES += macmorefiles
+endif
+
+CPPSRCS = \
+ nsFileSpec.cpp \
+ nsFileStream.cpp \
+ nsIFileStream.cpp \
+ nsFileSpecImpl.cpp \
+ nsSpecialSystemDirectory.cpp \
+ $(NULL)
+
+ifeq ($(OS_ARCH),WINNT)
+REQUIRES += libreg
+CPPSRCS += dlldeps.cpp
+endif
+
+EXPORTS = \
+ xpcomobsolete.h \
+ nsFileSpec.h \
+ nsFileStream.h \
+ nsIFileStream.h \
+ nsSpecialSystemDirectory.h \
+ nsIRegistryUtils.h \
+ $(NULL)
+
+LOCAL_INCLUDES = \
+ -I.. \
+ -I$(srcdir)/../io \
+ $(NULL)
+
+XPIDLSRCS = nsIFileSpec.idl \
+ nsIRegistry.idl \
+ $(NULL)
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+SHARED_LIBRARY_LIBS = \
+ $(DIST)/lib/$(LIB_PREFIX)mozreg_s.$(LIB_SUFFIX) \
+ $(NULL)
+
+# due to symbol conflicts on win32, this needs to be shared
+FORCE_SHARED_LIB = 1
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -D_IMPL_NS_COM_OBSOLETE
+
+
+EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS)
+
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+CXXFLAGS += $(TK_CFLAGS)
+EXTRA_DSO_LDOPTS += $(TK_LIBS)
+endif
+
+ifeq ($(OS_ARCH),BeOS)
+EXTRA_DSO_LDOPTS += -lbe
+endif
+
+ifeq ($(OS_ARCH),WINNT)
+EXTRA_DSO_LDOPTS += $(call EXPAND_LIBNAME, shell32 ole32)
+ifneq (,$(MOZ_DEBUG)$(NS_TRACE_MALLOC))
+EXTRA_DSO_LDOPTS += $(call EXPAND_LIBNAME, imagehlp)
+endif
+ifdef GNU_CXX
+DSO_LDOPTS += -Wl,--export-all-symbols
+endif
+endif # WINNT
+
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/component/Makefile.in b/src/libs/xpcom18a4/xpcom/obsolete/component/Makefile.in
new file mode 100644
index 00000000..a8bec32d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/component/Makefile.in
@@ -0,0 +1,81 @@
+#
+# ***** 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_compat_c
+MODULE_NAME = xpcomObsoleteModule
+LIBRARY_NAME = xpcom_compat_c
+ifneq ($(OS_ARCH),WINNT)
+SHORT_LIBNAME = xpcomctc
+endif
+
+ifndef MINIMO
+EXPORT_LIBRARY = 1
+endif
+IS_COMPONENT = 1
+GRE_MODULE = 1
+
+PACKAGE_FILE = xpcomobsoletec.pkg
+
+REQUIRES = xpcom \
+ xpcom_obsolete \
+ string \
+ libreg \
+ $(NULL)
+
+CPPSRCS = \
+ nsXPCOMObsolete.cpp \
+ nsRegistry.cpp \
+ $(NULL)
+
+
+LOCAL_INCLUDES = \
+ -I$(srcdir)/../ \
+ $(NULL)
+
+EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS) \
+ $(MOZ_XPCOM_OBSOLETE_LIBS) \
+ $(NULL)
+
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/component/nsFileSpecImpl.cpp b/src/libs/xpcom18a4/xpcom/obsolete/component/nsFileSpecImpl.cpp
new file mode 100644
index 00000000..7f51cdca
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/component/nsFileSpecImpl.cpp
@@ -0,0 +1,857 @@
+/* -*- 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 "nsFileSpecImpl.h"// Always first, to ensure that it compiles alone.
+
+#include "nsIFileStream.h"
+#include "nsFileStream.h"
+
+#include "nsILocalFile.h"
+
+#include "prmem.h"
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsFileSpecImpl, nsIFileSpec)
+
+#ifdef NS_DEBUG
+#define TEST_OUT_PTR(p) \
+ if (!(p)) \
+ return NS_ERROR_NULL_POINTER;
+#else
+#define TEST_OUT_PTR(p)
+#endif
+
+//----------------------------------------------------------------------------------------
+nsFileSpecImpl::nsFileSpecImpl()
+//----------------------------------------------------------------------------------------
+ : mInputStream(nsnull)
+ , mOutputStream(nsnull)
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpecImpl::nsFileSpecImpl(const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+ : mFileSpec(inSpec)
+ , mInputStream(nsnull)
+ , mOutputStream(nsnull)
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpecImpl::~nsFileSpecImpl()
+//----------------------------------------------------------------------------------------
+{
+ CloseStream();
+}
+
+//----------------------------------------------------------------------------------------
+/* static */
+nsresult nsFileSpecImpl::MakeInterface(const nsFileSpec& inSpec, nsIFileSpec** result)
+//----------------------------------------------------------------------------------------
+{
+ nsFileSpecImpl* it = new nsFileSpecImpl(inSpec);
+ if (!it)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return it->QueryInterface(NS_GET_IID(nsIFileSpec), (void **) result);
+} // nsFileSpecImpl::MakeInterface
+
+#define FILESPEC(ifilespec) ((nsFileSpecImpl*)ifilespec)->mFileSpec
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::FromFileSpec(const nsIFileSpec *original)
+//----------------------------------------------------------------------------------------
+{
+ if (original) {
+ nsresult rv = ((nsIFileSpec *)original)->GetFileSpec( &mFileSpec);
+ if (NS_SUCCEEDED( rv))
+ return mFileSpec.Error();
+ else
+ return( rv);
+ }
+ else
+ return( NS_ERROR_FAILURE);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsChildOf(nsIFileSpec *possibleParent,
+ PRBool *_retval)
+{
+ *_retval = mFileSpec.IsChildOf(FILESPEC(possibleParent));
+ return mFileSpec.Error();
+}
+//----------------------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetURLString(char * *aURLString)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aURLString)
+ if (mFileSpec.Failed())
+ return mFileSpec.Error();
+ nsFileURL url(mFileSpec);
+ *aURLString = nsCRT::strdup(url.GetURLString());
+ if (!*aURLString)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+} // nsFileSpecImpl::GetURLString
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetURLString(const char * aURLString)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec = nsFileURL(aURLString);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetUnixStyleFilePath(char * *aUnixStyleFilePath)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aUnixStyleFilePath)
+ if (mFileSpec.Failed())
+ return mFileSpec.Error();
+ nsFilePath path(mFileSpec);
+ *aUnixStyleFilePath = nsCRT::strdup((const char*) path);
+ if (!*aUnixStyleFilePath)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetUnixStyleFilePath(const char * aUnixStyleFilePath)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec = nsFilePath(aUnixStyleFilePath);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetPersistentDescriptorString(char * *aPersistentDescriptorString)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aPersistentDescriptorString)
+ if (mFileSpec.Failed())
+ return mFileSpec.Error();
+ nsPersistentFileDescriptor desc(mFileSpec);
+ nsCAutoString data;
+ desc.GetData(data);
+ *aPersistentDescriptorString = ToNewCString(data);
+ if (!*aPersistentDescriptorString)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetPersistentDescriptorString(const char * aPersistentDescriptorString)
+//----------------------------------------------------------------------------------------
+{
+ nsPersistentFileDescriptor desc(mFileSpec);
+ desc.SetData(nsDependentCString(aPersistentDescriptorString));
+ mFileSpec = desc;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetNativePath(char * *aNativePath)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aNativePath)
+ if (mFileSpec.Failed())
+ return mFileSpec.Error();
+ *aNativePath = nsCRT::strdup(mFileSpec.GetNativePathCString());
+ if (!*aNativePath)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetNativePath(const char * aNativePath)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec = aNativePath;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetNSPRPath(char * *aNSPRPath)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aNSPRPath)
+ if (mFileSpec.Failed())
+ return mFileSpec.Error();
+ nsNSPRPath path(mFileSpec);
+ *aNSPRPath = nsCRT::strdup((const char*) path);
+ if (!*aNSPRPath)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Error()
+//----------------------------------------------------------------------------------------
+{
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsValid(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.Valid();
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Failed(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ *_retval = mFileSpec.Failed();
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetLeafName(char * *aLeafName)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aLeafName)
+ *aLeafName = mFileSpec.GetLeafName();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetLeafName(const char * aLeafName)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec.SetLeafName(aLeafName);
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetParent(nsIFileSpec * *aParent)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aParent)
+ nsFileSpec parent;
+ mFileSpec.GetParent(parent);
+ return MakeInterface(parent, aParent);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::MakeUnique()
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec.MakeUnique();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::MakeUniqueWithSuggestedName(const char *suggestedName)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec.MakeUnique(suggestedName);
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetModDate(PRUint32 *aModDate)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aModDate)
+ nsFileSpec::TimeStamp stamp;
+ mFileSpec.GetModDate(stamp);
+ *aModDate = stamp;
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::ModDateChanged(PRUint32 oldStamp, PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.ModDateChanged(oldStamp);
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsDirectory(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.IsDirectory();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsFile(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.IsFile();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Exists(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.Exists();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsHidden(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.IsHidden();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsSymlink(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.IsSymlink();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::ResolveSymlink()
+//----------------------------------------------------------------------------------------
+{
+ PRBool ignore;
+ return mFileSpec.ResolveSymlink(ignore);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetFileSize(PRUint32 *aFileSize)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aFileSize)
+ *aFileSize = mFileSpec.GetFileSize();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aDiskSpaceAvailable)
+ *aDiskSpaceAvailable = mFileSpec.GetDiskSpaceAvailable();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::AppendRelativeUnixPath(const char *relativePath)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec += relativePath;
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Touch()
+//----------------------------------------------------------------------------------------
+{
+ // create an empty file, like the UNIX touch command.
+ nsresult rv;
+ rv = OpenStreamForWriting();
+ if (NS_FAILED(rv)) return rv;
+ rv = CloseStream();
+ return rv;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::CreateDir()
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec.CreateDir();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Delete(PRBool aRecursive)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec.Delete(aRecursive);
+ return mFileSpec.Error();
+}
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Truncate(PRInt32 aNewLength)
+//----------------------------------------------------------------------------------------
+{
+ return mFileSpec.Truncate(aNewLength);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Rename(const char *newLeafName)
+//----------------------------------------------------------------------------------------
+{
+ return mFileSpec.Rename(newLeafName);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::CopyToDir(const nsIFileSpec *newParentDir)
+//----------------------------------------------------------------------------------------
+{
+ return mFileSpec.CopyToDir(FILESPEC(newParentDir));
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::MoveToDir(const nsIFileSpec *newParentDir)
+//----------------------------------------------------------------------------------------
+{
+ return mFileSpec.MoveToDir(FILESPEC(newParentDir));
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Execute(const char *args)
+//----------------------------------------------------------------------------------------
+{
+ return mFileSpec.Execute(args);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::OpenStreamForReading()
+//----------------------------------------------------------------------------------------
+{
+ if (mInputStream || mOutputStream)
+ return NS_ERROR_FAILURE;
+ return NS_NewTypicalInputFileStream((nsISupports**)&mInputStream, mFileSpec);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::OpenStreamForWriting()
+//----------------------------------------------------------------------------------------
+{
+ if (mInputStream || mOutputStream)
+ return NS_ERROR_FAILURE;
+ return NS_NewTypicalOutputFileStream((nsISupports**)&mOutputStream, mFileSpec);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::OpenStreamForReadingAndWriting()
+//----------------------------------------------------------------------------------------
+{
+ if (mInputStream || mOutputStream)
+ return NS_ERROR_FAILURE;
+ nsresult result = NS_NewTypicalInputFileStream((nsISupports**)&mInputStream, mFileSpec);
+ if (NS_SUCCEEDED(result))
+ result = NS_NewTypicalOutputFileStream((nsISupports**)&mOutputStream, mFileSpec);
+ return result;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::CloseStream()
+//----------------------------------------------------------------------------------------
+{
+ NS_IF_RELEASE(mInputStream);
+ NS_IF_RELEASE(mOutputStream);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsStreamOpen(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = (mInputStream || mOutputStream);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetInputStream(nsIInputStream** _retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ if (!mInputStream) {
+ nsresult rv = OpenStreamForReading();
+ if (NS_FAILED(rv)) return rv;
+ }
+ *_retval = mInputStream;
+ NS_IF_ADDREF(mInputStream);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetOutputStream(nsIOutputStream** _retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ if (!mOutputStream) {
+ nsresult rv = OpenStreamForWriting();
+ if (NS_FAILED(rv)) return rv;
+ }
+ *_retval = mOutputStream;
+ NS_IF_ADDREF(mOutputStream);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetFileContents(const char* inString)
+//----------------------------------------------------------------------------------------
+{
+ nsresult rv = OpenStreamForWriting();
+ if (NS_FAILED(rv)) return rv;
+ PRInt32 count;
+ rv = Write(inString, PL_strlen(inString), &count);
+ nsresult rv2 = CloseStream();
+ return NS_FAILED(rv) ? rv : rv2;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetFileContents(char** _retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = nsnull;
+ nsresult rv = OpenStreamForReading();
+ if (NS_FAILED(rv)) return rv;
+ PRInt32 theSize;
+ rv = GetFileSize((PRUint32*)&theSize);
+ if (NS_SUCCEEDED(rv))
+ rv = Read(_retval, theSize, &theSize);
+ if (NS_SUCCEEDED(rv))
+ (*_retval)[theSize] = 0;
+ nsresult rv2 = CloseStream();
+ return NS_FAILED(rv) ? rv : rv2;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetFileSpec(nsFileSpec *aFileSpec)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aFileSpec)
+ *aFileSpec = mFileSpec;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Equals(nsIFileSpec *spec, PRBool *result)
+//----------------------------------------------------------------------------------------
+{
+ nsresult rv;
+
+ if (!result || !spec) return NS_ERROR_NULL_POINTER;
+
+ nsFileSpec otherSpec;
+
+ rv = spec->GetFileSpec(&otherSpec);
+ if (NS_FAILED(rv)) return rv;
+
+ if (mFileSpec == otherSpec) {
+ *result = PR_TRUE;
+ }
+ else {
+ *result = PR_FALSE;
+ }
+
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetFromFileSpec(const nsFileSpec& aFileSpec)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec = aFileSpec;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Eof(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ if (!mInputStream)
+ return NS_ERROR_NULL_POINTER;
+ nsInputFileStream s(mInputStream);
+ *_retval = s.eof();
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Read(char** buffer, PRInt32 requestedCount, PRInt32 *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ TEST_OUT_PTR(buffer)
+ if (!mInputStream) {
+ nsresult rv = OpenStreamForReading();
+ if (NS_FAILED(rv)) return rv;
+ }
+ if (!*buffer)
+ *buffer = (char*)PR_Malloc(requestedCount + 1);
+ if (!mInputStream)
+ return NS_ERROR_NULL_POINTER;
+ nsInputFileStream s(mInputStream);
+ *_retval = s.read(*buffer, requestedCount);
+ return s.error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::ReadLine(char** line, PRInt32 bufferSize, PRBool *wasTruncated)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(wasTruncated)
+ TEST_OUT_PTR(line)
+ if (!mInputStream) {
+ nsresult rv = OpenStreamForReading();
+ if (NS_FAILED(rv)) return rv;
+ }
+ if (!*line)
+ *line = (char*)PR_Malloc(bufferSize + 1);
+ if (!mInputStream)
+ return NS_ERROR_NULL_POINTER;
+ nsInputFileStream s(mInputStream);
+ *wasTruncated = !s.readline(*line, bufferSize);
+ return s.error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Write(const char * data, PRInt32 requestedCount, PRInt32 *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ //if (!mOutputStream)
+ // return NS_ERROR_NULL_POINTER;
+ if (!mOutputStream) {
+ nsresult rv = OpenStreamForWriting();
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ nsOutputFileStream s(mOutputStream);
+ *_retval = s.write(data, requestedCount);
+ return s.error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Flush()
+//----------------------------------------------------------------------------------------
+{
+ if (!mOutputStream)
+ return NS_ERROR_NULL_POINTER;
+ nsOutputFileStream s(mOutputStream);
+ s.flush();
+ return s.error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Seek(PRInt32 offset)
+//----------------------------------------------------------------------------------------
+{
+ nsresult result = NS_OK;
+ if (mOutputStream)
+ {
+ nsOutputFileStream os(mOutputStream);
+ os.seek(offset);
+ result = os.error();
+ }
+ if (NS_SUCCEEDED(result) && mInputStream)
+ {
+ nsInputFileStream is(mInputStream);
+ is.seek(offset);
+ result = is.error();
+ }
+ return result;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Tell(PRInt32 *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ if (!mInputStream)
+ return NS_ERROR_NULL_POINTER;
+ nsInputFileStream s(mInputStream);
+ *_retval = s.tell();
+ return s.error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::EndLine()
+//----------------------------------------------------------------------------------------
+{
+ nsOutputFileStream s(mOutputStream);
+ s << nsEndl;
+ return s.error();
+}
+
+NS_IMPL_ISUPPORTS1(nsDirectoryIteratorImpl, nsIDirectoryIterator)
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIteratorImpl::nsDirectoryIteratorImpl()
+//----------------------------------------------------------------------------------------
+ : mDirectoryIterator(nsnull)
+{
+}
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIteratorImpl::~nsDirectoryIteratorImpl()
+//----------------------------------------------------------------------------------------
+{
+ delete mDirectoryIterator;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsDirectoryIteratorImpl::Init(nsIFileSpec *parent, PRBool resolveSymlink)
+//----------------------------------------------------------------------------------------
+{
+ delete mDirectoryIterator;
+ mDirectoryIterator = new nsDirectoryIterator(FILESPEC(parent), resolveSymlink);
+ if (!mDirectoryIterator)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsDirectoryIteratorImpl::Exists(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ if (!mDirectoryIterator)
+ return NS_ERROR_NULL_POINTER;
+ *_retval = mDirectoryIterator->Exists();
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsDirectoryIteratorImpl::Next()
+//----------------------------------------------------------------------------------------
+{
+ if (!mDirectoryIterator)
+ return NS_ERROR_NULL_POINTER;
+ (*mDirectoryIterator)++;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsDirectoryIteratorImpl::GetCurrentSpec(nsIFileSpec * *aCurrentSpec)
+//----------------------------------------------------------------------------------------
+{
+ if (!mDirectoryIterator)
+ return NS_ERROR_NULL_POINTER;
+ return nsFileSpecImpl::MakeInterface(mDirectoryIterator->Spec(), aCurrentSpec);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsDirectoryIteratorImpl::Create(nsISupports* outer, const nsIID& aIID, void* *aIFileSpec)
+//----------------------------------------------------------------------------------------
+{
+ if (aIFileSpec == NULL)
+ return NS_ERROR_NULL_POINTER;
+
+ nsDirectoryIteratorImpl* it = new nsDirectoryIteratorImpl;
+ if (!it)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = it->QueryInterface(aIID, aIFileSpec);
+ if (NS_FAILED(rv))
+ {
+ delete it;
+ return rv;
+ }
+ return rv;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Create(nsISupports* outer, const nsIID& aIID, void* *aIFileSpec)
+//----------------------------------------------------------------------------------------
+{
+ if (aIFileSpec == NULL)
+ return NS_ERROR_NULL_POINTER;
+
+ nsFileSpecImpl* it = new nsFileSpecImpl;
+ if (!it)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = it->QueryInterface(aIID, aIFileSpec);
+ if (NS_FAILED(rv))
+ {
+ delete it;
+ return rv;
+ }
+ return rv;
+}
+
+//----------------------------------------------------------------------------------------
+nsresult NS_NewFileSpecWithSpec(const nsFileSpec& aSrcFileSpec, nsIFileSpec **result)
+//----------------------------------------------------------------------------------------
+{
+ if (!result)
+ return NS_ERROR_NULL_POINTER;
+
+ return nsFileSpecImpl::MakeInterface(aSrcFileSpec, result);
+}
+
+//----------------------------------------------------------------------------------------
+nsresult NS_NewFileSpec(nsIFileSpec** result)
+//----------------------------------------------------------------------------------------
+{
+ return nsFileSpecImpl::Create(nsnull, NS_GET_IID(nsIFileSpec), (void**)result);
+}
+
+//----------------------------------------------------------------------------------------
+nsresult NS_NewFileSpecFromIFile(nsIFile *aFile, nsIFileSpec **result)
+//----------------------------------------------------------------------------------------
+{
+ nsresult rv = nsFileSpecImpl::Create(nsnull, NS_GET_IID(nsIFileSpec), (void**)result);
+ if (NS_FAILED(rv)) return rv;
+
+ nsCAutoString path;
+ rv = aFile->GetNativePath(path);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = (*result)->SetNativePath(path.get());
+ if (NS_FAILED(rv))
+ NS_RELEASE(*result);
+ return rv;
+}
+
+//----------------------------------------------------------------------------------------
+nsresult NS_NewDirectoryIterator(nsIDirectoryIterator** result)
+//----------------------------------------------------------------------------------------
+{
+ return nsDirectoryIteratorImpl::Create(nsnull, NS_GET_IID(nsIDirectoryIterator), (void**)result);
+}
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/component/nsFileSpecImpl.h b/src/libs/xpcom18a4/xpcom/obsolete/component/nsFileSpecImpl.h
new file mode 100644
index 00000000..502e254f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/component/nsFileSpecImpl.h
@@ -0,0 +1,116 @@
+/* -*- 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 _FILESPECIMPL_H_
+#define _FILESPECIMPL_H_
+
+#include "nscore.h"
+#include "nsIFileSpec.h"
+#include "nsFileSpec.h"
+
+//========================================================================================
+class nsFileSpecImpl
+//========================================================================================
+ : public nsIFileSpec
+{
+
+ public:
+
+ NS_DECL_ISUPPORTS
+
+ NS_DECL_NSIFILESPEC
+
+ //----------------------
+ // COM Cruft
+ //----------------------
+
+ static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aIFileSpec);
+
+ //----------------------
+ // Implementation
+ //----------------------
+
+ nsFileSpecImpl();
+ nsFileSpecImpl(const nsFileSpec& inSpec);
+ static nsresult MakeInterface(const nsFileSpec& inSpec, nsIFileSpec** outSpec);
+
+ //----------------------
+ // Data
+ //----------------------
+
+ nsFileSpec mFileSpec;
+ nsIInputStream* mInputStream;
+ nsIOutputStream* mOutputStream;
+
+private:
+ ~nsFileSpecImpl();
+}; // class nsFileSpecImpl
+
+//========================================================================================
+class nsDirectoryIteratorImpl
+//========================================================================================
+ : public nsIDirectoryIterator
+{
+
+public:
+
+ nsDirectoryIteratorImpl();
+
+ NS_DECL_ISUPPORTS
+
+ NS_IMETHOD Init(nsIFileSpec *parent, PRBool resolveSymlink);
+
+ NS_IMETHOD Exists(PRBool *_retval);
+
+ NS_IMETHOD Next();
+
+ NS_IMETHOD GetCurrentSpec(nsIFileSpec * *aCurrentSpec);
+
+ //----------------------
+ // COM Cruft
+ //----------------------
+
+ static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aIFileSpec);
+
+private:
+ ~nsDirectoryIteratorImpl();
+
+protected:
+ nsDirectoryIterator* mDirectoryIterator;
+}; // class nsDirectoryIteratorImpl
+
+#endif // _FILESPECIMPL_H_
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/component/nsIRegistry.idl b/src/libs/xpcom18a4/xpcom/obsolete/component/nsIRegistry.idl
new file mode 100644
index 00000000..bc9990e2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/component/nsIRegistry.idl
@@ -0,0 +1,186 @@
+/* -*- 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) 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"
+#include "nsIEnumerator.idl"
+
+interface nsIFile;
+
+typedef PRUint32 nsRegistryKey;
+typedef long nsWellKnownRegistry;
+
+[scriptable,uuid(5D41A440-8E37-11d2-8059-00600811A9C3)]
+interface nsIRegistry : nsISupports
+{
+ const long None = 0;
+ const long Users = 1;
+ const long Common = 2;
+ const long CurrentUser = 3;
+
+ const long ApplicationComponentRegistry = 1;
+ const long ApplicationRegistry = 2;
+
+ // Dont use this one. This for internal use only.
+ const long ApplicationCustomRegistry = -1;
+
+ void open(in nsIFile regFile);
+ void openWellKnownRegistry(in nsWellKnownRegistry regid);
+
+ void flush();
+ boolean isOpen();
+
+ nsRegistryKey addKey(in nsRegistryKey baseKey, in wstring keyname);
+ nsRegistryKey getKey(in nsRegistryKey baseKey, in wstring keyname);
+ void removeKey(in nsRegistryKey baseKey, in wstring keyname);
+
+ wstring getString(in nsRegistryKey baseKey, in wstring valname);
+ void setString(in nsRegistryKey baseKey, in wstring valname, in wstring value);
+
+ string getStringUTF8(in nsRegistryKey baseKey, in string path);
+ void setStringUTF8(in nsRegistryKey baseKey, in string path, in string value);
+
+ void getBytesUTF8(in nsRegistryKey baseKey, in string path, out PRUint32 length, [retval, array, size_is(length)] out PRUint8 valueArray);
+ void setBytesUTF8(in nsRegistryKey baseKey, in string path, in PRUint32 length, [array, size_is(length)] in PRUint8 valueArray);
+ PRInt32 getInt(in nsRegistryKey baseKey, in string path);
+ void setInt(in nsRegistryKey baseKey, in string path, in PRInt32 value);
+ PRInt64 getLongLong(in nsRegistryKey baseKey, in string path);
+ void setLongLong(in nsRegistryKey baseKey, in string path, inout PRInt64 value);
+
+ /**
+ * addSubtree() and friends need to be renamed to addKeyUTF8().
+ * If you are using these forms make sure you pass UTF8 data
+ */
+ nsRegistryKey addSubtree(in nsRegistryKey baseKey, in string path);
+ void removeSubtree(in nsRegistryKey baseKey, in string path);
+ nsRegistryKey getSubtree(in nsRegistryKey baseKey, in string path);
+
+ nsRegistryKey addSubtreeRaw(in nsRegistryKey baseKey, in string path);
+ void removeSubtreeRaw(in nsRegistryKey baseKey, in string path);
+ nsRegistryKey getSubtreeRaw(in nsRegistryKey baseKey, in string path);
+
+ nsIEnumerator enumerateSubtrees(in nsRegistryKey baseKey);
+ nsIEnumerator enumerateAllSubtrees(in nsRegistryKey baseKey);
+ nsIEnumerator enumerateValues(in nsRegistryKey baseKey);
+
+ const unsigned long String = 1;
+ const unsigned long Int32 = 2;
+ const unsigned long Bytes = 3;
+ const unsigned long File = 4;
+
+ unsigned long getValueType(in nsRegistryKey baseKey, in string path);
+ PRUint32 getValueLength(in nsRegistryKey baseKey, in string path);
+ void deleteValue(in nsRegistryKey baseKey, in string path);
+
+ /**
+ * escapeKey() takes arbitrary binary data and converts it into
+ * valid ASCII which can be used as registry key or value names
+ */
+ void escapeKey([array, size_is(length)] in PRUint8 key, in PRUint32 terminator, inout PRUint32 length, [retval, array, size_is(length)] out PRUint8 escaped);
+ void unescapeKey([array, size_is(length)] in PRUint8 escaped, in PRUint32 terminator, inout PRUint32 length, [retval, array, size_is(length)] out PRUint8 key);
+
+ attribute string currentUserName;
+
+ void pack();
+};
+
+[scriptable, uuid(8cecf236-1dd2-11b2-893c-f9848956eaec)]
+interface nsIRegistryEnumerator : nsIEnumerator
+{
+ void currentItemInPlaceUTF8(out nsRegistryKey key,
+ [shared, retval] out string item);
+};
+
+[scriptable, uuid(D1B54831-AC07-11d2-805E-00600811A9C3)]
+interface nsIRegistryNode : nsISupports
+{
+ readonly attribute string nameUTF8;
+ readonly attribute wstring name;
+ readonly attribute nsRegistryKey key;
+};
+
+[scriptable,uuid(5316C380-B2F8-11d2-A374-0080C6F80E4B)]
+interface nsIRegistryValue : nsISupports
+{
+ readonly attribute wstring name;
+ readonly attribute string nameUTF8;
+ readonly attribute unsigned long type;
+ readonly attribute PRUint32 length;
+};
+
+[uuid(3A15FC88-7A61-4Ab4-8E58-31E95fAB3DA8)]
+/**
+ * It sucks that nsIRegistry has to always allocate and return
+ * strings. nsIRegistryGetter adds in interfaces for non allocating getters
+ * to registry values.
+ */
+interface nsIRegistryGetter : nsISupports
+{
+ /**
+ * Get a string value of attribute valname in widestring or utf8 format
+ *
+ * @return
+ * NS_OK on success.
+ * buf has the string value copied into it. length is NOT changed.
+ * NS_ERROR_REG_BUFFER_TOO_SMALL if not enough buffer space.
+ * length is updated to actual length in chars including
+ * terminating NULL and buf will be unchanged.
+ * NS_ERROR_FAILURE if an unknown error happened. state of buf and
+ * length undefined.
+ * various failure codes otherwise. buf and length wont be updated.
+ */
+ void getStringUTF8IntoBuffer(in nsRegistryKey baseKey, in string path,
+ inout char buf, inout PRUint32 length);
+
+ /**
+ * Get a a byte array value of attribute valname
+ *
+ * @return
+ * NS_OK on success. buf has the string value copied into it.
+ * length is updated to actual number of bytes copied into buf.
+ * NS_ERROR_REG_BUFFER_TOO_SMALL if not enough buffer space.
+ * length is updated to actual length in PRUint8s including
+ * terminating NULL and buf will be unchanged.
+ * NS_ERROR_FAILURE if an unknown error happened. state of buf and
+ * length undefined.
+ * various other failure codes otherwise. buf and length wont be updated.
+ */
+ void getBytesUTF8IntoBuffer(in nsRegistryKey baseKey, in string path,
+ inout PRUint8 buf, inout PRUint32 length);
+};
+
+%{ C++
+#include "nsIRegistryUtils.h"
+%}
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/component/nsIRegistryUtils.h b/src/libs/xpcom18a4/xpcom/obsolete/component/nsIRegistryUtils.h
new file mode 100644
index 00000000..a3d74d7a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/component/nsIRegistryUtils.h
@@ -0,0 +1,63 @@
+/* -*- 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 __nsIRegistryUtils_h
+#define __nsIRegistryUtils_h
+
+#define NS_REGISTRY_CONTRACTID "@mozilla.org/registry;1"
+#define NS_REGISTRY_CLASSNAME "Mozilla Registry"
+/* be761f00-a3b0-11d2-996c-0080c7cb1081 */
+#define NS_REGISTRY_CID \
+{ \
+ 0xbe761f00, \
+ 0xa3b0, \
+ 0x11d2, \
+ {0x99, 0x6c, 0x00, 0x80, 0xc7, 0xcb, 0x10, 0x81} \
+}
+
+/*------------------------------- Error Codes ----------------------------------
+------------------------------------------------------------------------------*/
+#define NS_ERROR_REG_BADTYPE NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 1 )
+#define NS_ERROR_REG_NO_MORE NS_ERROR_GENERATE_SUCCESS( NS_ERROR_MODULE_REG, 2 )
+#define NS_ERROR_REG_NOT_FOUND NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 3 )
+#define NS_ERROR_REG_NOFILE NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 4 )
+#define NS_ERROR_REG_BUFFER_TOO_SMALL NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 5 )
+#define NS_ERROR_REG_NAME_TOO_LONG NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 6 )
+#define NS_ERROR_REG_NO_PATH NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 7 )
+#define NS_ERROR_REG_READ_ONLY NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 8 )
+#define NS_ERROR_REG_BAD_UTF8 NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 9 )
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/component/nsRegistry.cpp b/src/libs/xpcom18a4/xpcom/obsolete/component/nsRegistry.cpp
new file mode 100644
index 00000000..d3ecfe62
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/component/nsRegistry.cpp
@@ -0,0 +1,2019 @@
+/* -*- 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 ***** */
+
+#ifdef MOZ_LOGGING
+#define FORCE_PR_LOG /* Allow logging in the release build */
+#endif
+
+#include "nsIGenericFactory.h"
+
+#include "nsRegistry.h"
+#include "nsIEnumerator.h"
+#include "nsDirectoryService.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsAppDirectoryServiceDefs.h"
+#include "NSReg.h"
+#include "prmem.h"
+#include "prlock.h"
+#include "prlog.h"
+#include "prprf.h"
+#include "nsCRT.h"
+#include "nsMemory.h"
+
+#include "nsCOMPtr.h"
+#include "nsILocalFile.h"
+#include "nsIServiceManager.h"
+#include "nsTextFormatter.h"
+
+#ifdef XP_BEOS
+#include <FindDirectory.h>
+#include <Path.h>
+#endif
+
+/* extra locking for the paranoid */
+/* #define EXTRA_THREADSAFE */
+#ifndef EXTRA_THREADSAFE
+#define PR_Lock(x) (void)0
+#define PR_Unlock(x) (void)0
+#endif
+
+// Logging of debug output
+extern PRLogModuleInfo *nsComponentManagerLog;
+
+PRUnichar widestrFormat[] = { PRUnichar('%'),PRUnichar('s'),PRUnichar(0)};
+
+/*-------------------------------- nsRegistry ----------------------------------
+| This class implements the nsIRegistry interface using the functions |
+| provided by libreg (as declared in mozilla/modules/libreg/include/NSReg.h). |
+| |
+| Since that interface is designed to match the libreg function, this class |
+| is implemented with each member function being a simple wrapper for the |
+| corresponding libreg function. |
+| |
+| #define EXTRA_THREADSAFE if you are worried about libreg thread safety. |
+| It should not be necessary, but I'll leave in the code for the paranoid. |
+------------------------------------------------------------------------------*/
+
+#define NS_MOZILLA_DIR_PERMISSION 00700
+
+#include "nsRegistry.h"
+/*
+struct nsRegistry : public nsIRegistry {
+ // This class implements the nsISupports interface functions.
+ NS_DECL_ISUPPORTS
+
+ // This class implements the nsIRegistry interface functions.
+ NS_DECL_NSIREGISTRY
+
+ // ctor/dtor
+ nsRegistry();
+
+private:
+ ~nsRegistry();
+
+protected:
+ HREG mReg; // Registry handle.
+#ifdef EXTRA_THREADSAFE
+ PRLock *mregLock; // libreg isn't threadsafe. Use locks to synchronize.
+#endif
+ char *mCurRegFile; // these are to prevent open from opening the registry again
+ nsWellKnownRegistry mCurRegID;
+
+ NS_IMETHOD Close();
+}; // nsRegistry
+*/
+
+#include "nsIFactory.h"
+/*----------------------------- nsRegistryFactory ------------------------------
+| Class factory for nsRegistry objects. |
+------------------------------------------------------------------------------*/
+struct nsRegistryFactory : public nsIFactory {
+ // This class implements the nsISupports interface functions.
+ NS_DECL_ISUPPORTS
+
+ // nsIFactory methods
+ NS_IMETHOD CreateInstance(nsISupports *,const nsIID &,void **);
+ NS_IMETHOD LockFactory(PRBool aLock);
+
+ // ctor
+ nsRegistryFactory();
+};
+
+
+/*--------------------------- nsRegSubtreeEnumerator ---------------------------
+| This class implements the nsIEnumerator interface and is used to implement |
+| the nsRegistry EnumerateSubtrees and EnumerateAllSubtrees functions. |
+------------------------------------------------------------------------------*/
+struct nsRegSubtreeEnumerator : public nsIRegistryEnumerator {
+ // This class implements the nsISupports interface functions.
+ NS_DECL_ISUPPORTS
+
+ // This class implements the nsIEnumerator interface functions.
+ NS_DECL_NSIENUMERATOR
+
+ // And our magic behind-the-back fast-path thing.
+ NS_DECL_NSIREGISTRYENUMERATOR
+
+ // ctor/dtor
+ nsRegSubtreeEnumerator( HREG hReg, RKEY rKey, PRBool all );
+ // virtual dtor since subclasses call our Release()
+ virtual ~nsRegSubtreeEnumerator();
+
+protected:
+ NS_IMETHOD advance(); // Implementation file; does appropriate NR_RegEnum call.
+ HREG mReg; // Handle to registry we're affiliated with.
+ RKEY mKey; // Base key being enumerated.
+ char mName[MAXREGPATHLEN]; // The name of the current key which is in mNext
+ REGENUM mEnum; // Corresponding libreg "enumerator".
+ REGENUM mNext; // Lookahead value.
+ PRUint32 mStyle; // Style (indicates all or some);
+ PRBool mDone; // Done flag.
+#ifdef EXTRA_THREADSAFE
+ PRLock *mregLock;
+#endif
+}; // nsRegSubtreeEnumerator
+
+
+/*--------------------------- nsRegValueEnumerator -----------------------------
+| This class is a variation on nsRegSubtreeEnumerator that allocates |
+| nsRegistryValue objects rather than nsRegistryNode objects. It also |
+| overrides certain functions to make sure the "value" oriented libreg |
+| functions used rather than the subtree oriented ones. |
+------------------------------------------------------------------------------*/
+struct nsRegValueEnumerator : public nsRegSubtreeEnumerator {
+ // Override CurrentItem to allocate nsRegistryValue objects.
+ NS_IMETHOD CurrentItem( nsISupports **result );
+
+ // Override advance() to use proper NR_RegEnumEntries.
+ NS_IMETHOD advance();
+
+ // ctor/dtor
+ nsRegValueEnumerator( HREG hReg, RKEY rKey );
+}; // nsRegValueEnumerator
+
+/*------------------------------ nsRegistryNode --------------------------------
+| This class implements the nsIRegistryNode interface. Instances are |
+| allocated by nsRegSubtreeEnumerator::CurrentItem. |
+------------------------------------------------------------------------------*/
+struct nsRegistryNode : public nsIRegistryNode {
+ // This class implements the nsISupports interface functions.
+ NS_DECL_ISUPPORTS
+
+ // This class implements the nsIRegistryNode interface functions.
+ NS_DECL_NSIREGISTRYNODE
+
+ // ctor
+ nsRegistryNode( HREG hReg, char *name, RKEY childKey );
+
+private:
+ ~nsRegistryNode();
+
+protected:
+ HREG mReg; // Handle to registry this node is part of.
+ char mName[MAXREGPATHLEN]; // Buffer to hold name.
+ RKEY mChildKey; // Key corresponding to mName
+#ifdef EXTRA_THREADSAFE
+ PRLock *mregLock;
+#endif
+}; // nsRegistryNode
+
+
+/*------------------------------ nsRegistryValue -------------------------------
+| This class implements the nsIRegistryValue interface. Instances are |
+| allocated by nsRegValueEnumerator::CurrentItem. |
+------------------------------------------------------------------------------*/
+struct nsRegistryValue : public nsIRegistryValue {
+ // This class implements the nsISupports interface functions.
+ NS_DECL_ISUPPORTS
+
+ // This class implements the nsIRegistryValue interface functions.
+ NS_DECL_NSIREGISTRYVALUE
+
+ // ctor
+ nsRegistryValue( HREG hReg, RKEY key, REGENUM slot );
+
+private:
+ ~nsRegistryValue();
+
+protected:
+ nsresult getInfo(); // Get registry info.
+ HREG mReg; // Handle to registry this node is part of.
+ RKEY mKey; // Key this node is under.
+ REGENUM mEnum; // Copy of corresponding content of parent enumerator.
+ REGINFO mInfo; // Value info.
+ char mName[MAXREGNAMELEN]; // Buffer to hold name.
+ REGERR mErr; // XXX This causes this class to be NON THREAD SAFE
+#ifdef EXTRA_THREADSAFE
+ PRLock *mregLock;
+#endif
+}; // nsRegistryValue
+
+
+/*----------------------------- regerr2nsresult --------------------------------
+| This utility function maps a REGERR value to a corresponding nsresult |
+| error code. |
+------------------------------------------------------------------------------*/
+static nsresult regerr2nsresult( REGERR err ) {
+ nsresult rv = NS_ERROR_UNEXPECTED;
+ switch( err ) {
+ case REGERR_OK:
+ rv = NS_OK;
+ break;
+
+ case REGERR_FAIL:
+ rv = NS_ERROR_FAILURE;
+ break;
+
+ case REGERR_NOMORE:
+ rv = NS_ERROR_REG_NO_MORE;
+ break;
+
+ case REGERR_NOFIND:
+ rv = NS_ERROR_REG_NOT_FOUND;
+ break;
+
+ case REGERR_PARAM:
+ case REGERR_BADTYPE:
+ case REGERR_BADNAME:
+ rv = NS_ERROR_INVALID_ARG;
+ break;
+
+ case REGERR_NOFILE:
+ rv = NS_ERROR_REG_NOFILE;
+ break;
+
+ case REGERR_MEMORY:
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ break;
+
+ case REGERR_BUFTOOSMALL:
+ rv = NS_ERROR_REG_BUFFER_TOO_SMALL;
+ break;
+
+ case REGERR_NAMETOOLONG:
+ rv = NS_ERROR_REG_NAME_TOO_LONG;
+ break;
+
+ case REGERR_NOPATH:
+ rv = NS_ERROR_REG_NO_PATH;
+ break;
+
+ case REGERR_READONLY:
+ rv = NS_ERROR_REG_READ_ONLY;
+ break;
+
+ case REGERR_BADUTF8:
+ rv = NS_ERROR_REG_BAD_UTF8;
+ break;
+
+ }
+ return rv;
+}
+
+/*----------------------------- reginfo2DataType -------------------------------
+| This utility function converts the type field in the REGINFO structure to |
+| the corresponding nsIRegistry::DataType value. |
+------------------------------------------------------------------------------*/
+static void reginfo2DataType( const REGINFO &in, PRUint32 &out ) {
+ // Transfer information, based on entry type.
+ switch( in.entryType ) {
+ case REGTYPE_ENTRY_STRING_UTF:
+ out = nsIRegistry::String;
+ //out.length = in.entryLength;
+ break;
+
+ case REGTYPE_ENTRY_INT32_ARRAY:
+ out = nsIRegistry::Int32;
+ // Convert length in bytes to array dimension.
+ //out.length = in.entryLength / sizeof(PRInt32);
+ break;
+
+ case REGTYPE_ENTRY_BYTES:
+ out = nsIRegistry::Bytes;
+ //out.length = in.entryLength;
+ break;
+
+ case REGTYPE_ENTRY_FILE:
+ out = nsIRegistry::File;
+ //out.length = in.entryLength;
+ break;
+ }
+}
+
+/*----------------------------- reginfo2DataType -------------------------------
+| This utility function converts the length field in the REGINFO structure to |
+| the proper units (if type==Int32 array, we divide by sizeof(PRInt32)). |
+------------------------------------------------------------------------------*/
+static void reginfo2Length( const REGINFO &in, PRUint32 &out ) {
+ // Transfer information, based on entry type.
+ switch( in.entryType ) {
+ case REGTYPE_ENTRY_STRING_UTF:
+ out = in.entryLength;
+ break;
+
+ case REGTYPE_ENTRY_INT32_ARRAY:
+ // Convert length in bytes to array dimension.
+ out = in.entryLength / sizeof(PRInt32);
+ break;
+
+ case REGTYPE_ENTRY_BYTES:
+ out = in.entryLength;
+ break;
+
+ case REGTYPE_ENTRY_FILE:
+ out = in.entryLength;
+ break;
+ }
+}
+
+/*------------------------ nsISupports Implementation --------------------------
+| This code generates the implementation of the nsISupports member functions |
+| for each class implemented in this file. |
+------------------------------------------------------------------------------*/
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsRegistry, nsIRegistry, nsIRegistryGetter)
+NS_IMPL_ISUPPORTS2( nsRegSubtreeEnumerator, nsIEnumerator,
+ nsIRegistryEnumerator)
+NS_IMPL_ISUPPORTS1( nsRegistryNode, nsIRegistryNode )
+NS_IMPL_ISUPPORTS1( nsRegistryValue, nsIRegistryValue )
+
+/*-------------------------- nsRegistry::nsRegistry ----------------------------
+| Vanilla nsRegistry constructor. |
+------------------------------------------------------------------------------*/
+nsRegistry::nsRegistry()
+ : mReg(0), mCurRegID(0) {
+#ifdef EXTRA_THREADSAFE
+ mregLock = PR_NewLock();
+#endif
+ NR_StartupRegistry();
+ return;
+}
+
+/*------------------------- nsRegistry::~nsRegistry ----------------------------
+| The dtor closes the registry file(if open). |
+------------------------------------------------------------------------------*/
+nsRegistry::~nsRegistry() {
+ if( mReg ) {
+ Close();
+ }
+#ifdef EXTRA_THREADSAFE
+ if (mregLock) {
+ PR_DestroyLock(mregLock);
+ }
+#endif
+ NR_ShutdownRegistry();
+ return;
+}
+
+/*----------------------------- nsRegistry::Open -------------------------------
+| If the argument is null, delegate to OpenDefault, else open the registry |
+| file. We first check to see if a registry file is already open and close |
+| it if so. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::Open( nsIFile *regFile ) {
+ REGERR err = REGERR_OK;
+
+ // Check for default.
+ if( !regFile ) {
+ return OpenWellKnownRegistry(nsIRegistry::ApplicationRegistry);
+ }
+
+ nsCAutoString regPath;
+ nsresult rv = regFile->GetNativePath(regPath);
+ if (NS_FAILED(rv)) return rv;
+
+#ifdef DEBUG_dp
+ printf("nsRegistry: Opening registry %s\n", regPath.get());
+#endif /* DEBUG_dp */
+
+ if (mCurRegID != nsIRegistry::None && mCurRegID != nsIRegistry::ApplicationCustomRegistry)
+ {
+ // Cant open another registry without closing explictly.
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ // Do we have an open registry ?
+ if (mCurRegID != nsIRegistry::None)
+ {
+ PRBool equals;
+ if (mCurRegFile && NS_SUCCEEDED(mCurRegFile->Equals(regFile, &equals)) && equals)
+ {
+ // The right one is already open
+ return NS_OK;
+ }
+ else
+ {
+ // Opening a new registry without closing an already open one.
+ // This is an error.
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ // Open specified registry.
+ PR_Lock(mregLock);
+ err = NR_RegOpen(NS_CONST_CAST(char*,regPath.get()), &mReg);
+ PR_Unlock(mregLock);
+
+ mCurRegID = nsIRegistry::ApplicationCustomRegistry;
+
+ // No error checking for no mem. Trust me.
+ if (NS_FAILED(regFile->Clone(getter_AddRefs(mCurRegFile))))
+ mCurRegFile = nsnull; // not fatal
+
+ // Convert the result.
+ return regerr2nsresult( err );
+}
+
+static void
+EnsureDefaultRegistryDirectory() {
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
+ // Create ~/.mozilla as that is the default place for the registry file
+
+ /* The default registry on the unix system is $HOME/.mozilla/registry per
+ * vr_findGlobalRegName(). vr_findRegFile() will create the registry file
+ * if it doesn't exist. But it wont create directories.
+ *
+ * Hence we need to create the directory if it doesn't exist already.
+ *
+ * Why create it here as opposed to the app ?
+ * ------------------------------------------
+ * The app cannot create the directory in main() as most of the registry
+ * and initialization happens due to use of static variables.
+ * And we dont want to be dependent on the order in which
+ * these static stuff happen.
+ *
+ * Permission for the $HOME/.mozilla will be Read,Write,Execute
+ * for user only. Nothing to group and others.
+ */
+ char *home = getenv("HOME");
+ if (home != NULL)
+ {
+ char dotMozillaDir[1024];
+ PR_snprintf(dotMozillaDir, sizeof(dotMozillaDir),
+ "%s/" MOZ_USER_DIR, home);
+ if (PR_Access(dotMozillaDir, PR_ACCESS_EXISTS) != PR_SUCCESS)
+ {
+ PR_MkDir(dotMozillaDir, NS_MOZILLA_DIR_PERMISSION);
+ PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
+ ("nsComponentManager: Creating Directory %s", dotMozillaDir));
+ }
+ }
+#endif /* XP_UNIX */
+
+#ifdef XP_BEOS
+ BPath p;
+ const char *settings = "/boot/home/config/settings";
+ if(find_directory(B_USER_SETTINGS_DIRECTORY, &p) == B_OK)
+ settings = p.Path();
+ char settingsMozillaDir[1024];
+ PR_snprintf(settingsMozillaDir, sizeof(settingsMozillaDir),
+ "%s/" MOZ_USER_DIR, settings);
+ if (PR_Access(settingsMozillaDir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
+ PR_MkDir(settingsMozillaDir, NS_MOZILLA_DIR_PERMISSION);
+ PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
+ ("nsComponentManager: Creating Directory %s", settingsMozillaDir));
+ }
+#endif
+}
+
+/*----------------------------- nsRegistry::OpenWellKnownRegistry --------------
+| Takes a registry id and maps that to a file name for opening. We first check |
+| to see if a registry file is already open and close it if so. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::OpenWellKnownRegistry( nsWellKnownRegistry regid )
+{
+ REGERR err = REGERR_OK;
+
+ if (mCurRegID != nsIRegistry::None && mCurRegID != regid)
+ {
+ // Cant open another registry without closing explictly.
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ if (mCurRegID == regid)
+ {
+ // Already opened.
+ return NS_OK;
+ }
+
+ nsresult rv;
+ nsCOMPtr<nsIFile> registryLocation;
+
+ PRBool foundReg = PR_FALSE;
+ nsCAutoString regFile;
+
+ switch ( (nsWellKnownRegistry) regid ) {
+ case ApplicationComponentRegistry:
+ NS_WARNING("ApplicationComponentRegistry is unsupported!");
+ break;
+ case ApplicationRegistry:
+ {
+ EnsureDefaultRegistryDirectory();
+ nsCOMPtr<nsIProperties> directoryService = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
+ if (NS_FAILED(rv)) return rv;
+ directoryService->Get(NS_APP_APPLICATION_REGISTRY_FILE, NS_GET_IID(nsIFile),
+ getter_AddRefs(registryLocation));
+
+ if (registryLocation)
+ {
+ foundReg = PR_TRUE;
+ rv = registryLocation->GetNativePath(regFile); // dougt fix...
+ // dveditz needs to fix his registry so that I can pass an
+ // nsIFile interface and not hack
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (foundReg == PR_FALSE) {
+ return NS_ERROR_REG_BADTYPE;
+ }
+
+#ifdef DEBUG_dp
+ printf("nsRegistry: Opening std registry %s\n", regFile.get());
+#endif /* DEBUG_dp */
+
+ PR_Lock(mregLock);
+ err = NR_RegOpen(NS_CONST_CAST(char*, regFile.get()), &mReg );
+ PR_Unlock(mregLock);
+
+ // Store the registry that was opened for optimizing future opens.
+ mCurRegID = regid;
+
+ // Convert the result.
+ return regerr2nsresult( err );
+}
+
+#if 0
+/*-------------------------- nsRegistry::OpenDefault ---------------------------
+| Open the "default" registry; in the case of this libreg-based implementation |
+| that is done by passing a null file name pointer to NR_RegOpen. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::OpenDefault() {
+ return OpenWellKnownRegistry(nsIRegistry::ApplicationRegistry);
+}
+#endif
+
+/*----------------------------- nsRegistry::Close ------------------------------
+| Tests the mReg handle and if non-null, closes the registry via NR_RegClose. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::Close() {
+ REGERR err = REGERR_OK;
+ if( mReg ) {
+ PR_Lock(mregLock);
+ err = NR_RegClose( mReg );
+ PR_Unlock(mregLock);
+ mReg = 0;
+ mCurRegFile = nsnull;
+ mCurRegID = 0;
+ }
+ return regerr2nsresult( err );
+}
+
+/*----------------------------- nsRegistry::Flush ------------------------------
+| Flushes the registry via NR_RegFlush. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::Flush() {
+ REGERR err = REGERR_FAIL;
+ if( mReg ) {
+ PR_Lock(mregLock);
+ err = NR_RegFlush( mReg );
+ PR_Unlock(mregLock);
+ }
+ return regerr2nsresult( err );
+}
+
+/*----------------------------- nsRegistry::IsOpen -----------------------------
+| Tests the mReg handle and returns whether the registry is open or not. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::IsOpen( PRBool *result ) {
+ *result = ( mReg != 0 );
+ return NS_OK;
+}
+
+
+/*--------------------------- nsRegistry::AddKey -------------------------------
+| Add a key into the registry or find an existing one. This is generally used |
+| instead of GetKey unless it's an error for the key not to exist already i
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::AddKey( nsRegistryKey baseKey, const PRUnichar *keyname, nsRegistryKey *_retval)
+{
+ if ( !keyname )
+ return NS_ERROR_NULL_POINTER;
+
+ return AddSubtree( baseKey, NS_ConvertUCS2toUTF8(keyname).get(), _retval );
+}
+
+/*--------------------------- nsRegistry::GetKey -------------------------------
+| returns the nsRegistryKey associated with a given node in the registry |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::GetKey(nsRegistryKey baseKey, const PRUnichar *keyname, nsRegistryKey *_retval)
+{
+ if ( !keyname || !_retval )
+ return NS_ERROR_NULL_POINTER;
+
+ return GetSubtree( baseKey, NS_ConvertUCS2toUTF8(keyname).get(), _retval );
+}
+
+/*--------------------------- nsRegistry::RemoveKey ----------------------------
+| Delete a key from the registry |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::RemoveKey(nsRegistryKey baseKey, const PRUnichar *keyname)
+{
+ if ( !keyname )
+ return NS_ERROR_NULL_POINTER;
+
+ return RemoveSubtree( baseKey, NS_ConvertUCS2toUTF8(keyname).get() );
+}
+
+NS_IMETHODIMP nsRegistry::GetString(nsRegistryKey baseKey, const PRUnichar *valname, PRUnichar **_retval)
+{
+ // Make sure caller gave us place for result.
+ if ( !valname || !_retval )
+ return NS_ERROR_NULL_POINTER;
+
+ // initialize the return value
+ *_retval = nsnull;
+ nsXPIDLCString tmpstr;
+
+ nsresult rv = GetStringUTF8( baseKey, NS_ConvertUCS2toUTF8(valname).get(), getter_Copies(tmpstr) );
+
+ if (NS_SUCCEEDED(rv))
+ {
+ *_retval = nsTextFormatter::smprintf( widestrFormat, tmpstr.get() );
+ if ( *_retval == nsnull )
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ return rv;
+}
+
+NS_IMETHODIMP nsRegistry::SetString(nsRegistryKey baseKey, const PRUnichar *valname, const PRUnichar *value)
+{
+ if ( !valname || ! value )
+ return NS_ERROR_NULL_POINTER;
+
+ return SetStringUTF8( baseKey,
+ NS_ConvertUCS2toUTF8(valname).get(),
+ NS_ConvertUCS2toUTF8(value).get() );
+}
+
+/*--------------------------- nsRegistry::GetString ----------------------------
+| First, look for the entry using GetValueInfo. If found, and it's a string, |
+| allocate space for it and fetch the value. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::GetStringUTF8( nsRegistryKey baseKey, const char *path, char **result ) {
+ nsresult rv = NS_OK;
+ REGERR err = REGERR_OK;
+
+ // Make sure caller gave us place for result.
+ if ( !result )
+ return NS_ERROR_NULL_POINTER;
+
+ char regStr[MAXREGPATHLEN];
+
+ // initialize the return value
+ *result = 0;
+
+ // Attempt to get string into our fixed buffer
+ PR_Lock(mregLock);
+ err = NR_RegGetEntryString( mReg,(RKEY)baseKey,(char*)path, regStr,
+ sizeof(regStr) );
+ PR_Unlock(mregLock);
+
+ if ( err == REGERR_OK )
+ {
+ *result = nsCRT::strdup(regStr);
+ if (!*result)
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ else if ( err == REGERR_BUFTOOSMALL )
+ {
+ // find the real size and malloc it
+ PRUint32 length;
+ rv = GetValueLength( baseKey, path, &length );
+ // See if that worked.
+ if( rv == NS_OK )
+ {
+ *result =(char*)nsMemory::Alloc( length + 1 );
+ if( *result )
+ {
+ // Get string from registry into result buffer.
+ PR_Lock(mregLock);
+ err = NR_RegGetEntryString( mReg,(RKEY)baseKey,(char*)path, *result, length+1 );
+ PR_Unlock(mregLock);
+
+ // Convert status.
+ rv = regerr2nsresult( err );
+ if ( rv != NS_OK )
+ {
+ // Didn't get result, free buffer
+ nsCRT::free( *result );
+ *result = 0;
+ }
+ }
+ else
+ {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ }
+ else
+ {
+ // Convert status.
+ rv = regerr2nsresult( err );
+ NS_ASSERTION(NS_FAILED(rv), "returning success code on failure");
+ }
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsRegistry::GetStringUTF8IntoBuffer( nsRegistryKey baseKey, const char *path,
+ char *buf, PRUint32 *length )
+{
+ REGERR err = REGERR_OK;
+
+ // Attempt to get string into our fixed buffer
+ PR_Lock(mregLock);
+ err = NR_RegGetEntryString( mReg,(RKEY)baseKey,(char*)path, buf, *length );
+ PR_Unlock(mregLock);
+
+ // Convert status.
+ nsresult rv = regerr2nsresult( err );
+
+ if (rv == NS_ERROR_REG_BUFFER_TOO_SMALL) {
+ // fill length with the actual length
+ nsresult rv1 = GetValueLength( baseKey, path, length );
+ if(NS_FAILED(rv1))
+ return rv1;
+ }
+
+ return rv;
+}
+
+/*--------------------------- nsRegistry::SetString ----------------------------
+| Simply sets the registry contents using NR_RegSetEntryString. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::SetStringUTF8( nsRegistryKey baseKey, const char *path, const char *value ) {
+ REGERR err = REGERR_OK;
+ // Set the contents.
+ PR_Lock(mregLock);
+ err = NR_RegSetEntryString( mReg,(RKEY)baseKey,(char*)path,(char*)value );
+ PR_Unlock(mregLock);
+ // Convert result.
+ return regerr2nsresult( err );
+}
+
+/*---------------------------- nsRegistry::GetBytesUTF8 ------------------------------
+| This function is just shorthand for fetching a char array. We |
+| implement it "manually" using NR_RegGetEntry |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::GetBytesUTF8( nsRegistryKey baseKey, const char *path, PRUint32* length, PRUint8** result) {
+ nsresult rv = NS_OK;
+ REGERR err = REGERR_OK;
+
+ if ( !result )
+ return NS_ERROR_NULL_POINTER;
+
+ char regStr[MAXREGPATHLEN];
+
+ // initialize the return value
+ *length = 0;
+ *result = 0;
+
+ // Get info about the requested entry.
+ PRUint32 type;
+ rv = GetValueType( baseKey, path, &type );
+ // See if that worked.
+ if( rv == NS_OK )
+ {
+ // Make sure the entry is an PRInt8 array.
+ if( type == Bytes )
+ {
+ // Attempt to get string into our fixed buffer
+ PR_Lock(mregLock);
+ uint32 length2 = sizeof regStr;
+ err = NR_RegGetEntry( mReg,(RKEY)baseKey,NS_CONST_CAST(char*,path), regStr, &length2);
+ PR_Unlock(mregLock);
+
+ if ( err == REGERR_OK )
+ {
+ *length = length2;
+ *result = (PRUint8*)(nsCRT::strdup(regStr));
+ if (!*result)
+ {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ *length = 0;
+ }
+ else
+ {
+ *length = length2;
+ }
+ }
+ else if ( err == REGERR_BUFTOOSMALL )
+ {
+ // find the real size and malloc it
+ rv = GetValueLength( baseKey, path, length );
+ // See if that worked.
+ if( rv == NS_OK )
+ {
+ *result = NS_REINTERPRET_CAST(PRUint8*,nsMemory::Alloc( *length ));
+ if( *result )
+ {
+ // Get bytes from registry into result field.
+ PR_Lock(mregLock);
+ length2 = *length;
+ err = NR_RegGetEntry( mReg,(RKEY)baseKey,NS_CONST_CAST(char*,path), *result, &length2);
+ *length = length2;
+ PR_Unlock(mregLock);
+ // Convert status.
+ rv = regerr2nsresult( err );
+ if ( rv != NS_OK )
+ {
+ // Didn't get result, free buffer
+ nsCRT::free( NS_REINTERPRET_CAST(char*, *result) );
+ *result = 0;
+ *length = 0;
+ }
+ }
+ else
+ {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ }
+ }
+ else
+ {
+ // They asked for the wrong type of value.
+ rv = NS_ERROR_REG_BADTYPE;
+ }
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsRegistry::GetBytesUTF8IntoBuffer( nsRegistryKey baseKey, const char *path,
+ PRUint8 *buf, PRUint32* length )
+{
+ REGERR err = REGERR_OK;
+
+ // Get info about the requested entry.
+ PRUint32 type;
+ nsresult rv = GetValueType( baseKey, path, &type );
+ // See if that worked.
+ if(NS_FAILED(rv))
+ return rv;
+ // Make sure we are dealing with bytes
+ if (type != Bytes)
+ return NS_ERROR_REG_BADTYPE;
+
+ // Attempt to get bytes into our fixed buffer
+ PR_Lock(mregLock);
+ err = NR_RegGetEntry( mReg,(RKEY)baseKey,NS_CONST_CAST(char*,path),
+ buf, (uint32 *)length );
+ PR_Unlock(mregLock);
+
+ rv = regerr2nsresult(rv);
+
+ if (rv == NS_ERROR_REG_BUFFER_TOO_SMALL) {
+ // fill length with the actual length
+ nsresult rv1 = GetValueLength( baseKey, path, length );
+ if(NS_FAILED(rv1))
+ return rv1;
+ }
+
+
+ return rv;
+}
+
+/*---------------------------- nsRegistry::GetInt ------------------------------
+| This function is just shorthand for fetching a 1-element PRInt32 array. We |
+| implement it "manually" using NR_RegGetEntry |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::GetInt( nsRegistryKey baseKey, const char *path, PRInt32 *result ) {
+ nsresult rv = NS_OK;
+ REGERR err = REGERR_OK;
+
+ // Make sure caller gave us place for result.
+ if( result ) {
+ // Get info about the requested entry.
+ PRUint32 type;
+ rv = GetValueType( baseKey, path, &type );
+ // See if that worked.
+ if( rv == NS_OK ) {
+ // Make sure the entry is an PRInt32 array.
+ if( type == Int32 ) {
+ uint32 len = sizeof *result;
+ // Get int from registry into result field.
+ PR_Lock(mregLock);
+ err = NR_RegGetEntry( mReg,(RKEY)baseKey,(char*)path, result, &len );
+ PR_Unlock(mregLock);
+ // Convert status.
+ rv = regerr2nsresult( err );
+ } else {
+ // They asked for the wrong type of value.
+ rv = NS_ERROR_REG_BADTYPE;
+ }
+ }
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+
+/*---------------------------- nsRegistry::GetLongLong--------------------------
+| This function is just shorthand for fetching a 1-element PRInt64 array. We |
+| implement it "manually" using NR_RegGetEntry |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::GetLongLong( nsRegistryKey baseKey, const char *path, PRInt64 *result ) {
+ REGERR err = REGERR_OK;
+
+ PR_Lock(mregLock);
+
+ uint32 length = sizeof(PRInt64);
+ err = NR_RegGetEntry( mReg,(RKEY)baseKey,(char*)path,(void*)result,&length);
+
+ PR_Unlock(mregLock);
+
+ // Convert status.
+ return regerr2nsresult( err );
+}
+/*---------------------------- nsRegistry::SetBytesUTF8 ------------------------------
+| Write out the value as a char array, using NR_RegSetEntry. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::SetBytesUTF8( nsRegistryKey baseKey, const char *path, PRUint32 length, PRUint8* value) {
+ REGERR err = REGERR_OK;
+ // Set the contents.
+ PR_Lock(mregLock);
+ err = NR_RegSetEntry( mReg,
+ (RKEY)baseKey,
+ (char*)path,
+ REGTYPE_ENTRY_BYTES,
+ (char*)value,
+ length);
+ PR_Unlock(mregLock);
+ // Convert result.
+ return regerr2nsresult( err );
+}
+
+/*---------------------------- nsRegistry::SetInt ------------------------------
+| Write out the value as a one-element PRInt32 array, using NR_RegSetEntry. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::SetInt( nsRegistryKey baseKey, const char *path, PRInt32 value ) {
+ REGERR err = REGERR_OK;
+ // Set the contents.
+ PR_Lock(mregLock);
+ err = NR_RegSetEntry( mReg,
+ (RKEY)baseKey,
+ (char*)path,
+ REGTYPE_ENTRY_INT32_ARRAY,
+ &value,
+ sizeof value );
+ PR_Unlock(mregLock);
+ // Convert result.
+ return regerr2nsresult( err );
+}
+
+
+
+/*---------------------------- nsRegistry::SetLongLong---------------------------
+| Write out the value as a one-element PRInt64 array, using NR_RegSetEntry. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::SetLongLong( nsRegistryKey baseKey, const char *path, PRInt64* value ) {
+ REGERR err = REGERR_OK;
+ // Set the contents.
+ PR_Lock(mregLock);
+
+ err = NR_RegSetEntry( mReg,
+ (RKEY)baseKey,
+ (char*)path,
+ REGTYPE_ENTRY_BYTES,
+ (void*)value,
+ sizeof(PRInt64) );
+
+ PR_Unlock(mregLock);
+ // Convert result.
+ return regerr2nsresult( err );
+}
+
+/*-------------------------- nsRegistry::AddSubtree ----------------------------
+| Add a new registry subkey with the specified name, using NR_RegAddKey. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::AddSubtree( nsRegistryKey baseKey, const char *path, nsRegistryKey *result ) {
+ REGERR err = REGERR_OK;
+ // Add the subkey.
+ PR_Lock(mregLock);
+ err = NR_RegAddKey( mReg,(RKEY)baseKey,(char*)path,(RKEY*)result );
+ PR_Unlock(mregLock);
+ // Convert result.
+ return regerr2nsresult( err );
+}
+
+/*-------------------------- nsRegistry::AddSubtreeRaw--------------------------
+| Add a new registry subkey with the specified name, using NR_RegAddKeyRaw |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::AddSubtreeRaw( nsRegistryKey baseKey, const char *path, nsRegistryKey *result ) {
+ REGERR err = REGERR_OK;
+ // Add the subkey.
+ PR_Lock(mregLock);
+ err = NR_RegAddKeyRaw( mReg,(RKEY)baseKey,(char*)path,(RKEY*)result );
+ PR_Unlock(mregLock);
+ // Convert result.
+ return regerr2nsresult( err );
+}
+
+
+/*------------------------- nsRegistry::RemoveSubtree --------------------------
+| Deletes the subtree at a given location using NR_RegDeleteKey. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::RemoveSubtree( nsRegistryKey baseKey, const char *path ) {
+ nsresult rv = NS_OK;
+ REGERR err = REGERR_OK;
+
+ // libreg doesn't delete keys if there are subkeys under the key
+ // Hence we have to recurse through to delete the subtree
+
+ RKEY key;
+
+ PR_Lock(mregLock);
+ err = NR_RegGetKey(mReg, baseKey, (char *)path, &key);
+ PR_Unlock(mregLock);
+ if (err != REGERR_OK)
+ {
+ rv = regerr2nsresult( err );
+ return rv;
+ }
+
+ // Now recurse through and delete all keys under hierarchy
+
+ char subkeyname[MAXREGPATHLEN+1];
+ REGENUM state = 0;
+ subkeyname[0] = '\0';
+ while (NR_RegEnumSubkeys(mReg, key, &state, subkeyname, sizeof(subkeyname),
+ REGENUM_NORMAL) == REGERR_OK)
+ {
+#ifdef DEBUG_dp
+ printf("...recursing into %s\n", subkeyname);
+#endif /* DEBUG_dp */
+ // Even though this is not a "Raw" API the subkeys may still, in fact,
+ // *be* raw. Since we're recursively deleting this will work either way.
+ // If we were guaranteed none would be raw then a depth-first enumeration
+ // would be much more efficient.
+ err = RemoveSubtreeRaw(key, subkeyname);
+ if (err != REGERR_OK) break;
+ }
+
+ // If success in deleting all subkeys, delete this key too
+ if (err == REGERR_OK)
+ {
+#ifdef DEBUG_dp
+ printf("...deleting %s\n", path);
+#endif /* DEBUG_dp */
+ PR_Lock(mregLock);
+ err = NR_RegDeleteKey(mReg, baseKey, (char *)path);
+ PR_Unlock(mregLock);
+ }
+
+ // Convert result.
+ rv = regerr2nsresult( err );
+ return rv;
+}
+
+
+/*------------------------- nsRegistry::RemoveSubtreeRaw -----------------------
+| Deletes the subtree at a given location using NR_RegDeleteKeyRaw |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::RemoveSubtreeRaw( nsRegistryKey baseKey, const char *keyname ) {
+ nsresult rv = NS_OK;
+ REGERR err = REGERR_OK;
+
+ // libreg doesn't delete keys if there are subkeys under the key
+ // Hence we have to recurse through to delete the subtree
+
+ RKEY key;
+ char subkeyname[MAXREGPATHLEN+1];
+ int n = sizeof(subkeyname);
+ REGENUM state = 0;
+
+ PR_Lock(mregLock);
+ err = NR_RegGetKeyRaw(mReg, baseKey, (char *)keyname, &key);
+ PR_Unlock(mregLock);
+ if (err != REGERR_OK)
+ {
+ rv = regerr2nsresult( err );
+ return rv;
+ }
+
+ // Now recurse through and delete all keys under hierarchy
+
+ subkeyname[0] = '\0';
+ while (NR_RegEnumSubkeys(mReg, key, &state, subkeyname, n, REGENUM_NORMAL) == REGERR_OK)
+ {
+#ifdef DEBUG_dp
+ printf("...recursing into %s\n", subkeyname);
+#endif /* DEBUG_dp */
+ err = RemoveSubtreeRaw(key, subkeyname);
+ if (err != REGERR_OK) break;
+ }
+
+ // If success in deleting all subkeys, delete this key too
+ if (err == REGERR_OK)
+ {
+#ifdef DEBUG_dp
+ printf("...deleting %s\n", keyname);
+#endif /* DEBUG_dp */
+ PR_Lock(mregLock);
+ err = NR_RegDeleteKeyRaw(mReg, baseKey, (char *)keyname);
+ PR_Unlock(mregLock);
+ }
+
+ // Convert result.
+ rv = regerr2nsresult( err );
+ return rv;
+}
+/*-------------------------- nsRegistry::GetSubtree ----------------------------
+| Returns a nsRegistryKey(RKEY) for a given key/path. The key is |
+| obtained using NR_RegGetKey. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::GetSubtree( nsRegistryKey baseKey, const char *path, nsRegistryKey *result ) {
+ nsresult rv = NS_OK;
+ REGERR err = REGERR_OK;
+ // Make sure we have a place for the result.
+ if( result ) {
+ // Get key.
+ PR_Lock(mregLock);
+ err = NR_RegGetKey( mReg,(RKEY)baseKey,(char*)path,(RKEY*)result );
+ PR_Unlock(mregLock);
+ // Convert result.
+ rv = regerr2nsresult( err );
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*-------------------------- nsRegistry::GetSubtreeRaw--------------------------
+| Returns a nsRegistryKey(RKEY) for a given key/path. The key is |
+| obtained using NR_RegGetKeyRaw. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::GetSubtreeRaw( nsRegistryKey baseKey, const char *path, nsRegistryKey *result ) {
+ nsresult rv = NS_OK;
+ REGERR err = REGERR_OK;
+ // Make sure we have a place for the result.
+ if( result ) {
+ // Get key.
+ PR_Lock(mregLock);
+ err = NR_RegGetKeyRaw( mReg,(RKEY)baseKey,(char*)path,(RKEY*)result );
+ PR_Unlock(mregLock);
+ // Convert result.
+ rv = regerr2nsresult( err );
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+
+/*----------------------- nsRegistry::EnumerateSubtrees ------------------------
+| Allocate a nsRegSubtreeEnumerator object and return it to the caller. |
+| We construct the enumerator using the registry handle from this registry |
+| object, the user-specified registry key, and indicate that we don't want |
+| to recurse down subtrees. No libreg functions are invoked at this point |
+|(that will happen when the enumerator member functions are called). |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::EnumerateSubtrees( nsRegistryKey baseKey, nsIEnumerator **result ) {
+ nsresult rv = NS_OK;
+ // Make sure we have a place to put the result.
+ if( result ) {
+ *result = new nsRegSubtreeEnumerator( mReg,(RKEY)baseKey, PR_FALSE );
+ // Check for success.
+ if( *result ) {
+ // Bump refcnt on behalf of caller.
+ NS_ADDREF(*result);
+ } else {
+ // Unable to allocate space for the enumerator object.
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*--------------------- nsRegistry::EnumerateAllSubtrees -----------------------
+| Same as EnumerateSubtrees but we pass PR_TRUE to request that the |
+| enumerator object descend subtrees when it is used. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::EnumerateAllSubtrees( nsRegistryKey baseKey, nsIEnumerator **result ) {
+ nsresult rv = NS_OK;
+ // Make sure we have a place to put the result.
+ if( result ) {
+ *result = new nsRegSubtreeEnumerator( mReg,(RKEY)baseKey, PR_TRUE );
+ // Check for success.
+ if( *result ) {
+ // Bump refcnt on behalf of caller.
+ NS_ADDREF(*result);
+ } else {
+ // Unable to allocate space for the enumerator object.
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*------------------------- nsRegistry::GetValueType ---------------------------
+| Gets the type from the registry using the NR_GetEntryInfo libreg API. |
+| The result is transferred to the PRUint32 value passed in (with conversion |
+| to the appropriate nsIRegistry::DataType value). |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::GetValueType( nsRegistryKey baseKey, const char *path, PRUint32 *result ) {
+ nsresult rv = NS_OK;
+ REGERR err = REGERR_OK;
+ // Make sure we have a place to put the result.
+ if( result ) {
+ // Get registry info into local structure.
+ REGINFO info = { sizeof info, 0, 0 };
+ PR_Lock(mregLock);
+ err = NR_RegGetEntryInfo( mReg,(RKEY)baseKey,(char*)path, &info );
+ PR_Unlock(mregLock);
+ if( err == REGERR_OK ) {
+ // Copy info to user's result value.
+ reginfo2DataType( info, *result );
+ } else {
+ rv = regerr2nsresult( err );
+ }
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*------------------------ nsRegistry::GetValueLength --------------------------
+| Gets the registry value info via NR_RegGetEntryInfo. The length is |
+| converted to the proper "units" via reginfo2Length. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::GetValueLength( nsRegistryKey baseKey, const char *path, PRUint32 *result ) {
+ nsresult rv = NS_OK;
+ REGERR err = REGERR_OK;
+ // Make sure we have a place to put the result.
+ if( result ) {
+ // Get registry info into local structure.
+ REGINFO info = { sizeof info, 0, 0 };
+ PR_Lock(mregLock);
+ err = NR_RegGetEntryInfo( mReg,(RKEY)baseKey,(char*)path, &info );
+ PR_Unlock(mregLock);
+ if( err == REGERR_OK ) {
+ // Copy info to user's result value.
+ reginfo2Length( info, *result );
+ } else {
+ rv = regerr2nsresult( err );
+ }
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*-------------------------- nsRegistry::DeleteValue ---------------------------
+| Remove the registry value with the specified name |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::DeleteValue( nsRegistryKey baseKey, const char *path)
+{
+ REGERR err = REGERR_OK;
+ // Delete the value
+ PR_Lock(mregLock);
+ err = NR_RegDeleteEntry( mReg,(RKEY)baseKey,(char*)path );
+ PR_Unlock(mregLock);
+ // Convert result.
+ return regerr2nsresult( err );
+}
+
+/*------------------------ nsRegistry::EnumerateValues -------------------------
+| Allocates and returns an instance of nsRegValueEnumerator constructed in |
+| a similar fashion as the nsRegSubtreeEnumerator is allocated/returned by |
+| EnumerateSubtrees. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::EnumerateValues( nsRegistryKey baseKey, nsIEnumerator **result ) {
+ nsresult rv = NS_OK;
+ // Make sure we have a place to put the result.
+ if( result ) {
+ *result = new nsRegValueEnumerator( mReg,(RKEY)baseKey );
+ // Check for success.
+ if( *result ) {
+ // Bump refcnt on behalf of caller.
+ NS_ADDREF(*result);
+ } else {
+ // Unable to allocate space for the enumerator object.
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*---------------------- nsRegistry::GetCurrentUserName ------------------------
+| Simple wrapper for NR_RegGetUsername. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::GetCurrentUserName( char **result ) {
+ nsresult rv = NS_OK;
+ REGERR err = REGERR_OK;
+ // Make sure we have a place to put the result.
+ if( result ) {
+ // Get the user name.
+ PR_Lock(mregLock);
+ err = NR_RegGetUsername( result );
+ PR_Unlock(mregLock);
+ // Convert the result.
+ rv = regerr2nsresult( err );
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*---------------------- nsRegistry::SetCurrentUserName ------------------------
+| Simple wrapper for NR_RegSetUsername. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::SetCurrentUserName( const char *name ) {
+ nsresult rv = NS_OK;
+ REGERR err = REGERR_OK;
+ // Set the user name.
+ PR_Lock(mregLock);
+ err = NR_RegSetUsername( name );
+ PR_Unlock(mregLock);
+ // Convert result.
+ rv = regerr2nsresult( err );
+ return rv;
+}
+
+/*----------------------------- nsRegistry::Pack -------------------------------
+| Simple wrapper for NR_RegPack. We don't set up any callback. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::Pack() {
+ nsresult rv = NS_OK;
+ REGERR err = REGERR_OK;
+ // Pack the registry.
+ PR_Lock(mregLock);
+ err = NR_RegPack( mReg, 0, 0 );
+ PR_Unlock(mregLock);
+ // Convert result.
+ rv = regerr2nsresult( err );
+ return rv;
+}
+
+/*----------------------------- nsRegistry::EscapeKey -------------------------------
+| Escape a binary key so that the registry works OK, since it expects UTF8
+| with no slashes or control characters. This is probably better than raw.
+| If no escaping is required, then the method is successful and a null is
+| returned, indicating that the caller should use the original string.
+------------------------------------------------------------------------------*/
+static const char sEscapeKeyHex[] = "0123456789abcdef0123456789ABCDEF";
+NS_IMETHODIMP nsRegistry::EscapeKey(PRUint8* key, PRUint32 termination, PRUint32* length, PRUint8** escaped)
+{
+ nsresult rv = NS_OK;
+ char* value = (char*)key;
+ char* b = value;
+ char* e = b + *length;
+ int escapees = 0;
+ while (b < e) // Count characters outside legal range or slash
+ {
+ int c = *b++;
+ if (c <= ' '
+ || c > '~'
+ || c == '/'
+ || c == '%')
+ {
+ escapees++;
+ }
+ }
+ if (escapees == 0) // If no escapees, then no results
+ {
+ *length = 0;
+ *escaped = nsnull;
+ return NS_OK;
+ }
+ // New length includes two extra chars for escapees.
+ *length += escapees * 2;
+ *escaped = (PRUint8*)nsMemory::Alloc(*length + termination);
+ if (*escaped == nsnull)
+ {
+ *length = 0;
+ *escaped = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ char* n = (char*)*escaped;
+ b = value;
+ while (escapees && b < e)
+ {
+ char c = *b++;
+ if (c < ' '
+ || c > '~'
+ || c == '/'
+ || c == '%')
+ {
+ *(n++) = '%';
+ *(n++) = sEscapeKeyHex[ 0xF & (c >> 4) ];
+ *(n++) = sEscapeKeyHex[ 0xF & c ];
+ escapees--;
+ }
+ else
+ {
+ *(n++) = c;
+ }
+ }
+ e += termination;
+ if (b < e)
+ {
+ strncpy(n, b, e - b);
+ }
+ return rv;
+}
+
+/*----------------------------- nsRegistry::UnescapeKey -------------------------------
+| Unscape a binary key so that the registry works OK, since it expects UTF8
+| with no slashes or control characters. This is probably better than raw.
+| If no escaping is required, then the method is successful and a null is
+| returned, indicating that the caller should use the original string.
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistry::UnescapeKey(PRUint8* escaped, PRUint32 termination, PRUint32* length, PRUint8** key)
+{
+ nsresult rv = NS_OK;
+ char* value = (char*)escaped;
+ char* b = value;
+ char* e = b + *length;
+ int escapees = 0;
+ while (b < e) // Count characters outside legal range or slash
+ {
+ if (*b++ == '%')
+ {
+ escapees++;
+ }
+ }
+ if (escapees == 0) // If no escapees, then no results
+ {
+ *length = 0;
+ *key = nsnull;
+ return NS_OK;
+ }
+ // New length includes two extra chars for escapees.
+ *length -= escapees * 2;
+ *key = (PRUint8*)nsMemory::Alloc(*length + termination);
+ if (*key == nsnull)
+ {
+ *length = 0;
+ *key = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ char* n = (char*)*key;
+ b = value;
+ while (escapees && b < e)
+ {
+ char c = *(b++);
+ if (c == '%')
+ {
+ if (e - b >= 2)
+ {
+ const char* c1 = strchr(sEscapeKeyHex, *(b++));
+ const char* c2 = strchr(sEscapeKeyHex, *(b++));
+ if (c1 != nsnull
+ && c2 != nsnull)
+ {
+ *(n++) = ((c2 - sEscapeKeyHex) & 0xF)
+ | (((c1 - sEscapeKeyHex) & 0xF) << 4);
+ }
+ else
+ {
+ escapees = -1;
+ }
+ }
+ else
+ {
+ escapees = -1;
+ }
+ escapees--;
+ }
+ else
+ {
+ *(n++) = c;
+ }
+ }
+ if (escapees < 0)
+ {
+ nsMemory::Free(*key);
+ *length = 0;
+ *key = nsnull;
+ return NS_ERROR_INVALID_ARG;
+ }
+ e += termination;
+ if (b < e)
+ {
+ strncpy(n, b, e - b);
+ }
+ return rv;
+}
+
+
+/*-------------- nsRegistry::SetBufferSize-------------------------------------
+| Sets the size of the file used for the registry's buffer size. |
+------------------------------------------------------------------------------*/
+int nsRegistry::SetBufferSize( int bufsize )
+{
+ int newSize;
+ // set the file buffer size
+ PR_Lock(mregLock);
+ newSize = NR_RegSetBufferSize( mReg, bufsize );
+ PR_Unlock(mregLock);
+ return newSize;
+}
+
+
+/*-------------- nsRegSubtreeEnumerator::nsRegSubtreeEnumerator ----------------
+| The ctor simply stashes all the information that will be needed to enumerate |
+| the subkeys. |
+------------------------------------------------------------------------------*/
+nsRegSubtreeEnumerator::nsRegSubtreeEnumerator( HREG hReg, RKEY rKey, PRBool all )
+ : mReg( hReg ), mKey( rKey ), mEnum( 0 ), mNext( 0 ),
+ mStyle( all ? REGENUM_DESCEND : REGENUM_CHILDREN ), mDone( PR_FALSE ) {
+
+ mName[0] = '\0';
+
+#ifdef EXTRA_THREADSAFE
+ // Create a registry lock
+ mregLock = PR_NewLock();
+#endif
+ return;
+}
+
+nsRegSubtreeEnumerator::~nsRegSubtreeEnumerator()
+{
+#ifdef EXTRA_THREADSAFE
+ if (mregLock) {
+ PR_DestroyLock(mregLock);
+ }
+#endif
+}
+
+/*----------------------- nsRegSubtreeEnumerator::First ------------------------
+| Set mEnum to 0; this will cause the next NR_RegEnum call to go to |
+| the beginning. We then do a Next() call in order to do a "lookahead" to |
+| properly detect an empty list (i.e., set the mDone flag). |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP
+nsRegSubtreeEnumerator::First() {
+ nsresult rv = NS_OK;
+ // Reset "done" flag.
+ mDone = PR_FALSE;
+ // Clear Name
+ mName[0] = '\0';
+ // Go to beginning.
+ mEnum = mNext = 0;
+ // Lookahead so mDone flag gets set for empty list.
+ rv = Next();
+ return rv;
+}
+
+/*----------------------- nsRegSubtreeEnumerator::Next -------------------------
+| First, we check if we've already advanced to the end by checking the mDone |
+| flag. |
+| |
+| We advance mEnum to the next enumeration value which is in the mNext |
+| lookahead buffer. We must then call advance to lookahead and properly set |
+| the isDone flag. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP
+nsRegSubtreeEnumerator::Next() {
+ nsresult rv = NS_OK;
+ // Check for at end.
+ if ( !mDone ) {
+ // Advance to next spot.
+ mEnum = mNext;
+ // Lookahead so mDone is properly set (and to update mNext).
+ rv = advance();
+ } else {
+ // Set result accordingly.
+ rv = regerr2nsresult( REGERR_NOMORE );
+ }
+ return rv;
+}
+
+/*---------------------- nsRegSubtreeEnumerator::advance -----------------------
+| Advance mNext to next subkey using NR_RegEnumSubkeys. We set mDone if |
+| there are no more subkeys. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegSubtreeEnumerator::advance() {
+ REGERR err = REGERR_OK;
+ PR_Lock(mregLock);
+ err = NR_RegEnumSubkeys( mReg, mKey, &mNext, mName, sizeof mName, mStyle );
+ // See if we ran off end.
+ if( err == REGERR_NOMORE ) {
+ // Remember we've run off end.
+ mDone = PR_TRUE;
+ }
+ PR_Unlock(mregLock);
+ // Convert result.
+ nsresult rv = regerr2nsresult( err );
+ return rv;
+}
+
+/*-------------------- nsRegSubtreeEnumerator::CurrentItem ---------------------
+| Allocates and returns a new instance of class nsRegistryNode. The node |
+| object will hold the curent mEnum value so it can obtain its name from |
+| the registry when asked. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP
+nsRegSubtreeEnumerator::CurrentItem( nsISupports **result) {
+ nsresult rv = NS_OK;
+ // Make sure there is a place to put the result.
+ if( result ) {
+ *result = new nsRegistryNode( mReg, mName, (RKEY) mNext );
+ if( *result ) {
+ NS_ADDREF(*result);
+ } else {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*--------------nsRegSubtreeEnumerator::CurrentItemInPlaceUTF8-----------------
+| An ugly name for an ugly function. Hands back a shared pointer to the |
+| name (encoded as UTF-8), and the subkey identifier. |
+-----------------------------------------------------------------------------*/
+NS_IMETHODIMP
+nsRegSubtreeEnumerator::CurrentItemInPlaceUTF8( nsRegistryKey *childKey ,
+ const char **name )
+{
+ *childKey = mNext;
+ /* [shared] */
+ *name = mName;
+ return NS_OK;
+}
+
+/*---------------------- nsRegSubtreeEnumerator::IsDone ------------------------
+| Simply return mDone. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP
+nsRegSubtreeEnumerator::IsDone() {
+ nsresult rv = mDone ? NS_OK : NS_ENUMERATOR_FALSE;
+ return rv;
+}
+
+
+/*---------------- nsRegValueEnumerator::nsRegValueEnumerator ------------------
+| Delegates everything to the base class constructor. |
+------------------------------------------------------------------------------*/
+nsRegValueEnumerator::nsRegValueEnumerator( HREG hReg, RKEY rKey )
+ : nsRegSubtreeEnumerator( hReg, rKey, PR_FALSE ) {
+ return;
+}
+
+
+/*--------------------- nsRegValueEnumerator::CurrentItem ----------------------
+| As the nsRegSubtreeEnumerator counterpart, but allocates an object of |
+| class nsRegistryValue. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP
+nsRegValueEnumerator::CurrentItem( nsISupports **result ) {
+ nsresult rv = NS_OK;
+ // Make sure there is a place to put the result.
+ if( result ) {
+ *result = new nsRegistryValue( mReg, mKey, mEnum );
+ if( *result ) {
+ NS_ADDREF(*result);
+ } else {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*----------------------- nsRegValueEnumerator::advance ------------------------
+| Advance mNext to next subkey using NR_RegEnumEntries. We set mDone if |
+| there are no more entries. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegValueEnumerator::advance() {
+ REGERR err = REGERR_OK;
+ char name[MAXREGNAMELEN];
+ PRUint32 len = sizeof name;
+ REGINFO info = { sizeof info, 0, 0 };
+ PR_Lock(mregLock);
+ err = NR_RegEnumEntries( mReg, mKey, &mNext, name, len, &info );
+ // See if we ran off end.
+ if( err == REGERR_NOMORE ) {
+ // Remember we've run off end.
+ mDone = PR_TRUE;
+ }
+ PR_Unlock(mregLock);
+ // Convert result.
+ nsresult rv = regerr2nsresult( err );
+ return rv;
+}
+
+
+/*---------------------- nsRegistryNode::nsRegistryNode ------------------------
+| Store the arguments in the corresponding data members and initialize |
+| the other data members. We defer the libreg calls till we're asked for |
+| our name. We use mErr==-1 to indicate we haven't fetched the name yet. |
+------------------------------------------------------------------------------*/
+nsRegistryNode::nsRegistryNode( HREG hReg, char *name, RKEY childKey )
+ : mReg( hReg ), mChildKey( childKey ) {
+
+ PR_ASSERT(name != nsnull);
+ strcpy(mName, name);
+
+#ifdef EXTRA_THREADSAFE
+ mregLock = PR_NewLock();
+#endif
+
+ return;
+}
+
+nsRegistryNode::~nsRegistryNode()
+{
+#ifdef EXTRA_THREADSAFE
+ if (mregLock) {
+ PR_DestroyLock(mregLock);
+ }
+#endif
+}
+
+/*-------------------------- nsRegistryNode::GetName ---------------------------
+| If we haven't fetched it yet, get the name of the corresponding subkey now, |
+| using NR_RegEnumSubkeys. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistryNode::GetName( PRUnichar **result ) {
+ if (result == nsnull) return NS_ERROR_NULL_POINTER;
+ // Make sure there is a place to put the result.
+ *result = nsTextFormatter::smprintf( widestrFormat, mName );
+ if ( !*result ) return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+/*-------------------------- nsRegistryNode::GetNameUTF8 -----------------------
+| If we haven't fetched it yet, get the name of the corresponding subkey now, |
+| using NR_RegEnumSubkeys. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistryNode::GetNameUTF8( char **result ) {
+ if (result == nsnull) return NS_ERROR_NULL_POINTER;
+ // Make sure there is a place to put the result.
+ *result = nsCRT::strdup( mName );
+ if ( !*result ) return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+/*-------------------------- nsRegistryNode::GetKey ----------------------------
+| Get the subkey corresponding to this node |
+| using NR_RegEnumSubkeys. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistryNode::GetKey( nsRegistryKey *r_key ) {
+ nsresult rv = NS_OK;
+ if (r_key == nsnull) return NS_ERROR_NULL_POINTER;
+ *r_key = mChildKey;
+ return rv;
+}
+
+
+
+/*--------------------- nsRegistryValue::nsRegistryValue -----------------------
+| Implemented the same way as the nsRegistryNode ctor. |
+------------------------------------------------------------------------------*/
+nsRegistryValue::nsRegistryValue( HREG hReg, RKEY key, REGENUM slot )
+ : mReg( hReg ), mKey( key ), mEnum( slot ), mErr( -1 ) {
+#ifdef EXTRA_THREADSAFE
+ mregLock = PR_NewLock();
+#endif
+ mInfo.size = sizeof(REGINFO);
+}
+
+nsRegistryValue::~nsRegistryValue()
+{
+#ifdef EXTRA_THREADSAFE
+ if (mregLock) {
+ PR_DestroyLock(mregLock);
+ }
+#endif
+}
+
+/*------------------------- nsRegistryValue::GetName ---------------------------
+| See nsRegistryNode::GetName; we use NR_RegEnumEntries in this case. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistryValue::GetName( PRUnichar **result ) {
+ nsresult rv = NS_OK;
+ // Make sure we have a place to put the result.
+ if( result ) {
+ // Ensure we've got the info we need.
+ rv = getInfo();
+ if( rv == NS_OK || rv == NS_ERROR_REG_NO_MORE ) {
+ // worked, return actual result.
+ *result = nsTextFormatter::smprintf( widestrFormat, mName );
+ if ( *result ) {
+ rv = NS_OK;
+ } else {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*------------------------- nsRegistryValue::GetNameUTF8 -----------------------
+| See nsRegistryNode::GetName; we use NR_RegEnumEntries in this case. |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistryValue::GetNameUTF8( char **result ) {
+ nsresult rv = NS_OK;
+ // Make sure we have a place to put the result.
+ if( result ) {
+ // Ensure we've got the info we need.
+ rv = getInfo();
+ if( rv == NS_OK || rv == NS_ERROR_REG_NO_MORE ) {
+ // worked, return actual result.
+ *result = nsCRT::strdup( mName );
+ if ( *result ) {
+ rv = NS_OK;
+ } else {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*----------------------- nsRegistryValue::GetType ------------------------
+| We test if we've got the info already. If not, we git it by calling |
+| getInfo. We calculate the result by converting the REGINFO type field to |
+| a nsIRegistry::DataType value (using reginfo2DataType). |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistryValue::GetType( PRUint32 *result ) {
+ nsresult rv = NS_OK;
+ // Make sure we have room for th result.
+ if( result ) {
+ // Make sure we've got the info we need.
+ rv = getInfo();
+ // Check if it worked.
+ if( rv == NS_OK ) {
+ // Convert result from REGINFO to nsIRegistry::ValueInfo.
+ reginfo2DataType( mInfo, *result );
+ }
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*---------------------- nsRegistryValue::GetLength -----------------------
+| We test if we've got the info already. If not, we git it by calling |
+| getInfo. We calculate the result by converting the REGINFO type field to |
+| a nsIRegistry::DataType value (using reginfo2Length). |
+------------------------------------------------------------------------------*/
+NS_IMETHODIMP nsRegistryValue::GetLength( PRUint32 *result ) {
+ nsresult rv = NS_OK;
+ // Make sure we have room for th result.
+ if( result ) {
+ // Make sure we've got the info we need.
+ rv = getInfo();
+ // Check if it worked.
+ if( rv == NS_OK ) {
+ // Convert result from REGINFO to length.
+ reginfo2Length( mInfo, *result );
+ }
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+ return rv;
+}
+
+/*------------------------- nsRegistryValue::getInfo ---------------------------
+| Call NR_RegEnumEntries to set the mInfo/mName data members. |
+------------------------------------------------------------------------------*/
+nsresult nsRegistryValue::getInfo() {
+ nsresult rv = NS_OK;
+ // Test whether we haven't tried to get it yet.
+ if( mErr == -1 ) {
+ REGENUM temp = mEnum;
+ // Get name and info.
+ PR_Lock(mregLock);
+ mErr = NR_RegEnumEntries( mReg, mKey, &temp, mName, sizeof mName, &mInfo );
+ // Convert result.
+ rv = regerr2nsresult( mErr );
+ PR_Unlock(mregLock);
+ }
+ return rv;
+}
+
+
+nsRegistryFactory::nsRegistryFactory() {
+}
+
+NS_IMPL_ISUPPORTS1(nsRegistryFactory, nsIFactory)
+
+NS_IMETHODIMP
+nsRegistryFactory::CreateInstance(nsISupports *aOuter,
+ const nsIID &aIID,
+ void **aResult) {
+ nsresult rv = NS_OK;
+ nsRegistry* newRegistry;
+
+ if(aResult == nsnull) {
+ return NS_ERROR_NULL_POINTER;
+ } else {
+ *aResult = nsnull;
+ }
+
+ if(0 != aOuter) {
+ return NS_ERROR_NO_AGGREGATION;
+ }
+
+ NS_NEWXPCOM(newRegistry, nsRegistry);
+
+ if(newRegistry == nsnull) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ NS_ADDREF(newRegistry);
+ rv = newRegistry->QueryInterface(aIID, aResult);
+ NS_RELEASE(newRegistry);
+
+ return rv;
+}
+
+nsresult
+nsRegistryFactory::LockFactory(PRBool aLock)
+{
+ // Not implemented in simplest case.
+ return NS_OK;
+}
+
+// This is a temporary hack; needs work to support dynamic binding
+// via nsComponentManager and support for multiple factories per DLL.
+extern "C" NS_EXPORT nsresult
+NS_RegistryGetFactory(nsIFactory** aFactory ) {
+ nsresult rv = NS_OK;
+
+ if( aFactory == 0 ) {
+ return NS_ERROR_NULL_POINTER;
+ } else {
+ *aFactory = 0;
+ }
+
+ nsIFactory* inst = new nsRegistryFactory();
+ if(0 == inst) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ } else {
+ NS_ADDREF(inst);
+ *aFactory = inst;
+ }
+
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/component/nsRegistry.h b/src/libs/xpcom18a4/xpcom/obsolete/component/nsRegistry.h
new file mode 100644
index 00000000..8b59db36
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/component/nsRegistry.h
@@ -0,0 +1,77 @@
+/* -*- 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):
+ * Edward Kandrot <kandrot@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 nsRegistry_h__
+#define nsRegistry_h__
+
+#include "nsIRegistry.h"
+#include "NSReg.h"
+#include "nsIFile.h"
+#include "nsCOMPtr.h"
+
+struct nsRegistry : public nsIRegistry, nsIRegistryGetter {
+ // This class implements the nsISupports interface functions.
+ NS_DECL_ISUPPORTS
+
+ // This class implements the nsIRegistry interface functions.
+ NS_DECL_NSIREGISTRY
+
+ // Fast registry getters
+ NS_DECL_NSIREGISTRYGETTER
+
+ int SetBufferSize( int bufsize ); // changes the file buffer size for this registry
+
+ // ctor/dtor
+ nsRegistry();
+
+private:
+ ~nsRegistry();
+
+protected:
+ HREG mReg; // Registry handle.
+#ifdef EXTRA_THREADSAFE
+ PRLock *mregLock; // libreg isn't threadsafe. Use locks to synchronize.
+#endif
+ nsCOMPtr<nsIFile> mCurRegFile; // these are to prevent open from opening the registry again
+ nsWellKnownRegistry mCurRegID;
+
+ NS_IMETHOD Close();
+}; // nsRegistry
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/component/nsXPCOMObsolete.cpp b/src/libs/xpcom18a4/xpcom/obsolete/component/nsXPCOMObsolete.cpp
new file mode 100644
index 00000000..9a71a916
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/component/nsXPCOMObsolete.cpp
@@ -0,0 +1,57 @@
+/* -*- 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 "nsXPCOM.h"
+#include "nsIGenericFactory.h"
+
+#include "nsFileSpecImpl.h"
+#include "nsRegistry.h"
+
+#define COMPONENT(NAME, Ctor) \
+ { NS_##NAME##_CLASSNAME, NS_##NAME##_CID, NS_##NAME##_CONTRACTID, Ctor }
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsRegistry)
+
+static const nsModuleComponentInfo components[] =
+{
+ COMPONENT(FILESPEC, nsFileSpecImpl::Create),
+ COMPONENT(DIRECTORYITERATOR, nsDirectoryIteratorImpl::Create),
+ COMPONENT(REGISTRY, nsRegistryConstructor),
+};
+
+NS_IMPL_NSGETMODULE(xpcomObsoleteModule, components)
+
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/component/regExport.cpp b/src/libs/xpcom18a4/xpcom/obsolete/component/regExport.cpp
new file mode 100644
index 00000000..d1b2f85e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/component/regExport.cpp
@@ -0,0 +1,357 @@
+/* -*- 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 <stdio.h>
+
+#include "nsIServiceManager.h"
+#include "nsIComponentManager.h"
+#include "nsCOMPtr.h"
+#include "nsIRegistry.h"
+#include "nsIEnumerator.h"
+#include "nsILocalFile.h"
+#include "nsDependentString.h"
+#include "prmem.h"
+#include "plstr.h"
+#include "nsMemory.h"
+
+static void display( nsIRegistry *reg, nsRegistryKey root, const char *name );
+static void displayValues( nsIRegistry *reg, nsRegistryKey root );
+static void printString( const char *value, int indent );
+
+int main( int argc, char *argv[] ) {
+
+
+#ifdef __MWERKS__
+ // Hack in some arguments. A NULL registry name is supposed to tell libreg
+ // to use the default registry (which does seem to work).
+ argc = 1;
+ const char* myArgs[] =
+ {
+ "regExport"
+ };
+ argv = const_cast<char**>(myArgs);
+#endif
+
+ nsresult rv;
+
+ // Initialize XPCOM
+ nsIServiceManager *servMgr = NULL;
+ rv = NS_InitXPCOM2(&servMgr, NULL, NULL);
+ if (NS_FAILED(rv))
+ {
+ // Cannot initialize XPCOM
+ printf("Cannot initialize XPCOM. Exit. [rv=0x%08X]\n", (int)rv);
+ exit(-1);
+ }
+ {
+ // Get the component manager
+ static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
+ nsCOMPtr<nsIComponentManager> compMgr = do_GetService(kComponentManagerCID, &rv);
+ if (NS_FAILED(rv))
+ {
+ // Cant get component manager
+ printf("Cannot get component manager from service manager.. Exit. [rv=0x%08X]\n", (int)rv);
+ exit(-1);
+ }
+
+ nsIRegistry *reg;
+
+ if (argc>1) {
+ // Create the registry
+ rv = compMgr->CreateInstanceByContractID(NS_REGISTRY_CONTRACTID, NULL,
+ NS_GET_IID(nsIRegistry),
+ (void **) &reg);
+ // Check result.
+ if ( NS_FAILED(rv) )
+ {
+ printf( "Error opening registry file %s, rv=0x%08X\n", argv[1] , (int)rv );
+ return rv;
+ }
+ // Open it against the input file name.
+ nsCOMPtr<nsILocalFile> regFile;
+ rv = NS_NewNativeLocalFile( nsDependentCString(argv[1]), PR_FALSE, getter_AddRefs(regFile) );
+ if ( NS_FAILED(rv) ) {
+ printf( "Error instantiating local file for %s, rv=0x%08X\n", argv[1], (int)rv );
+ return rv;
+ }
+
+ rv = reg->Open( regFile );
+
+ if ( rv == NS_OK )
+ {
+ printf( "Registry %s opened OK.\n", argv[1] );
+
+ // Recurse over all 3 branches.
+ display( reg, nsIRegistry::Common, "nsRegistry::Common" );
+ display( reg, nsIRegistry::Users, "nsRegistry::Users" );
+ }
+ NS_RELEASE(reg);
+ }
+ else
+ {
+ // Called with no arguments. Print both the default registry and
+ // the components registry. We already printed the default regsitry.
+ // So just do the component registry.
+ rv = compMgr->CreateInstanceByContractID(NS_REGISTRY_CONTRACTID, NULL,
+ NS_GET_IID(nsIRegistry),
+ (void **) &reg);
+
+ // Check result.
+ if ( NS_FAILED(rv) )
+ {
+ printf( "Error opening creating registry instance, rv=0x%08X\n", (int)rv );
+ return rv;
+ }
+ rv = reg->OpenWellKnownRegistry(nsIRegistry::ApplicationComponentRegistry);
+ if ( rv == NS_ERROR_REG_BADTYPE ) {
+ printf( "\n\n\nThere is no <Application Component Registry>\n" );
+ }
+ else if ( rv == NS_OK ) {
+
+ printf( "\n\n\nRegistry %s opened OK.\n", "<Application Component Registry>\n" );
+
+ // Recurse over all 3 branches.
+ display( reg, nsIRegistry::Common, "nsRegistry::Common" );
+ display( reg, nsIRegistry::Users, "nsRegistry::Users" );
+ }
+ NS_RELEASE(reg);
+ }
+ }
+ NS_ShutdownXPCOM( servMgr );
+
+ return rv;
+}
+
+void display( nsIRegistry *reg, nsRegistryKey root, const char *rootName ) {
+ // Print out key name.
+ printf( "%s\n", rootName );
+
+ // Make sure it isn't a "root" key.
+ if ( root != nsIRegistry::Common
+ &&
+ root != nsIRegistry::Users
+ &&
+ root != nsIRegistry::CurrentUser ) {
+ // Print values stored under this key.
+ displayValues( reg, root );
+ }
+
+ // Enumerate all subkeys (immediately) under the given node.
+ nsIEnumerator *keys;
+ nsresult rv = reg->EnumerateSubtrees( root, &keys );
+
+ // Check result.
+ if ( rv == NS_OK ) {
+ // Set enumerator to beginning.
+ rv = keys->First();
+ // Enumerate subkeys till done.
+ while( NS_SUCCEEDED( rv ) && (NS_OK != keys->IsDone()) ) {
+ nsISupports *base;
+ rv = keys->CurrentItem( &base );
+ // Test result.
+ if ( rv == NS_OK ) {
+ // Get specific interface.
+ nsIRegistryNode *node;
+ nsIID nodeIID = NS_IREGISTRYNODE_IID;
+ rv = base->QueryInterface( nodeIID, (void**)&node );
+ // Test that result.
+ if ( rv == NS_OK ) {
+ // Get node name.
+ char *name;
+ rv = node->GetNameUTF8( &name );
+ // Test result.
+ if ( rv == NS_OK ) {
+ // Build complete name.
+ char *fullName = new char[ PL_strlen(rootName) + PL_strlen(name) + 5 ];
+ PL_strcpy( fullName, rootName );
+ PL_strcat( fullName, " - " );
+ PL_strcat( fullName, name );
+ // Display contents under this subkey.
+ nsRegistryKey key;
+ rv = reg->GetSubtreeRaw( root, name, &key );
+ if ( rv == NS_OK ) {
+ display( reg, key, fullName );
+ printf( "\n" );
+ } else {
+ printf( "Error getting key, rv=0x%08X\n", (int)rv );
+ }
+ delete [] fullName;
+ } else {
+ printf( "Error getting subtree name, rv=0x%08X\n", (int)rv );
+ }
+ // Release node.
+ node->Release();
+ } else {
+ printf( "Error converting base node ptr to nsIRegistryNode, rv=0x%08X\n", (int)rv );
+ }
+ // Release item.
+ base->Release();
+
+ // Advance to next key.
+ rv = keys->Next();
+ // Check result.
+ if ( NS_SUCCEEDED( rv ) ) {
+ } else {
+ printf( "Error advancing enumerator, rv=0x%08X\n", (int)rv );
+ }
+ } else {
+ printf( "Error getting current item, rv=0x%08X\n", (int)rv );
+ }
+ }
+ // Release key enumerator.
+ keys->Release();
+ } else {
+ printf( "Error creating enumerator for %s, root=0x%08X, rv=0x%08X\n",
+ rootName, (int)root, (int)rv );
+ }
+ return;
+}
+
+static void displayValues( nsIRegistry *reg, nsRegistryKey root ) {
+ // Emumerate values at this registry location.
+ nsIEnumerator *values;
+ nsresult rv = reg->EnumerateValues( root, &values );
+
+ // Check result.
+ if ( rv == NS_OK ) {
+ // Go to beginning.
+ rv = values->First();
+
+ // Enumerate values till done.
+ while( rv == NS_OK && (NS_OK != values->IsDone()) ) {
+ nsISupports *base;
+ rv = values->CurrentItem( &base );
+ // Test result.
+ if ( rv == NS_OK ) {
+ // Get specific interface.
+ nsIRegistryValue *value;
+ nsIID valueIID = NS_IREGISTRYVALUE_IID;
+ rv = base->QueryInterface( valueIID, (void**)&value );
+ // Test that result.
+ if ( rv == NS_OK ) {
+ // Get node name.
+ char *name;
+ rv = value->GetNameUTF8( &name );
+ // Test result.
+ if ( rv == NS_OK ) {
+ // Print name:
+ printf( "\t\t%s", name );
+ // Get info about this value.
+ PRUint32 type;
+ rv = reg->GetValueType( root, name, &type );
+ if ( rv == NS_OK ) {
+ // Print value contents.
+ switch ( type ) {
+ case nsIRegistry::String: {
+ char *strValue;
+ rv = reg->GetStringUTF8( root, name, &strValue );
+ if ( rv == NS_OK ) {
+ printString( strValue, strlen(name) );
+ nsMemory::Free( strValue );
+ } else {
+ printf( "\t Error getting string value, rv=0x%08X", (int)rv );
+ }
+ }
+ break;
+
+ case nsIRegistry::Int32:
+ {
+ PRInt32 val = 0;
+ rv = reg->GetInt( root, name, &val );
+ if (NS_SUCCEEDED(rv)) {
+ printf( "\t= Int32 [%d, 0x%x]", val, val);
+ }
+ else {
+ printf( "\t Error getting int32 value, rv=%08X", (int)rv);
+ }
+ }
+ break;
+
+ case nsIRegistry::Bytes:
+ printf( "\t= Bytes" );
+ break;
+
+ case nsIRegistry::File:
+ printf( "\t= File (?)" );
+ break;
+
+ default:
+ printf( "\t= ? (unknown type=0x%02X)", (int)type );
+ break;
+ }
+ } else {
+ printf( "\t= ? (error getting value, rv=0x%08X)", (int)rv );
+ }
+ printf("\n");
+ nsMemory::Free( name );
+ } else {
+ printf( "Error getting value name, rv=0x%08X\n", (int)rv );
+ }
+ // Release node.
+ value->Release();
+ } else {
+ printf( "Error converting base node ptr to nsIRegistryNode, rv=0x%08X\n", (int)rv );
+ }
+ // Release item.
+ base->Release();
+
+ // Advance to next key.
+ rv = values->Next();
+ // Check result.
+ if ( NS_SUCCEEDED( rv ) ) {
+ } else {
+ printf( "Error advancing enumerator, rv=0x%08X\n", (int)rv );
+ break;
+ }
+ } else {
+ printf( "Error getting current item, rv=0x%08X\n", (int)rv );
+ break;
+ }
+ }
+
+ values->Release();
+ } else {
+ printf( "\t\tError enumerating values, rv=0x%08X\n", (int)rv );
+ }
+ return;
+}
+
+static void printString( const char *value, int /*indent*/ ) {
+ // For now, just dump contents.
+ printf( "\t = %s", value );
+ return;
+}
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/component/xpcomobsoletec.pkg b/src/libs/xpcom18a4/xpcom/obsolete/component/xpcomobsoletec.pkg
new file mode 100644
index 00000000..88cbf236
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/component/xpcomobsoletec.pkg
@@ -0,0 +1,6 @@
+[gecko xpi-bootstrap]
+#if SHARED_LIBRARY
+dist/bin/components/@SHARED_LIBRARY@
+#else
+!staticcomp @LIBRARY@ @MODULE_NAME@
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/dlldeps.cpp b/src/libs/xpcom18a4/xpcom/obsolete/dlldeps.cpp
new file mode 100644
index 00000000..d904e071
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/dlldeps.cpp
@@ -0,0 +1,50 @@
+/* -*- 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) 2003
+ * 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 ***** */
+
+// Force references to all of the symbols that we want exported from
+// the dll that are located in the .lib files we link with
+
+#include "nsFileSpec.h"
+#include "NSReg.h"
+
+void XXXNeverCalled()
+{
+ nsFileURL(NULL);
+ nsFileSpec s;
+
+ NR_RegSetBufferSize(NULL, 0);
+}
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpec.cpp b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpec.cpp
new file mode 100644
index 00000000..9be29eb9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpec.cpp
@@ -0,0 +1,1367 @@
+/* -*- 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 "nsFileSpec.h"
+
+#include "nsDebug.h"
+#include "nsEscape.h"
+#include "nsMemory.h"
+
+#include "prtypes.h"
+#include "plstr.h"
+#include "plbase64.h"
+#include "prmem.h"
+
+#include "nsCOMPtr.h"
+#include "nsIServiceManager.h"
+#include "nsILocalFile.h"
+
+#include <string.h>
+#include <stdio.h>
+
+#if defined(XP_WIN)
+#include <mbstring.h>
+#endif
+
+#ifdef XP_OS2
+extern unsigned char* _mbsrchr( const unsigned char*, int);
+#endif
+
+// return pointer to last instance of the given separator
+static inline char *GetLastSeparator(const char *str, char sep)
+{
+#if defined(XP_WIN) || defined(XP_OS2)
+ return (char*) _mbsrchr((const unsigned char *) str, sep);
+#else
+ return (char*) strrchr(str, sep);
+#endif
+}
+
+#if defined(XP_MACOSX)
+#include <sys/stat.h>
+#endif
+
+#if defined(XP_MAC) || defined(XP_MACOSX)
+#include <Aliases.h>
+#include <TextUtils.h>
+#endif
+
+//========================================================================================
+// class nsSimpleCharString
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsSimpleCharString::nsSimpleCharString()
+//----------------------------------------------------------------------------------------
+: mData(nsnull)
+{
+
+} // nsSimpleCharString::nsSimpleCharString
+
+//----------------------------------------------------------------------------------------
+nsSimpleCharString::nsSimpleCharString(const char* inString)
+//----------------------------------------------------------------------------------------
+: mData(nsnull)
+{
+ if (inString)
+ CopyFrom(inString, strlen(inString));
+} // nsSimpleCharString::nsSimpleCharString
+
+//----------------------------------------------------------------------------------------
+nsSimpleCharString::nsSimpleCharString(const nsString& inString)
+//----------------------------------------------------------------------------------------
+: mData(nsnull)
+{
+ *this = inString;
+} // nsSimpleCharString::nsSimpleCharString
+
+//----------------------------------------------------------------------------------------
+nsSimpleCharString::nsSimpleCharString(const nsSimpleCharString& inOther)
+//----------------------------------------------------------------------------------------
+{
+ mData = inOther.mData;
+ AddRefData();
+} // nsSimpleCharString::nsSimpleCharString
+
+//----------------------------------------------------------------------------------------
+nsSimpleCharString::nsSimpleCharString(const char* inData, PRUint32 inLength)
+//----------------------------------------------------------------------------------------
+: mData(nsnull)
+{
+ CopyFrom(inData, inLength);
+} // nsSimpleCharString::nsSimpleCharString
+
+//----------------------------------------------------------------------------------------
+nsSimpleCharString::~nsSimpleCharString()
+//----------------------------------------------------------------------------------------
+{
+ ReleaseData();
+} // nsSimpleCharString::nsSimpleCharString
+
+//----------------------------------------------------------------------------------------
+void nsSimpleCharString::operator = (const char* inString)
+//----------------------------------------------------------------------------------------
+{
+ if (inString)
+ CopyFrom(inString, strlen(inString));
+ else
+ SetToEmpty();
+} // nsSimpleCharString::operator =
+
+//----------------------------------------------------------------------------------------
+void nsSimpleCharString::operator = (const nsString& inString)
+//----------------------------------------------------------------------------------------
+{
+ PRUint32 len = inString.Length();
+ ReallocData(len);
+ if (!mData)
+ return;
+ inString.ToCString(mData->mString, len + 1);
+} // nsSimpleCharString::operator =
+
+//----------------------------------------------------------------------------------------
+void nsSimpleCharString::operator = (const nsSimpleCharString& inOther)
+//----------------------------------------------------------------------------------------
+{
+ if (mData == inOther.mData)
+ return;
+ ReleaseData();
+ mData = inOther.mData;
+ AddRefData();
+} // nsSimpleCharString::operator =
+
+//----------------------------------------------------------------------------------------
+void nsSimpleCharString::operator += (const char* inOther)
+//----------------------------------------------------------------------------------------
+{
+ if (!inOther)
+ return;
+ int newLength = Length() + strlen(inOther);
+ ReallocData(newLength);
+ strcat(mData->mString, inOther);
+} // nsSimpleCharString::operator =
+
+//----------------------------------------------------------------------------------------
+nsSimpleCharString nsSimpleCharString::operator + (const char* inOther) const
+//----------------------------------------------------------------------------------------
+{
+ nsSimpleCharString result(*this);
+ result += inOther;
+ return result;
+} // nsSimpleCharString::operator =
+
+//----------------------------------------------------------------------------------------
+void nsSimpleCharString::Catenate(const char* inString1, const char* inString2)
+//----------------------------------------------------------------------------------------
+{
+ if (!inString2)
+ {
+ *this += inString1;
+ return;
+ }
+ int newLength = Length() + strlen(inString1) + strlen(inString2);
+ ReallocData(newLength);
+ strcat(mData->mString, inString1);
+ strcat(mData->mString, inString2);
+} // nsSimpleCharString::operator =
+
+//----------------------------------------------------------------------------------------
+void nsSimpleCharString::CopyFrom(const char* inData, PRUint32 inLength)
+//----------------------------------------------------------------------------------------
+{
+ if (!inData)
+ return;
+ ReallocData(inLength);
+ if (!mData)
+ return;
+ if (inLength != 0) {
+ memcpy(mData->mString, inData, inLength);
+ }
+ mData->mString[inLength] = '\0';
+} // nsSimpleCharString::CopyFrom
+
+//----------------------------------------------------------------------------------------
+void nsSimpleCharString::SetToEmpty()
+//----------------------------------------------------------------------------------------
+{
+ ReleaseData();
+} // nsSimpleCharString::SetToEmpty
+
+//----------------------------------------------------------------------------------------
+void nsSimpleCharString::Unescape()
+//----------------------------------------------------------------------------------------
+{
+ if (!mData)
+ return;
+ ReallocData(mData->mLength);
+ if (!mData)
+ return;
+ nsUnescape(mData->mString);
+ mData->mLength = strlen(mData->mString);
+} // nsSimpleCharString::Unescape
+
+
+//----------------------------------------------------------------------------------------
+void nsSimpleCharString::AddRefData()
+//----------------------------------------------------------------------------------------
+{
+ if (mData)
+ ++mData->mRefCount;
+} // nsSimpleCharString::AddRefData
+
+//----------------------------------------------------------------------------------------
+void nsSimpleCharString::ReleaseData()
+//----------------------------------------------------------------------------------------
+{
+ if (!mData)
+ return;
+ NS_ASSERTION(mData->mRefCount > 0, "String deleted too many times!");
+ if (--mData->mRefCount == 0)
+ PR_Free(mData);
+ mData = nsnull;
+} // nsSimpleCharString::ReleaseData
+
+//----------------------------------------------------------------------------------------
+inline PRUint32 CalculateAllocLength(PRUint32 logicalLength)
+// Round up to the next multiple of 256.
+//----------------------------------------------------------------------------------------
+{
+ return ((1 + (logicalLength >> 8)) << 8);
+}
+
+//----------------------------------------------------------------------------------------
+void nsSimpleCharString::ReallocData(PRUint32 inLength)
+// Reallocate mData to a new length. Since this presumably precedes a change to the string,
+// we want to detach ourselves if the data is shared by another string, even if the length
+// requested would not otherwise require a reallocation.
+//----------------------------------------------------------------------------------------
+{
+ PRUint32 newAllocLength = CalculateAllocLength(inLength);
+ PRUint32 oldAllocLength = CalculateAllocLength(Length());
+ if (mData)
+ {
+ NS_ASSERTION(mData->mRefCount > 0, "String deleted too many times!");
+ if (mData->mRefCount == 1)
+ {
+ // We are the sole owner, so just change its length, if necessary.
+ if (newAllocLength > oldAllocLength)
+ mData = (Data*)PR_Realloc(mData, newAllocLength + sizeof(Data));
+ mData->mLength = inLength;
+ mData->mString[inLength] = '\0'; // we may be truncating
+ return;
+ }
+ }
+ PRUint32 copyLength = Length();
+ if (inLength < copyLength)
+ copyLength = inLength;
+ Data* newData = (Data*)PR_Malloc(newAllocLength + sizeof(Data));
+ // If data was already allocated when we get to here, then we are cloning the data
+ // from a shared pointer.
+ if (mData)
+ {
+ memcpy(newData, mData, sizeof(Data) + copyLength);
+ mData->mRefCount--; // Say goodbye
+ }
+ else
+ newData->mString[0] = '\0';
+
+ mData = newData;
+ mData->mRefCount = 1;
+ mData->mLength = inLength;
+} // nsSimpleCharString::ReleaseData
+
+
+//========================================================================================
+NS_NAMESPACE nsFileSpecHelpers
+//========================================================================================
+{
+ enum
+ { kMaxFilenameLength = 31 // should work on Macintosh, Unix, and Win32.
+ , kMaxAltDigitLength = 5
+ , kMaxCoreLeafNameLength = (kMaxFilenameLength - (kMaxAltDigitLength + 1))
+ };
+#if !defined(XP_MAC)
+ NS_NAMESPACE_PROTOTYPE void Canonify(nsSimpleCharString& ioPath, PRBool inMakeDirs);
+ NS_NAMESPACE_PROTOTYPE void MakeAllDirectories(const char* inPath, int mode);
+#endif
+#if defined(XP_WIN) || defined(XP_OS2)
+ NS_NAMESPACE_PROTOTYPE void NativeToUnix(nsSimpleCharString& ioPath);
+ NS_NAMESPACE_PROTOTYPE void UnixToNative(nsSimpleCharString& ioPath);
+#endif
+} NS_NAMESPACE_END
+
+//----------------------------------------------------------------------------------------
+nsresult ns_file_convert_result(PRInt32 nativeErr)
+//----------------------------------------------------------------------------------------
+{
+ return nativeErr ?
+ NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES,((nativeErr)&0xFFFF))
+ : NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+void nsSimpleCharString::LeafReplace(char inSeparator, const char* inLeafName)
+//----------------------------------------------------------------------------------------
+{
+ // Find the existing leaf name
+ if (IsEmpty())
+ return;
+ if (!inLeafName)
+ {
+ SetToEmpty();
+ return;
+ }
+ char* chars = mData->mString;
+ char* lastSeparator = GetLastSeparator(chars, inSeparator);
+ int oldLength = Length();
+ PRBool trailingSeparator = (lastSeparator + 1 == chars + oldLength);
+ if (trailingSeparator)
+ {
+ char savedCh = *lastSeparator;
+ char *savedLastSeparator = lastSeparator;
+ *lastSeparator = '\0';
+ lastSeparator = GetLastSeparator(chars, inSeparator);
+ *savedLastSeparator = savedCh;
+ }
+ if (lastSeparator)
+ lastSeparator++; // point at the trailing string
+ else
+ lastSeparator = chars; // the full monty
+
+ PRUint32 savedLastSeparatorOffset = (lastSeparator - chars);
+ int newLength =
+ (lastSeparator - chars) + strlen(inLeafName) + (trailingSeparator != 0);
+ ReallocData(newLength);
+
+ chars = mData->mString; // it might have moved.
+ chars[savedLastSeparatorOffset] = '\0'; // strip the current leaf name
+
+ strcat(chars, inLeafName);
+ if (trailingSeparator)
+ {
+ // If the original ended in a slash, then the new one should, too.
+ char sepStr[2] = "/";
+ *sepStr = inSeparator;
+ strcat(chars, sepStr);
+ }
+} // nsSimpleCharString::LeafReplace
+
+//----------------------------------------------------------------------------------------
+char* nsSimpleCharString::GetLeaf(char inSeparator) const
+// Returns a pointer to an allocated string representing the leaf.
+//----------------------------------------------------------------------------------------
+{
+ if (IsEmpty())
+ return nsnull;
+
+ char* chars = mData->mString;
+ const char* lastSeparator = GetLastSeparator(chars, inSeparator);
+ // If there was no separator, then return a copy of our path.
+ if (!lastSeparator)
+ return nsCRT::strdup(*this);
+
+ // So there's at least one separator. What's just after it?
+ // If the separator was not the last character, return the trailing string.
+ const char* leafPointer = lastSeparator + 1;
+ if (*leafPointer)
+ return nsCRT::strdup(leafPointer);
+
+ // So now, separator was the last character. Poke in a null instead.
+ *(char*)lastSeparator = '\0'; // Should use const_cast, but Unix has old compiler.
+ leafPointer = GetLastSeparator(chars, inSeparator);
+ char* result = leafPointer ? nsCRT::strdup(++leafPointer) : nsCRT::strdup(chars);
+ // Restore the poked null before returning.
+ *(char*)lastSeparator = inSeparator;
+#if defined(XP_WIN) || defined(XP_OS2)
+ // If it's a drive letter use the colon notation.
+ if (!leafPointer && result[1] == '|' && result[2] == 0)
+ result[1] = ':';
+#endif
+ return result;
+} // nsSimpleCharString::GetLeaf
+
+
+#if 0
+#pragma mark -
+#endif
+
+#if (defined(XP_UNIX) || defined(XP_WIN) || defined(XP_OS2) || defined(XP_BEOS))
+
+//----------------------------------------------------------------------------------------
+void nsFileSpecHelpers::MakeAllDirectories(const char* inPath, int mode)
+// Make the path a valid one by creating all the intermediate directories. Does NOT
+// make the leaf into a directory. This should be a unix path.
+//----------------------------------------------------------------------------------------
+{
+ if (!inPath)
+ return;
+
+ char* pathCopy = nsCRT::strdup( inPath );
+ if (!pathCopy)
+ return;
+
+ const char kSeparator = '/'; // I repeat: this should be a unix-style path.
+ const int kSkipFirst = 1;
+
+#if defined(XP_WIN) || defined(XP_OS2)
+ // Either this is a relative path, or we ensure that it has
+ // a drive letter specifier.
+ NS_ASSERTION( pathCopy[0] != '/' || (pathCopy[1] && (pathCopy[2] == '|' || pathCopy[2] == '/')),
+ "Not a UNC path and no drive letter!" );
+#endif
+ char* currentStart = pathCopy;
+ char* currentEnd = strchr(currentStart + kSkipFirst, kSeparator);
+ if (currentEnd)
+ {
+ nsFileSpec spec;
+ *currentEnd = '\0';
+
+#if defined(XP_WIN) || defined(XP_OS2)
+ /*
+ if we have a drive letter path, we must make sure that the inital path has a '/' on it, or
+ Canonify will turn "/c|" into a path relative to the running executable.
+ */
+ if (pathCopy[0] == '/' && pathCopy[1] && pathCopy[2] == '|')
+ {
+ char* startDir = (char*)PR_Malloc(strlen(pathCopy) + 2);
+ strcpy(startDir, pathCopy);
+ strcat(startDir, "/");
+
+ spec = nsFilePath(startDir, PR_FALSE);
+
+ PR_Free(startDir);
+ }
+ else
+ {
+ // move after server name and share name in UNC path
+ if (pathCopy[0] == '/' &&
+ currentEnd == currentStart+kSkipFirst)
+ {
+ *currentEnd = '/';
+ currentStart = strchr(pathCopy+2, kSeparator);
+ currentStart = strchr(currentStart+1, kSeparator);
+ currentEnd = strchr(currentStart+1, kSeparator);
+ if (currentEnd)
+ *currentEnd = '\0';
+ }
+ spec = nsFilePath(pathCopy, PR_FALSE);
+ }
+#else
+ spec = nsFilePath(pathCopy, PR_FALSE);
+#endif
+ do
+ {
+ // If the node doesn't exist, and it is not the initial node in a full path,
+ // then make a directory (We cannot make the initial (volume) node).
+ if (!spec.Exists() && *currentStart != kSeparator)
+ spec.CreateDirectory(mode);
+
+ currentStart = ++currentEnd;
+ currentEnd = strchr(currentStart, kSeparator);
+ if (!currentEnd)
+ break;
+
+ *currentEnd = '\0';
+
+ spec += currentStart; // "lengthen" the path, adding the next node.
+ } while (currentEnd);
+ }
+ nsCRT::free(pathCopy);
+} // nsFileSpecHelpers::MakeAllDirectories
+
+#endif // XP_UNIX || XP_WIN || XP_OS2 || XP_BEOS
+
+#if 0
+#pragma mark -
+#endif
+
+#if defined(XP_WIN)
+#include "nsFileSpecWin.cpp" // Windows-specific implementations
+#elif defined(XP_MAC)
+//#include "nsFileSpecMac.cpp" // Macintosh-specific implementations
+// we include the .cpp file in the project now.
+#elif defined(XP_BEOS)
+#include "nsFileSpecBeOS.cpp" // BeOS-specific implementations
+#elif defined(XP_UNIX) || defined(XP_MACOSX)
+#include "nsFileSpecUnix.cpp" // Unix-specific implementations
+#elif defined(XP_OS2)
+#include "nsFileSpecOS2.cpp" // OS/2-specific implementations
+#endif
+
+//========================================================================================
+// nsFileURL implementation
+//========================================================================================
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+nsFileURL::nsFileURL(const char* inString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+{
+ if (!inString)
+ return;
+ NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
+ // Make canonical and absolute. Since it's a parameter to this constructor,
+ // inString is escaped. We want to make an nsFilePath, which requires
+ // an unescaped string.
+ nsSimpleCharString unescapedPath(inString + kFileURLPrefixLength);
+ unescapedPath.Unescape();
+ nsFilePath path(unescapedPath, inCreateDirs);
+ *this = path;
+} // nsFileURL::nsFileURL
+#endif
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+nsFileURL::nsFileURL(const nsString& inString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+{
+ NS_LossyConvertUCS2toASCII cstring(inString);
+ if (!inString.Length())
+ return;
+ NS_ASSERTION(strstr(cstring.get(), kFileURLPrefix) == cstring.get(),
+ "Not a URL!");
+ // Make canonical and absolute. Since it's a parameter to this constructor,
+ // inString is escaped. We want to make an nsFilePath, which requires
+ // an unescaped string.
+ nsSimpleCharString unescapedPath(cstring.get() + kFileURLPrefixLength);
+ unescapedPath.Unescape();
+ nsFilePath path(unescapedPath, inCreateDirs);
+ *this = path;
+} // nsFileURL::nsFileURL
+#endif
+
+//----------------------------------------------------------------------------------------
+nsFileURL::nsFileURL(const nsFileURL& inOther)
+//----------------------------------------------------------------------------------------
+: mURL(inOther.mURL)
+#if defined(XP_MAC)
+, mFileSpec(inOther.GetFileSpec())
+#endif
+{
+} // nsFileURL::nsFileURL
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+nsFileURL::nsFileURL(const nsFilePath& inOther)
+//----------------------------------------------------------------------------------------
+{
+ *this = inOther;
+} // nsFileURL::nsFileURL
+#endif
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+nsFileURL::nsFileURL(const nsFileSpec& inOther)
+//----------------------------------------------------------------------------------------
+{
+ *this = inOther;
+} // nsFileURL::nsFileURL
+#endif
+
+//----------------------------------------------------------------------------------------
+nsFileURL::~nsFileURL()
+//----------------------------------------------------------------------------------------
+{
+}
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+void nsFileURL::operator = (const char* inString)
+//----------------------------------------------------------------------------------------
+{
+ // XXX is this called by nsFileSpecImpl.cpp::SetURLString?
+ // if so, there's a bug...
+
+ mURL = inString;
+ NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
+} // nsFileURL::operator =
+#endif
+
+//----------------------------------------------------------------------------------------
+void nsFileURL::operator +=(const char* inRelativeUnixPath)
+//----------------------------------------------------------------------------------------
+{
+ char* escapedPath = nsEscape(inRelativeUnixPath, url_Path);
+ mURL += escapedPath;
+ nsCRT::free(escapedPath);
+#if defined(XP_MAC)
+ mFileSpec += inRelativeUnixPath;
+#endif
+} // nsFileURL::operator +=
+
+//----------------------------------------------------------------------------------------
+nsFileURL nsFileURL::operator +(const char* inRelativeUnixPath) const
+//----------------------------------------------------------------------------------------
+{
+ nsFileURL result(*this);
+ result += inRelativeUnixPath;
+ return result;
+} // nsFileURL::operator +
+
+//----------------------------------------------------------------------------------------
+void nsFileURL::operator = (const nsFileURL& inOther)
+//----------------------------------------------------------------------------------------
+{
+ mURL = inOther.mURL;
+#if defined(XP_MAC)
+ mFileSpec = inOther.GetFileSpec();
+#endif
+} // nsFileURL::operator =
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+void nsFileURL::operator = (const nsFilePath& inOther)
+//----------------------------------------------------------------------------------------
+{
+ mURL = kFileURLPrefix;
+ char* original = (char*)(const char*)inOther; // we shall modify, but restore.
+ if (!original || !*original) return;
+#if defined(XP_WIN) || defined(XP_OS2)
+ // because we don't want to escape the '|' character, change it to a letter.
+ // Note that a UNC path will not have a '|' character.
+ char oldchar = original[2];
+ original[2] = 'x';
+ char* escapedPath = nsEscape(original, url_Path);
+ original[2] = escapedPath[2] = oldchar; // restore it
+#else
+ char* escapedPath = nsEscape(original, url_Path);
+#endif
+ if (escapedPath)
+ mURL += escapedPath;
+ nsCRT::free(escapedPath);
+} // nsFileURL::operator =
+#endif
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+void nsFileURL::operator = (const nsFileSpec& inOther)
+//----------------------------------------------------------------------------------------
+{
+ *this = nsFilePath(inOther);
+ if (mURL[mURL.Length() - 1] != '/' && inOther.IsDirectory())
+ mURL += "/";
+} // nsFileURL::operator =
+#endif
+
+#if 0
+#pragma mark -
+#endif
+
+//========================================================================================
+// nsFilePath implementation
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsFilePath::nsFilePath(const nsFilePath& inPath)
+//----------------------------------------------------------------------------------------
+ : mPath(inPath.mPath)
+#if defined(XP_MAC)
+ , mFileSpec(inPath.mFileSpec)
+#endif
+{
+}
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+nsFilePath::nsFilePath(const char* inString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+: mPath(inString)
+{
+ if (mPath.IsEmpty())
+ return;
+
+ NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path");
+
+#if defined(XP_WIN) || defined(XP_OS2)
+ nsFileSpecHelpers::UnixToNative(mPath);
+#endif
+ // Make canonical and absolute.
+ nsFileSpecHelpers::Canonify(mPath, inCreateDirs);
+#if defined(XP_WIN) || defined(XP_OS2)
+ // Assert native path is of one of these forms:
+ // - regular: X:\some\path
+ // - UNC: \\some_machine\some\path
+ NS_ASSERTION( mPath[1] == ':' || (mPath[0] == '\\' && mPath[1] == '\\'),
+ "unexpected canonical path" );
+ nsFileSpecHelpers::NativeToUnix(mPath);
+#endif
+}
+#endif
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+nsFilePath::nsFilePath(const nsString& inString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+: mPath(inString)
+{
+ if (mPath.IsEmpty())
+ return;
+
+ NS_ASSERTION(strstr((const char*)mPath, kFileURLPrefix) != (const char*)mPath, "URL passed as path");
+#if defined(XP_WIN) || defined(XP_OS2)
+ nsFileSpecHelpers::UnixToNative(mPath);
+#endif
+ // Make canonical and absolute.
+ nsFileSpecHelpers::Canonify(mPath, inCreateDirs);
+#if defined(XP_WIN) || defined(XP_OS2)
+ NS_ASSERTION( mPath[1] == ':' || (mPath[0] == '\\' && mPath[1] == '\\'),
+ "unexpected canonical path" );
+ nsFileSpecHelpers::NativeToUnix(mPath);
+#endif
+}
+#endif
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+nsFilePath::nsFilePath(const nsFileURL& inOther)
+//----------------------------------------------------------------------------------------
+{
+ mPath = (const char*)inOther.mURL + kFileURLPrefixLength;
+ mPath.Unescape();
+}
+#endif
+
+#if (defined XP_UNIX || defined XP_BEOS)
+//----------------------------------------------------------------------------------------
+nsFilePath::nsFilePath(const nsFileSpec& inOther)
+//----------------------------------------------------------------------------------------
+: mPath(inOther.mPath)
+{
+}
+#endif // XP_UNIX
+
+//----------------------------------------------------------------------------------------
+nsFilePath::~nsFilePath()
+//----------------------------------------------------------------------------------------
+{
+}
+
+#if (defined XP_UNIX || defined XP_BEOS)
+//----------------------------------------------------------------------------------------
+void nsFilePath::operator = (const nsFileSpec& inOther)
+//----------------------------------------------------------------------------------------
+{
+ // XXX bug here, again if.
+
+ mPath = inOther.mPath;
+}
+#endif // XP_UNIX
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+void nsFilePath::operator = (const char* inString)
+//----------------------------------------------------------------------------------------
+{
+
+ NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path");
+ mPath = inString;
+ if (mPath.IsEmpty())
+ return;
+#if defined(XP_WIN) || defined(XP_OS2)
+ nsFileSpecHelpers::UnixToNative(mPath);
+#endif
+ // Make canonical and absolute.
+ nsFileSpecHelpers::Canonify(mPath, PR_FALSE /* XXX? */);
+#if defined(XP_WIN) || defined(XP_OS2)
+ nsFileSpecHelpers::NativeToUnix(mPath);
+#endif
+}
+#endif // XP_MAC
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+void nsFilePath::operator = (const nsFileURL& inOther)
+//----------------------------------------------------------------------------------------
+{
+ mPath = (const char*)nsFilePath(inOther);
+}
+#endif
+
+//----------------------------------------------------------------------------------------
+void nsFilePath::operator = (const nsFilePath& inOther)
+//----------------------------------------------------------------------------------------
+{
+ mPath = inOther.mPath;
+#if defined(XP_MAC)
+ mFileSpec = inOther.GetFileSpec();
+#endif
+}
+
+//----------------------------------------------------------------------------------------
+void nsFilePath::operator +=(const char* inRelativeUnixPath)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inRelativeUnixPath, "Attempt append relative path with null path");
+
+ char* escapedPath = nsEscape(inRelativeUnixPath, url_Path);
+ mPath += escapedPath;
+ nsCRT::free(escapedPath);
+#if defined(XP_MAC)
+ mFileSpec += inRelativeUnixPath;
+#endif
+} // nsFilePath::operator +=
+
+//----------------------------------------------------------------------------------------
+nsFilePath nsFilePath::operator +(const char* inRelativeUnixPath) const
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inRelativeUnixPath, "Attempt append relative path with null path");
+
+ nsFilePath resultPath(*this);
+ resultPath += inRelativeUnixPath;
+ return resultPath;
+} // nsFilePath::operator +
+
+
+#if 0
+#pragma mark -
+#endif
+
+//========================================================================================
+// nsFileSpec implementation
+//========================================================================================
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec()
+//----------------------------------------------------------------------------------------
+: mError(NS_OK) // XXX shouldn't this be NS_ERROR_NOT_INITIALIZED?
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+}
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::Clear()
+//----------------------------------------------------------------------------------------
+{
+ mPath.SetToEmpty();
+ mError = NS_ERROR_NOT_INITIALIZED;
+}
+
+#endif
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::~nsFileSpec()
+//----------------------------------------------------------------------------------------
+{
+ // mPath cleans itself up
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const nsPersistentFileDescriptor& inDescriptor)
+//----------------------------------------------------------------------------------------
+{
+ *this = inDescriptor;
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const nsFileURL& inURL)
+//----------------------------------------------------------------------------------------
+{
+ *this = nsFilePath(inURL); // convert to unix path first
+}
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::MakeUnique(const char* inSuggestedLeafName)
+//----------------------------------------------------------------------------------------
+{
+ if (inSuggestedLeafName && *inSuggestedLeafName)
+ SetLeafName(inSuggestedLeafName);
+
+ MakeUnique();
+} // nsFileSpec::MakeUnique
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::MakeUnique()
+//----------------------------------------------------------------------------------------
+{
+ if (!Exists())
+ return;
+
+ char* leafName = GetLeafName();
+ if (!leafName)
+ return;
+
+ char* lastDot = strrchr(leafName, '.');
+ char* suffix = "";
+ if (lastDot)
+ {
+ suffix = nsCRT::strdup(lastDot); // include '.'
+ *lastDot = '\0'; // strip suffix and dot.
+ }
+ const int kMaxRootLength
+ = nsFileSpecHelpers::kMaxCoreLeafNameLength - strlen(suffix) - 1;
+ if ((int)strlen(leafName) > (int)kMaxRootLength)
+ leafName[kMaxRootLength] = '\0';
+ for (short indx = 1; indx < 1000 && Exists(); indx++)
+ {
+ // start with "Picture-1.jpg" after "Picture.jpg" exists
+ char newName[nsFileSpecHelpers::kMaxFilenameLength + 1];
+ sprintf(newName, "%s-%d%s", leafName, indx, suffix);
+ SetLeafName(newName);
+ }
+ if (*suffix)
+ nsCRT::free(suffix);
+ nsCRT::free(leafName);
+} // nsFileSpec::MakeUnique
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator = (const nsFileURL& inURL)
+//----------------------------------------------------------------------------------------
+{
+ *this = nsFilePath(inURL); // convert to unix path first
+}
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator = (const nsPersistentFileDescriptor& inDescriptor)
+//----------------------------------------------------------------------------------------
+{
+
+ nsCAutoString data;
+ inDescriptor.GetData(data);
+
+#if defined (XP_MAC) || defined(XP_MACOSX)
+ // Decode descriptor into a Handle (which is actually an AliasHandle)
+ char* decodedData = PL_Base64Decode(data.get(), data.Length(), nsnull);
+ Handle aliasH = nsnull;
+ mError = NS_FILE_RESULT(::PtrToHand(decodedData, &aliasH, (data.Length() * 3) / 4));
+ PR_Free(decodedData);
+ if (NS_FAILED(mError))
+ return; // not enough memory?
+#endif
+
+#if defined(XP_MAC)
+ Boolean changed;
+ mError = NS_FILE_RESULT(::ResolveAlias(nsnull, (AliasHandle)aliasH, &mSpec, &changed));
+ DisposeHandle((Handle) aliasH);
+ mPath.SetToEmpty();
+#elif defined(XP_MACOSX)
+ Boolean changed;
+ FSRef fileRef;
+ mError = NS_FILE_RESULT(::FSResolveAlias(nsnull, (AliasHandle)aliasH, &fileRef, &changed));
+ ::DisposeHandle(aliasH);
+
+ UInt8 pathBuf[PATH_MAX];
+ mError = NS_FILE_RESULT(::FSRefMakePath(&fileRef, pathBuf, PATH_MAX));
+ if (NS_FAILED(mError))
+ return;
+ mPath = (const char*)pathBuf;
+#else
+ mPath = data.get();
+ mError = NS_OK;
+#endif
+}
+
+//========================================================================================
+// UNIX & WIN nsFileSpec implementation
+//========================================================================================
+
+#if (defined XP_UNIX || defined XP_BEOS)
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const nsFilePath& inPath)
+//----------------------------------------------------------------------------------------
+: mPath((const char*)inPath)
+, mError(NS_OK)
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+}
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator = (const nsFilePath& inPath)
+//----------------------------------------------------------------------------------------
+{
+ mPath = (const char*)inPath;
+ mError = NS_OK;
+}
+#endif //XP_UNIX
+
+#if (defined(XP_UNIX) || defined(XP_WIN) || defined(XP_OS2) || defined(XP_BEOS))
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+: mPath(inSpec.mPath)
+, mError(NS_OK)
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const char* inString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+: mPath(inString)
+, mError(NS_OK)
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+ // Make canonical and absolute.
+ nsFileSpecHelpers::Canonify(mPath, inCreateDirs);
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const nsString& inString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+: mPath(inString)
+, mError(NS_OK)
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+ // Make canonical and absolute.
+ nsFileSpecHelpers::Canonify(mPath, inCreateDirs);
+}
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator = (const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+{
+ mPath = inSpec.mPath;
+ mError = inSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator = (const char* inString)
+//----------------------------------------------------------------------------------------
+{
+ mPath = inString;
+ // Make canonical and absolute.
+ nsFileSpecHelpers::Canonify(mPath, PR_FALSE /* XXX? */);
+ mError = NS_OK;
+}
+#endif //XP_UNIX,XP_WIN,XP_OS2,XP_BEOS
+
+//----------------------------------------------------------------------------------------
+nsFileSpec nsFileSpec::operator + (const char* inRelativePath) const
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inRelativePath, "Attempt to append name with a null string");
+
+ nsFileSpec resultSpec = *this;
+ resultSpec += inRelativePath;
+ return resultSpec;
+} // nsFileSpec::operator +
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::operator == (const nsFileSpec& inOther) const
+//----------------------------------------------------------------------------------------
+{
+
+#if defined(XP_MAC)
+ if ( inOther.mSpec.vRefNum == mSpec.vRefNum &&
+ inOther.mSpec.parID == mSpec.parID &&
+ EqualString(inOther.mSpec.name, mSpec.name, false, true))
+ return PR_TRUE;
+#else
+ PRBool amEmpty = mPath.IsEmpty();
+ PRBool heEmpty = inOther.mPath.IsEmpty();
+ if (amEmpty) // we're the same if he's empty...
+ return heEmpty;
+ if (heEmpty) // ('cuz I'm not...)
+ return PR_FALSE;
+
+ nsSimpleCharString str = mPath;
+ nsSimpleCharString inStr = inOther.mPath;
+
+ // Length() is size of buffer, not length of string
+ PRUint32 strLast = str.Length() - 1, inLast = inStr.Length() - 1;
+#if defined(XP_WIN) || defined(XP_OS2)
+#define DIR_SEPARATOR '\\' // XXX doesn't NSPR have this?
+ /* windows does not care about case. */
+#ifdef XP_OS2
+#define DIR_STRCMP strcmp
+#else
+#define DIR_STRCMP _stricmp
+#endif
+#else
+#define DIR_SEPARATOR '/'
+#if defined(VMS)
+#define DIR_STRCMP strcasecmp
+#else
+#define DIR_STRCMP strcmp
+#endif
+#endif
+
+ if(str[strLast] == DIR_SEPARATOR)
+ str[strLast] = '\0';
+
+ if(inStr[inLast] == DIR_SEPARATOR)
+ inStr[inLast] = '\0';
+
+ if (DIR_STRCMP(str, inStr ) == 0)
+ return PR_TRUE;
+#undef DIR_SEPARATOR
+#undef DIR_STRCMP
+#endif
+ return PR_FALSE;
+}
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::operator != (const nsFileSpec& inOther) const
+//----------------------------------------------------------------------------------------
+{
+ return (! (*this == inOther) );
+}
+
+#if !defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+// This is the only automatic conversion to const char*
+// that is provided, and it allows the
+// path to be "passed" to NSPR file routines. This practice
+// is VERY EVIL and should only be used to support legacy
+// code. Using it guarantees bugs on Macintosh. The path is NOT allocated, so do
+// not even think of deleting (or freeing) it.
+const char* nsFileSpec::GetCString() const
+//----------------------------------------------------------------------------------------
+{
+ return mPath;
+}
+#endif
+
+//----------------------------------------------------------------------------------------
+// Is our spec a child of the provided parent?
+PRBool nsFileSpec::IsChildOf(nsFileSpec &possibleParent)
+//----------------------------------------------------------------------------------------
+{
+ nsFileSpec iter = *this, parent;
+#ifdef DEBUG
+ int depth = 0;
+#endif
+ while (1) {
+#ifdef DEBUG
+ // sanity
+ NS_ASSERTION(depth < 100, "IsChildOf has lost its little mind");
+ if (depth > 100)
+ return PR_FALSE;
+#endif
+ if (iter == possibleParent)
+ return PR_TRUE;
+
+ iter.GetParent(parent); // shouldn't this be an error on parent?
+ if (iter.Failed())
+ return PR_FALSE;
+
+ if (iter == parent) // hit bottom
+ return PR_FALSE;
+
+ iter = parent;
+#ifdef DEBUG
+ depth++;
+#endif
+ }
+
+ // not reached, but I bet some compiler will whine
+ return PR_FALSE;
+}
+
+#if 0
+#pragma mark -
+#endif
+
+//========================================================================================
+// class nsPersistentFileDescriptor
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsPersistentFileDescriptor::nsPersistentFileDescriptor(const nsPersistentFileDescriptor& inDesc)
+//----------------------------------------------------------------------------------------
+ : mDescriptorString(inDesc.mDescriptorString)
+{
+} // nsPersistentFileDescriptor::nsPersistentFileDescriptor
+
+//----------------------------------------------------------------------------------------
+void nsPersistentFileDescriptor::operator = (const nsPersistentFileDescriptor& inDesc)
+//----------------------------------------------------------------------------------------
+{
+ mDescriptorString = inDesc.mDescriptorString;
+} // nsPersistentFileDescriptor::operator =
+
+//----------------------------------------------------------------------------------------
+nsPersistentFileDescriptor::nsPersistentFileDescriptor(const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+{
+ *this = inSpec;
+} // nsPersistentFileDescriptor::nsPersistentFileDescriptor
+
+//----------------------------------------------------------------------------------------
+void nsPersistentFileDescriptor::operator = (const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+{
+#if defined(XP_MAC)
+ if (inSpec.Error())
+ return;
+ AliasHandle aliasH;
+ OSErr err = NewAlias(nil, inSpec.GetFSSpecPtr(), &aliasH);
+ if (err != noErr)
+ return;
+
+ PRUint32 bytes = GetHandleSize((Handle) aliasH);
+ HLock((Handle) aliasH);
+ char* buf = PL_Base64Encode((const char*)*aliasH, bytes, nsnull);
+ DisposeHandle((Handle) aliasH);
+
+ mDescriptorString = buf;
+ PR_Free(buf);
+#elif defined(XP_MACOSX)
+ if (inSpec.Error())
+ return;
+
+ FSRef fileRef;
+ Boolean isDir;
+ OSErr err = ::FSPathMakeRef((const UInt8*)inSpec.GetCString(), &fileRef, &isDir);
+ if (err != noErr)
+ return;
+
+ AliasHandle aliasH;
+ err = ::FSNewAlias(nsnull, &fileRef, &aliasH);
+ if (err != noErr)
+ return;
+
+ PRUint32 bytes = ::GetHandleSize((Handle) aliasH);
+ ::HLock((Handle)aliasH);
+ char* buf = PL_Base64Encode((const char*)*aliasH, bytes, nsnull);
+ ::DisposeHandle((Handle) aliasH);
+
+ mDescriptorString = buf;
+ PR_Free(buf);
+#else
+ mDescriptorString = inSpec.GetCString();
+#endif // XP_MAC
+} // nsPersistentFileDescriptor::operator =
+
+//----------------------------------------------------------------------------------------
+nsPersistentFileDescriptor::~nsPersistentFileDescriptor()
+//----------------------------------------------------------------------------------------
+{
+} // nsPersistentFileDescriptor::~nsPersistentFileDescriptor
+
+//----------------------------------------------------------------------------------------
+void nsPersistentFileDescriptor::GetData(nsAFlatCString& outData) const
+//----------------------------------------------------------------------------------------
+{
+ outData.Assign(mDescriptorString, mDescriptorString.Length());
+}
+
+//----------------------------------------------------------------------------------------
+void nsPersistentFileDescriptor::SetData(const nsAFlatCString& inData)
+//----------------------------------------------------------------------------------------
+{
+ mDescriptorString.CopyFrom(inData.get(), inData.Length());
+}
+
+//----------------------------------------------------------------------------------------
+void nsPersistentFileDescriptor::SetData(const char* inData, PRInt32 inSize)
+//----------------------------------------------------------------------------------------
+{
+ mDescriptorString.CopyFrom(inData, inSize);
+}
+
+//========================================================================================
+// class nsNSPRPath
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsNSPRPath::operator const char*() const
+// NSPR expects a UNIX path on unix and Macintosh, but a native path on windows. NSPR
+// cannot be changed, so we have to do the dirty work.
+//----------------------------------------------------------------------------------------
+{
+#if defined(XP_WIN) || defined(XP_OS2)
+ if (!modifiedNSPRPath)
+ {
+ // If this is the first call, initialize modifiedNSPRPath. Start by cloning
+ // mFilePath, but strip the leading separator, if present
+ const char* unixPath = (const char*)mFilePath;
+ if (!unixPath)
+ return nsnull;
+
+ ((nsNSPRPath*)this)->modifiedNSPRPath
+ = nsCRT::strdup(*unixPath == '/' ? unixPath + 1: unixPath);
+
+ // Replace the bar
+ if (modifiedNSPRPath[1] == '|')
+ modifiedNSPRPath[1] = ':';
+
+ // Remove the ending separator only if it is not the last separator
+ int len = strlen(modifiedNSPRPath);
+ if (modifiedNSPRPath[len - 1 ] == '/' && modifiedNSPRPath[len - 2 ] != ':')
+ modifiedNSPRPath[len - 1 ] = '\0';
+ }
+ return modifiedNSPRPath;
+#else
+ return (const char*)mFilePath;
+#endif
+}
+
+//----------------------------------------------------------------------------------------
+nsNSPRPath::~nsNSPRPath()
+//----------------------------------------------------------------------------------------
+{
+#if defined(XP_WIN) || defined(XP_OS2)
+ if (modifiedNSPRPath)
+ nsCRT::free(modifiedNSPRPath);
+#endif
+}
+
+
+nsresult
+NS_FileSpecToIFile(nsFileSpec* fileSpec, nsILocalFile* *result)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsILocalFile> file(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
+
+ if (!file) return NS_ERROR_FAILURE;
+
+#if defined(XP_MAC)
+ {
+ FSSpec spec = fileSpec->GetFSSpec();
+ nsCOMPtr<nsILocalFileMac> psmAppMacFile = do_QueryInterface(file, &rv);
+ if (NS_FAILED(rv)) return rv;
+ rv = psmAppMacFile->InitWithFSSpec(&spec);
+ if (NS_FAILED(rv)) return rv;
+ file = do_QueryInterface(psmAppMacFile, &rv);
+ }
+#else
+ // XP_MACOSX: do this for OS X to preserve long filenames
+ rv = file->InitWithNativePath(nsDependentCString(fileSpec->GetNativePathCString()));
+#endif
+ if (NS_FAILED(rv)) return rv;
+
+ *result = file;
+ NS_ADDREF(*result);
+ return NS_OK;
+}
+
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpec.h b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpec.h
new file mode 100644
index 00000000..53fa6c1a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpec.h
@@ -0,0 +1,782 @@
+/* -*- 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 ***** */
+
+
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ THESE CLASSES ARE DEPRECATED AND UNSUPPORTED! USE |nsIFile| and |nsILocalFile|.
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+
+
+
+
+
+
+
+
+
+// First checked in on 98/11/20 by John R. McMullen in the wrong directory.
+// Checked in again 98/12/04.
+// Polished version 98/12/08.
+
+//========================================================================================
+//
+// Classes defined:
+//
+// nsFilePath, nsFileURL, nsFileSpec, nsPersistentFileDescriptor
+// nsDirectoryIterator.
+//
+// Q. How should I represent files at run time?
+// A. Use nsFileSpec. Using char* will lose information on some platforms.
+//
+// Q. Then what are nsFilePath and nsFileURL for?
+// A. Only when you need a char* parameter for legacy code.
+//
+// Q. How should I represent files in a persistent way (eg, in a disk file)?
+// A. Use nsPersistentFileDescriptor. Convert to and from nsFileSpec at run time.
+//
+// This suite provides the following services:
+//
+// 1. Encapsulates all platform-specific file details, so that files can be
+// described correctly without any platform #ifdefs
+//
+// 2. Type safety. This will fix the problems that used to occur because people
+// confused file paths. They used to use const char*, which could mean three
+// or four different things. Bugs were introduced as people coded, right up
+// to the moment Communicator 4.5 shipped.
+//
+// 3. Used in conjunction with nsFileStream.h (q.v.), this supports all the power
+// and readability of the ansi stream syntax.
+//
+// Basic example:
+//
+// nsFilePath myPath("/Development/iotest.txt");
+//
+// nsOutputFileStream testStream(nsFileSpec(myPath));
+// testStream << "Hello World" << nsEndl;
+//
+// 4. Handy methods for manipulating file specifiers safely, e.g. MakeUnique(),
+// SetLeafName(), Exists().
+//
+// 5. Easy cross-conversion.
+//
+// Examples:
+//
+// Initialize a URL from a string
+//
+// nsFileURL fileURL("file:///Development/MPW/MPW%20Shell");
+//
+// Initialize a Unix-style path from a URL
+//
+// nsFilePath filePath(fileURL);
+//
+// Initialize a file spec from a URL
+//
+// nsFileSpec fileSpec(fileURL);
+//
+// Make the spec unique.
+//
+// fileSpec.MakeUnique();
+//
+// Assign the spec to a URL (causing conversion)
+//
+// fileURL = fileSpec;
+//
+// Assign a unix path using a string
+//
+// filePath = "/Development/MPW/SysErrs.err";
+//
+// Assign to a file spec using a unix path (causing conversion).
+//
+// fileSpec = filePath;
+//
+// Make this unique.
+//
+// fileSpec.MakeUnique();
+//
+// 6. Fixes a bug that have been there for a long time, and
+// is inevitable if you use NSPR alone, where files are described as paths.
+//
+// The problem affects platforms (Macintosh) in which a path does not fully
+// specify a file, because two volumes can have the same name. This
+// is solved by holding a "private" native file spec inside the
+// nsFilePath and nsFileURL classes, which is used when appropriate.
+//
+//========================================================================================
+
+#ifndef _FILESPEC_H_
+#define _FILESPEC_H_
+
+#include "xpcomobsolete.h"
+#include "nsError.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+#include "nsCRT.h"
+#include "prtypes.h"
+
+//========================================================================================
+// Compiler-specific macros, as needed
+//========================================================================================
+#if !defined(NS_USING_NAMESPACE) && (defined(__MWERKS__) || defined(_MSC_VER))
+#define NS_USING_NAMESPACE
+#endif
+
+#ifdef NS_USING_NAMESPACE
+
+#define NS_NAMESPACE_PROTOTYPE
+#define NS_NAMESPACE namespace
+#define NS_NAMESPACE_END
+#define NS_EXPLICIT explicit
+#else
+
+#define NS_NAMESPACE_PROTOTYPE static
+#define NS_NAMESPACE struct
+#define NS_NAMESPACE_END ;
+#define NS_EXPLICIT
+
+#endif
+//=========================== End Compiler-specific macros ===============================
+
+#include "nsILocalFile.h"
+#include "nsCOMPtr.h"
+
+#if defined(XP_MAC)
+#include <Files.h>
+#include "nsILocalFileMac.h"
+#elif defined(XP_UNIX) || defined(XP_BEOS)
+#include <dirent.h>
+#elif defined(XP_WIN)
+
+// This clashes with some of the Win32 system headers (specifically,
+// winbase.h). Hopefully they'll have been included first; else we may
+// have problems. We could include winbase.h before doing this;
+// unfortunately, it's bring in too much crap and'd slow stuff down
+// more than it's worth doing.
+#ifdef CreateDirectory
+#undef CreateDirectory
+#endif
+
+#include "prio.h"
+#elif defined(XP_OS2)
+#define INCL_DOS
+#define INCL_DOSERRORS
+#define INCL_WIN
+#define INCL_GPI
+#include <os2.h>
+#include "prio.h"
+#endif
+
+//========================================================================================
+// Here are the allowable ways to describe a file.
+//========================================================================================
+
+class nsFileSpec; // Preferred. For i/o use nsInputFileStream, nsOutputFileStream
+class nsFilePath;
+class nsFileURL;
+class nsNSPRPath; // This can be passed to NSPR file I/O routines, if you must.
+class nsPersistentFileDescriptor; // Used for storage across program launches.
+
+#define kFileURLPrefix "file://"
+#define kFileURLPrefixLength (7)
+
+class nsOutputStream;
+class nsInputStream;
+class nsIOutputStream;
+class nsIInputStream;
+class nsOutputFileStream;
+class nsInputFileStream;
+class nsOutputConsoleStream;
+
+class nsIUnicodeEncoder;
+class nsIUnicodeDecoder;
+
+//========================================================================================
+// Conversion of native file errors to nsresult values. These are really only for use
+// in the file module, clients of this interface shouldn't really need them.
+// Error results returned from this interface have, in the low-order 16 bits,
+// native errors that are masked to 16 bits. Assumption: a native error of 0 is success
+// on all platforms. Note the way we define this using an inline function. This
+// avoids multiple evaluation if people go NS_FILE_RESULT(function_call()).
+#define NS_FILE_RESULT(x) ns_file_convert_result((PRInt32)x)
+nsresult ns_file_convert_result(PRInt32 nativeErr);
+#define NS_FILE_FAILURE NS_FILE_RESULT(-1)
+
+//========================================================================================
+class nsSimpleCharString
+// An envelope for char*: reference counted. Used internally by all the nsFileSpec
+// classes below.
+//========================================================================================
+{
+public:
+ nsSimpleCharString();
+ nsSimpleCharString(const char*);
+ nsSimpleCharString(const nsString&);
+ nsSimpleCharString(const nsSimpleCharString&);
+ nsSimpleCharString(const char* inData, PRUint32 inLength);
+
+ ~nsSimpleCharString();
+
+ void operator = (const char*);
+ void operator = (const nsString&);
+ void operator = (const nsSimpleCharString&);
+
+ operator const char*() const { return mData ? mData->mString : 0; }
+ operator char* ()
+ {
+ ReallocData(Length()); // requires detaching if shared...
+ return mData ? mData->mString : 0;
+ }
+ PRBool operator == (const char*);
+ PRBool operator == (const nsString&);
+ PRBool operator == (const nsSimpleCharString&);
+
+ void operator += (const char* inString);
+ nsSimpleCharString operator + (const char* inString) const;
+
+ char operator [](int i) const { return mData ? mData->mString[i] : '\0'; }
+ char& operator [](int i)
+ {
+ if (i >= (int)Length())
+ ReallocData((PRUint32)i + 1);
+ return mData->mString[i]; // caveat appelator
+ }
+ char& operator [](unsigned int i) { return (*this)[(int)i]; }
+
+ void Catenate(const char* inString1, const char* inString2);
+
+ void SetToEmpty();
+ PRBool IsEmpty() const { return Length() == 0; }
+
+ PRUint32 Length() const { return mData ? mData->mLength : 0; }
+ void SetLength(PRUint32 inLength) { ReallocData(inLength); }
+ void CopyFrom(const char* inData, PRUint32 inLength);
+ void LeafReplace(char inSeparator, const char* inLeafName);
+ char* GetLeaf(char inSeparator) const; // use PR_Free()
+ void Unescape();
+
+protected:
+
+ void AddRefData();
+ void ReleaseData();
+ void ReallocData(PRUint32 inLength);
+
+ //--------------------------------------------------
+ // Data
+ //--------------------------------------------------
+
+protected:
+
+ struct Data {
+ int mRefCount;
+ PRUint32 mLength;
+ char mString[1];
+ };
+ Data* mData;
+}; // class nsSimpleCharString
+
+//========================================================================================
+class NS_COM_OBSOLETE nsFileSpec
+// This is whatever each platform really prefers to describe files as. Declared first
+// because the other two types have an embedded nsFileSpec object.
+//========================================================================================
+{
+ public:
+ nsFileSpec();
+
+ // These two meathods take *native* file paths.
+ NS_EXPLICIT nsFileSpec(const char* inNativePath, PRBool inCreateDirs = PR_FALSE);
+ NS_EXPLICIT nsFileSpec(const nsString& inNativePath, PRBool inCreateDirs = PR_FALSE);
+
+
+ NS_EXPLICIT nsFileSpec(const nsFilePath& inPath);
+ NS_EXPLICIT nsFileSpec(const nsFileURL& inURL);
+ nsFileSpec(const nsFileSpec& inPath);
+ virtual ~nsFileSpec();
+
+ // These two operands take *native* file paths.
+ void operator = (const char* inNativePath);
+
+ void operator = (const nsFilePath& inPath);
+ void operator = (const nsFileURL& inURL);
+ void operator = (const nsFileSpec& inOther);
+ void operator = (const nsPersistentFileDescriptor& inOther);
+
+ PRBool operator ==(const nsFileSpec& inOther) const;
+ PRBool operator !=(const nsFileSpec& inOther) const;
+
+
+ // Returns a native path, and allows the
+ // path to be "passed" to legacy code. This practice
+ // is VERY EVIL and should only be used to support legacy
+ // code. Using it guarantees bugs on Macintosh.
+ // The path is cached and freed by the nsFileSpec destructor
+ // so do not delete (or free) it. See also nsNSPRPath below,
+ // if you really must pass a string to PR_OpenFile().
+ // Doing so will introduce two automatic bugs.
+ const char* GetCString() const;
+
+ // Same as GetCString (please read the comments).
+ // Do not try to free this!
+ operator const char* () const { return GetCString(); }
+
+ // Same as GetCString (please read the comments).
+ // Do not try to free this!
+ const char* GetNativePathCString() const { return GetCString(); }
+
+ PRBool IsChildOf(nsFileSpec &possibleParent);
+
+#if defined(XP_MAC)
+ // For Macintosh people, this is meant to be useful in its own right as a C++ version
+ // of the FSSpec struct.
+ nsFileSpec(
+ short vRefNum,
+ long parID,
+ ConstStr255Param name,
+ PRBool resolveAlias = PR_TRUE);
+
+ nsFileSpec(const FSSpec& inSpec, PRBool resolveAlias = PR_TRUE);
+ void operator = (const FSSpec& inSpec);
+
+ operator FSSpec* () { return &mSpec; }
+ operator const FSSpec* const () { return &mSpec; }
+ operator FSSpec& () { return mSpec; }
+ operator const FSSpec& () const { return mSpec; }
+
+ const FSSpec& GetFSSpec() const { return mSpec; }
+ FSSpec& GetFSSpec() { return mSpec; }
+ ConstFSSpecPtr GetFSSpecPtr() const { return &mSpec; }
+ FSSpecPtr GetFSSpecPtr() { return &mSpec; }
+ void MakeAliasSafe();
+ void MakeUnique(ConstStr255Param inSuggestedLeafName);
+ StringPtr GetLeafPName() { return mSpec.name; }
+ ConstStr255Param GetLeafPName() const { return mSpec.name; }
+
+ OSErr GetCatInfo(CInfoPBRec& outInfo) const;
+
+ OSErr SetFileTypeAndCreator(OSType type, OSType creator);
+ OSErr GetFileTypeAndCreator(OSType* type, OSType* creator);
+
+#endif // end of Macintosh utility methods.
+
+ PRBool Valid() const { return NS_SUCCEEDED(Error()); }
+ nsresult Error() const
+ {
+#if !defined(XP_MAC)
+ if (mPath.IsEmpty() && NS_SUCCEEDED(mError))
+ ((nsFileSpec*)this)->mError = NS_ERROR_NOT_INITIALIZED;
+#endif
+ return mError;
+ }
+ PRBool Failed() const { return (PRBool)NS_FAILED(Error()); }
+
+ //--------------------------------------------------
+ // Queries and path algebra. These do not modify the disk.
+ //--------------------------------------------------
+
+ char* GetLeafName() const; // Allocated. Use nsCRT::free().
+ // inLeafName can be a relative path, so this allows
+ // one kind of concatenation of "paths".
+ void SetLeafName(const char* inLeafName);
+
+ // Return the filespec of the parent directory. Used
+ // in conjunction with GetLeafName(), this lets you
+ // parse a path into a list of node names. Beware,
+ // however, that the top node is still not a name,
+ // but a spec. Volumes on Macintosh can have identical
+ // names. Perhaps could be used for an operator --() ?
+ void GetParent(nsFileSpec& outSpec) const;
+
+
+ // ie nsFileSpec::TimeStamp. This is 32 bits now,
+ // but might change, eg, to a 64-bit class. So use the
+ // typedef, and use a streaming operator to convert
+ // to a string, so that your code won't break. It's
+ // none of your business what the number means. Don't
+ // rely on the implementation.
+ typedef PRUint32 TimeStamp;
+
+ // This will return different values on different
+ // platforms, even for the same file (eg, on a server).
+ // But if the platform is constant, it will increase after
+ // every file modification.
+ void GetModDate(TimeStamp& outStamp) const;
+
+ PRBool ModDateChanged(const TimeStamp& oldStamp) const
+ {
+ TimeStamp newStamp;
+ GetModDate(newStamp);
+ return newStamp != oldStamp;
+ }
+
+ PRUint32 GetFileSize() const;
+ PRInt64 GetDiskSpaceAvailable() const;
+
+ nsFileSpec operator + (const char* inRelativeUnixPath) const;
+
+ // Concatenate the relative path to this directory.
+ // Used for constructing the filespec of a descendant.
+ // This must be a directory for this to work. This differs
+ // from SetLeafName(), since the latter will work
+ // starting with a sibling of the directory and throws
+ // away its leaf information, whereas this one assumes
+ // this is a directory, and the relative path starts
+ // "below" this.
+ void operator += (const char* inRelativeUnixPath);
+
+
+ void MakeUnique();
+ void MakeUnique(const char* inSuggestedLeafName);
+
+
+ PRBool IsDirectory() const; // More stringent than Exists()
+ PRBool IsFile() const; // More stringent than Exists()
+ PRBool Exists() const;
+
+ PRBool IsHidden() const;
+
+ PRBool IsSymlink() const;
+
+ //--------------------------------------------------
+ // Creation and deletion of objects. These can modify the disk.
+ //--------------------------------------------------
+
+ // Called for the spec of an alias. Modifies the spec to
+ // point to the original. Sets mError.
+ nsresult ResolveSymlink(PRBool& wasSymlink);
+
+ void CreateDirectory(int mode = 0775 /* for unix */);
+ void CreateDir(int mode = 0775) { CreateDirectory(mode); }
+ // workaround for yet another VC++ bug with long identifiers.
+ void Delete(PRBool inRecursive) const;
+ nsresult Truncate(PRInt32 aNewLength) const;
+ void RecursiveCopy(nsFileSpec newDir) const;
+
+ nsresult Rename(const char* inNewName); // not const: gets updated
+ nsresult CopyToDir(const nsFileSpec& inNewParentDirectory) const;
+ nsresult MoveToDir(const nsFileSpec& inNewParentDirectory);
+ nsresult Execute(const char* args) const;
+
+ protected:
+
+ //--------------------------------------------------
+ // Data
+ //--------------------------------------------------
+
+ protected:
+
+ // Clear the nsFileSpec contents, resetting it
+ // to the uninitialized state;
+ void Clear();
+
+ friend class nsFilePath;
+ friend class nsFileURL;
+ friend class nsDirectoryIterator;
+#if defined(XP_MAC)
+ FSSpec mSpec;
+#endif
+ nsSimpleCharString mPath;
+ nsresult mError;
+
+private:
+ NS_EXPLICIT nsFileSpec(const nsPersistentFileDescriptor& inURL);
+
+}; // class nsFileSpec
+
+// FOR HISTORICAL REASONS:
+
+typedef nsFileSpec nsNativeFileSpec;
+
+//========================================================================================
+class NS_COM_OBSOLETE nsFileURL
+// This is an escaped string that looks like "file:///foo/bar/mumble%20fish". Since URLs
+// are the standard way of doing things in mozilla, this allows a string constructor,
+// which just stashes the string with no conversion.
+//========================================================================================
+{
+ public:
+ nsFileURL(const nsFileURL& inURL);
+ NS_EXPLICIT nsFileURL(const char* inURLString, PRBool inCreateDirs = PR_FALSE);
+ NS_EXPLICIT nsFileURL(const nsString& inURLString, PRBool inCreateDirs = PR_FALSE);
+ NS_EXPLICIT nsFileURL(const nsFilePath& inPath);
+ NS_EXPLICIT nsFileURL(const nsFileSpec& inPath);
+ virtual ~nsFileURL();
+
+// nsString GetString() const { return mPath; }
+ // may be needed for implementation reasons,
+ // but should not provide a conversion constructor.
+
+ void operator = (const nsFileURL& inURL);
+ void operator = (const char* inURLString);
+ void operator = (const nsString& inURLString)
+ {
+ *this = NS_LossyConvertUCS2toASCII(inURLString).get();
+ }
+ void operator = (const nsFilePath& inOther);
+ void operator = (const nsFileSpec& inOther);
+
+ void operator +=(const char* inRelativeUnixPath);
+ nsFileURL operator +(const char* inRelativeUnixPath) const;
+ operator const char* () const { return (const char*)mURL; } // deprecated.
+ const char* GetURLString() const { return (const char*)mURL; }
+ // Not allocated, so don't free it.
+ const char* GetAsString() const { return (const char*)mURL; }
+ // Not allocated, so don't free it.
+
+#if defined(XP_MAC)
+ // Accessor to allow quick assignment to a mFileSpec
+ const nsFileSpec& GetFileSpec() const { return mFileSpec; }
+#endif
+
+ //--------------------------------------------------
+ // Data
+ //--------------------------------------------------
+
+ protected:
+ friend class nsFilePath; // to allow construction of nsFilePath
+ nsSimpleCharString mURL;
+
+#if defined(XP_MAC)
+ // Since the path on the macintosh does not uniquely specify a file (volumes
+ // can have the same name), stash the secret nsFileSpec, too.
+ nsFileSpec mFileSpec;
+#endif
+}; // class nsFileURL
+
+//========================================================================================
+class NS_COM_OBSOLETE nsFilePath
+// This is a string that looks like "/foo/bar/mumble fish". Same as nsFileURL, but
+// without the "file:// prefix", and NOT %20 ENCODED! Strings passed in must be
+// valid unix-style paths in this format.
+//========================================================================================
+{
+ public:
+ nsFilePath(const nsFilePath& inPath);
+ NS_EXPLICIT nsFilePath(const char* inUnixPathString, PRBool inCreateDirs = PR_FALSE);
+ NS_EXPLICIT nsFilePath(const nsString& inUnixPathString, PRBool inCreateDirs = PR_FALSE);
+ NS_EXPLICIT nsFilePath(const nsFileURL& inURL);
+ NS_EXPLICIT nsFilePath(const nsFileSpec& inPath);
+ virtual ~nsFilePath();
+
+
+ operator const char* () const { return mPath; }
+ // This will return a UNIX string. If you
+ // need a string that can be passed into
+ // NSPR, take a look at the nsNSPRPath class.
+
+ void operator = (const nsFilePath& inPath);
+ void operator = (const char* inUnixPathString);
+ void operator = (const nsString& inUnixPathString)
+ {
+ *this = NS_LossyConvertUCS2toASCII(inUnixPathString).get();
+ }
+ void operator = (const nsFileURL& inURL);
+ void operator = (const nsFileSpec& inOther);
+
+ void operator +=(const char* inRelativeUnixPath);
+ nsFilePath operator +(const char* inRelativeUnixPath) const;
+
+#if defined(XP_MAC)
+ public:
+ // Accessor to allow quick assignment to a mFileSpec
+ const nsFileSpec& GetFileSpec() const { return mFileSpec; }
+#endif
+
+ //--------------------------------------------------
+ // Data
+ //--------------------------------------------------
+
+ private:
+
+ nsSimpleCharString mPath;
+#if defined(XP_MAC)
+ // Since the path on the macintosh does not uniquely specify a file (volumes
+ // can have the same name), stash the secret nsFileSpec, too.
+ nsFileSpec mFileSpec;
+#endif
+}; // class nsFilePath
+
+//========================================================================================
+class nsPersistentFileDescriptor
+// To save information about a file's location in another file, initialize
+// one of these from your nsFileSpec, and then write this out to your output stream.
+// To retrieve the info, create one of these, read its value from an input stream.
+// and then make an nsFileSpec from it.
+//========================================================================================
+{
+ public:
+ nsPersistentFileDescriptor() {}
+ // For use prior to reading in from a stream
+ nsPersistentFileDescriptor(const nsPersistentFileDescriptor& inEncodedData);
+ virtual ~nsPersistentFileDescriptor();
+ void operator = (const nsPersistentFileDescriptor& inEncodedData);
+
+ // Conversions
+ NS_EXPLICIT nsPersistentFileDescriptor(const nsFileSpec& inSpec);
+ void operator = (const nsFileSpec& inSpec);
+
+ // The following four functions are declared here (as friends). Their implementations
+ // are in mozilla/base/src/nsFileSpecStreaming.cpp.
+
+ friend nsresult Read(nsIInputStream* aStream, nsPersistentFileDescriptor&);
+ friend nsresult Write(nsIOutputStream* aStream, const nsPersistentFileDescriptor&);
+ // writes the data to a file
+ friend NS_COM_OBSOLETE nsInputStream& operator >> (nsInputStream&, nsPersistentFileDescriptor&);
+ // reads the data from a file
+ friend NS_COM_OBSOLETE nsOutputStream& operator << (nsOutputStream&, const nsPersistentFileDescriptor&);
+ // writes the data to a file
+ friend class nsFileSpec;
+
+ void GetData(nsAFlatCString& outData) const;
+ void SetData(const nsAFlatCString& inData);
+ void SetData(const char* inData, PRInt32 inSize);
+
+ //--------------------------------------------------
+ // Data
+ //--------------------------------------------------
+
+ protected:
+
+ nsSimpleCharString mDescriptorString;
+
+}; // class nsPersistentFileDescriptor
+
+//========================================================================================
+class NS_COM_OBSOLETE nsDirectoryIterator
+// Example:
+//
+// nsFileSpec parentDir(...); // directory over whose children we shall iterate
+// for (nsDirectoryIterator i(parentDir, PR_FALSE); i.Exists(); i++)
+// {
+// // do something with i.Spec()
+// }
+//
+// - or -
+//
+// for (nsDirectoryIterator i(parentDir, PR_TRUE); i.Exists(); i--)
+// {
+// // do something with i.Spec()
+// }
+// This one passed the PR_TRUE flag which will resolve any symlink encountered.
+//========================================================================================
+{
+ public:
+ nsDirectoryIterator( const nsFileSpec& parent,
+ PRBool resoveSymLinks);
+#if !defined(XP_MAC)
+ // Macintosh currently doesn't allocate, so needn't clean up.
+ virtual ~nsDirectoryIterator();
+#endif
+ PRBool Exists() const { return mExists; }
+ nsDirectoryIterator& operator ++(); // moves to the next item, if any.
+ nsDirectoryIterator& operator ++(int) { return ++(*this); } // post-increment.
+ nsDirectoryIterator& operator --(); // moves to the previous item, if any.
+ nsDirectoryIterator& operator --(int) { return --(*this); } // post-decrement.
+ operator nsFileSpec&() { return mCurrent; }
+
+ nsFileSpec& Spec() { return mCurrent; }
+
+ private:
+
+#if defined(XP_MAC)
+ OSErr SetToIndex();
+#endif
+
+ //--------------------------------------------------
+ // Data
+ //--------------------------------------------------
+
+ private:
+
+ nsFileSpec mCurrent;
+ PRBool mExists;
+ PRBool mResoveSymLinks;
+
+#if (defined(XP_UNIX) || defined(XP_BEOS) || defined (XP_WIN) || defined(XP_OS2))
+ nsFileSpec mStarting;
+#endif
+
+#if defined(XP_MAC)
+ short mVRefNum;
+ long mParID;
+ short mIndex;
+ short mMaxIndex;
+#elif defined(XP_UNIX) || defined(XP_BEOS)
+ DIR* mDir;
+#elif defined(XP_WIN) || defined(XP_OS2)
+ PRDir* mDir; // XXX why not use PRDir for Unix too?
+#endif
+}; // class nsDirectoryIterator
+
+//========================================================================================
+class NS_COM_OBSOLETE nsNSPRPath
+// This class will allow you to pass any one of the nsFile* classes directly into NSPR
+// without the need to worry about whether you have the right kind of filepath or not.
+// It will also take care of cleaning up any allocated memory.
+//========================================================================================
+{
+public:
+ NS_EXPLICIT nsNSPRPath(const nsFileSpec& inSpec)
+ : mFilePath(inSpec), modifiedNSPRPath(nsnull) {}
+ NS_EXPLICIT nsNSPRPath(const nsFileURL& inURL)
+ : mFilePath(inURL), modifiedNSPRPath(nsnull) {}
+ NS_EXPLICIT nsNSPRPath(const nsFilePath& inUnixPath)
+ : mFilePath(inUnixPath), modifiedNSPRPath(nsnull) {}
+
+ virtual ~nsNSPRPath();
+
+ operator const char*() const;
+ // Returns the path
+ // that NSPR file routines expect on each platform.
+ // Concerning constness, this can modify
+ // modifiedNSPRPath, but it's really just "mutable".
+
+ //--------------------------------------------------
+ // Data
+ //--------------------------------------------------
+
+private:
+
+ nsFilePath mFilePath;
+ char* modifiedNSPRPath; // Currently used only on XP_WIN,XP_OS2
+}; // class nsNSPRPath
+
+
+NS_COM_OBSOLETE nsresult NS_FileSpecToIFile(nsFileSpec* fileSpec, nsILocalFile* *result);
+
+#endif // _FILESPEC_H_
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecBeOS.cpp b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecBeOS.cpp
new file mode 100644
index 00000000..20a38f5e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecBeOS.cpp
@@ -0,0 +1,547 @@
+/* -*- 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 ***** */
+
+// This file is included by nsFileSpec.cpp, and includes the Unix-specific
+// implementations.
+
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <errno.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "nsError.h"
+#include "prio.h" /* for PR_Rename */
+
+// BeOS specific headers
+#include <Entry.h>
+#include <Path.h>
+#include <Volume.h>
+
+//----------------------------------------------------------------------------------------
+void nsFileSpecHelpers::Canonify(nsSimpleCharString& ioPath, PRBool inMakeDirs)
+// Canonify, make absolute, and check whether directories exist
+//----------------------------------------------------------------------------------------
+{
+ if (ioPath.IsEmpty())
+ return;
+ if (inMakeDirs)
+ {
+ const mode_t mode = 0700;
+ nsFileSpecHelpers::MakeAllDirectories((const char*)ioPath, mode);
+ }
+ char buffer[MAXPATHLEN];
+ errno = 0;
+ *buffer = '\0';
+ BEntry e((const char *)ioPath, true);
+ BPath p;
+ e.GetPath(&p);
+ ioPath = p.Path();
+} // nsFileSpecHelpers::Canonify
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::SetLeafName(const char* inLeafName)
+//----------------------------------------------------------------------------------------
+{
+ mPath.LeafReplace('/', inLeafName);
+} // nsFileSpec::SetLeafName
+
+//----------------------------------------------------------------------------------------
+char* nsFileSpec::GetLeafName() const
+//----------------------------------------------------------------------------------------
+{
+ return mPath.GetLeaf('/');
+} // nsFileSpec::GetLeafName
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::Exists() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ return !mPath.IsEmpty() && 0 == stat(mPath, &st);
+} // nsFileSpec::Exists
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::GetModDate(TimeStamp& outStamp) const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ if (!mPath.IsEmpty() && stat(mPath, &st) == 0)
+ outStamp = st.st_mtime;
+ else
+ outStamp = 0;
+} // nsFileSpec::GetModDate
+
+//----------------------------------------------------------------------------------------
+PRUint32 nsFileSpec::GetFileSize() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ if (!mPath.IsEmpty() && stat(mPath, &st) == 0)
+ return (PRUint32)st.st_size;
+ return 0;
+} // nsFileSpec::GetFileSize
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsFile() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ return !mPath.IsEmpty() && stat(mPath, &st) == 0 && S_ISREG(st.st_mode);
+} // nsFileSpec::IsFile
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsDirectory() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ return !mPath.IsEmpty() && 0 == stat(mPath, &st) && S_ISDIR(st.st_mode);
+} // nsFileSpec::IsDirectory
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsHidden() const
+//----------------------------------------------------------------------------------------
+{
+ PRBool hidden = PR_TRUE;
+ char *leafname = GetLeafName();
+ if (nsnull != leafname)
+ {
+ if ((!strcmp(leafname, ".")) || (!strcmp(leafname, "..")))
+ {
+ hidden = PR_FALSE;
+ }
+ nsCRT::free(leafname);
+ }
+ return hidden;
+} // nsFileSpec::IsHidden
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsSymlink() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ if (!mPath.IsEmpty() && stat(mPath, &st) == 0 && S_ISLNK(st.st_mode))
+ return PR_TRUE;
+
+ return PR_FALSE;
+} // nsFileSpec::IsSymlink
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::ResolveSymlink(PRBool& wasAliased)
+//----------------------------------------------------------------------------------------
+{
+ wasAliased = PR_FALSE;
+
+ char resolvedPath[MAXPATHLEN];
+ int charCount = readlink(mPath, (char*)&resolvedPath, MAXPATHLEN);
+ if (0 < charCount)
+ {
+ if (MAXPATHLEN > charCount)
+ resolvedPath[charCount] = '\0';
+
+ wasAliased = PR_TRUE;
+ /* if it's not an absolute path,
+ replace the leaf with what got resolved */
+ if (resolvedPath[0] != '/') {
+ SetLeafName(resolvedPath);
+ }
+ else {
+ mPath = (char*)resolvedPath;
+ }
+
+ BEntry e((const char *)mPath, true); // traverse symlink
+ BPath p;
+ status_t err;
+ err = e.GetPath(&p);
+ NS_ASSERTION(err == B_OK, "realpath failed");
+
+ const char* canonicalPath = p.Path();
+ if(err == B_OK)
+ mPath = (char*)canonicalPath;
+ else
+ return NS_ERROR_FAILURE;
+ }
+ return NS_OK;
+} // nsFileSpec::ResolveSymlink
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::GetParent(nsFileSpec& outSpec) const
+//----------------------------------------------------------------------------------------
+{
+ outSpec.mPath = mPath;
+ char* chars = (char*)outSpec.mPath;
+ chars[outSpec.mPath.Length() - 1] = '\0'; // avoid trailing separator, if any
+ char* cp = strrchr(chars, '/');
+ if (cp++)
+ outSpec.mPath.SetLength(cp - chars); // truncate.
+} // nsFileSpec::GetParent
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator += (const char* inRelativePath)
+//----------------------------------------------------------------------------------------
+{
+ if (!inRelativePath || mPath.IsEmpty())
+ return;
+
+ char endChar = mPath[(int)(strlen(mPath) - 1)];
+ if (endChar == '/')
+ mPath += "x";
+ else
+ mPath += "/x";
+ SetLeafName(inRelativePath);
+} // nsFileSpec::operator +=
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::CreateDirectory(int mode)
+//----------------------------------------------------------------------------------------
+{
+ // Note that mPath is canonical!
+ if (mPath.IsEmpty())
+ return;
+ mkdir(mPath, mode);
+} // nsFileSpec::CreateDirectory
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::Delete(PRBool inRecursive) const
+// To check if this worked, call Exists() afterwards, see?
+//----------------------------------------------------------------------------------------
+{
+ if (IsDirectory())
+ {
+ if (inRecursive)
+ {
+ for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
+ {
+ nsFileSpec& child = (nsFileSpec&)i;
+ child.Delete(inRecursive);
+ }
+ }
+ rmdir(mPath);
+ }
+ else if (!mPath.IsEmpty())
+ remove(mPath);
+} // nsFileSpec::Delete
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const
+//----------------------------------------------------------------------------------------
+{
+ if (IsDirectory())
+ {
+ if (!(newDir.Exists()))
+ {
+ newDir.CreateDirectory();
+ }
+
+ for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
+ {
+ nsFileSpec& child = (nsFileSpec&)i;
+
+ if (child.IsDirectory())
+ {
+ nsFileSpec tmpDirSpec(newDir);
+
+ char *leafname = child.GetLeafName();
+ tmpDirSpec += leafname;
+ nsCRT::free(leafname);
+
+ child.RecursiveCopy(tmpDirSpec);
+ }
+ else
+ {
+ child.RecursiveCopy(newDir);
+ }
+ }
+ }
+ else if (!mPath.IsEmpty())
+ {
+ nsFileSpec& filePath = (nsFileSpec&) *this;
+
+ if (!(newDir.Exists()))
+ {
+ newDir.CreateDirectory();
+ }
+
+ filePath.CopyToDir(newDir);
+ }
+} // nsFileSpec::RecursiveCopy
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Truncate(PRInt32 offset) const
+//----------------------------------------------------------------------------------------
+{
+ char* Path = nsCRT::strdup(mPath);
+
+ int rv = truncate(Path, offset) ;
+
+ nsCRT::free(Path) ;
+
+ if(!rv)
+ return NS_OK ;
+ else
+ return NS_ERROR_FAILURE ;
+} // nsFileSpec::Truncate
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Rename(const char* inNewName)
+//----------------------------------------------------------------------------------------
+{
+ // This function should not be used to move a file on disk.
+ if (mPath.IsEmpty() || strchr(inNewName, '/'))
+ return NS_FILE_FAILURE;
+
+ char* oldPath = nsCRT::strdup(mPath);
+
+ SetLeafName(inNewName);
+
+ if (PR_Rename(oldPath, mPath) != NS_OK)
+ {
+ // Could not rename, set back to the original.
+ mPath = oldPath;
+ return NS_FILE_FAILURE;
+ }
+
+ nsCRT::free(oldPath);
+
+ return NS_OK;
+} // nsFileSpec::Rename
+
+//----------------------------------------------------------------------------------------
+static int CrudeFileCopy(const char* in, const char* out)
+//----------------------------------------------------------------------------------------
+{
+ struct stat in_stat;
+ int stat_result = -1;
+
+ char buf [1024];
+ FILE *ifp, *ofp;
+ int rbytes, wbytes;
+
+ if (!in || !out)
+ return -1;
+
+ stat_result = stat (in, &in_stat);
+
+ ifp = fopen (in, "r");
+ if (!ifp)
+ {
+ return -1;
+ }
+
+ ofp = fopen (out, "w");
+ if (!ofp)
+ {
+ fclose (ifp);
+ return -1;
+ }
+
+ while ((rbytes = fread (buf, 1, sizeof(buf), ifp)) > 0)
+ {
+ while (rbytes > 0)
+ {
+ if ( (wbytes = fwrite (buf, 1, rbytes, ofp)) < 0 )
+ {
+ fclose (ofp);
+ fclose (ifp);
+ unlink(out);
+ return -1;
+ }
+ rbytes -= wbytes;
+ }
+ }
+ fclose (ofp);
+ fclose (ifp);
+
+ if (stat_result == 0)
+ chmod (out, in_stat.st_mode & 0777);
+
+ return 0;
+} // nsFileSpec::Rename
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::CopyToDir(const nsFileSpec& inParentDirectory) const
+//----------------------------------------------------------------------------------------
+{
+ // We can only copy into a directory, and (for now) can not copy entire directories
+ nsresult result = NS_FILE_FAILURE;
+
+ if (inParentDirectory.IsDirectory() && (! IsDirectory() ) )
+ {
+ char *leafname = GetLeafName();
+ nsSimpleCharString destPath(inParentDirectory.GetCString());
+ destPath += "/";
+ destPath += leafname;
+ nsCRT::free(leafname);
+ result = NS_FILE_RESULT(CrudeFileCopy(GetCString(), destPath));
+ }
+ return result;
+} // nsFileSpec::CopyToDir
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::MoveToDir(const nsFileSpec& inNewParentDirectory)
+//----------------------------------------------------------------------------------------
+{
+ // We can only copy into a directory, and (for now) can not copy entire directories
+ nsresult result = NS_FILE_FAILURE;
+
+ if (inNewParentDirectory.IsDirectory() && !IsDirectory())
+ {
+ char *leafname = GetLeafName();
+ nsSimpleCharString destPath(inNewParentDirectory.GetCString());
+ destPath += "/";
+ destPath += leafname;
+ nsCRT::free(leafname);
+
+ result = NS_FILE_RESULT(CrudeFileCopy(GetCString(), (const char*)destPath));
+ if (result == NS_OK)
+ {
+ // cast to fix const-ness
+ ((nsFileSpec*)this)->Delete(PR_FALSE);
+
+ *this = inNewParentDirectory + GetLeafName();
+ }
+ }
+ return result;
+}
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Execute(const char* inArgs ) const
+//----------------------------------------------------------------------------------------
+{
+ nsresult result = NS_FILE_FAILURE;
+
+ if (!mPath.IsEmpty() && !IsDirectory())
+ {
+ nsSimpleCharString fileNameWithArgs = mPath + " " + inArgs;
+ result = NS_FILE_RESULT(system(fileNameWithArgs));
+ }
+
+ return result;
+
+} // nsFileSpec::Execute
+
+//----------------------------------------------------------------------------------------
+PRInt64 nsFileSpec::GetDiskSpaceAvailable() const
+//----------------------------------------------------------------------------------------
+{
+ char curdir [MAXPATHLEN];
+ if (!mPath || !*mPath)
+ {
+ (void) getcwd(curdir, MAXPATHLEN);
+ if (!curdir)
+ return ULONGLONG_MAX; /* hope for the best as we did in cheddar */
+ }
+ else
+ sprintf(curdir, "%.200s", (const char*)mPath);
+
+ BEntry e(curdir);
+ if(e.InitCheck() != B_OK)
+ return ULONGLONG_MAX; /* hope for the best as we did in cheddar */
+ entry_ref ref;
+ e.GetRef(&ref);
+ BVolume v(ref.device);
+
+#ifdef DEBUG_DISK_SPACE
+ printf("DiskSpaceAvailable: %d bytes\n", space);
+#endif
+ return v.FreeBytes();
+} // nsFileSpec::GetDiskSpace()
+
+//========================================================================================
+// nsDirectoryIterator
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator::nsDirectoryIterator(
+ const nsFileSpec& inDirectory
+, PRBool resolveSymlinks)
+//----------------------------------------------------------------------------------------
+ : mCurrent(inDirectory)
+ , mStarting(inDirectory)
+ , mExists(PR_FALSE)
+ , mDir(nsnull)
+ , mResoveSymLinks(resolveSymlinks)
+{
+ mStarting += "sysygy"; // save off the starting directory
+ mCurrent += "sysygy"; // prepare the path for SetLeafName
+ mDir = opendir((const char*)nsFilePath(inDirectory));
+ ++(*this);
+} // nsDirectoryIterator::nsDirectoryIterator
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator::~nsDirectoryIterator()
+//----------------------------------------------------------------------------------------
+{
+ if (mDir)
+ closedir(mDir);
+} // nsDirectoryIterator::nsDirectoryIterator
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator& nsDirectoryIterator::operator ++ ()
+//----------------------------------------------------------------------------------------
+{
+ mExists = PR_FALSE;
+ if (!mDir)
+ return *this;
+ char* dot = ".";
+ char* dotdot = "..";
+ struct dirent* entry = readdir(mDir);
+ if (entry && strcmp(entry->d_name, dot) == 0)
+ entry = readdir(mDir);
+ if (entry && strcmp(entry->d_name, dotdot) == 0)
+ entry = readdir(mDir);
+ if (entry)
+ {
+ mExists = PR_TRUE;
+ mCurrent = mStarting; // restore mCurrent to be the starting directory. ResolveSymlink() may have taken us to another directory
+ mCurrent.SetLeafName(entry->d_name);
+ if (mResoveSymLinks)
+ {
+ PRBool ignore;
+ mCurrent.ResolveSymlink(ignore);
+ }
+ }
+ return *this;
+} // nsDirectoryIterator::operator ++
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator& nsDirectoryIterator::operator -- ()
+//----------------------------------------------------------------------------------------
+{
+ return ++(*this); // can't do it backwards.
+} // nsDirectoryIterator::operator --
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecImpl.cpp b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecImpl.cpp
new file mode 100644
index 00000000..b0e3cc15
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecImpl.cpp
@@ -0,0 +1,879 @@
+/* -*- 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 "nsFileSpecImpl.h"// Always first, to ensure that it compiles alone.
+
+#include "nsIFileStream.h"
+#include "nsFileStream.h"
+
+#include "nsILocalFile.h"
+#include "nsNativeCharsetUtils.h"
+
+#include "prmem.h"
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsFileSpecImpl, nsIFileSpec)
+
+#ifdef NS_DEBUG
+#define TEST_OUT_PTR(p) \
+ if (!(p)) \
+ return NS_ERROR_NULL_POINTER;
+#else
+#define TEST_OUT_PTR(p)
+#endif
+
+//----------------------------------------------------------------------------------------
+nsFileSpecImpl::nsFileSpecImpl()
+//----------------------------------------------------------------------------------------
+ : mInputStream(nsnull)
+ , mOutputStream(nsnull)
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpecImpl::nsFileSpecImpl(const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+ : mFileSpec(inSpec)
+ , mInputStream(nsnull)
+ , mOutputStream(nsnull)
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpecImpl::~nsFileSpecImpl()
+//----------------------------------------------------------------------------------------
+{
+ CloseStream();
+}
+
+//----------------------------------------------------------------------------------------
+/* static */
+nsresult nsFileSpecImpl::MakeInterface(const nsFileSpec& inSpec, nsIFileSpec** result)
+//----------------------------------------------------------------------------------------
+{
+ nsFileSpecImpl* it = new nsFileSpecImpl(inSpec);
+ if (!it)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return it->QueryInterface(NS_GET_IID(nsIFileSpec), (void **) result);
+} // nsFileSpecImpl::MakeInterface
+
+#define FILESPEC(ifilespec) ((nsFileSpecImpl*)ifilespec)->mFileSpec
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::FromFileSpec(const nsIFileSpec *original)
+//----------------------------------------------------------------------------------------
+{
+ if (original) {
+ nsresult rv = ((nsIFileSpec *)original)->GetFileSpec( &mFileSpec);
+ if (NS_SUCCEEDED( rv))
+ return mFileSpec.Error();
+ else
+ return( rv);
+ }
+ else
+ return( NS_ERROR_FAILURE);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsChildOf(nsIFileSpec *possibleParent,
+ PRBool *_retval)
+{
+ *_retval = mFileSpec.IsChildOf(FILESPEC(possibleParent));
+ return mFileSpec.Error();
+}
+//----------------------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetURLString(char * *aURLString)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aURLString)
+ if (mFileSpec.Failed())
+ return mFileSpec.Error();
+ nsFileURL url(mFileSpec);
+ *aURLString = nsCRT::strdup(url.GetURLString());
+ if (!*aURLString)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+} // nsFileSpecImpl::GetURLString
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetURLString(const char * aURLString)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec = nsFileURL(aURLString);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetUnixStyleFilePath(char * *aUnixStyleFilePath)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aUnixStyleFilePath)
+ if (mFileSpec.Failed())
+ return mFileSpec.Error();
+ nsFilePath path(mFileSpec);
+ *aUnixStyleFilePath = nsCRT::strdup((const char*) path);
+ if (!*aUnixStyleFilePath)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetUnixStyleFilePath(const char * aUnixStyleFilePath)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec = nsFilePath(aUnixStyleFilePath);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetPersistentDescriptorString(char * *aPersistentDescriptorString)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aPersistentDescriptorString)
+ if (mFileSpec.Failed())
+ return mFileSpec.Error();
+ nsPersistentFileDescriptor desc(mFileSpec);
+ nsCAutoString data;
+ desc.GetData(data);
+ *aPersistentDescriptorString = ToNewCString(data);
+ if (!*aPersistentDescriptorString)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetPersistentDescriptorString(const char * aPersistentDescriptorString)
+//----------------------------------------------------------------------------------------
+{
+ nsPersistentFileDescriptor desc(mFileSpec);
+ desc.SetData(nsDependentCString(aPersistentDescriptorString));
+ mFileSpec = desc;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetNativePath(char * *aNativePath)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aNativePath)
+ if (mFileSpec.Failed())
+ return mFileSpec.Error();
+ *aNativePath = nsCRT::strdup(mFileSpec.GetNativePathCString());
+ if (!*aNativePath)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetNativePath(const char * aNativePath)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec = aNativePath;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetUnicodePath(nsAString & aUnicodePath)
+//----------------------------------------------------------------------------------------
+{
+ nsCAutoString native;
+ native = mFileSpec.GetNativePathCString();
+ NS_CopyNativeToUnicode(native, aUnicodePath);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetUnicodePath(const nsAString & aUnicodePath)
+//----------------------------------------------------------------------------------------
+{
+ nsCAutoString native;
+
+ NS_CopyUnicodeToNative(aUnicodePath, native);
+ mFileSpec = native.get();
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetNSPRPath(char * *aNSPRPath)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aNSPRPath)
+ if (mFileSpec.Failed())
+ return mFileSpec.Error();
+ nsNSPRPath path(mFileSpec);
+ *aNSPRPath = nsCRT::strdup((const char*) path);
+ if (!*aNSPRPath)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Error()
+//----------------------------------------------------------------------------------------
+{
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsValid(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.Valid();
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Failed(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ *_retval = mFileSpec.Failed();
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetLeafName(char * *aLeafName)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aLeafName)
+ *aLeafName = mFileSpec.GetLeafName();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetLeafName(const char * aLeafName)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec.SetLeafName(aLeafName);
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetParent(nsIFileSpec * *aParent)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aParent)
+ nsFileSpec parent;
+ mFileSpec.GetParent(parent);
+ return MakeInterface(parent, aParent);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::MakeUnique()
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec.MakeUnique();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::MakeUniqueWithSuggestedName(const char *suggestedName)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec.MakeUnique(suggestedName);
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetModDate(PRUint32 *aModDate)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aModDate)
+ nsFileSpec::TimeStamp stamp;
+ mFileSpec.GetModDate(stamp);
+ *aModDate = stamp;
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::ModDateChanged(PRUint32 oldStamp, PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.ModDateChanged(oldStamp);
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsDirectory(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.IsDirectory();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsFile(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.IsFile();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Exists(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.Exists();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsHidden(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.IsHidden();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsSymlink(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = mFileSpec.IsSymlink();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::ResolveSymlink()
+//----------------------------------------------------------------------------------------
+{
+ PRBool ignore;
+ return mFileSpec.ResolveSymlink(ignore);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetFileSize(PRUint32 *aFileSize)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aFileSize)
+ *aFileSize = mFileSpec.GetFileSize();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aDiskSpaceAvailable)
+ *aDiskSpaceAvailable = mFileSpec.GetDiskSpaceAvailable();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::AppendRelativeUnixPath(const char *relativePath)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec += relativePath;
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Touch()
+//----------------------------------------------------------------------------------------
+{
+ // create an empty file, like the UNIX touch command.
+ nsresult rv;
+ rv = OpenStreamForWriting();
+ if (NS_FAILED(rv)) return rv;
+ rv = CloseStream();
+ return rv;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::CreateDir()
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec.CreateDir();
+ return mFileSpec.Error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Delete(PRBool aRecursive)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec.Delete(aRecursive);
+ return mFileSpec.Error();
+}
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Truncate(PRInt32 aNewLength)
+//----------------------------------------------------------------------------------------
+{
+ return mFileSpec.Truncate(aNewLength);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Rename(const char *newLeafName)
+//----------------------------------------------------------------------------------------
+{
+ return mFileSpec.Rename(newLeafName);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::CopyToDir(const nsIFileSpec *newParentDir)
+//----------------------------------------------------------------------------------------
+{
+ return mFileSpec.CopyToDir(FILESPEC(newParentDir));
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::MoveToDir(const nsIFileSpec *newParentDir)
+//----------------------------------------------------------------------------------------
+{
+ return mFileSpec.MoveToDir(FILESPEC(newParentDir));
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Execute(const char *args)
+//----------------------------------------------------------------------------------------
+{
+ return mFileSpec.Execute(args);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::OpenStreamForReading()
+//----------------------------------------------------------------------------------------
+{
+ if (mInputStream || mOutputStream)
+ return NS_ERROR_FAILURE;
+ return NS_NewTypicalInputFileStream((nsISupports**)&mInputStream, mFileSpec);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::OpenStreamForWriting()
+//----------------------------------------------------------------------------------------
+{
+ if (mInputStream || mOutputStream)
+ return NS_ERROR_FAILURE;
+ return NS_NewTypicalOutputFileStream((nsISupports**)&mOutputStream, mFileSpec);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::OpenStreamForReadingAndWriting()
+//----------------------------------------------------------------------------------------
+{
+ if (mInputStream || mOutputStream)
+ return NS_ERROR_FAILURE;
+ nsresult result = NS_NewTypicalInputFileStream((nsISupports**)&mInputStream, mFileSpec);
+ if (NS_SUCCEEDED(result))
+ result = NS_NewTypicalOutputFileStream((nsISupports**)&mOutputStream, mFileSpec);
+ return result;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::CloseStream()
+//----------------------------------------------------------------------------------------
+{
+ NS_IF_RELEASE(mInputStream);
+ NS_IF_RELEASE(mOutputStream);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::IsStreamOpen(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = (mInputStream || mOutputStream);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetInputStream(nsIInputStream** _retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ if (!mInputStream) {
+ nsresult rv = OpenStreamForReading();
+ if (NS_FAILED(rv)) return rv;
+ }
+ *_retval = mInputStream;
+ NS_IF_ADDREF(mInputStream);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetOutputStream(nsIOutputStream** _retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ if (!mOutputStream) {
+ nsresult rv = OpenStreamForWriting();
+ if (NS_FAILED(rv)) return rv;
+ }
+ *_retval = mOutputStream;
+ NS_IF_ADDREF(mOutputStream);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetFileContents(const char* inString)
+//----------------------------------------------------------------------------------------
+{
+ nsresult rv = OpenStreamForWriting();
+ if (NS_FAILED(rv)) return rv;
+ PRInt32 count;
+ rv = Write(inString, PL_strlen(inString), &count);
+ nsresult rv2 = CloseStream();
+ return NS_FAILED(rv) ? rv : rv2;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetFileContents(char** _retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ *_retval = nsnull;
+ nsresult rv = OpenStreamForReading();
+ if (NS_FAILED(rv)) return rv;
+ PRInt32 theSize;
+ rv = GetFileSize((PRUint32*)&theSize);
+ if (NS_SUCCEEDED(rv))
+ rv = Read(_retval, theSize, &theSize);
+ if (NS_SUCCEEDED(rv))
+ (*_retval)[theSize] = 0;
+ nsresult rv2 = CloseStream();
+ return NS_FAILED(rv) ? rv : rv2;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::GetFileSpec(nsFileSpec *aFileSpec)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(aFileSpec)
+ *aFileSpec = mFileSpec;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Equals(nsIFileSpec *spec, PRBool *result)
+//----------------------------------------------------------------------------------------
+{
+ nsresult rv;
+
+ if (!result || !spec) return NS_ERROR_NULL_POINTER;
+
+ nsFileSpec otherSpec;
+
+ rv = spec->GetFileSpec(&otherSpec);
+ if (NS_FAILED(rv)) return rv;
+
+ if (mFileSpec == otherSpec) {
+ *result = PR_TRUE;
+ }
+ else {
+ *result = PR_FALSE;
+ }
+
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::SetFromFileSpec(const nsFileSpec& aFileSpec)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec = aFileSpec;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Eof(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ if (!mInputStream)
+ return NS_ERROR_NULL_POINTER;
+ nsInputFileStream s(mInputStream);
+ *_retval = s.eof();
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Read(char** buffer, PRInt32 requestedCount, PRInt32 *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ TEST_OUT_PTR(buffer)
+ if (!mInputStream) {
+ nsresult rv = OpenStreamForReading();
+ if (NS_FAILED(rv)) return rv;
+ }
+ if (!*buffer)
+ *buffer = (char*)PR_Malloc(requestedCount + 1);
+ if (!mInputStream)
+ return NS_ERROR_NULL_POINTER;
+ nsInputFileStream s(mInputStream);
+ *_retval = s.read(*buffer, requestedCount);
+ return s.error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::ReadLine(char** line, PRInt32 bufferSize, PRBool *wasTruncated)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(wasTruncated)
+ TEST_OUT_PTR(line)
+ if (!mInputStream) {
+ nsresult rv = OpenStreamForReading();
+ if (NS_FAILED(rv)) return rv;
+ }
+ if (!*line)
+ *line = (char*)PR_Malloc(bufferSize + 1);
+ if (!mInputStream)
+ return NS_ERROR_NULL_POINTER;
+ nsInputFileStream s(mInputStream);
+ *wasTruncated = !s.readline(*line, bufferSize);
+ return s.error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Write(const char * data, PRInt32 requestedCount, PRInt32 *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ //if (!mOutputStream)
+ // return NS_ERROR_NULL_POINTER;
+ if (!mOutputStream) {
+ nsresult rv = OpenStreamForWriting();
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ nsOutputFileStream s(mOutputStream);
+ *_retval = s.write(data, requestedCount);
+ return s.error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Flush()
+//----------------------------------------------------------------------------------------
+{
+ if (!mOutputStream)
+ return NS_ERROR_NULL_POINTER;
+ nsOutputFileStream s(mOutputStream);
+ s.flush();
+ return s.error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Seek(PRInt32 offset)
+//----------------------------------------------------------------------------------------
+{
+ nsresult result = NS_OK;
+ if (mOutputStream)
+ {
+ nsOutputFileStream os(mOutputStream);
+ os.seek(offset);
+ result = os.error();
+ }
+ if (NS_SUCCEEDED(result) && mInputStream)
+ {
+ nsInputFileStream is(mInputStream);
+ is.seek(offset);
+ result = is.error();
+ }
+ return result;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Tell(PRInt32 *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ if (!mInputStream)
+ return NS_ERROR_NULL_POINTER;
+ nsInputFileStream s(mInputStream);
+ *_retval = s.tell();
+ return s.error();
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::EndLine()
+//----------------------------------------------------------------------------------------
+{
+ nsOutputFileStream s(mOutputStream);
+ s << nsEndl;
+ return s.error();
+}
+
+NS_IMPL_ISUPPORTS1(nsDirectoryIteratorImpl, nsIDirectoryIterator)
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIteratorImpl::nsDirectoryIteratorImpl()
+//----------------------------------------------------------------------------------------
+ : mDirectoryIterator(nsnull)
+{
+}
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIteratorImpl::~nsDirectoryIteratorImpl()
+//----------------------------------------------------------------------------------------
+{
+ delete mDirectoryIterator;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsDirectoryIteratorImpl::Init(nsIFileSpec *parent, PRBool resolveSymlink)
+//----------------------------------------------------------------------------------------
+{
+ delete mDirectoryIterator;
+ mDirectoryIterator = new nsDirectoryIterator(FILESPEC(parent), resolveSymlink);
+ if (!mDirectoryIterator)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsDirectoryIteratorImpl::Exists(PRBool *_retval)
+//----------------------------------------------------------------------------------------
+{
+ TEST_OUT_PTR(_retval)
+ if (!mDirectoryIterator)
+ return NS_ERROR_NULL_POINTER;
+ *_retval = mDirectoryIterator->Exists();
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsDirectoryIteratorImpl::Next()
+//----------------------------------------------------------------------------------------
+{
+ if (!mDirectoryIterator)
+ return NS_ERROR_NULL_POINTER;
+ (*mDirectoryIterator)++;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsDirectoryIteratorImpl::GetCurrentSpec(nsIFileSpec * *aCurrentSpec)
+//----------------------------------------------------------------------------------------
+{
+ if (!mDirectoryIterator)
+ return NS_ERROR_NULL_POINTER;
+ return nsFileSpecImpl::MakeInterface(mDirectoryIterator->Spec(), aCurrentSpec);
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsDirectoryIteratorImpl::Create(nsISupports* outer, const nsIID& aIID, void* *aIFileSpec)
+//----------------------------------------------------------------------------------------
+{
+ if (aIFileSpec == NULL)
+ return NS_ERROR_NULL_POINTER;
+
+ nsDirectoryIteratorImpl* it = new nsDirectoryIteratorImpl;
+ if (!it)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = it->QueryInterface(aIID, aIFileSpec);
+ if (NS_FAILED(rv))
+ {
+ delete it;
+ return rv;
+ }
+ return rv;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP nsFileSpecImpl::Create(nsISupports* outer, const nsIID& aIID, void* *aIFileSpec)
+//----------------------------------------------------------------------------------------
+{
+ if (aIFileSpec == NULL)
+ return NS_ERROR_NULL_POINTER;
+
+ nsFileSpecImpl* it = new nsFileSpecImpl;
+ if (!it)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ nsresult rv = it->QueryInterface(aIID, aIFileSpec);
+ if (NS_FAILED(rv))
+ {
+ delete it;
+ return rv;
+ }
+ return rv;
+}
+
+//----------------------------------------------------------------------------------------
+nsresult NS_NewFileSpecWithSpec(const nsFileSpec& aSrcFileSpec, nsIFileSpec **result)
+//----------------------------------------------------------------------------------------
+{
+ if (!result)
+ return NS_ERROR_NULL_POINTER;
+
+ return nsFileSpecImpl::MakeInterface(aSrcFileSpec, result);
+}
+
+//----------------------------------------------------------------------------------------
+nsresult NS_NewFileSpec(nsIFileSpec** result)
+//----------------------------------------------------------------------------------------
+{
+ return nsFileSpecImpl::Create(nsnull, NS_GET_IID(nsIFileSpec), (void**)result);
+}
+
+//----------------------------------------------------------------------------------------
+nsresult NS_NewFileSpecFromIFile(nsIFile *aFile, nsIFileSpec **result)
+//----------------------------------------------------------------------------------------
+{
+ nsresult rv = nsFileSpecImpl::Create(nsnull, NS_GET_IID(nsIFileSpec), (void**)result);
+ if (NS_FAILED(rv)) return rv;
+
+ nsCAutoString path;
+ rv = aFile->GetNativePath(path);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = (*result)->SetNativePath(path.get());
+ if (NS_FAILED(rv))
+ NS_RELEASE(*result);
+ return rv;
+}
+
+//----------------------------------------------------------------------------------------
+nsresult NS_NewDirectoryIterator(nsIDirectoryIterator** result)
+//----------------------------------------------------------------------------------------
+{
+ return nsDirectoryIteratorImpl::Create(nsnull, NS_GET_IID(nsIDirectoryIterator), (void**)result);
+}
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecImpl.h b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecImpl.h
new file mode 100644
index 00000000..811749cb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecImpl.h
@@ -0,0 +1,116 @@
+/* -*- 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 _FILESPECIMPL_H_
+#define _FILESPECIMPL_H_
+
+#include "nscore.h"
+#include "nsIFileSpec.h"
+#include "nsFileSpec.h"
+
+//========================================================================================
+class NS_COM_OBSOLETE nsFileSpecImpl
+//========================================================================================
+ : public nsIFileSpec
+{
+
+ public:
+
+ NS_DECL_ISUPPORTS
+
+ NS_DECL_NSIFILESPEC
+
+ //----------------------
+ // COM Cruft
+ //----------------------
+
+ static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aIFileSpec);
+
+ //----------------------
+ // Implementation
+ //----------------------
+
+ nsFileSpecImpl();
+ nsFileSpecImpl(const nsFileSpec& inSpec);
+ static nsresult MakeInterface(const nsFileSpec& inSpec, nsIFileSpec** outSpec);
+
+ //----------------------
+ // Data
+ //----------------------
+
+ nsFileSpec mFileSpec;
+ nsIInputStream* mInputStream;
+ nsIOutputStream* mOutputStream;
+
+private:
+ ~nsFileSpecImpl();
+}; // class nsFileSpecImpl
+
+//========================================================================================
+class NS_COM_OBSOLETE nsDirectoryIteratorImpl
+//========================================================================================
+ : public nsIDirectoryIterator
+{
+
+public:
+
+ nsDirectoryIteratorImpl();
+
+ NS_DECL_ISUPPORTS
+
+ NS_IMETHOD Init(nsIFileSpec *parent, PRBool resolveSymlink);
+
+ NS_IMETHOD Exists(PRBool *_retval);
+
+ NS_IMETHOD Next();
+
+ NS_IMETHOD GetCurrentSpec(nsIFileSpec * *aCurrentSpec);
+
+ //----------------------
+ // COM Cruft
+ //----------------------
+
+ static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aIFileSpec);
+
+private:
+ ~nsDirectoryIteratorImpl();
+
+protected:
+ nsDirectoryIterator* mDirectoryIterator;
+}; // class nsDirectoryIteratorImpl
+
+#endif // _FILESPECIMPL_H_
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecMac.cpp b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecMac.cpp
new file mode 100644
index 00000000..fd208fb7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecMac.cpp
@@ -0,0 +1,1471 @@
+/* -*- 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 file is included by nsFile.cp, and includes the Macintosh-specific
+// implementations.
+
+
+#include <string.h>
+
+#include "prtypes.h"
+#include "nscore.h"
+
+#include "FullPath.h"
+#include "FileCopy.h"
+#include "MoreFilesExtras.h"
+
+#include <Aliases.h>
+#include <Folders.h>
+#include <Math64.h>
+#include <TextUtils.h>
+#include <Processes.h>
+#include <limits.h> // ULONG_MAX
+
+#include "nsFileSpec.h"
+#include "nsEscape.h"
+#include "nsXPIDLString.h"
+
+
+const unsigned char* kAliasHavenFolderName = "\pnsAliasHaven";
+
+//========================================================================================
+namespace MacFileHelpers
+//========================================================================================
+{
+ inline void PLstrcpy(Str255 dst, ConstStr255Param src)
+ {
+ memcpy(dst, src, 1 + src[0]);
+ }
+
+ void PLstrcpy(Str255 dst, const char* src, int inMaxLen=255);
+ void PLstrncpy(Str255 dst, const char* src, int inMaxLen);
+
+ void SwapSlashColon(char * s);
+ OSErr FSSpecFromUnixPath(
+ const char * unixPath,
+ FSSpec& ioSpec,
+ Boolean hexDecode,
+ Boolean resolveAlias,
+ Boolean allowPartial = false,
+ Boolean createDirs = false);
+ char* MacPathFromUnixPath(
+ const char* unixPath,
+ Boolean hexDecode);
+ char* EncodeMacPath(
+ char* inPath, // NOT const - gets clobbered
+ Boolean prependSlash,
+ Boolean doEscape );
+ OSErr FSSpecFromPathname(
+ const char* inPathNamePtr,
+ FSSpec& ioSpec,
+ Boolean inCreateDirs);
+ char* PathNameFromFSSpec(
+ const FSSpec& inSpec );
+ OSErr CreateFolderInFolder(
+ short refNum, // Parent directory/volume
+ long dirID,
+ ConstStr255Param folderName, // Name of the new folder
+ short& outRefNum, // Volume of the created folder
+ long& outDirID); //
+
+ // Some routines to support an "alias haven" directory. Aliases in this directory
+ // are never resolved. There is a ResolveAlias here that respects that. This is
+ // to support attaching of aliases in mail.
+ void EnsureAliasHaven();
+ void SetNoResolve(Boolean inResolve);
+ PRBool IsAliasSafe(const FSSpec& inSpec);
+ OSErr MakeAliasSafe(FSSpec& inOutSpec);
+ OSErr ResolveAliasFile(FSSpec& inOutSpec, Boolean& wasAliased);
+
+ Boolean sNoResolve = false;
+ long sAliasHavenDirID = 0;
+ short sAliasHavenVRefNum = 0;
+} // namespace MacFileHelpers
+
+//----------------------------------------------------------------------------------------
+void MacFileHelpers::PLstrcpy(Str255 dst, const char* src, int inMax)
+//----------------------------------------------------------------------------------------
+{
+ int srcLength = strlen(src);
+ NS_ASSERTION(srcLength <= inMax, "Oops, string is too long!");
+ if (srcLength > inMax)
+ srcLength = inMax;
+ dst[0] = srcLength;
+ memcpy(&dst[1], src, srcLength);
+}
+
+//----------------------------------------------------------------------------------------
+void MacFileHelpers::PLstrncpy(Str255 dst, const char* src, int inMax)
+//----------------------------------------------------------------------------------------
+{
+ int srcLength = strlen(src);
+ if (srcLength > inMax)
+ srcLength = inMax;
+ dst[0] = srcLength;
+ memcpy(&dst[1], src, srcLength);
+}
+
+//-----------------------------------
+void MacFileHelpers::SwapSlashColon(char * s)
+//-----------------------------------
+
+{
+ while (*s)
+ {
+ if (*s == '/')
+ *s++ = ':';
+ else if (*s == ':')
+ *s++ = '/';
+ else
+ *s++;
+ }
+} // MacFileHelpers::SwapSlashColon
+
+//-----------------------------------
+char* MacFileHelpers::EncodeMacPath(
+ char* inPath, // NOT const, gets clobbered
+ Boolean prependSlash,
+ Boolean doEscape )
+// Transforms Macintosh style path into Unix one
+// Method: Swap ':' and '/', hex escape the result
+//-----------------------------------
+{
+ if (inPath == nsnull)
+ return nsnull;
+ int pathSize = strlen(inPath);
+
+ // XP code sometimes chokes if there's a final slash in the unix path.
+ // Since correct mac paths to folders and volumes will end in ':', strip this
+ // first.
+ char* c = inPath + pathSize - 1;
+ if (*c == ':')
+ {
+ *c = 0;
+ pathSize--;
+ }
+
+ char * newPath = nsnull;
+ char * finalPath = nsnull;
+
+ if (prependSlash)
+ {
+ newPath = new char[pathSize + 2];
+ newPath[0] = ':'; // It will be converted to '/'
+ memcpy(&newPath[1], inPath, pathSize + 1);
+ }
+ else
+ {
+ newPath = new char[pathSize + 1];
+ strcpy(newPath, inPath);
+ }
+ if (newPath)
+ {
+ SwapSlashColon( newPath );
+ if (doEscape)
+ {
+ finalPath = nsEscape(newPath, url_Path);
+ delete [] newPath;
+ }
+ else
+ finalPath = newPath;
+ }
+ delete [] inPath;
+ return finalPath;
+} // MacFileHelpers::EncodeMacPath
+
+//----------------------------------------------------------------------------------------
+inline void MacFileHelpers::SetNoResolve(Boolean inResolve)
+//----------------------------------------------------------------------------------------
+{
+ sNoResolve = inResolve;
+} // MacFileHelpers::SetNoResolve
+
+//----------------------------------------------------------------------------------------
+OSErr MacFileHelpers::MakeAliasSafe(FSSpec& inOutSpec)
+// Pass in the spec of an alias. This copies the file to the safe haven folder, and
+// returns the spec of the copy to the caller
+//----------------------------------------------------------------------------------------
+{
+ EnsureAliasHaven();
+ nsFileSpec dstDirSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\p");
+
+ // Make sure its name is unique
+ nsFileSpec havenSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\pG'day");
+ if (havenSpec.Valid())
+ havenSpec.MakeUnique(inOutSpec.name);
+ // Copy the file into the haven directory
+ if (havenSpec.Valid())
+ {
+ OSErr err = ::FSpFileCopy(
+ &inOutSpec,
+ dstDirSpec,
+ havenSpec.GetLeafPName(),
+ nil, 0, true);
+ // Return the spec of the copy to the caller.
+ if (err != noErr)
+ return err;
+ inOutSpec = havenSpec;
+ }
+ return noErr;
+} // MacFileHelpers::MakeAliasSafe
+
+//----------------------------------------------------------------------------------------
+char* MacFileHelpers::MacPathFromUnixPath(const char* unixPath, Boolean hexDecode)
+//----------------------------------------------------------------------------------------
+{
+ // Relying on the fact that the unix path is always longer than the mac path:
+ size_t len = strlen(unixPath);
+ char* result = new char[len + 2]; // ... but allow for the initial colon in a partial name
+ // REMEMBER: at the end we call SwapSlashColon, so bear that in mind when you see
+ // this code using '/' as a separator in what is supposed to be a Macintosh path!
+ if (result)
+ {
+ char* dst = result;
+ const char* src = unixPath;
+ if (*src == '/') // * full path
+ src++;
+ else if (strchr(src, '/') && *src != '.')
+ {
+ // * partial path, and not just a leaf name. The '.' test is there because
+ // the loop below will add sufficient colons in that case.
+ *dst++ = '/';
+ }
+ // Copy src to dst, but watch out for .. and .
+ char c = '/';
+ do
+ {
+ char cprev = c; // remember the previous char (initially /)
+ c = *src++;
+ if (c == '.' && cprev == '/')
+ {
+ char* dstSaved = dst;
+ // Special cases: "." and "..". Convert to ':' and '::'
+ *dst++ = '/'; // . becomes :
+ c = *src++;
+ if (c == '.')
+ {
+ *dst++ = '/'; // .. becomes ::
+ c = *src++;
+ }
+ if (c == '/')
+ {
+ // ../ becomes :: so just skip the slash
+ // ./ becomes : " " " " "
+ src++;
+ }
+ else if (c)
+ {
+ // Oh. A file called ".foo" or "..foo"
+ // Back up and just do the normal thing.
+ src -= (dst - dstSaved);
+ dst = dstSaved;
+ // Since c is not '/', we won't do this stuff on the
+ // next iteration.
+ }
+ continue;
+ }
+ else if (c == '/' && cprev == '/')
+ {
+ // Hmm. A 'run on' path with two slashes right next to each other.
+ // This is an illegal path, but, hey, we'll be tough and try to
+ // deal with it (especially since '::' has loaded semantics in
+ // a Mac path)
+ continue;
+ }
+ *dst++ = c;
+ } while (c);
+ if (hexDecode)
+ nsUnescape(result); // Hex Decode
+ MacFileHelpers::SwapSlashColon(result);
+ }
+ return result;
+} // MacFileHelpers::MacPathFromUnixPath
+
+//----------------------------------------------------------------------------------------
+OSErr MacFileHelpers::FSSpecFromPathname(
+ const char* inPathNamePtr,
+ FSSpec& ioSpec, // used as in-parameter for a relative path.
+ Boolean inCreateDirs)
+// FSSpecFromPathname reverses PathNameFromFSSpec.
+// It returns a FSSpec given a c string which is a mac pathname.
+//----------------------------------------------------------------------------------------
+{
+ OSErr err;
+ // Simplify this routine to use FSMakeFSSpec if length < 255. Otherwise use the MoreFiles
+ // routine FSpLocationFromFullPath, which allocates memory, to handle longer pathnames.
+
+ short inVRefNum = ioSpec.vRefNum;
+ long inParID = ioSpec.parID;
+
+ size_t inLength = strlen(inPathNamePtr);
+ bool isRelative = (strchr(inPathNamePtr, ':') == 0 || *inPathNamePtr == ':');
+#ifdef NS_DEBUG
+ // Attempt to catch people sending unix paths in to routines that expect native ones.
+ NS_ASSERTION(strchr(inPathNamePtr, '/') == 0,
+ "Possible unix path where native path is required");
+#endif
+ if (inLength < 255)
+ {
+ Str255 pascalpath;
+ MacFileHelpers::PLstrcpy(pascalpath, inPathNamePtr);
+ if (isRelative)
+ err = ::FSMakeFSSpec(inVRefNum, inParID, pascalpath, &ioSpec);
+ else
+ err = ::FSMakeFSSpec(0, 0, pascalpath, &ioSpec);
+ }
+ else if (!isRelative)
+ err = FSpLocationFromFullPath(inLength, inPathNamePtr, &ioSpec);
+ else
+ err = bdNamErr;
+
+ if ((err == dirNFErr || err == bdNamErr) && inCreateDirs)
+ {
+ const char* path = inPathNamePtr;
+ if (isRelative)
+ {
+ ioSpec.vRefNum = inVRefNum;
+ ioSpec.parID = inParID;
+ }
+ else
+ {
+ ioSpec.vRefNum = 0;
+ ioSpec.parID = 0;
+ }
+ do {
+ // Locate the colon that terminates the node.
+ // But if we've a partial path (starting with a colon), find the second one.
+ const char* nextColon = strchr(path + (*path == ':'), ':');
+ // Well, if there are no more colons, point to the end of the string.
+ if (!nextColon)
+ nextColon = path + strlen(path);
+
+ // Make a pascal string out of this node. Include initial
+ // and final colon, if any!
+ Str255 ppath;
+ MacFileHelpers::PLstrncpy(ppath, path, nextColon - path + 1);
+
+ // Use this string as a relative path using the directory created
+ // on the previous round (or directory 0,0 on the first round).
+ err = ::FSMakeFSSpec(ioSpec.vRefNum, ioSpec.parID, ppath, &ioSpec);
+
+ // If this was the leaf node, then we are done.
+ if (!*nextColon)
+ break;
+
+ // Since there's more to go, we have to get the directory ID, which becomes
+ // the parID for the next round.
+ if (err == noErr)
+ {
+ // The directory (or perhaps a file) exists. Find its dirID.
+ long dirID;
+ Boolean isDirectory;
+ err = ::FSpGetDirectoryID(&ioSpec, &dirID, &isDirectory);
+ if (!isDirectory)
+ return dupFNErr; // oops! a file exists with that name.
+ if (err)
+ return err;
+ ioSpec.parID = dirID;
+ }
+ else if (err == fnfErr)
+ {
+ // If we got "file not found", then
+ // we need to create a directory.
+ err = ::FSpDirCreate(&ioSpec, smCurrentScript, &ioSpec.parID);
+ // For some reason, this usually returns fnfErr, even though it works.
+ if (err == fnfErr)
+ err = noErr;
+ }
+ if (err != noErr)
+ return err;
+ path = nextColon; // next round
+ } while (1);
+ }
+ return err;
+} // MacFileHelpers::FSSpecFromPathname
+
+//----------------------------------------------------------------------------------------
+OSErr MacFileHelpers::CreateFolderInFolder(
+ short refNum, // Parent directory/volume
+ long dirID,
+ ConstStr255Param folderName, // Name of the new folder
+ short& outRefNum, // Volume of the created folder
+ long& outDirID) //
+// Creates a folder named 'folderName' inside a folder.
+// The errors returned are same as PBDirCreate
+//----------------------------------------------------------------------------------------
+{
+ HFileParam hpb;
+ hpb.ioVRefNum = refNum;
+ hpb.ioDirID = dirID;
+ hpb.ioNamePtr = (StringPtr)&folderName;
+
+ OSErr err = PBDirCreateSync((HParmBlkPtr)&hpb);
+ if (err == noErr)
+ {
+ outRefNum = hpb.ioVRefNum;
+ outDirID = hpb.ioDirID;
+ }
+ else
+ {
+ outRefNum = 0;
+ outDirID = 0;
+ }
+ return err;
+} // MacFileHelpers::CreateFolderInFolder
+
+//----------------------------------------------------------------------------------------
+void MacFileHelpers::EnsureAliasHaven()
+//----------------------------------------------------------------------------------------
+{
+ // Alias Haven is a directory in which we never resolve aliases.
+ if (sAliasHavenVRefNum != 0)
+ return;
+
+
+ FSSpec temp;
+ if (FindFolder(0, kTemporaryFolderType, true, & temp.vRefNum, &temp.parID) == noErr)
+ {
+ CreateFolderInFolder(
+ temp.vRefNum, // Parent directory/volume
+ temp.parID,
+ kAliasHavenFolderName, // Name of the new folder
+ sAliasHavenVRefNum, // Volume of the created folder
+ sAliasHavenDirID);
+ }
+} // MacFileHelpers::EnsureAliasHaven
+
+//----------------------------------------------------------------------------------------
+PRBool MacFileHelpers::IsAliasSafe(const FSSpec& inSpec)
+// Returns true if the alias is in the alias haven directory, or if alias resolution
+// has been turned off.
+//----------------------------------------------------------------------------------------
+{
+ return sNoResolve
+ || (inSpec.parID == sAliasHavenDirID && inSpec.vRefNum == sAliasHavenVRefNum);
+} // MacFileHelpers::IsAliasSafe
+
+//----------------------------------------------------------------------------------------
+OSErr MacFileHelpers::ResolveAliasFile(FSSpec& inOutSpec, Boolean& wasAliased)
+//----------------------------------------------------------------------------------------
+{
+ wasAliased = false;
+ if (IsAliasSafe(inOutSpec))
+ return noErr;
+ Boolean dummy;
+ return ::ResolveAliasFile(&inOutSpec, TRUE, &dummy, &wasAliased);
+} // MacFileHelpers::ResolveAliasFile
+
+//-----------------------------------
+OSErr MacFileHelpers::FSSpecFromUnixPath(
+ const char * unixPath,
+ FSSpec& ioSpec,
+ Boolean hexDecode,
+ Boolean resolveAlias,
+ Boolean allowPartial,
+ Boolean createDirs)
+// File spec from URL. Reverses GetURLFromFileSpec
+// Its input is only the <path> part of the URL
+// JRM 97/01/08 changed this so that if it's a partial path (doesn't start with '/'),
+// then it is combined with inOutSpec's vRefNum and parID to form a new spec.
+//-----------------------------------
+{
+ if (unixPath == nsnull)
+ return badFidErr;
+ char* macPath = MacPathFromUnixPath(unixPath, hexDecode);
+ if (!macPath)
+ return memFullErr;
+
+ OSErr err = noErr;
+ if (!allowPartial)
+ {
+ NS_ASSERTION(*unixPath == '/' /*full path*/, "Not a full Unix path!");
+ }
+ err = FSSpecFromPathname(macPath, ioSpec, createDirs);
+ if (err == fnfErr)
+ err = noErr;
+ Boolean dummy;
+ if (err == noErr && resolveAlias) // Added
+ err = MacFileHelpers::ResolveAliasFile(ioSpec, dummy);
+ delete [] macPath;
+ NS_ASSERTION(err==noErr||err==fnfErr||err==dirNFErr||err==nsvErr, "Not a path!");
+ return err;
+} // MacFileHelpers::FSSpecFromLocalUnixPath
+
+//-----------------------------------
+char* MacFileHelpers::PathNameFromFSSpec( const FSSpec& inSpec )
+// Returns a full pathname to the given file
+// Returned value is allocated with new [], and must be freed with delete []
+// For consistency and to work under OS X this creates an nsILocalFileMac and has it do the work.
+//-----------------------------------
+{
+ char* result = nil;
+ nsresult rv;
+
+ FSSpec nonConstSpec = inSpec;
+ nsCAutoString path;
+ nsCOMPtr<nsILocalFileMac> macFile;
+
+ rv = NS_NewLocalFileWithFSSpec(&nonConstSpec, PR_TRUE, getter_AddRefs(macFile));
+ if (NS_FAILED(rv)) return nsnull;
+ nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(macFile, &rv));
+ if (NS_FAILED(rv)) return nsnull;
+ rv = localFile->GetNativePath(path);
+ if (NS_FAILED(rv)) return nsnull;
+ PRInt32 strLen = path.Length();
+ result = new char [strLen + 1];
+ if (!result) return nsnull;
+ memcpy(result, path.get(), strLen);
+ result[ strLen ] = 0;
+
+ return result;
+} // MacFileHelpers::PathNameFromFSSpec
+
+
+#pragma mark -
+
+//========================================================================================
+// Macintosh nsFileSpec implementation
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec()
+//----------------------------------------------------------------------------------------
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+ Clear();
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const FSSpec& inSpec, PRBool resolveAlias)
+//----------------------------------------------------------------------------------------
+: mSpec(inSpec)
+, mError(NS_OK)
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+ if (resolveAlias)
+ {
+ PRBool dummy;
+ ResolveSymlink(dummy);
+ }
+}
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator = (const FSSpec& inSpec)
+//----------------------------------------------------------------------------------------
+{
+ mSpec = inSpec;
+ mError = NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+: mSpec(inSpec.mSpec)
+, mError(inSpec.Error())
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const char* inNativePathString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+ Clear(); // this sets mError to NS_ERROR_NOT_INITIALIZED
+
+ if (inNativePathString)
+ {
+ mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromPathname(
+ inNativePathString, mSpec, inCreateDirs));
+ if (mError == NS_FILE_RESULT(fnfErr))
+ mError = NS_OK;
+ }
+
+} // nsFileSpec::nsFileSpec
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const nsString& inNativePathString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+ Clear(); // this sets mError to NS_ERROR_NOT_INITIALIZED
+
+ mError = NS_FILE_RESULT(
+ MacFileHelpers::FSSpecFromPathname(
+ NS_LossyConvertUCS2toASCII(inNativePathString).get(),
+ mSpec, inCreateDirs));
+ if (mError == NS_FILE_RESULT(fnfErr))
+ mError = NS_OK;
+
+} // nsFileSpec::nsFileSpec
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(short vRefNum, long parID, ConstStr255Param fileName, PRBool resolveAlias)
+//----------------------------------------------------------------------------------------
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+ mError = NS_FILE_RESULT(::FSMakeFSSpec(vRefNum, parID, fileName, &mSpec));
+ if (mError == NS_FILE_RESULT(fnfErr))
+ mError = NS_OK;
+
+ if (resolveAlias)
+ {
+ PRBool dummy;
+ ResolveSymlink(dummy);
+ }
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const nsFilePath& inPath)
+//----------------------------------------------------------------------------------------
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+ *this = inPath.GetFileSpec();
+}
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator = (const char* inString)
+//----------------------------------------------------------------------------------------
+{
+ Clear(); // this sets mError to NS_ERROR_NOT_INITIALIZED
+
+ if (inString)
+ {
+ mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromPathname(inString, mSpec, true));
+ if (mError == NS_FILE_RESULT(fnfErr))
+ mError = NS_OK;
+ }
+
+} // nsFileSpec::operator =
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator = (const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+{
+ mPath.SetToEmpty();
+ mSpec.vRefNum = inSpec.mSpec.vRefNum;
+ mSpec.parID = inSpec.mSpec.parID;
+
+ PRInt32 copySize = inSpec.mSpec.name[0] + 1;
+ if (copySize > sizeof(inSpec.mSpec.name))
+ copySize = sizeof(inSpec.mSpec.name);
+ memcpy(mSpec.name, inSpec.mSpec.name, copySize);
+ mError = inSpec.Error(); // note that the error is propagated
+} // nsFileSpec::operator =
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator = (const nsFilePath& inPath)
+//----------------------------------------------------------------------------------------
+{
+ *this = inPath.GetFileSpec();
+} // nsFileSpec::operator =
+
+//----------------------------------------------------------------------------------------
+inline void nsFileSpec::Clear()
+//----------------------------------------------------------------------------------------
+{
+ mPath.SetToEmpty();
+ mSpec.vRefNum = 0;
+ mSpec.parID = 0;
+ mSpec.name[0] = 0;
+ mError = NS_ERROR_NOT_INITIALIZED;
+}
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::Exists() const
+//----------------------------------------------------------------------------------------
+{
+ if (NS_FAILED(mError)) return PR_FALSE;
+ FSSpec temp;
+ return ::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, mSpec.name, &temp) == noErr;
+} // nsFileSpec::Exists()
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::GetModDate(TimeStamp& outStamp) const
+//----------------------------------------------------------------------------------------
+{
+ CInfoPBRec pb;
+ if (GetCatInfo(pb) == noErr)
+ outStamp = ((DirInfo*)&pb)->ioDrMdDat; // The mod date is in the same spot for files and dirs.
+ else
+ outStamp = 0;
+} // nsFileSpec::GetModDate
+
+//----------------------------------------------------------------------------------------
+PRUint32 nsFileSpec::GetFileSize() const
+//----------------------------------------------------------------------------------------
+{
+ CInfoPBRec pb;
+ if (noErr == GetCatInfo(pb))
+ return (PRUint32)((HFileInfo*)&pb)->ioFlLgLen;
+ return 0;
+} // nsFileSpec::GetFileSize
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::SetLeafName(const char* inLeafName)
+// In leaf name can actually be a partial path...
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inLeafName, "Attempt to set leaf name with a null string");
+
+ mPath.SetToEmpty();
+
+ if (inLeafName)
+ {
+ // what about long relative paths? Hmm? We don't have a routine for this anywhere.
+ Str255 partialPath;
+ MacFileHelpers::PLstrcpy(partialPath, inLeafName);
+ mError = NS_FILE_RESULT(
+ ::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, partialPath, &mSpec));
+ if (mError == NS_FILE_RESULT(fnfErr))
+ mError = NS_OK;
+ }
+
+} // nsFileSpec::SetLeafName
+
+//----------------------------------------------------------------------------------------
+char* nsFileSpec::GetLeafName() const
+// Result needs to be nsCRT::free()ed.
+//----------------------------------------------------------------------------------------
+{
+ char leaf[sizeof(mSpec.name)];
+ memcpy(leaf, &mSpec.name[1], mSpec.name[0]);
+ leaf[mSpec.name[0]] = '\0';
+ return nsCRT::strdup(leaf);
+} // nsFileSpec::GetLeafName
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::MakeAliasSafe()
+//----------------------------------------------------------------------------------------
+{
+ mPath.SetToEmpty();
+ mError = NS_FILE_RESULT(MacFileHelpers::MakeAliasSafe(mSpec));
+} // nsFileSpec::MakeAliasSafe
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::MakeUnique(ConstStr255Param inSuggestedLeafName)
+//----------------------------------------------------------------------------------------
+{
+ mPath.SetToEmpty();
+ if (inSuggestedLeafName[0] > 0)
+ MacFileHelpers::PLstrcpy(mSpec.name, inSuggestedLeafName);
+
+ MakeUnique();
+} // nsFileSpec::MakeUnique
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsFile() const
+//----------------------------------------------------------------------------------------
+{
+ long dirID;
+ Boolean isDirectory;
+ return (noErr == ::FSpGetDirectoryID(&mSpec, &dirID, &isDirectory) && !isDirectory);
+} // nsFileSpec::IsFile
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsDirectory() const
+//----------------------------------------------------------------------------------------
+{
+ long dirID;
+ Boolean isDirectory;
+ return (noErr == ::FSpGetDirectoryID(&mSpec, &dirID, &isDirectory) && isDirectory);
+} // nsFileSpec::IsDirectory
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsHidden() const
+//----------------------------------------------------------------------------------------
+{
+ CInfoPBRec cInfo;
+ PRBool hidden = PR_FALSE;
+
+ if (noErr == GetCatInfo(cInfo))
+ if (cInfo.hFileInfo.ioFlFndrInfo.fdFlags & kIsInvisible)
+ hidden = PR_TRUE;
+
+ return hidden;
+} // nsFileSpec::IsHidden
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsSymlink() const
+//----------------------------------------------------------------------------------------
+{
+ CInfoPBRec cInfo;
+ PRBool hidden = PR_FALSE;
+
+ if (noErr == GetCatInfo(cInfo))
+ if (cInfo.hFileInfo.ioFlFndrInfo.fdFlags & kIsAlias)
+ hidden = PR_TRUE;
+
+ return hidden;
+} // nsFileSpec::IsSymlink
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::ResolveSymlink(PRBool& wasAliased)
+//----------------------------------------------------------------------------------------
+{
+ Boolean wasAliased2; // Type conversion Boolean <--> PRBool
+ OSErr err = MacFileHelpers::ResolveAliasFile(mSpec, wasAliased2);
+ if (wasAliased2)
+ {
+ mError = NS_FILE_RESULT(err);
+ wasAliased = PR_TRUE;
+ }
+ else
+ wasAliased = PR_FALSE;
+
+ return mError;
+} // nsFileSpec::ResolveSymlink
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::GetParent(nsFileSpec& outSpec) const
+//----------------------------------------------------------------------------------------
+{
+ if (NS_SUCCEEDED(mError))
+ outSpec.mError = NS_FILE_RESULT(::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, nsnull, outSpec));
+} // nsFileSpec::GetParent
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator += (const char* inRelativePath)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inRelativePath, "Attempt to append relative path with null path");
+
+ // Invalidate the path cache string, since we're changing ourselves.
+ mPath.SetToEmpty();
+
+ // if we are already bad, don't allow appendage
+ if (NS_FAILED(Error()))
+ {
+ NS_WARNING("trying to append to a bad nsFileSpec");
+ return;
+ }
+
+ // Find the dirID of the directory described by this spec
+ long dirID;
+ Boolean isDirectory;
+ mError = NS_FILE_RESULT(::FSpGetDirectoryID(&mSpec, &dirID, &isDirectory));
+ if (NS_FAILED(mError) || !isDirectory || !inRelativePath)
+ return;
+ // mSpec.vRefNum is already correct.
+ mSpec.parID = dirID;
+
+ // Next, determine if it is a UNIX or Mac style path. Now, Macintosh relative paths
+ // are either leaf names (in which the distinction between unix and macintosh
+ // relative paths disappears) or they start with a colon. If we find an initial colon,
+ // then assume it's a macintosh path.
+ // If it is a UNIX path (including just a leaf name), we will also look for ':' and
+ // assert if we find one.
+ if (*inRelativePath != ':')
+ {
+ // Looks like a UNIX path (including possibly just a leaf name)
+ NS_ASSERTION(strchr(inRelativePath, ':') == nsnull, "Can not determine path type");
+ // Convert unix path (which is unencoded) to a spec
+ mError = NS_FILE_RESULT(
+ MacFileHelpers::FSSpecFromUnixPath(inRelativePath, mSpec, false, false, true, true));
+ }
+ else
+ {
+ // We must be a mac path!
+ mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromPathname(inRelativePath, mSpec, true));
+ }
+ if (mError == NS_FILE_RESULT(fnfErr))
+ mError = NS_OK;
+
+} // nsFileSpec::operator +=
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::CreateDirectory(int /* unix mode */)
+//----------------------------------------------------------------------------------------
+{
+ long ignoredDirID;
+ OSErr err = ::FSpDirCreate(&mSpec, smCurrentScript, &ignoredDirID);
+ // it's OK if the dir already exists
+ if (err != noErr && IsDirectory())
+ err = noErr;
+
+ mError = NS_FILE_RESULT(err);
+
+} // nsFileSpec::CreateDirectory
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::Delete(PRBool inRecursive) const
+//----------------------------------------------------------------------------------------
+{
+ OSErr anErr;
+
+ nsresult& mutableError = const_cast<nsFileSpec*>(this)->mError;
+ if (inRecursive)
+ {
+ // MoreFilesExtras
+ anErr = ::DeleteDirectory(
+ mSpec.vRefNum,
+ mSpec.parID,
+ const_cast<unsigned char*>(mSpec.name));
+ }
+ else
+ anErr = ::FSpDelete(&mSpec);
+
+ if (anErr == fnfErr) // deleting a file that doesn't exist isn't an error!
+ anErr = noErr;
+
+ mutableError = NS_FILE_RESULT(anErr);
+
+} // nsFileSpec::Delete
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const
+//----------------------------------------------------------------------------------------
+{
+ if (IsDirectory())
+ {
+ if (!(newDir.Exists()))
+ {
+ newDir.CreateDirectory();
+ }
+
+ for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
+ {
+ nsFileSpec& child = (nsFileSpec&)i;
+
+ if (child.IsDirectory())
+ {
+ nsFileSpec tmpDirSpec(newDir);
+
+ char *leafname = child.GetLeafName();
+ tmpDirSpec += leafname;
+ nsCRT::free(leafname);
+
+ child.RecursiveCopy(tmpDirSpec);
+ }
+ else
+ {
+ child.RecursiveCopy(newDir);
+ }
+ }
+ }
+ else
+ {
+ nsFileSpec& filePath = (nsFileSpec&) *this;
+
+ if (!(newDir.Exists()))
+ {
+ newDir.CreateDirectory();
+ }
+
+ filePath.CopyToDir(newDir);
+ }
+} // nsFileSpec::RecursiveCopy
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Truncate(PRInt32 aNewLength) const
+//----------------------------------------------------------------------------------------
+{
+ short refNum;
+ OSErr err;
+
+ // First see if we have an internal error set
+ if (NS_FAILED(mError))
+ return mError;
+
+ // Need to open the file to trunc
+ if (::FSpOpenDF(&mSpec, fsWrPerm, &refNum) != noErr)
+ return NS_FILE_FAILURE;
+
+ err = ::SetEOF(refNum, aNewLength);
+
+ // Close the file unless we got an error that it was already closed
+ if (err != fnOpnErr)
+ (void)::FSClose(refNum);
+
+ if (err != noErr)
+ return NS_FILE_FAILURE;
+
+ return NS_OK;
+} // nsFileSpec::Truncate
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Rename(const char* inNewName)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inNewName, "Attempt to rename with null new name");
+
+ if (strchr(inNewName, '/'))
+ return NS_FILE_FAILURE; // no relative paths here!
+
+ Str255 pName;
+ MacFileHelpers::PLstrcpy(pName, inNewName);
+ if (::FSpRename(&mSpec, pName) != noErr)
+ return NS_FILE_FAILURE;
+ SetLeafName(inNewName);
+ return NS_OK;
+} // nsFileSpec::Rename
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::CopyToDir(const nsFileSpec& newParentDir) const
+//----------------------------------------------------------------------------------------
+{
+ // We can only copy into a directory, and (for now) can not copy entire directories
+
+ if (!newParentDir.IsDirectory() || (IsDirectory() ) )
+ return NS_FILE_FAILURE;
+
+ nsresult rv = NS_FILE_RESULT(::FSpFileCopy(&mSpec,
+ &newParentDir.mSpec,
+ const_cast<StringPtr>(GetLeafPName()),
+ nsnull,
+ 0,
+ true));
+
+ return rv;
+
+} // nsFileSpec::CopyToDir
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::MoveToDir(const nsFileSpec& newParentDir)
+//----------------------------------------------------------------------------------------
+{
+ // We can only move into a directory
+
+ if (!newParentDir.IsDirectory())
+ return NS_FILE_FAILURE;
+
+ nsresult result = NS_FILE_RESULT(::FSpMoveRenameCompat(&mSpec,
+ &newParentDir.mSpec,
+ const_cast<StringPtr>(GetLeafPName())));
+
+ if ( NS_SUCCEEDED(result) )
+ {
+ char* leafName = GetLeafName();
+ *this = newParentDir + leafName;
+ nsCRT::free(leafName);
+ }
+ return result;
+} // nsFileSpec::MoveToDir
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Execute(const char* /*args - how can this be cross-platform? problem! */ ) const
+//----------------------------------------------------------------------------------------
+{
+ if (IsDirectory())
+ return NS_FILE_FAILURE;
+
+ LaunchParamBlockRec launchThis;
+ launchThis.launchAppSpec = const_cast<FSSpec*>(&mSpec);
+ launchThis.launchAppParameters = nsnull; // args;
+ /* launch the thing */
+ launchThis.launchBlockID = extendedBlock;
+ launchThis.launchEPBLength = extendedBlockLen;
+ launchThis.launchFileFlags = nsnull;
+ launchThis.launchControlFlags = launchContinue + launchNoFileFlags + launchUseMinimum;
+ launchThis.launchControlFlags += launchDontSwitch;
+
+ nsresult result = NS_FILE_RESULT(::LaunchApplication(&launchThis));
+ return result;
+
+} // nsFileSpec::Execute
+
+//----------------------------------------------------------------------------------------
+OSErr nsFileSpec::GetCatInfo(CInfoPBRec& outInfo) const
+//----------------------------------------------------------------------------------------
+{
+ DirInfo *dipb=(DirInfo *)&outInfo;
+ dipb->ioCompletion = nsnull;
+ dipb->ioFDirIndex = 0; // use dirID and name
+ dipb->ioVRefNum = mSpec.vRefNum;
+ dipb->ioDrDirID = mSpec.parID;
+ dipb->ioNamePtr = const_cast<nsFileSpec*>(this)->mSpec.name;
+ return PBGetCatInfoSync(&outInfo);
+} // nsFileSpec::GetCatInfo()
+
+//----------------------------------------------------------------------------------------
+OSErr nsFileSpec::SetFileTypeAndCreator(OSType type, OSType creator)
+//----------------------------------------------------------------------------------------
+{
+ FInfo info;
+ OSErr err = ::FSpGetFInfo(&mSpec, &info);
+ if (err != noErr)
+ return err;
+ info.fdType = type;
+ info.fdCreator = creator;
+ err = ::FSpSetFInfo(&mSpec, &info);
+ return err;
+}
+
+//----------------------------------------------------------------------------------------
+OSErr nsFileSpec::GetFileTypeAndCreator(OSType* type, OSType* creator)
+//----------------------------------------------------------------------------------------
+{
+ FInfo info;
+ OSErr err = ::FSpGetFInfo(&mSpec, &info);
+ if (err != noErr)
+ return err;
+ *type = info.fdType;
+ *creator = info.fdCreator;
+ return noErr;
+}
+
+//----------------------------------------------------------------------------------------
+PRInt64 nsFileSpec::GetDiskSpaceAvailable() const
+//----------------------------------------------------------------------------------------
+{
+ PRInt64 space64Bits;
+
+ LL_I2L(space64Bits , LONG_MAX);
+
+ XVolumeParam pb;
+ pb.ioCompletion = nsnull;
+ pb.ioVolIndex = 0;
+ pb.ioNamePtr = nsnull;
+ pb.ioVRefNum = mSpec.vRefNum;
+
+ // PBXGetVolInfoSync works on HFS+ volumes too!
+ OSErr err = ::PBXGetVolInfoSync(&pb);
+
+ if (err == noErr)
+ {
+#ifdef HAVE_LONG_LONG
+ space64Bits = pb.ioVFreeBytes;
+#else
+ const UnsignedWide& freeBytes = UInt64ToUnsignedWide(pb.ioVFreeBytes);
+ space64Bits.lo = freeBytes.lo;
+ space64Bits.hi = freeBytes.hi;
+#endif
+ }
+
+ return space64Bits;
+} // nsFileSpec::GetDiskSpace()
+
+//----------------------------------------------------------------------------------------
+const char* nsFileSpec::GetCString() const
+// This is the only conversion to const char* that is provided, and it allows the
+// path to be "passed" to NSPR file routines. This practice is VERY EVIL and should only
+// be used to support legacy code. Using it guarantees bugs on Macintosh. The string is
+// cached and freed by the nsFileSpec destructor, so do not delete (or free) it.
+//----------------------------------------------------------------------------------------
+{
+ if (mPath.IsEmpty())
+ {
+ char* path = MacFileHelpers::PathNameFromFSSpec(mSpec);
+ if (path != NULL) {
+ const_cast<nsFileSpec*>(this)->mPath = path; // operator =() copies the string!!!
+ delete[] path;
+ } else {
+ const_cast<nsFileSpec*>(this)->mError = NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ return mPath;
+}
+
+#pragma mark -
+
+//========================================================================================
+// Macintosh nsFilePath implementation
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+static void AssignFromPath(nsFilePath& ioPath, const char* inString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inString, "AssignFromPath called with null inString");
+ NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path");
+
+ FSSpec spec;
+ spec.vRefNum = 0;
+ spec.parID = 0;
+ spec.name[0] = 0;
+ MacFileHelpers::FSSpecFromUnixPath(
+ inString,
+ spec,
+ false,
+ true, // resolve alias
+ true,
+ inCreateDirs);
+ // Now we have a spec,
+ // Invoke operator = (const nsFileSpec&) to do the rest.
+ // Why didn't we just say mPath = inString to get the path? Well, we want it to be
+ // canonical and absolute.
+ ioPath = spec;
+}
+
+//----------------------------------------------------------------------------------------
+nsFilePath::nsFilePath(const char* inString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+{
+ AssignFromPath(*this, inString, inCreateDirs);
+} //nsFilePath::nsFilePath
+
+//----------------------------------------------------------------------------------------
+nsFilePath::nsFilePath(const nsString& inString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+{
+ AssignFromPath(*this, NS_LossyConvertUCS2toASCII(inString).get(),
+ inCreateDirs);
+}
+
+//----------------------------------------------------------------------------------------
+void nsFilePath::operator = (const char* inString)
+//----------------------------------------------------------------------------------------
+{
+ AssignFromPath(*this, inString, PR_FALSE);
+}
+
+//----------------------------------------------------------------------------------------
+nsFilePath::nsFilePath(const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+{
+ *this = inSpec;
+}
+
+//----------------------------------------------------------------------------------------
+nsFilePath::nsFilePath(const nsFileURL& inOther)
+//----------------------------------------------------------------------------------------
+{
+ *this = inOther;
+}
+
+//----------------------------------------------------------------------------------------
+void nsFilePath::operator = (const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+{
+ char * path = MacFileHelpers::PathNameFromFSSpec(inSpec);
+ path = MacFileHelpers::EncodeMacPath(path, true, false);
+ mPath = path;
+ nsCRT::free(path);
+ mFileSpec = inSpec;
+} // nsFilePath::operator =
+
+//----------------------------------------------------------------------------------------
+void nsFilePath::operator = (const nsFileURL& inOther)
+//----------------------------------------------------------------------------------------
+{
+ char * path = MacFileHelpers::PathNameFromFSSpec(inOther.mFileSpec);
+ path = MacFileHelpers::EncodeMacPath(path, true, false);
+ mPath = path;
+ nsCRT::free(path);
+ mFileSpec = inOther.GetFileSpec();
+}
+
+#pragma mark -
+
+//========================================================================================
+// nsFileURL implementation
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsFileURL::nsFileURL(const char* inString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+: mURL(inString)
+{
+ NS_ASSERTION(inString, "nsFileURL constructed with null inString");
+ NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
+ mFileSpec.mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromUnixPath(
+ inString + kFileURLPrefixLength,
+ mFileSpec.mSpec,
+ true, // need to decode
+ false, // resolve alias
+ false, // must be a full path
+ inCreateDirs));
+ if (mFileSpec.mError == NS_FILE_RESULT(fnfErr))
+ mFileSpec.mError = NS_OK;
+} // nsFileURL::nsFileURL
+
+//----------------------------------------------------------------------------------------
+nsFileURL::nsFileURL(const nsString& inString, PRBool inCreateDirs)
+//----------------------------------------------------------------------------------------
+: mURL(nsnull)
+{
+ NS_LossyConvertUCS2toASCII cstring(inString);
+ mURL = cstring.get();
+ NS_ASSERTION(strstr(cstring.get(), kFileURLPrefix) == cstring.get(),
+ "Not a URL!");
+ mFileSpec.mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromUnixPath(
+ cstring.get() + kFileURLPrefixLength,
+ mFileSpec.mSpec,
+ true, // need to decode
+ false, // resolve alias
+ false, // must be a full path
+ inCreateDirs));
+ if (mFileSpec.mError == NS_FILE_RESULT(fnfErr))
+ mFileSpec.mError = NS_OK;
+} // nsFileURL::nsFileURL
+
+//----------------------------------------------------------------------------------------
+nsFileURL::nsFileURL(const nsFilePath& inOther)
+//----------------------------------------------------------------------------------------
+{
+ *this = inOther.GetFileSpec();
+} // nsFileURL::nsFileURL
+
+//----------------------------------------------------------------------------------------
+nsFileURL::nsFileURL(const nsFileSpec& inOther)
+//----------------------------------------------------------------------------------------
+{
+ *this = inOther;
+} // nsFileURL::nsFileURL
+
+//----------------------------------------------------------------------------------------
+void nsFileURL::operator = (const nsFilePath& inOther)
+//----------------------------------------------------------------------------------------
+{
+ *this = inOther.GetFileSpec();
+} // nsFileURL::operator =
+
+//----------------------------------------------------------------------------------------
+void nsFileURL::operator = (const nsFileSpec& inOther)
+//----------------------------------------------------------------------------------------
+{
+ mFileSpec = inOther;
+ char* path = MacFileHelpers::PathNameFromFSSpec( mFileSpec );
+ char* encodedPath = MacFileHelpers::EncodeMacPath(path, true, true);
+ nsSimpleCharString encodedURL(kFileURLPrefix);
+ encodedURL += encodedPath;
+ nsCRT::free(encodedPath);
+ mURL = encodedURL;
+ if (encodedURL[encodedURL.Length() - 1] != '/' && inOther.IsDirectory())
+ mURL += "/";
+} // nsFileURL::operator =
+
+//----------------------------------------------------------------------------------------
+void nsFileURL::operator = (const char* inString)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inString, "nsFileURL operator= constructed with null inString");
+
+ mURL = inString;
+ NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
+ mFileSpec.mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromUnixPath(
+ inString + kFileURLPrefixLength,
+ mFileSpec.mSpec,
+ true, // need to decode
+ true, // resolve alias
+ false, // must be a full path
+ false)); // don't create dirs.
+ if (mFileSpec.mError == NS_FILE_RESULT(fnfErr))
+ mFileSpec.mError = NS_OK;
+} // nsFileURL::operator =
+
+#pragma mark -
+
+//========================================================================================
+// nsDirectoryIterator
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator::nsDirectoryIterator(
+ const nsFileSpec& inDirectory
+, PRBool resolveSymLinks)
+//----------------------------------------------------------------------------------------
+ : mCurrent(inDirectory)
+ , mExists(false)
+ , mResoveSymLinks(resolveSymLinks)
+ , mIndex(-1)
+{
+ CInfoPBRec pb;
+ OSErr err = inDirectory.GetCatInfo(pb);
+
+ // test that we have got a directory back, not a file
+ DirInfo* dipb = (DirInfo*)&pb;
+ if (err != noErr || !( dipb->ioFlAttrib & 0x0010))
+ return;
+ // Sorry about this, there seems to be a bug in CWPro 4:
+ FSSpec& currentSpec = mCurrent.nsFileSpec::operator FSSpec&();
+ mVRefNum = currentSpec.vRefNum;
+ mParID = dipb->ioDrDirID;
+ mMaxIndex = pb.dirInfo.ioDrNmFls;
+ mIndex = 0; // ready to increment
+ ++(*this); // the pre-increment operator
+
+} // nsDirectoryIterator::nsDirectoryIterator
+
+//----------------------------------------------------------------------------------------
+OSErr nsDirectoryIterator::SetToIndex()
+//----------------------------------------------------------------------------------------
+{
+ CInfoPBRec cipb;
+ DirInfo *dipb=(DirInfo *)&cipb;
+ Str255 objectName;
+ dipb->ioCompletion = nsnull;
+ dipb->ioFDirIndex = mIndex;
+ // Sorry about this, there seems to be a bug in CWPro 4:
+ FSSpec& currentSpec = mCurrent.nsFileSpec::operator FSSpec&();
+ dipb->ioVRefNum = mVRefNum; /* Might need to use vRefNum, not sure*/
+ dipb->ioDrDirID = mParID;
+ dipb->ioNamePtr = objectName;
+ OSErr err = PBGetCatInfoSync(&cipb);
+ FSSpec temp;
+ if (err == noErr)
+ err = FSMakeFSSpec(mVRefNum, mParID, objectName, &temp);
+ mCurrent = temp; // use the operator: it clears the string cache.
+ mExists = err == noErr;
+
+ if (mExists && mResoveSymLinks)
+ {
+ PRBool ignore;
+ mCurrent.ResolveSymlink(ignore);
+ }
+ return err;
+} // nsDirectoryIterator::SetToIndex()
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator& nsDirectoryIterator::operator -- ()
+//----------------------------------------------------------------------------------------
+{
+ mExists = false;
+ while (--mIndex > 0)
+ {
+ OSErr err = SetToIndex();
+ if (err == noErr)
+ break;
+ }
+ return *this;
+} // nsDirectoryIterator::operator --
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator& nsDirectoryIterator::operator ++ ()
+//----------------------------------------------------------------------------------------
+{
+ mExists = false;
+ if (mIndex >= 0) // probably trying to use a file as a directory!
+ while (++mIndex <= mMaxIndex)
+ {
+ OSErr err = SetToIndex();
+ if (err == noErr)
+ break;
+ }
+ return *this;
+} // nsDirectoryIterator::operator ++
+
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecOS2.cpp b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecOS2.cpp
new file mode 100644
index 00000000..4621d8b8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecOS2.cpp
@@ -0,0 +1,840 @@
+/* ***** 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 the Mozilla OS/2 libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * John Fairhurst, <john_fairhurst@iname.com>.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Henry Sobotka <sobotka@axess.com>
+ * 00/01/06: general review and update against Win/Unix versions;
+ * replaced nsFileSpec::Execute implementation with system() call
+ *
+ * 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
+ * 03/23/2000 IBM Corp. Fixed bug where 2 char or less profile names treated as drive letters.
+ * 06/20/2000 IBM Corp. Make it more like Windows version.
+ */
+
+#define INCL_DOSERRORS
+#define INCL_DOS
+#define INCL_WINWORKPLACE
+#include <os2.h>
+
+#ifdef XP_OS2_VACPP
+#include <direct.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <ctype.h>
+#include <io.h>
+
+//----------------------------------------------------------------------------------------
+void nsFileSpecHelpers::Canonify(nsSimpleCharString& ioPath, PRBool inMakeDirs)
+// Canonify, make absolute, and check whether directories exist. This
+// takes a (possibly relative) native path and converts it into a
+// fully qualified native path.
+//----------------------------------------------------------------------------------------
+{
+ if (ioPath.IsEmpty())
+ return;
+
+ NS_ASSERTION(strchr((const char*)ioPath, '/') == 0,
+ "This smells like a Unix path. Native path expected! "
+ "Please fix.");
+ if (inMakeDirs)
+ {
+ const int mode = 0700;
+ nsSimpleCharString unixStylePath = ioPath;
+ nsFileSpecHelpers::NativeToUnix(unixStylePath);
+ nsFileSpecHelpers::MakeAllDirectories((const char*)unixStylePath, mode);
+ }
+ char buffer[_MAX_PATH];
+ errno = 0;
+ *buffer = '\0';
+#ifdef XP_OS2
+ PRBool removedBackslash = PR_FALSE;
+ PRUint32 lenstr = ioPath.Length();
+ char &lastchar = ioPath[lenstr -1];
+
+ // Strip off any trailing backslash UNLESS it's the backslash that
+ // comes after "X:". Note also that "\" is valid. Sheesh.
+ //
+ if( lastchar == '\\' && (lenstr != 3 || ioPath[1] != ':') && lenstr != 1)
+ {
+ lastchar = '\0';
+ removedBackslash = PR_TRUE;
+ }
+
+ char canonicalPath[CCHMAXPATH] = "";
+
+ DosQueryPathInfo( (char*) ioPath,
+ FIL_QUERYFULLNAME,
+ canonicalPath,
+ CCHMAXPATH);
+#else
+ char* canonicalPath = _fullpath(buffer, ioPath, _MAX_PATH);
+#endif
+
+ if (canonicalPath)
+ {
+ NS_ASSERTION( canonicalPath[0] != '\0', "Uh oh...couldn't convert" );
+ if (canonicalPath[0] == '\0')
+ return;
+#ifdef XP_OS2
+ // If we removed that backslash, add it back onto the fullpath
+ if (removedBackslash)
+ strcat( canonicalPath, "\\");
+#endif
+ }
+ ioPath = canonicalPath;
+} // nsFileSpecHelpers::Canonify
+
+//----------------------------------------------------------------------------------------
+void nsFileSpecHelpers::UnixToNative(nsSimpleCharString& ioPath)
+// This just does string manipulation. It doesn't check reality, or canonify, or
+// anything
+//----------------------------------------------------------------------------------------
+{
+ // Allow for relative or absolute. We can do this in place, because the
+ // native path is never longer.
+
+ if (ioPath.IsEmpty())
+ return;
+
+ // Strip initial slash for an absolute path
+ char* src = (char*)ioPath;
+ if (*src == '/') {
+ if (!src[1]) {
+ // allocate new string by copying from ioPath[1]
+ nsSimpleCharString temp = src + 1;
+ ioPath = temp;
+ return;
+ }
+ // Since it was an absolute path, check for the drive letter
+ char* colonPointer = src + 2;
+ if (strstr(src, "|/") == colonPointer)
+ *colonPointer = ':';
+ // allocate new string by copying from ioPath[1]
+ nsSimpleCharString temp = src + 1;
+ ioPath = temp;
+ }
+
+ src = (char*)ioPath;
+
+ if (*src) {
+ // Convert '/' to '\'.
+ while (*++src)
+ {
+ if (*src == '/')
+ *src = '\\';
+ }
+ }
+} // nsFileSpecHelpers::UnixToNative
+
+//----------------------------------------------------------------------------------------
+void nsFileSpecHelpers::NativeToUnix(nsSimpleCharString& ioPath)
+// This just does string manipulation. It doesn't check reality, or canonify, or
+// anything. The unix path is longer, so we can't do it in place.
+//----------------------------------------------------------------------------------------
+{
+ if (ioPath.IsEmpty())
+ return;
+
+ // Convert the drive-letter separator, if present
+ nsSimpleCharString temp("/");
+
+ char* cp = (char*)ioPath + 1;
+ if (strstr(cp, ":\\") == cp)
+ *cp = '|'; // absolute path
+ else
+ temp[0] = '\0'; // relative path
+
+ // Convert '\' to '/'
+ for (; *cp; cp++)
+ {
+#ifdef XP_OS2
+ // OS2TODO - implement equivalent of IsDBCSLeadByte
+#else
+ if(IsDBCSLeadByte(*cp) && *(cp+1) != nsnull)
+ {
+ cp++;
+ continue;
+ }
+#endif
+ if (*cp == '\\')
+ *cp = '/';
+ }
+ // Add the slash in front.
+ temp += ioPath;
+ ioPath = temp;
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const nsFilePath& inPath)
+//----------------------------------------------------------------------------------------
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+ *this = inPath;
+}
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator = (const nsFilePath& inPath)
+//----------------------------------------------------------------------------------------
+{
+ mPath = (const char*)inPath;
+ nsFileSpecHelpers::UnixToNative(mPath);
+ mError = NS_OK;
+} // nsFileSpec::operator =
+
+//----------------------------------------------------------------------------------------
+nsFilePath::nsFilePath(const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+{
+ *this = inSpec;
+} // nsFilePath::nsFilePath
+
+//----------------------------------------------------------------------------------------
+void nsFilePath::operator = (const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+{
+ mPath = inSpec.mPath;
+ nsFileSpecHelpers::NativeToUnix(mPath);
+} // nsFilePath::operator =
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::SetLeafName(const char* inLeafName)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inLeafName, "Attempt to SetLeafName with a null string");
+ mPath.LeafReplace('\\', inLeafName);
+} // nsFileSpec::SetLeafName
+
+//----------------------------------------------------------------------------------------
+char* nsFileSpec::GetLeafName() const
+//----------------------------------------------------------------------------------------
+{
+ return mPath.GetLeaf('\\');
+} // nsFileSpec::GetLeafName
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::Exists() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st);
+} // nsFileSpec::Exists
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::GetModDate(TimeStamp& outStamp) const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ if (!mPath.IsEmpty() && stat(nsNSPRPath(*this), &st) == 0)
+ outStamp = st.st_mtime;
+ else
+ outStamp = 0;
+} // nsFileSpec::GetModDate
+
+//----------------------------------------------------------------------------------------
+PRUint32 nsFileSpec::GetFileSize() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ if (!mPath.IsEmpty() && stat(nsNSPRPath(*this), &st) == 0)
+ return (PRUint32)st.st_size;
+ return 0;
+} // nsFileSpec::GetFileSize
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsFile() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+#ifdef XP_OS2
+ return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && ( S_IFREG & st.st_mode);
+#else
+ return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && (_S_IFREG & st.st_mode);
+#endif
+} // nsFileSpec::IsFile
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsDirectory() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+#ifdef XP_OS2
+ return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && ( S_IFDIR & st.st_mode);
+#else
+ return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && (_S_IFDIR & st.st_mode);
+#endif
+} // nsFileSpec::IsDirectory
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsHidden() const
+//----------------------------------------------------------------------------------------
+{
+ PRBool hidden = PR_FALSE;
+ if (!mPath.IsEmpty())
+ {
+#ifdef XP_OS2
+ FILESTATUS3 fs3;
+ APIRET rc;
+
+ rc = DosQueryPathInfo( mPath,
+ FIL_STANDARD,
+ &fs3,
+ sizeof fs3);
+ if(!rc)
+ hidden = fs3.attrFile & FILE_HIDDEN ? PR_TRUE : PR_FALSE;
+#else
+ DWORD attr = GetFileAttributes(mPath);
+ if (FILE_ATTRIBUTE_HIDDEN & attr)
+ hidden = PR_TRUE;
+#endif
+ }
+ return hidden;
+}
+// nsFileSpec::IsHidden
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsSymlink() const
+//----------------------------------------------------------------------------------------
+{
+#ifdef XP_OS2
+ return PR_FALSE; // No symlinks on OS/2
+#else
+ HRESULT hres;
+ IShellLink* psl;
+
+ PRBool isSymlink = PR_FALSE;
+
+ CoInitialize(NULL);
+ // Get a pointer to the IShellLink interface.
+ hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl);
+ if (SUCCEEDED(hres))
+ {
+ IPersistFile* ppf;
+
+ // Get a pointer to the IPersistFile interface.
+ hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
+
+ if (SUCCEEDED(hres))
+ {
+ WORD wsz[MAX_PATH];
+ // Ensure that the string is Unicode.
+ MultiByteToWideChar(CP_ACP, 0, mPath, -1, wsz, MAX_PATH);
+
+ // Load the shortcut.
+ hres = ppf->Load(wsz, STGM_READ);
+ if (SUCCEEDED(hres))
+ {
+ isSymlink = PR_TRUE;
+ }
+
+ // Release the pointer to the IPersistFile interface.
+ ppf->Release();
+ }
+
+ // Release the pointer to the IShellLink interface.
+ psl->Release();
+ }
+
+ CoUninitialize();
+
+ return isSymlink;
+#endif
+}
+
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::ResolveSymlink(PRBool& wasSymlink)
+//----------------------------------------------------------------------------------------
+{
+#ifdef XP_OS2
+ return NS_OK; // no symlinks on OS/2
+#else
+ wasSymlink = PR_FALSE; // assume failure
+
+ if (Exists())
+ return NS_OK;
+
+
+ HRESULT hres;
+ IShellLink* psl;
+
+ CoInitialize(NULL);
+
+ // Get a pointer to the IShellLink interface.
+ hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl);
+ if (SUCCEEDED(hres))
+ {
+ IPersistFile* ppf;
+
+ // Get a pointer to the IPersistFile interface.
+ hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
+
+ if (SUCCEEDED(hres))
+ {
+ WORD wsz[MAX_PATH];
+ // Ensure that the string is Unicode.
+ MultiByteToWideChar(CP_ACP, 0, mPath, -1, wsz, MAX_PATH);
+
+ // Load the shortcut.
+ hres = ppf->Load(wsz, STGM_READ);
+ if (SUCCEEDED(hres))
+ {
+ wasSymlink = PR_TRUE;
+
+ // Resolve the link.
+ hres = psl->Resolve(nsnull, SLR_NO_UI );
+ if (SUCCEEDED(hres))
+ {
+ char szGotPath[MAX_PATH];
+ WIN32_FIND_DATA wfd;
+
+ // Get the path to the link target.
+ hres = psl->GetPath( szGotPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY );
+
+ if (SUCCEEDED(hres))
+ {
+ // Here we modify the nsFileSpec;
+ mPath = szGotPath;
+ mError = NS_OK;
+ }
+ }
+ }
+ else {
+ // It wasn't a shortcut. Oh well. Leave it like it was.
+ hres = 0;
+ }
+
+ // Release the pointer to the IPersistFile interface.
+ ppf->Release();
+ }
+ // Release the pointer to the IShellLink interface.
+ psl->Release();
+ }
+
+ CoUninitialize();
+
+ if (SUCCEEDED(hres))
+ return NS_OK;
+
+ return NS_FILE_FAILURE;
+#endif
+}
+
+
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::GetParent(nsFileSpec& outSpec) const
+//----------------------------------------------------------------------------------------
+{
+ outSpec.mPath = mPath;
+ char* chars = (char*)outSpec.mPath;
+ chars[outSpec.mPath.Length() - 1] = '\0'; // avoid trailing separator, if any
+ char* cp = strrchr(chars, '\\');
+ if (cp++)
+ outSpec.mPath.SetLength(cp - chars); // truncate.
+} // nsFileSpec::GetParent
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator += (const char* inRelativePath)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inRelativePath, "Attempt to do += with a null string");
+
+ if (!inRelativePath || mPath.IsEmpty())
+ return;
+
+ if (mPath[mPath.Length() - 1] == '\\')
+ mPath += "x";
+ else
+ mPath += "\\x";
+
+ // If it's a (unix) relative path, make it native
+ nsSimpleCharString dosPath = inRelativePath;
+ nsFileSpecHelpers::UnixToNative(dosPath);
+ SetLeafName(dosPath);
+} // nsFileSpec::operator +=
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::CreateDirectory(int /*mode*/)
+//----------------------------------------------------------------------------------------
+{
+ // Note that mPath is canonical!
+ if (!mPath.IsEmpty())
+#ifdef XP_OS2
+ // OS2TODO - vacpp complains about mkdir but PR_MkDir should be ok?
+ PR_MkDir(nsNSPRPath(*this), PR_CREATE_FILE);
+#else
+ mkdir(nsNSPRPath(*this));
+#endif
+} // nsFileSpec::CreateDirectory
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::Delete(PRBool inRecursive) const
+//----------------------------------------------------------------------------------------
+{
+ if (IsDirectory())
+ {
+ if (inRecursive)
+ {
+ for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
+ {
+ nsFileSpec& child = i.Spec();
+ child.Delete(inRecursive);
+ }
+ }
+#ifdef XP_OS2
+ // OS2TODO - vacpp complains if use rmdir but PR_RmDir should be ok?
+ PR_RmDir(nsNSPRPath(*this));
+#else
+ rmdir(nsNSPRPath(*this));
+#endif
+ }
+ else if (!mPath.IsEmpty())
+ {
+ remove(nsNSPRPath(*this));
+ }
+} // nsFileSpec::Delete
+
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const
+//----------------------------------------------------------------------------------------
+{
+ if (IsDirectory())
+ {
+ if (!(newDir.Exists()))
+ {
+ newDir.CreateDirectory();
+ }
+
+ for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
+ {
+ nsFileSpec& child = i.Spec();
+
+ if (child.IsDirectory())
+ {
+ nsFileSpec tmpDirSpec(newDir);
+
+ char *leafname = child.GetLeafName();
+ tmpDirSpec += leafname;
+ nsCRT::free(leafname);
+
+ child.RecursiveCopy(tmpDirSpec);
+ }
+ else
+ {
+ child.RecursiveCopy(newDir);
+ }
+ }
+ }
+ else if (!mPath.IsEmpty())
+ {
+ nsFileSpec& filePath = (nsFileSpec&) *this;
+
+ if (!(newDir.Exists()))
+ {
+ newDir.CreateDirectory();
+ }
+
+ filePath.CopyToDir(newDir);
+ }
+} // nsFileSpec::RecursiveCopy
+
+//----------------------------------------------------------------------------------------
+nsresult
+nsFileSpec::Truncate(PRInt32 aNewFileLength) const
+//----------------------------------------------------------------------------------------
+{
+#ifdef XP_OS2
+ APIRET rc;
+ HFILE hFile;
+ ULONG actionTaken;
+
+ rc = DosOpen(mPath,
+ &hFile,
+ &actionTaken,
+ 0,
+ FILE_NORMAL,
+ OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
+ OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE,
+ NULL);
+
+ if (rc != NO_ERROR)
+ return NS_FILE_FAILURE;
+
+ rc = DosSetFileSize(hFile, aNewFileLength);
+
+ if (rc == NO_ERROR)
+ DosClose(hFile);
+ else
+ goto error;
+#else
+ DWORD status;
+ HANDLE hFile;
+
+ // Leave it to Microsoft to open an existing file with a function
+ // named "CreateFile".
+ hFile = CreateFile(mPath,
+ GENERIC_WRITE,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ return NS_FILE_FAILURE;
+
+ // Seek to new, desired end of file
+ status = SetFilePointer(hFile, aNewFileLength, NULL, FILE_BEGIN);
+ if (status == 0xffffffff)
+ goto error;
+
+ // Truncate file at current cursor position
+ if (!SetEndOfFile(hFile))
+ goto error;
+
+ if (!CloseHandle(hFile))
+ return NS_FILE_FAILURE;
+#endif
+
+ return NS_OK;
+
+ error:
+#ifdef XP_OS2
+ DosClose(hFile);
+#else
+ CloseHandle(hFile);
+#endif
+ return NS_FILE_FAILURE;
+
+} // nsFileSpec::Truncate
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Rename(const char* inNewName)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inNewName, "Attempt to Rename with a null string");
+
+ // This function should not be used to move a file on disk.
+ if (strchr(inNewName, '/'))
+ return NS_FILE_FAILURE;
+
+ char* oldPath = nsCRT::strdup(mPath);
+
+ SetLeafName(inNewName);
+
+ if (PR_Rename(oldPath, mPath) != NS_OK)
+ {
+ // Could not rename, set back to the original.
+ mPath = oldPath;
+ return NS_FILE_FAILURE;
+ }
+
+ nsCRT::free(oldPath);
+
+ return NS_OK;
+} // nsFileSpec::Rename
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::CopyToDir(const nsFileSpec& inParentDirectory) const
+//----------------------------------------------------------------------------------------
+{
+ // We can only copy into a directory, and (for now) can not copy entire directories
+ if (inParentDirectory.IsDirectory() && (! IsDirectory() ) )
+ {
+ char *leafname = GetLeafName();
+ nsSimpleCharString destPath(inParentDirectory.GetCString());
+ destPath += "\\";
+ destPath += leafname;
+ nsCRT::free(leafname);
+
+ // CopyFile returns non-zero if succeeds
+#ifdef XP_OS2
+ APIRET rc;
+ PRBool copyOK;
+
+ rc = DosCopy(GetCString(), (PSZ)destPath, DCPY_EXISTING);
+
+ if (rc == NO_ERROR)
+ copyOK = PR_TRUE;
+ else
+ copyOK = PR_FALSE;
+#else
+ int copyOK = CopyFile(GetCString(), destPath, PR_TRUE);
+#endif
+ if (copyOK)
+ return NS_OK;
+ }
+ return NS_FILE_FAILURE;
+} // nsFileSpec::CopyToDir
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::MoveToDir(const nsFileSpec& inNewParentDirectory)
+//----------------------------------------------------------------------------------------
+{
+ // We can only copy into a directory, and (for now) can not copy entire directories
+ if (inNewParentDirectory.IsDirectory() && (! IsDirectory() ) )
+ {
+ char *leafname = GetLeafName();
+ nsSimpleCharString destPath(inNewParentDirectory.GetCString());
+ destPath += "\\";
+ destPath += leafname;
+ nsCRT::free(leafname);
+
+ if (DosMove(GetCString(), destPath) == NO_ERROR)
+ {
+ *this = inNewParentDirectory + GetLeafName();
+ return NS_OK;
+ }
+
+ }
+ return NS_FILE_FAILURE;
+} // nsFileSpec::MoveToDir
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Execute(const char* inArgs ) const
+//----------------------------------------------------------------------------------------
+{
+ if (!IsDirectory())
+ {
+#ifdef XP_OS2
+ nsresult result = NS_FILE_FAILURE;
+
+ if (!mPath.IsEmpty())
+ {
+ nsSimpleCharString fileNameWithArgs = mPath + " " + inArgs;
+ result = NS_FILE_RESULT(system(fileNameWithArgs));
+ }
+ return result;
+#else
+ nsSimpleCharString fileNameWithArgs = "\"";
+ fileNameWithArgs += mPath + "\" " + inArgs;
+ int execResult = WinExec( fileNameWithArgs, SW_NORMAL );
+ if (execResult > 31)
+ return NS_OK;
+#endif
+ }
+ return NS_FILE_FAILURE;
+} // nsFileSpec::Execute
+
+
+//----------------------------------------------------------------------------------------
+PRInt64 nsFileSpec::GetDiskSpaceAvailable() const
+//----------------------------------------------------------------------------------------
+{
+ PRInt64 nBytes = 0;
+ ULONG ulDriveNo = toupper(mPath[0]) + 1 - 'A';
+ FSALLOCATE fsAllocate;
+ APIRET rc = DosQueryFSInfo(ulDriveNo,
+ FSIL_ALLOC,
+ &fsAllocate,
+ sizeof(fsAllocate));
+
+ if (rc == NO_ERROR) {
+ nBytes = fsAllocate.cUnitAvail;
+ nBytes *= fsAllocate.cSectorUnit;
+ nBytes *= fsAllocate.cbSector;
+ }
+
+ return nBytes;
+}
+
+
+
+//========================================================================================
+// nsDirectoryIterator
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator::nsDirectoryIterator(const nsFileSpec& inDirectory, PRBool resolveSymlink)
+//----------------------------------------------------------------------------------------
+ : mCurrent(inDirectory)
+ , mDir(nsnull)
+ , mStarting(inDirectory)
+ , mExists(PR_FALSE)
+ , mResoveSymLinks(resolveSymlink)
+{
+ mDir = PR_OpenDir(inDirectory);
+ mCurrent += "dummy";
+ mStarting += "dummy";
+ ++(*this);
+} // nsDirectoryIterator::nsDirectoryIterator
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator::~nsDirectoryIterator()
+//----------------------------------------------------------------------------------------
+{
+ if (mDir)
+ PR_CloseDir(mDir);
+} // nsDirectoryIterator::nsDirectoryIterator
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator& nsDirectoryIterator::operator ++ ()
+//----------------------------------------------------------------------------------------
+{
+ mExists = PR_FALSE;
+ if (!mDir)
+ return *this;
+ PRDirEntry* entry = PR_ReadDir(mDir, PR_SKIP_BOTH); // Ignore '.' && '..'
+ if (entry)
+ {
+ mExists = PR_TRUE;
+ mCurrent = mStarting;
+ mCurrent.SetLeafName(entry->name);
+ if (mResoveSymLinks)
+ {
+ PRBool ignore;
+ mCurrent.ResolveSymlink(ignore);
+ }
+ }
+ return *this;
+} // nsDirectoryIterator::operator ++
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator& nsDirectoryIterator::operator -- ()
+//----------------------------------------------------------------------------------------
+{
+ return ++(*this); // can't do it backwards.
+} // nsDirectoryIterator::operator --
+
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecUnix.cpp b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecUnix.cpp
new file mode 100644
index 00000000..8acb6330
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecUnix.cpp
@@ -0,0 +1,703 @@
+/* -*- 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):
+ * Henry Sobotka <sobotka@axess.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 ***** */
+
+// This file is included by nsFileSpec.cpp, and includes the Unix-specific
+// implementations.
+
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <errno.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "xpcom-private.h"
+#include "nsError.h"
+#include "prio.h" /* for PR_Rename */
+#include "nsAutoBuffer.h"
+
+#if defined(_SCO_DS)
+#define _SVID3 /* for statvfs.h */
+#endif
+
+#ifdef HAVE_SYS_STATVFS_H
+#include <sys/statvfs.h>
+#endif
+
+#ifdef HAVE_SYS_VFS_H
+#include <sys/vfs.h>
+#endif
+
+#ifdef HAVE_SYS_STATFS_H
+#include <sys/statfs.h>
+#endif
+
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
+#undef Free
+#endif
+
+#ifdef HAVE_STATVFS
+#define STATFS statvfs
+#else
+#define STATFS statfs
+#endif
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024 /* Guessing this is okay. Works for SCO. */
+#endif
+
+#if defined(__QNX__)
+#include <unix.h> /* for realpath */
+#define f_bavail f_bfree
+extern "C" int truncate(const char *, off_t);
+#endif
+
+#if defined(SUNOS4)
+extern "C" int statfs(char *, struct statfs *);
+#endif
+
+#if defined(OSF1)
+extern "C" int statvfs(const char *, struct statvfs *);
+#endif
+
+#ifdef XP_MACOSX
+static void CopyUTF8toUTF16NFC(const nsACString& aSrc, nsAString& aResult);
+#endif
+
+//----------------------------------------------------------------------------------------
+void nsFileSpecHelpers::Canonify(nsSimpleCharString& ioPath, PRBool inMakeDirs)
+// Canonify, make absolute, and check whether directories exist
+//----------------------------------------------------------------------------------------
+{
+ if (ioPath.IsEmpty())
+ return;
+ if (inMakeDirs)
+ {
+ const mode_t mode = 0700;
+ nsFileSpecHelpers::MakeAllDirectories((const char*)ioPath, mode);
+ }
+
+ errno = 0; // needed?
+
+ if (ioPath[0] != '/')
+ {
+ // the ioPath that was passed in is relative. We must cat it to the cwd.
+ char buffer[MAXPATHLEN];
+
+ (void) getcwd(buffer, MAXPATHLEN);
+
+ strcat(buffer, "/");
+ strcat(buffer, ioPath);
+
+ ioPath = buffer;
+ }
+} // nsFileSpecHelpers::Canonify
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::SetLeafName(const char* inLeafName)
+//----------------------------------------------------------------------------------------
+{
+ mPath.LeafReplace('/', inLeafName);
+} // nsFileSpec::SetLeafName
+
+//----------------------------------------------------------------------------------------
+char* nsFileSpec::GetLeafName() const
+//----------------------------------------------------------------------------------------
+{
+#ifndef XP_MACOSX
+ return mPath.GetLeaf('/');
+#else
+ char *name = mPath.GetLeaf('/');
+ if (!name || !*name)
+ return name;
+ nsAutoString nameInNFC;
+ CopyUTF8toUTF16NFC(nsDependentCString(name), nameInNFC);
+ nsCRT::free(name);
+ return nsCRT::strdup(NS_ConvertUTF16toUTF8(nameInNFC).get());
+#endif
+} // nsFileSpec::GetLeafName
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::Exists() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ return !mPath.IsEmpty() && 0 == stat(mPath, &st);
+} // nsFileSpec::Exists
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::GetModDate(TimeStamp& outStamp) const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ if (!mPath.IsEmpty() && stat(mPath, &st) == 0)
+ outStamp = st.st_mtime;
+ else
+ outStamp = 0;
+} // nsFileSpec::GetModDate
+
+//----------------------------------------------------------------------------------------
+PRUint32 nsFileSpec::GetFileSize() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ if (!mPath.IsEmpty() && stat(mPath, &st) == 0)
+ return (PRUint32)st.st_size;
+ return 0;
+} // nsFileSpec::GetFileSize
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsFile() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ return !mPath.IsEmpty() && stat(mPath, &st) == 0 && S_ISREG(st.st_mode);
+} // nsFileSpec::IsFile
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsDirectory() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ return !mPath.IsEmpty() && 0 == stat(mPath, &st) && S_ISDIR(st.st_mode);
+} // nsFileSpec::IsDirectory
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsHidden() const
+//----------------------------------------------------------------------------------------
+{
+ PRBool hidden = PR_FALSE;
+ char *leafname = GetLeafName();
+ if (nsnull != leafname)
+ {
+ // rjc: don't return ".", "..", or any file/directory that begins with a "."
+
+ /* if ((!strcmp(leafname, ".")) || (!strcmp(leafname, ".."))) */
+ if (leafname[0] == '.')
+ {
+ hidden = PR_TRUE;
+ }
+ nsCRT::free(leafname);
+ }
+ return hidden;
+} // nsFileSpec::IsHidden
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsSymlink() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ if (!mPath.IsEmpty() && stat(mPath, &st) == 0 && S_ISLNK(st.st_mode))
+ return PR_TRUE;
+
+ return PR_FALSE;
+} // nsFileSpec::IsSymlink
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::ResolveSymlink(PRBool& wasAliased)
+//----------------------------------------------------------------------------------------
+{
+ wasAliased = PR_FALSE;
+
+ char resolvedPath[MAXPATHLEN];
+ int charCount = readlink(mPath, (char*)&resolvedPath, MAXPATHLEN);
+ if (0 < charCount)
+ {
+ if (MAXPATHLEN > charCount)
+ resolvedPath[charCount] = '\0';
+
+ wasAliased = PR_TRUE;
+
+ /* if it's not an absolute path,
+ replace the leaf with what got resolved */
+ if (resolvedPath[0] != '/') {
+ SetLeafName(resolvedPath);
+ }
+ else {
+ mPath = (char*)&resolvedPath;
+ }
+
+ char* canonicalPath = realpath((const char *)mPath, resolvedPath);
+ NS_ASSERTION(canonicalPath, "realpath failed");
+ if (canonicalPath) {
+ mPath = (char*)&resolvedPath;
+ }
+ else {
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ return NS_OK;
+} // nsFileSpec::ResolveSymlink
+
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::GetParent(nsFileSpec& outSpec) const
+//----------------------------------------------------------------------------------------
+{
+ outSpec.mPath = mPath;
+ char* chars = (char*)outSpec.mPath;
+ chars[outSpec.mPath.Length() - 1] = '\0'; // avoid trailing separator, if any
+ char* cp = strrchr(chars, '/');
+ if (cp++)
+ outSpec.mPath.SetLength(cp - chars); // truncate.
+} // nsFileSpec::GetParent
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator += (const char* inRelativePath)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inRelativePath, "Attempt to do += with a null string");
+
+ if (!inRelativePath || mPath.IsEmpty())
+ return;
+
+ char endChar = mPath[(int)(strlen(mPath) - 1)];
+ if (endChar == '/')
+ mPath += "x";
+ else
+ mPath += "/x";
+ SetLeafName(inRelativePath);
+} // nsFileSpec::operator +=
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::CreateDirectory(int mode)
+//----------------------------------------------------------------------------------------
+{
+ // Note that mPath is canonical!
+ if (mPath.IsEmpty())
+ return;
+ mkdir(mPath, mode);
+} // nsFileSpec::CreateDirectory
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::Delete(PRBool inRecursive) const
+// To check if this worked, call Exists() afterwards, see?
+//----------------------------------------------------------------------------------------
+{
+ if (IsDirectory())
+ {
+ if (inRecursive)
+ {
+ for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
+ {
+ nsFileSpec& child = (nsFileSpec&)i;
+ child.Delete(inRecursive);
+ }
+ }
+ rmdir(mPath);
+ }
+ else if (!mPath.IsEmpty())
+ remove(mPath);
+} // nsFileSpec::Delete
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const
+//----------------------------------------------------------------------------------------
+{
+ if (IsDirectory())
+ {
+ if (!(newDir.Exists()))
+ {
+ newDir.CreateDirectory();
+ }
+
+ for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
+ {
+ nsFileSpec& child = (nsFileSpec&)i;
+
+ if (child.IsDirectory())
+ {
+ nsFileSpec tmpDirSpec(newDir);
+
+ char *leafname = child.GetLeafName();
+ tmpDirSpec += leafname;
+ nsCRT::free(leafname);
+
+ child.RecursiveCopy(tmpDirSpec);
+ }
+ else
+ {
+ child.RecursiveCopy(newDir);
+ }
+ }
+ }
+ else if (!mPath.IsEmpty())
+ {
+ nsFileSpec& filePath = (nsFileSpec&) *this;
+
+ if (!(newDir.Exists()))
+ {
+ newDir.CreateDirectory();
+ }
+
+ filePath.CopyToDir(newDir);
+ }
+} // nsFileSpec::RecursiveCopy
+
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Truncate(PRInt32 offset) const
+//----------------------------------------------------------------------------------------
+{
+ char* Path = nsCRT::strdup(mPath);
+
+ int rv = truncate(Path, offset) ;
+
+ nsCRT::free(Path) ;
+
+ if(!rv)
+ return NS_OK ;
+ else
+ return NS_ERROR_FAILURE ;
+} // nsFileSpec::Truncate
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Rename(const char* inNewName)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inNewName, "Attempt to Rename with a null string");
+
+ // This function should not be used to move a file on disk.
+ if (mPath.IsEmpty() || strchr(inNewName, '/'))
+ return NS_FILE_FAILURE;
+
+ char* oldPath = nsCRT::strdup(mPath);
+
+ SetLeafName(inNewName);
+
+ if (PR_Rename(oldPath, mPath) != NS_OK)
+ {
+ // Could not rename, set back to the original.
+ mPath = oldPath;
+ return NS_FILE_FAILURE;
+ }
+
+ nsCRT::free(oldPath);
+
+ return NS_OK;
+} // nsFileSpec::Rename
+
+//----------------------------------------------------------------------------------------
+static int CrudeFileCopy(const char* in, const char* out)
+//----------------------------------------------------------------------------------------
+{
+ struct stat in_stat;
+ int stat_result = -1;
+
+ char buf [1024];
+ FILE *ifp, *ofp;
+ int rbytes, wbytes;
+
+ if (!in || !out)
+ return -1;
+
+ stat_result = stat (in, &in_stat);
+
+ ifp = fopen (in, "r");
+ if (!ifp)
+ {
+ return -1;
+ }
+
+ ofp = fopen (out, "w");
+ if (!ofp)
+ {
+ fclose (ifp);
+ return -1;
+ }
+
+ while ((rbytes = fread (buf, 1, sizeof(buf), ifp)) > 0)
+ {
+ while (rbytes > 0)
+ {
+ if ( (wbytes = fwrite (buf, 1, rbytes, ofp)) < 0 )
+ {
+ fclose (ofp);
+ fclose (ifp);
+ unlink(out);
+ return -1;
+ }
+ rbytes -= wbytes;
+ }
+ }
+ fclose (ofp);
+ fclose (ifp);
+
+ if (stat_result == 0)
+ chmod (out, in_stat.st_mode & 0777);
+
+ return 0;
+} // nsFileSpec::Rename
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::CopyToDir(const nsFileSpec& inParentDirectory) const
+//----------------------------------------------------------------------------------------
+{
+ // We can only copy into a directory, and (for now) can not copy entire directories
+ nsresult result = NS_FILE_FAILURE;
+
+ if (inParentDirectory.IsDirectory() && (! IsDirectory() ) )
+ {
+ char *leafname = GetLeafName();
+ nsSimpleCharString destPath(inParentDirectory.GetCString());
+ destPath += "/";
+ destPath += leafname;
+ nsCRT::free(leafname);
+ result = NS_FILE_RESULT(CrudeFileCopy(GetCString(), destPath));
+ }
+ return result;
+} // nsFileSpec::CopyToDir
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::MoveToDir(const nsFileSpec& inNewParentDirectory)
+//----------------------------------------------------------------------------------------
+{
+ // We can only copy into a directory, and (for now) can not copy entire directories
+ nsresult result = NS_FILE_FAILURE;
+
+ if (inNewParentDirectory.IsDirectory() && !IsDirectory())
+ {
+ char *leafname = GetLeafName();
+ nsSimpleCharString destPath(inNewParentDirectory.GetCString());
+ destPath += "/";
+ destPath += leafname;
+ nsCRT::free(leafname);
+
+ result = NS_FILE_RESULT(CrudeFileCopy(GetCString(), (const char*)destPath));
+ if (result == NS_OK)
+ {
+ // cast to fix const-ness
+ ((nsFileSpec*)this)->Delete(PR_FALSE);
+
+ *this = inNewParentDirectory + GetLeafName();
+ }
+ }
+ return result;
+}
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Execute(const char* inArgs ) const
+//----------------------------------------------------------------------------------------
+{
+ nsresult result = NS_FILE_FAILURE;
+
+ if (!mPath.IsEmpty() && !IsDirectory())
+ {
+ nsSimpleCharString fileNameWithArgs = mPath + " " + inArgs;
+ result = NS_FILE_RESULT(system(fileNameWithArgs));
+ }
+
+ return result;
+
+} // nsFileSpec::Execute
+
+//----------------------------------------------------------------------------------------
+PRInt64 nsFileSpec::GetDiskSpaceAvailable() const
+//----------------------------------------------------------------------------------------
+{
+ PRInt64 bytes; /* XXX dougt needs to fix this */
+ LL_I2L(bytes , LONG_MAX); // initialize to all the space in the world?
+
+
+#if defined(HAVE_SYS_STATFS_H) || defined(HAVE_SYS_STATVFS_H)
+
+ char curdir [MAXPATHLEN];
+ if (mPath.IsEmpty())
+ {
+ (void) getcwd(curdir, MAXPATHLEN);
+ if (!curdir)
+ return bytes; /* hope for the best as we did in cheddar */
+ }
+ else
+ sprintf(curdir, "%.200s", (const char*)mPath);
+
+ struct STATFS fs_buf;
+#if defined(__QNX__) && !defined(HAVE_STATVFS) /* Maybe this should be handled differently? */
+ if (STATFS(curdir, &fs_buf, 0, 0) < 0)
+#else
+ if (STATFS(curdir, &fs_buf) < 0)
+#endif
+ return bytes; /* hope for the best as we did in cheddar */
+
+#ifdef DEBUG_DISK_SPACE
+ printf("DiskSpaceAvailable: %d bytes\n",
+ fs_buf.f_bsize * (fs_buf.f_bavail - 1));
+#endif
+
+ PRInt64 bsize,bavail;
+ LL_I2L( bsize, fs_buf.f_bsize );
+ LL_I2L( bavail, fs_buf.f_bavail - 1 );
+ LL_MUL( bytes, bsize, bavail );
+ return bytes;
+
+#else
+ /*
+ ** This platform doesn't have statfs or statvfs, so we don't have much
+ ** choice but to "hope for the best as we did in cheddar".
+ */
+ return bytes;
+#endif /* HAVE_SYS_STATFS_H or HAVE_SYS_STATVFS_H */
+
+} // nsFileSpec::GetDiskSpace()
+
+//========================================================================================
+// nsDirectoryIterator
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator::nsDirectoryIterator(const nsFileSpec& inDirectory, PRBool resolveSymLinks)
+//----------------------------------------------------------------------------------------
+ : mCurrent(inDirectory)
+ , mExists(PR_FALSE)
+ , mResoveSymLinks(resolveSymLinks)
+ , mStarting(inDirectory)
+ , mDir(nsnull)
+
+{
+ mStarting += "sysygy"; // save off the starting directory
+ mCurrent += "sysygy"; // prepare the path for SetLeafName
+ mDir = opendir((const char*)nsFilePath(inDirectory));
+ ++(*this);
+} // nsDirectoryIterator::nsDirectoryIterator
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator::~nsDirectoryIterator()
+//----------------------------------------------------------------------------------------
+{
+ if (mDir)
+ closedir(mDir);
+} // nsDirectoryIterator::nsDirectoryIterator
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator& nsDirectoryIterator::operator ++ ()
+//----------------------------------------------------------------------------------------
+{
+ mExists = PR_FALSE;
+ if (!mDir)
+ return *this;
+ const char dot[] = ".";
+ const char dotdot[] = "..";
+ struct dirent* entry = readdir(mDir);
+ if (entry && strcmp(entry->d_name, dot) == 0)
+ entry = readdir(mDir);
+ if (entry && strcmp(entry->d_name, dotdot) == 0)
+ entry = readdir(mDir);
+ if (entry)
+ {
+ mExists = PR_TRUE;
+ mCurrent = mStarting; // restore mCurrent to be the starting directory. ResolveSymlink() may have taken us to another directory
+ mCurrent.SetLeafName(entry->d_name);
+ if (mResoveSymLinks)
+ {
+ PRBool ignore;
+ mCurrent.ResolveSymlink(ignore);
+ }
+ }
+ return *this;
+} // nsDirectoryIterator::operator ++
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator& nsDirectoryIterator::operator -- ()
+//----------------------------------------------------------------------------------------
+{
+ return ++(*this); // can't do it backwards.
+} // nsDirectoryIterator::operator --
+
+// Convert a UTF-8 string to a UTF-16 string while normalizing to
+// Normalization Form C (composed Unicode). We need this because
+// Mac OS X file system uses NFD (Normalization Form D : decomposed Unicode)
+// while most other OS', server-side programs usually expect NFC.
+
+#ifdef XP_MACOSX
+typedef void (*UnicodeNormalizer) (CFMutableStringRef, CFStringNormalizationForm);
+static void CopyUTF8toUTF16NFC(const nsACString& aSrc, nsAString& aResult)
+{
+ static PRBool sChecked = PR_FALSE;
+ static UnicodeNormalizer sUnicodeNormalizer = NULL;
+
+ // CFStringNormalize was not introduced until Mac OS 10.2
+ if (!sChecked) {
+ CFBundleRef carbonBundle =
+ CFBundleGetBundleWithIdentifier(CFSTR("com.apple.Carbon"));
+ if (carbonBundle)
+ sUnicodeNormalizer = (UnicodeNormalizer)
+ ::CFBundleGetFunctionPointerForName(carbonBundle,
+ CFSTR("CFStringNormalize"));
+ sChecked = PR_TRUE;
+ }
+
+ if (!sUnicodeNormalizer) { // OS X 10.1 or earlier
+ CopyUTF8toUTF16(aSrc, aResult);
+ return;
+ }
+
+ const nsAFlatCString &inFlatSrc = PromiseFlatCString(aSrc);
+
+ // The number of 16bit code units in a UTF-16 string will never be
+ // larger than the number of bytes in the corresponding UTF-8 string.
+ CFMutableStringRef inStr =
+ ::CFStringCreateMutable(NULL, inFlatSrc.Length());
+
+ if (!inStr) {
+ CopyUTF8toUTF16(aSrc, aResult);
+ return;
+ }
+
+ ::CFStringAppendCString(inStr, inFlatSrc.get(), kCFStringEncodingUTF8);
+
+ sUnicodeNormalizer(inStr, kCFStringNormalizationFormC);
+
+ CFIndex length = CFStringGetLength(inStr);
+ const UniChar* chars = CFStringGetCharactersPtr(inStr);
+
+ if (chars)
+ aResult.Assign(chars, length);
+ else {
+ nsAutoBuffer<UniChar, 512> buffer;
+ if (buffer.EnsureElemCapacity(length)) {
+ CFStringGetCharacters(inStr, CFRangeMake(0, length), buffer.get());
+ aResult.Assign(buffer.get(), length);
+ }
+ else
+ CopyUTF8toUTF16(aSrc, aResult);
+ }
+ CFRelease(inStr);
+}
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecWin.cpp b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecWin.cpp
new file mode 100644
index 00000000..7d7e863d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecWin.cpp
@@ -0,0 +1,766 @@
+/* -*- 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 ***** */
+
+// This file is included by nsFileSpec.cp, and includes the Windows-specific
+// implementations.
+
+#include <sys/stat.h>
+#include <direct.h>
+#include <limits.h>
+#include <stdlib.h>
+#include "prio.h"
+#include "nsError.h"
+
+#include <windows.h>
+
+#if (_MSC_VER == 1100) || defined(__GNUC__)
+#define INITGUID
+#include <objbase.h>
+DEFINE_OLEGUID(IID_IPersistFile, 0x0000010BL, 0, 0);
+#endif
+
+#include <shlobj.h>
+#include <shellapi.h>
+#include <shlguid.h>
+
+#ifdef UNICODE
+#define CreateDirectoryW CreateDirectory
+#else
+#define CreateDirectoryA CreateDirectory
+#endif
+
+//----------------------------------------------------------------------------------------
+void nsFileSpecHelpers::Canonify(nsSimpleCharString& ioPath, PRBool inMakeDirs)
+// Canonify, make absolute, and check whether directories exist. This
+// takes a (possibly relative) native path and converts it into a
+// fully qualified native path.
+//----------------------------------------------------------------------------------------
+{
+ if (ioPath.IsEmpty())
+ return;
+
+ NS_ASSERTION(strchr((const char*)ioPath, '/') == 0,
+ "This smells like a Unix path. Native path expected! "
+ "Please fix.");
+ if (inMakeDirs)
+ {
+ const int mode = 0755;
+ nsSimpleCharString unixStylePath = ioPath;
+ nsFileSpecHelpers::NativeToUnix(unixStylePath);
+ nsFileSpecHelpers::MakeAllDirectories((const char*)unixStylePath, mode);
+ }
+ char buffer[_MAX_PATH];
+ errno = 0;
+ *buffer = '\0';
+ char* canonicalPath = _fullpath(buffer, ioPath, _MAX_PATH);
+
+ if (canonicalPath)
+ {
+ NS_ASSERTION( canonicalPath[0] != '\0', "Uh oh...couldn't convert" );
+ if (canonicalPath[0] == '\0')
+ return;
+ }
+ ioPath = canonicalPath;
+} // nsFileSpecHelpers::Canonify
+
+//----------------------------------------------------------------------------------------
+void nsFileSpecHelpers::UnixToNative(nsSimpleCharString& ioPath)
+// This just does string manipulation. It doesn't check reality, or canonify, or
+// anything
+//----------------------------------------------------------------------------------------
+{
+ // Allow for relative or absolute. We can do this in place, because the
+ // native path is never longer.
+
+ if (ioPath.IsEmpty())
+ return;
+
+ // Strip initial slash for an absolute path
+ char* src = (char*)ioPath;
+ if (*src == '/') {
+ if (!src[1]) {
+ // allocate new string by copying from ioPath[1]
+ nsSimpleCharString temp = src + 1;
+ ioPath = temp;
+ return;
+ }
+ // Since it was an absolute path, check for the drive letter
+ char* colonPointer = src + 2;
+ if (strstr(src, "|/") == colonPointer)
+ *colonPointer = ':';
+ // allocate new string by copying from ioPath[1]
+ nsSimpleCharString temp = src + 1;
+ ioPath = temp;
+ }
+
+ // Convert '/' to '\'. (Must check EVERY character: consider UNC path
+ // case.)
+ for (src = (char*)ioPath; *src; ++src)
+ {
+ if (*src == '/')
+ *src = '\\';
+ }
+
+} // nsFileSpecHelpers::UnixToNative
+
+//----------------------------------------------------------------------------------------
+void nsFileSpecHelpers::NativeToUnix(nsSimpleCharString& ioPath)
+// This just does string manipulation. It doesn't check reality, or canonify, or
+// anything. The unix path is longer, so we can't do it in place.
+//----------------------------------------------------------------------------------------
+{
+ if (ioPath.IsEmpty())
+ return;
+
+ // Convert the drive-letter separator, if present
+ nsSimpleCharString temp("/");
+
+ char* cp = (char*)ioPath + 1;
+ if (strstr(cp, ":\\") == cp)
+ *cp = '|'; // absolute path
+ else
+ if (cp[0] == '\\') // unc path
+ cp--;
+ else
+ temp[0] = '\0'; // relative path
+
+ // Convert '\' to '/'
+ for (; *cp; cp++)
+ {
+ if(IsDBCSLeadByte(*cp) && *(cp+1) != nsnull)
+ {
+ cp++;
+ continue;
+ }
+ if (*cp == '\\')
+ *cp = '/';
+ }
+ // Add the slash in front.
+ temp += ioPath;
+ ioPath = temp;
+}
+
+//----------------------------------------------------------------------------------------
+nsFileSpec::nsFileSpec(const nsFilePath& inPath)
+//----------------------------------------------------------------------------------------
+{
+// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
+ *this = inPath;
+}
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator = (const nsFilePath& inPath)
+//----------------------------------------------------------------------------------------
+{
+ mPath = (const char*)inPath;
+ nsFileSpecHelpers::UnixToNative(mPath);
+ mError = NS_OK;
+} // nsFileSpec::operator =
+
+//----------------------------------------------------------------------------------------
+nsFilePath::nsFilePath(const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+{
+ *this = inSpec;
+} // nsFilePath::nsFilePath
+
+//----------------------------------------------------------------------------------------
+void nsFilePath::operator = (const nsFileSpec& inSpec)
+//----------------------------------------------------------------------------------------
+{
+ mPath = inSpec.mPath;
+ nsFileSpecHelpers::NativeToUnix(mPath);
+} // nsFilePath::operator =
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::SetLeafName(const char* inLeafName)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inLeafName, "Attempt to SetLeafName with a null string");
+ mPath.LeafReplace('\\', inLeafName);
+} // nsFileSpec::SetLeafName
+
+//----------------------------------------------------------------------------------------
+char* nsFileSpec::GetLeafName() const
+//----------------------------------------------------------------------------------------
+{
+ return mPath.GetLeaf('\\');
+} // nsFileSpec::GetLeafName
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::Exists() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st);
+} // nsFileSpec::Exists
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::GetModDate(TimeStamp& outStamp) const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ if (!mPath.IsEmpty() && stat(nsNSPRPath(*this), &st) == 0)
+ outStamp = st.st_mtime;
+ else
+ outStamp = 0;
+} // nsFileSpec::GetModDate
+
+//----------------------------------------------------------------------------------------
+PRUint32 nsFileSpec::GetFileSize() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ if (!mPath.IsEmpty() && stat(nsNSPRPath(*this), &st) == 0)
+ return (PRUint32)st.st_size;
+ return 0;
+} // nsFileSpec::GetFileSize
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsFile() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && (_S_IFREG & st.st_mode);
+} // nsFileSpec::IsFile
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsDirectory() const
+//----------------------------------------------------------------------------------------
+{
+ struct stat st;
+ return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && (_S_IFDIR & st.st_mode);
+} // nsFileSpec::IsDirectory
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsHidden() const
+//----------------------------------------------------------------------------------------
+{
+ PRBool hidden = PR_FALSE;
+ if (!mPath.IsEmpty())
+ {
+ DWORD attr = GetFileAttributes(mPath);
+ if (FILE_ATTRIBUTE_HIDDEN & attr)
+ hidden = PR_TRUE;
+ }
+ return hidden;
+}
+// nsFileSpec::IsHidden
+
+//----------------------------------------------------------------------------------------
+PRBool nsFileSpec::IsSymlink() const
+//----------------------------------------------------------------------------------------
+{
+ HRESULT hres;
+ IShellLink* psl;
+
+ PRBool isSymlink = PR_FALSE;
+
+ CoInitialize(NULL);
+ // Get a pointer to the IShellLink interface.
+ hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl);
+ if (SUCCEEDED(hres))
+ {
+ IPersistFile* ppf;
+
+ // Get a pointer to the IPersistFile interface.
+ hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
+
+ if (SUCCEEDED(hres))
+ {
+ WCHAR wsz[MAX_PATH];
+ // Ensure that the string is Unicode.
+ MultiByteToWideChar(CP_ACP, 0, mPath, -1, wsz, MAX_PATH);
+
+ // Load the shortcut.
+ hres = ppf->Load(wsz, STGM_READ);
+ if (SUCCEEDED(hres))
+ {
+ isSymlink = PR_TRUE;
+ }
+
+ // Release the pointer to the IPersistFile interface.
+ ppf->Release();
+ }
+
+ // Release the pointer to the IShellLink interface.
+ psl->Release();
+ }
+
+ CoUninitialize();
+
+ return isSymlink;
+}
+
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::ResolveSymlink(PRBool& wasSymlink)
+//----------------------------------------------------------------------------------------
+{
+ wasSymlink = PR_FALSE; // assume failure
+
+ if (Exists())
+ return NS_OK;
+
+
+ HRESULT hres;
+ IShellLink* psl;
+
+ CoInitialize(NULL);
+
+ // Get a pointer to the IShellLink interface.
+ hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl);
+ if (SUCCEEDED(hres))
+ {
+ IPersistFile* ppf;
+
+ // Get a pointer to the IPersistFile interface.
+ hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
+
+ if (SUCCEEDED(hres))
+ {
+ WCHAR wsz[MAX_PATH];
+ // Ensure that the string is Unicode.
+ MultiByteToWideChar(CP_ACP, 0, mPath, -1, wsz, MAX_PATH);
+
+ // Load the shortcut.
+ hres = ppf->Load(wsz, STGM_READ);
+ if (SUCCEEDED(hres))
+ {
+ wasSymlink = PR_TRUE;
+
+ // Resolve the link.
+ hres = psl->Resolve(nsnull, SLR_NO_UI );
+ if (SUCCEEDED(hres))
+ {
+ char szGotPath[MAX_PATH];
+ WIN32_FIND_DATA wfd;
+
+ // Get the path to the link target.
+ hres = psl->GetPath( szGotPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY );
+
+ if (SUCCEEDED(hres))
+ {
+ // Here we modify the nsFileSpec;
+ mPath = szGotPath;
+ mError = NS_OK;
+ }
+ }
+ }
+ else {
+ // It wasn't a shortcut. Oh well. Leave it like it was.
+ hres = 0;
+ }
+
+ // Release the pointer to the IPersistFile interface.
+ ppf->Release();
+ }
+ // Release the pointer to the IShellLink interface.
+ psl->Release();
+ }
+
+ CoUninitialize();
+
+ if (SUCCEEDED(hres))
+ return NS_OK;
+
+ return NS_FILE_FAILURE;
+}
+
+
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::GetParent(nsFileSpec& outSpec) const
+//----------------------------------------------------------------------------------------
+{
+ outSpec.mPath = mPath;
+ char* chars = (char*)outSpec.mPath;
+ chars[outSpec.mPath.Length() - 1] = '\0'; // avoid trailing separator, if any
+ char* cp = strrchr(chars, '\\');
+ if (cp++)
+ outSpec.mPath.SetLength(cp - chars); // truncate.
+} // nsFileSpec::GetParent
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::operator += (const char* inRelativePath)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inRelativePath, "Attempt to do += with a null string");
+
+ if (!inRelativePath || mPath.IsEmpty())
+ return;
+
+ if (mPath[mPath.Length() - 1] == '\\')
+ mPath += "x";
+ else
+ mPath += "\\x";
+
+ // If it's a (unix) relative path, make it native
+ nsSimpleCharString dosPath = inRelativePath;
+ nsFileSpecHelpers::UnixToNative(dosPath);
+ SetLeafName(dosPath);
+} // nsFileSpec::operator +=
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::CreateDirectory(int /*mode*/)
+//----------------------------------------------------------------------------------------
+{
+ // Note that mPath is canonical!
+ if (!mPath.IsEmpty())
+ mkdir(nsNSPRPath(*this));
+} // nsFileSpec::CreateDirectory
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::Delete(PRBool inRecursive) const
+//----------------------------------------------------------------------------------------
+{
+ if (IsDirectory())
+ {
+ if (inRecursive)
+ {
+ for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
+ {
+ nsFileSpec& child = (nsFileSpec&)i;
+ child.Delete(inRecursive);
+ }
+ }
+ rmdir(nsNSPRPath(*this));
+ }
+ else if (!mPath.IsEmpty())
+ {
+ remove(nsNSPRPath(*this));
+ }
+} // nsFileSpec::Delete
+
+
+//----------------------------------------------------------------------------------------
+void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const
+//----------------------------------------------------------------------------------------
+{
+ if (IsDirectory())
+ {
+ if (!(newDir.Exists()))
+ {
+ newDir.CreateDirectory();
+ }
+
+ for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
+ {
+ nsFileSpec& child = (nsFileSpec&)i;
+
+ if (child.IsDirectory())
+ {
+ nsFileSpec tmpDirSpec(newDir);
+
+ char *leafname = child.GetLeafName();
+ tmpDirSpec += leafname;
+ nsCRT::free(leafname);
+
+ child.RecursiveCopy(tmpDirSpec);
+ }
+ else
+ {
+ child.RecursiveCopy(newDir);
+ }
+ }
+ }
+ else if (!mPath.IsEmpty())
+ {
+ nsFileSpec& filePath = (nsFileSpec&) *this;
+
+ if (!(newDir.Exists()))
+ {
+ newDir.CreateDirectory();
+ }
+
+ filePath.CopyToDir(newDir);
+ }
+} // nsFileSpec::RecursiveCopy
+
+//----------------------------------------------------------------------------------------
+nsresult
+nsFileSpec::Truncate(PRInt32 aNewFileLength) const
+//----------------------------------------------------------------------------------------
+{
+ DWORD status;
+ HANDLE hFile;
+
+ // Leave it to Microsoft to open an existing file with a function
+ // named "CreateFile".
+ hFile = CreateFile(mPath,
+ GENERIC_WRITE,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ return NS_FILE_FAILURE;
+
+ // Seek to new, desired end of file
+ status = SetFilePointer(hFile, aNewFileLength, NULL, FILE_BEGIN);
+ if (status == 0xffffffff)
+ goto error;
+
+ // Truncate file at current cursor position
+ if (!SetEndOfFile(hFile))
+ goto error;
+
+ if (!CloseHandle(hFile))
+ return NS_FILE_FAILURE;
+
+ return NS_OK;
+
+ error:
+ CloseHandle(hFile);
+ return NS_FILE_FAILURE;
+
+} // nsFileSpec::Truncate
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Rename(const char* inNewName)
+//----------------------------------------------------------------------------------------
+{
+ NS_ASSERTION(inNewName, "Attempt to Rename with a null string");
+
+ // This function should not be used to move a file on disk.
+ if (strchr(inNewName, '/'))
+ return NS_FILE_FAILURE;
+
+ char* oldPath = nsCRT::strdup(mPath);
+
+ SetLeafName(inNewName);
+
+ if (PR_Rename(oldPath, mPath) != NS_OK)
+ {
+ // Could not rename, set back to the original.
+ mPath = oldPath;
+ return NS_FILE_FAILURE;
+ }
+
+ nsCRT::free(oldPath);
+
+ return NS_OK;
+} // nsFileSpec::Rename
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::CopyToDir(const nsFileSpec& inParentDirectory) const
+//----------------------------------------------------------------------------------------
+{
+ // We can only copy into a directory, and (for now) can not copy entire directories
+ if (inParentDirectory.IsDirectory() && (! IsDirectory() ) )
+ {
+ char *leafname = GetLeafName();
+ nsSimpleCharString destPath(inParentDirectory.GetCString());
+ destPath += "\\";
+ destPath += leafname;
+ nsCRT::free(leafname);
+
+ // CopyFile returns non-zero if succeeds
+ int copyOK = CopyFile(GetCString(), destPath, PR_TRUE);
+ if (copyOK)
+ return NS_OK;
+ }
+ return NS_FILE_FAILURE;
+} // nsFileSpec::CopyToDir
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::MoveToDir(const nsFileSpec& inNewParentDirectory)
+//----------------------------------------------------------------------------------------
+{
+ // We can only copy into a directory, and (for now) can not copy entire directories
+ if (inNewParentDirectory.IsDirectory() && (! IsDirectory() ) )
+ {
+ char *leafname = GetLeafName();
+ nsSimpleCharString destPath(inNewParentDirectory.GetCString());
+ destPath += "\\";
+ destPath += leafname;
+ nsCRT::free(leafname);
+
+ // MoveFile returns non-zero if succeeds
+ int copyOK = MoveFile(GetCString(), destPath);
+
+ if (copyOK)
+ {
+ *this = inNewParentDirectory + GetLeafName();
+ return NS_OK;
+ }
+
+ }
+ return NS_FILE_FAILURE;
+} // nsFileSpec::MoveToDir
+
+//----------------------------------------------------------------------------------------
+nsresult nsFileSpec::Execute(const char* inArgs ) const
+//----------------------------------------------------------------------------------------
+{
+ if (!IsDirectory())
+ {
+ nsSimpleCharString fileNameWithArgs = "\"";
+ fileNameWithArgs += mPath + "\" " + inArgs;
+ int execResult = WinExec( fileNameWithArgs, SW_NORMAL );
+ if (execResult > 31)
+ return NS_OK;
+ }
+ return NS_FILE_FAILURE;
+} // nsFileSpec::Execute
+
+
+//----------------------------------------------------------------------------------------
+PRInt64 nsFileSpec::GetDiskSpaceAvailable() const
+//----------------------------------------------------------------------------------------
+{
+ PRInt64 int64;
+
+ LL_I2L(int64 , LONG_MAX);
+
+ char aDrive[_MAX_DRIVE + 2];
+ _splitpath( (const char*)mPath, aDrive, NULL, NULL, NULL);
+
+ if (aDrive[0] == '\0')
+ {
+ // The back end is always trying to pass us paths that look
+ // like /c|/netscape/mail. See if we've got one of them
+ if (mPath.Length() > 2 && mPath[0] == '/' && mPath[2] == '|')
+ {
+ aDrive[0] = mPath[1];
+ aDrive[1] = ':';
+ aDrive[2] = '\0';
+ }
+ else
+ {
+ // Return bogus large number and hope for the best
+ return int64;
+ }
+ }
+
+ strcat(aDrive, "\\");
+
+ // Check disk space
+ DWORD dwSecPerClus, dwBytesPerSec, dwFreeClus, dwTotalClus;
+ ULARGE_INTEGER liFreeBytesAvailableToCaller, liTotalNumberOfBytes, liTotalNumberOfFreeBytes;
+ double nBytes = 0;
+
+ BOOL (WINAPI* getDiskFreeSpaceExA)(LPCTSTR lpDirectoryName,
+ PULARGE_INTEGER lpFreeBytesAvailableToCaller,
+ PULARGE_INTEGER lpTotalNumberOfBytes,
+ PULARGE_INTEGER lpTotalNumberOfFreeBytes) = NULL;
+
+ HINSTANCE hInst = LoadLibrary("KERNEL32.DLL");
+ NS_ASSERTION(hInst != NULL, "COULD NOT LOAD KERNEL32.DLL");
+ if (hInst != NULL)
+ {
+ getDiskFreeSpaceExA = (BOOL (WINAPI*)(LPCTSTR lpDirectoryName,
+ PULARGE_INTEGER lpFreeBytesAvailableToCaller,
+ PULARGE_INTEGER lpTotalNumberOfBytes,
+ PULARGE_INTEGER lpTotalNumberOfFreeBytes))
+ GetProcAddress(hInst, "GetDiskFreeSpaceExA");
+ FreeLibrary(hInst);
+ }
+
+ if (getDiskFreeSpaceExA && (*getDiskFreeSpaceExA)(aDrive,
+ &liFreeBytesAvailableToCaller,
+ &liTotalNumberOfBytes,
+ &liTotalNumberOfFreeBytes))
+ {
+ nBytes = (double)(signed __int64)liFreeBytesAvailableToCaller.QuadPart;
+ }
+ else if ( GetDiskFreeSpace(aDrive, &dwSecPerClus, &dwBytesPerSec, &dwFreeClus, &dwTotalClus))
+ {
+ nBytes = (double)dwFreeClus*(double)dwSecPerClus*(double) dwBytesPerSec;
+ }
+ return (PRInt64)nBytes;
+}
+
+
+
+//========================================================================================
+// nsDirectoryIterator
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator::nsDirectoryIterator(const nsFileSpec& inDirectory, PRBool resolveSymlink)
+//----------------------------------------------------------------------------------------
+ : mCurrent(inDirectory)
+ , mDir(nsnull)
+ , mStarting(inDirectory)
+ , mExists(PR_FALSE)
+ , mResoveSymLinks(resolveSymlink)
+{
+ mDir = PR_OpenDir(inDirectory);
+ mCurrent += "dummy";
+ mStarting += "dummy";
+ ++(*this);
+} // nsDirectoryIterator::nsDirectoryIterator
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator::~nsDirectoryIterator()
+//----------------------------------------------------------------------------------------
+{
+ if (mDir)
+ PR_CloseDir(mDir);
+} // nsDirectoryIterator::nsDirectoryIterator
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator& nsDirectoryIterator::operator ++ ()
+//----------------------------------------------------------------------------------------
+{
+ mExists = PR_FALSE;
+ if (!mDir)
+ return *this;
+ PRDirEntry* entry = PR_ReadDir(mDir, PR_SKIP_BOTH); // Ignore '.' && '..'
+ if (entry)
+ {
+ mExists = PR_TRUE;
+ mCurrent = mStarting;
+ mCurrent.SetLeafName(entry->name);
+ if (mResoveSymLinks)
+ {
+ PRBool ignore;
+ mCurrent.ResolveSymlink(ignore);
+ }
+ }
+ return *this;
+} // nsDirectoryIterator::operator ++
+
+//----------------------------------------------------------------------------------------
+nsDirectoryIterator& nsDirectoryIterator::operator -- ()
+//----------------------------------------------------------------------------------------
+{
+ return ++(*this); // can't do it backwards.
+} // nsDirectoryIterator::operator --
+
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsFileStream.cpp b/src/libs/xpcom18a4/xpcom/obsolete/nsFileStream.cpp
new file mode 100644
index 00000000..f20c60e3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsFileStream.cpp
@@ -0,0 +1,392 @@
+/* -*- 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 ***** */
+
+// First checked in on 98/12/08 by John R. McMullen.
+// Since nsFileStream.h is entirely templates, common code (such as open())
+// which does not actually depend on the charT, can be placed here.
+
+#include "nsFileStream.h"
+#include "nsFileSpec.h"
+#include "nsIFileSpec.h"
+#include "nsIStringStream.h"
+#include "nsInt64.h"
+#include <string.h>
+#include <stdio.h>
+
+
+//========================================================================================
+// nsInputStream
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsInputStream::~nsInputStream()
+//----------------------------------------------------------------------------------------
+{
+}
+
+//----------------------------------------------------------------------------------------
+char nsInputStream::get()
+//----------------------------------------------------------------------------------------
+{
+ char c;
+ if (read(&c, sizeof(c)) == sizeof(c))
+ return c;
+ return 0;
+}
+
+//----------------------------------------------------------------------------------------
+PRInt32 nsInputStream::read(void* s, PRInt32 n)
+//----------------------------------------------------------------------------------------
+{
+ if (!mInputStream)
+ return 0;
+ PRInt32 result = 0;
+ mInputStream->Read((char*)s, n, (PRUint32*)&result);
+ if (result == 0)
+ set_at_eof(PR_TRUE);
+ return result;
+} // nsInputStream::read
+
+//----------------------------------------------------------------------------------------
+static void TidyEndOfLine(char*& cp)
+// Assumes that cp is pointing at \n or \r. Nulls out the character, checks for
+// a second terminator (of the opposite persuasion), and returns cp pointing past the
+// entire eol construct (one or two characters).
+//----------------------------------------------------------------------------------------
+{
+ char ch = *cp;
+ *cp++ = '\0'; // terminate at the newline, then skip past it
+ if ((ch == '\n' && *cp == '\r') || (ch == '\r' && *cp == '\n'))
+ cp++; // possibly a pair.
+}
+
+//----------------------------------------------------------------------------------------
+nsInputStream& nsInputStream::operator >> (char& c)
+//----------------------------------------------------------------------------------------
+{
+ c = get();
+ return *this;
+}
+
+//========================================================================================
+// nsOutputStream
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsOutputStream::~nsOutputStream()
+//----------------------------------------------------------------------------------------
+{
+}
+
+//----------------------------------------------------------------------------------------
+void nsOutputStream::put(char c)
+//----------------------------------------------------------------------------------------
+{
+ write(&c, sizeof(c));
+}
+
+//----------------------------------------------------------------------------------------
+PRInt32 nsOutputStream::write(const void* s, PRInt32 n)
+//----------------------------------------------------------------------------------------
+{
+ if (!mOutputStream)
+ return 0;
+ PRInt32 result = 0;
+ mWriteStatus = mOutputStream->Write((char*)s, n, (PRUint32*)&result);
+ return result;
+} // nsOutputStream::write
+
+//----------------------------------------------------------------------------------------
+nsresult nsOutputStream::flush()
+//----------------------------------------------------------------------------------------
+{
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+nsresult nsOutputStream::lastWriteStatus()
+//----------------------------------------------------------------------------------------
+{
+ return mWriteStatus;
+}
+
+//----------------------------------------------------------------------------------------
+nsOutputStream& nsOutputStream::operator << (char c)
+//----------------------------------------------------------------------------------------
+{
+ put(c);
+ return *this;
+}
+
+//----------------------------------------------------------------------------------------
+nsOutputStream& nsOutputStream::operator << (const char* s)
+//----------------------------------------------------------------------------------------
+{
+ if (s)
+ write(s, strlen(s));
+ return *this;
+}
+
+//----------------------------------------------------------------------------------------
+nsOutputStream& nsOutputStream::operator << (short val)
+//----------------------------------------------------------------------------------------
+{
+ char buf[30];
+ sprintf(buf, "%hd", val);
+ return (*this << buf);
+}
+
+//----------------------------------------------------------------------------------------
+nsOutputStream& nsOutputStream::operator << (unsigned short val)
+//----------------------------------------------------------------------------------------
+{
+ char buf[30];
+ sprintf(buf, "%hu", val);
+ return (*this << buf);
+}
+
+//----------------------------------------------------------------------------------------
+nsOutputStream& nsOutputStream::operator << (long val)
+//----------------------------------------------------------------------------------------
+{
+ char buf[30];
+ sprintf(buf, "%ld", val);
+ return (*this << buf);
+}
+
+//----------------------------------------------------------------------------------------
+nsOutputStream& nsOutputStream::operator << (unsigned long val)
+//----------------------------------------------------------------------------------------
+{
+ char buf[30];
+ sprintf(buf, "%lu", val);
+ return (*this << buf);
+}
+
+//----------------------------------------------------------------------------------------
+nsOutputStream& nsOutputStream::operator << (int val)
+//----------------------------------------------------------------------------------------
+{
+ char buf[30];
+ sprintf(buf, "%d", val);
+ return (*this << buf);
+}
+
+//----------------------------------------------------------------------------------------
+nsOutputStream& nsOutputStream::operator << (unsigned int val)
+//----------------------------------------------------------------------------------------
+{
+ char buf[30];
+ sprintf(buf, "%u", val);
+ return (*this << buf);
+}
+
+//========================================================================================
+// nsRandomAccessInputStream
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+PRBool nsRandomAccessInputStream::readline(char* s, PRInt32 n)
+// This will truncate if the buffer is too small. Result will always be null-terminated.
+//----------------------------------------------------------------------------------------
+{
+ PRBool bufferLargeEnough = PR_TRUE; // result
+ if (!s || !n)
+ return PR_TRUE;
+
+ nsInt64 position = tell();
+ const nsInt64 zero(0);
+ if (position < zero)
+ return PR_FALSE;
+ PRInt32 bytesRead = read(s, n - 1);
+ if (failed())
+ return PR_FALSE;
+ s[bytesRead] = '\0'; // always terminate at the end of the buffer
+ char* tp = strpbrk(s, "\n\r");
+ if (tp)
+ {
+ TidyEndOfLine(tp);
+ bytesRead = (tp - s);
+ }
+ else if (!eof() && n-1 == bytesRead)
+ bufferLargeEnough = PR_FALSE;
+ position += bytesRead;
+ seek(position);
+ return bufferLargeEnough;
+} // nsRandomAccessInputStream::readline
+
+//========================================================================================
+// nsInputStringStream
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsInputStringStream::nsInputStringStream(const char* stringToRead)
+//----------------------------------------------------------------------------------------
+{
+ nsCOMPtr<nsIInputStream> stream;
+ if (NS_FAILED(NS_NewCharInputStream(getter_AddRefs(stream), stringToRead)))
+ return;
+ mInputStream = stream;
+ mStore = do_QueryInterface(stream);
+}
+
+//----------------------------------------------------------------------------------------
+nsInputStringStream::nsInputStringStream(const nsString& stringToRead)
+//----------------------------------------------------------------------------------------
+{
+ if (NS_FAILED(NS_NewStringInputStream(getter_AddRefs(mInputStream), stringToRead)))
+ return;
+ mStore = do_QueryInterface(mInputStream);
+}
+
+
+//========================================================================================
+// nsInputFileStream
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsInputFileStream::nsInputFileStream(
+ const nsFileSpec& inFile,
+ int nsprMode,
+ PRIntn accessMode)
+//----------------------------------------------------------------------------------------
+{
+ nsISupports* stream;
+ if (NS_FAILED(NS_NewIOFileStream(&stream, inFile, nsprMode, accessMode)))
+ return;
+ AssignFrom(stream);
+ NS_RELEASE(stream);
+} // nsInputFileStream::nsInputFileStream
+
+//----------------------------------------------------------------------------------------
+nsInputFileStream::nsInputFileStream(nsIFileSpec* inSpec)
+//----------------------------------------------------------------------------------------
+{
+ nsIInputStream* stream;
+ if (NS_FAILED(inSpec->GetInputStream(&stream)))
+ return;
+ AssignFrom(stream);
+ NS_RELEASE(stream);
+} // nsInputFileStream::nsInputFileStream
+
+//----------------------------------------------------------------------------------------
+nsInputFileStream::~nsInputFileStream()
+//----------------------------------------------------------------------------------------
+{
+// if (is_open())
+// close();
+}
+
+//----------------------------------------------------------------------------------------
+void nsInputFileStream::AssignFrom(nsISupports* stream)
+//----------------------------------------------------------------------------------------
+{
+ mFile = do_QueryInterface(stream);
+ mInputStream = do_QueryInterface(stream);
+ mStore = do_QueryInterface(stream);
+ mFileInputStream = do_QueryInterface(stream);
+}
+
+//========================================================================================
+// nsOutputFileStream
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsOutputFileStream::nsOutputFileStream(nsIFileSpec* inSpec)
+//----------------------------------------------------------------------------------------
+{
+ if (!inSpec)
+ return;
+ nsIOutputStream* stream;
+ if (NS_FAILED(inSpec->GetOutputStream(&stream)))
+ return;
+ AssignFrom(stream);
+ NS_RELEASE(stream);
+}
+
+//----------------------------------------------------------------------------------------
+nsOutputFileStream::~nsOutputFileStream()
+//----------------------------------------------------------------------------------------
+{
+// if (is_open())
+// close();
+}
+//----------------------------------------------------------------------------------------
+void nsOutputFileStream::AssignFrom(nsISupports* stream)
+//----------------------------------------------------------------------------------------
+{
+ mFile = do_QueryInterface(stream);
+ mOutputStream = do_QueryInterface(stream);
+ mStore = do_QueryInterface(stream);
+ mFileOutputStream = do_QueryInterface(stream);
+}
+
+//----------------------------------------------------------------------------------------
+nsresult nsOutputFileStream::flush()
+//----------------------------------------------------------------------------------------
+{
+ if (mFileOutputStream)
+ mFileOutputStream->Flush();
+ return error();
+}
+
+//----------------------------------------------------------------------------------------
+void nsOutputFileStream::abort()
+//----------------------------------------------------------------------------------------
+{
+ mResult = NS_FILE_FAILURE;
+ close();
+}
+
+//========================================================================================
+// Manipulators
+//========================================================================================
+
+//----------------------------------------------------------------------------------------
+nsOutputStream& nsEndl(nsOutputStream& os)
+//----------------------------------------------------------------------------------------
+{
+#if defined(XP_WIN) || defined(XP_OS2)
+ os.write("\r\n", 2);
+#elif defined (XP_MAC)
+ os.put('\r');
+#else
+ os.put('\n');
+#endif
+ //os.flush();
+ return os;
+} // nsEndl
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsFileStream.h b/src/libs/xpcom18a4/xpcom/obsolete/nsFileStream.h
new file mode 100644
index 00000000..b0cd5e8a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsFileStream.h
@@ -0,0 +1,772 @@
+/* -*- 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 ***** */
+
+// First checked in on 98/11/20 by John R. McMullen in the wrong directory.
+// Checked in again 98/12/04.
+// Polished version 98/12/08.
+// Completely rewritten to integrate with nsIInputStream and nsIOutputStream (the
+// xpcom stream objects.
+
+//========================================================================================
+//
+// Classes defined:
+//
+// nsInputStream, nsOutputStream
+// These are the lightweight STATICALLY LINKED wrappers for
+// the xpcom objects nsIInputStream and nsIOutputstream.
+// Possible uses:
+// If you are implementing a function that accepts one of these xpcom
+// streams, just make one of these little jobbies on the stack, and
+// the handy << or >> notation can be yours.
+//
+// nsInputFileStream, nsOutputFileStream
+// These are the STATICALLY LINKED wrappers for the file-related
+// versions of the above.
+// nsIOFileStream
+// An input and output file stream attached to the same file.
+//
+// This suite provide the following services:
+//
+// 1. Encapsulates all platform-specific file details, so that file i/o
+// can be done correctly without any platform #ifdefs
+//
+// 2. Uses NSPR file services (NOT ansi file I/O), in order to get best
+// native performance. This performance difference is especially large on
+// macintosh.
+//
+// 3. Allows all the power of the ansi stream syntax.
+//
+// Basic example:
+//
+// nsFileSpec myPath("/Development/iotest.txt");
+//
+// nsOutputFileStream testStream(myPath);
+// testStream << "Hello World" << nsEndl;
+//
+// 4. Requires streams to be constructed using typesafe nsFileSpec specifier
+// (not the notorious and bug prone const char*), namely nsFileSpec. See
+// nsFileSpec.h for more details.
+//
+// 5. Fixes a bug that have been there for a long time, and
+// is inevitable if you use NSPR alone:
+//
+// The problem on platforms (Macintosh) in which a path does not fully
+// specify a file, because two volumes can have the same name.
+//
+// Not yet provided:
+//
+// Endian-awareness for reading and writing crossplatform binary files. At this
+// time there seems to be no demand for this.
+//
+//========================================================================================
+
+#ifndef _FILESTREAM_H_
+#define _FILESTREAM_H_
+
+#include "xpcomobsolete.h"
+#include "nsStringFwd.h"
+
+#ifdef XP_MAC
+#include "pprio.h" // To get PR_ImportFile
+#else
+#include "prio.h"
+#endif
+
+#include "nsCOMPtr.h"
+#include "nsIFileStream.h"
+
+// Defined elsewhere
+class nsFileSpec;
+class nsIInputStream;
+class nsIOutputStream;
+class nsIFileSpec;
+
+//========================================================================================
+// Compiler-specific macros, as needed
+//========================================================================================
+#if !defined(NS_USING_NAMESPACE) && (defined(__MWERKS__) || defined(_MSC_VER))
+#define NS_USING_NAMESPACE
+#endif
+
+#ifdef NS_USING_NAMESPACE
+
+#define NS_NAMESPACE_PROTOTYPE
+#define NS_NAMESPACE namespace
+#define NS_NAMESPACE_END
+
+#else
+
+#define NS_NAMESPACE_PROTOTYPE static
+#define NS_NAMESPACE struct
+#define NS_NAMESPACE_END ;
+
+#endif // NS_USING_NAMESPACE
+
+#if !defined(XP_MAC) && !defined(__KCC)
+// PR_STDOUT and PR_STDIN are fatal on Macintosh. So for console i/o, we must use the std
+// stream stuff instead. However, we have to require that cout and cin are passed in
+// to the constructor because in the current build, there is a copy in the base.shlb,
+// and another in the caller's file. Passing it in as a parameter ensures that the
+// caller and this library are using the same global object. Groan.
+//
+// Unix currently does not support iostreams at all. Their compilers do not support
+// ANSI C++, or even ARM C++.
+//
+// Windows supports them, but only if you turn on the -GX compile flag, to support
+// exceptions.
+
+// Catch 22.
+#define NS_USE_PR_STDIO
+#endif
+
+#ifdef NS_USE_PR_STDIO
+class istream;
+class ostream;
+#define CONSOLE_IN 0
+#define CONSOLE_OUT 0
+#else
+#include <iostream>
+using std::istream;
+using std::ostream;
+#define CONSOLE_IN &std::cin
+#define CONSOLE_OUT &std::cout
+#endif
+
+//=========================== End Compiler-specific macros ===============================
+
+//========================================================================================
+class NS_COM_OBSOLETE nsInputStream
+// This is a convenience class, for use on the STACK ("new" junkies: get detoxed first).
+// Given a COM-style stream, this allows you to use the >> operators. It also acquires and
+// reference counts its stream.
+// Please read the comments at the top of this file
+//========================================================================================
+{
+public:
+ nsInputStream(nsIInputStream* inStream)
+ : mInputStream(do_QueryInterface(inStream))
+ , mEOF(PR_FALSE)
+ {}
+ virtual ~nsInputStream();
+
+ nsCOMPtr<nsIInputStream> GetIStream() const
+ {
+ return mInputStream;
+ }
+ PRBool eof() const { return get_at_eof(); }
+ char get();
+ nsresult close()
+ {
+ NS_ASSERTION(mInputStream, "mInputStream is null!");
+ if (mInputStream) {
+ return mInputStream->Close();
+ }
+ return NS_OK;
+ }
+ PRInt32 read(void* s, PRInt32 n);
+
+ // Input streamers. Add more as needed (int&, unsigned int& etc). (but you have to
+ // add delegators to the derived classes, too, because these operators don't inherit).
+ nsInputStream& operator >> (char& ch);
+
+ // Support manipulators
+ nsInputStream& operator >> (nsInputStream& (*pf)(nsInputStream&))
+ {
+ return pf(*this);
+ }
+
+protected:
+
+ // These certainly need to be overridden, they give the best shot we can at detecting
+ // eof in a simple nsIInputStream.
+ virtual void set_at_eof(PRBool atEnd)
+ {
+ mEOF = atEnd;
+ }
+ virtual PRBool get_at_eof() const
+ {
+ return mEOF;
+ }
+private:
+
+ nsInputStream& operator >> (char* buf); // TOO DANGEROUS. DON'T DEFINE.
+
+ // private and unimplemented to disallow copies and assigns
+ nsInputStream(const nsInputStream& rhs);
+ nsInputStream& operator=(const nsInputStream& rhs);
+
+// DATA
+protected:
+ nsCOMPtr<nsIInputStream> mInputStream;
+ PRBool mEOF;
+}; // class nsInputStream
+
+typedef nsInputStream nsBasicInStream; // historic support for this name
+
+//========================================================================================
+class NS_COM_OBSOLETE nsOutputStream
+// This is a convenience class, for use on the STACK ("new" junkies, get detoxed first).
+// Given a COM-style stream, this allows you to use the << operators. It also acquires and
+// reference counts its stream.
+// Please read the comments at the top of this file
+//========================================================================================
+{
+public:
+ nsOutputStream() {}
+ nsOutputStream(nsIOutputStream* inStream)
+ : mOutputStream(do_QueryInterface(inStream))
+ {}
+
+ virtual ~nsOutputStream();
+
+ nsCOMPtr<nsIOutputStream> GetIStream() const
+ {
+ return mOutputStream;
+ }
+ nsresult close()
+ {
+ if (mOutputStream)
+ return mOutputStream->Close();
+ return NS_OK;
+ }
+ void put(char c);
+ PRInt32 write(const void* s, PRInt32 n);
+ virtual nsresult flush();
+ nsresult lastWriteStatus();
+
+ // Output streamers. Add more as needed (but you have to add delegators to the derived
+ // classes, too, because these operators don't inherit).
+ nsOutputStream& operator << (const char* buf);
+ nsOutputStream& operator << (char ch);
+ nsOutputStream& operator << (short val);
+ nsOutputStream& operator << (unsigned short val);
+ nsOutputStream& operator << (long val);
+ nsOutputStream& operator << (unsigned long val);
+ nsOutputStream& operator << (int val);
+ nsOutputStream& operator << (unsigned int val);
+
+ // Support manipulators
+ nsOutputStream& operator << (nsOutputStream& (*pf)(nsOutputStream&))
+ {
+ return pf(*this);
+ }
+
+private:
+
+ // private and unimplemented to disallow copies and assigns
+ nsOutputStream(const nsOutputStream& rhs);
+ nsOutputStream& operator=(const nsOutputStream& rhs);
+
+ nsresult mWriteStatus;
+
+// DATA
+protected:
+ nsCOMPtr<nsIOutputStream> mOutputStream;
+}; // class nsOutputStream
+
+typedef nsOutputStream nsBasicOutStream; // Historic support for this name
+
+//========================================================================================
+class NS_COM_OBSOLETE nsErrorProne
+// Common (virtual) base class for remembering errors on demand
+//========================================================================================
+{
+public:
+ nsErrorProne() // for delayed opening
+ : mResult(NS_OK)
+ {
+ }
+ PRBool failed() const
+ {
+ return NS_FAILED(mResult);
+ }
+ nsresult error() const
+ {
+ return mResult;
+ }
+
+// DATA
+protected:
+ nsresult mResult;
+}; // class nsErrorProne
+
+//========================================================================================
+class NS_COM_OBSOLETE nsFileClient
+// Because COM does not allow us to write functions which return a boolean value etc,
+// this class is here to take care of the tedious "declare variable then call with
+// the address of the variable" chores.
+//========================================================================================
+: public virtual nsErrorProne
+{
+public:
+ nsFileClient(const nsCOMPtr<nsIOpenFile>& inFile)
+ : mFile(do_QueryInterface(inFile))
+ {
+ }
+ virtual ~nsFileClient() {}
+
+ void open(
+ const nsFileSpec& inFile,
+ int nsprMode,
+ PRIntn accessMode)
+ {
+ if (mFile)
+ mResult = mFile->Open(inFile, nsprMode, accessMode);
+ }
+ PRBool is_open() const
+ {
+ PRBool result = PR_FALSE;
+ if (mFile)
+ mFile->GetIsOpen(&result);
+ return result;
+ }
+ PRBool is_file() const
+ {
+ return mFile ? PR_TRUE : PR_FALSE;
+ }
+
+protected:
+
+ nsFileClient() // for delayed opening
+ {
+ }
+// DATA
+protected:
+ nsCOMPtr<nsIOpenFile> mFile;
+}; // class nsFileClient
+
+//========================================================================================
+class NS_COM_OBSOLETE nsRandomAccessStoreClient
+// Because COM does not allow us to write functions which return a boolean value etc,
+// this class is here to take care of the tedious "declare variable then call with
+// the address of the variable" chores.
+//========================================================================================
+: public virtual nsErrorProne
+{
+public:
+ nsRandomAccessStoreClient() // for delayed opening
+ {
+ }
+ nsRandomAccessStoreClient(const nsCOMPtr<nsIRandomAccessStore>& inStore)
+ : mStore(do_QueryInterface(inStore))
+ {
+ }
+ virtual ~nsRandomAccessStoreClient() {}
+
+ void seek(PRInt64 offset)
+ {
+ seek(PR_SEEK_SET, offset);
+ }
+
+ void seek(PRSeekWhence whence, PRInt64 offset)
+ {
+ set_at_eof(PR_FALSE);
+ if (mStore)
+ mResult = mStore->Seek(whence, offset);
+ }
+ PRInt64 tell()
+ {
+ PRInt64 result;
+ LL_I2L(result, -1);
+ if (mStore)
+ mResult = mStore->Tell(&result);
+ return result;
+ }
+
+protected:
+
+ virtual PRBool get_at_eof() const
+ {
+ PRBool result = PR_TRUE;
+ if (mStore)
+ mStore->GetAtEOF(&result);
+ return result;
+ }
+
+ virtual void set_at_eof(PRBool atEnd)
+ {
+ if (mStore)
+ mStore->SetAtEOF(atEnd);
+ }
+
+private:
+
+ // private and unimplemented to disallow copies and assigns
+ nsRandomAccessStoreClient(const nsRandomAccessStoreClient& rhs);
+ nsRandomAccessStoreClient& operator=(const nsRandomAccessStoreClient& rhs);
+
+// DATA
+protected:
+ nsCOMPtr<nsIRandomAccessStore> mStore;
+}; // class nsRandomAccessStoreClient
+
+//========================================================================================
+class NS_COM_OBSOLETE nsRandomAccessInputStream
+// Please read the comments at the top of this file
+//========================================================================================
+: public nsRandomAccessStoreClient
+, public nsInputStream
+{
+public:
+ nsRandomAccessInputStream(nsIInputStream* inStream)
+ : nsRandomAccessStoreClient(do_QueryInterface(inStream))
+ , nsInputStream(inStream)
+ {
+ }
+ PRBool readline(char* s, PRInt32 n);
+ // Result always null-terminated.
+ // Check eof() before each call.
+ // CAUTION: false result only indicates line was truncated
+ // to fit buffer, or an error occurred (OTHER THAN eof).
+
+ // Input streamers. Unfortunately, they don't inherit!
+ nsInputStream& operator >> (char& ch)
+ { return nsInputStream::operator >>(ch); }
+ nsInputStream& operator >> (nsInputStream& (*pf)(nsInputStream&))
+ { return nsInputStream::operator >>(pf); }
+
+protected:
+ nsRandomAccessInputStream()
+ : nsInputStream(nsnull)
+ {
+ }
+
+ virtual PRBool get_at_eof() const
+ {
+ return nsRandomAccessStoreClient::get_at_eof();
+ }
+
+ virtual void set_at_eof(PRBool atEnd)
+ {
+ nsRandomAccessStoreClient::set_at_eof(atEnd);
+ }
+
+private:
+
+ // private and unimplemented to disallow copies and assigns
+ nsRandomAccessInputStream(const nsRandomAccessInputStream& rhs);
+ nsRandomAccessInputStream& operator=(const nsRandomAccessInputStream& rhs);
+
+}; // class nsRandomAccessInputStream
+
+//========================================================================================
+class NS_COM_OBSOLETE nsInputStringStream
+//========================================================================================
+: public nsRandomAccessInputStream
+{
+public:
+ nsInputStringStream(const char* stringToRead);
+ nsInputStringStream(const nsString& stringToRead);
+
+ // Input streamers. Unfortunately, they don't inherit!
+ nsInputStream& operator >> (char& ch)
+ { return nsInputStream::operator >>(ch); }
+ nsInputStream& operator >> (nsInputStream& (*pf)(nsInputStream&))
+ { return nsInputStream::operator >>(pf); }
+
+
+private:
+
+ // private and unimplemented to disallow copies and assigns
+ nsInputStringStream(const nsInputStringStream& rhs);
+ nsInputStringStream& operator=(const nsInputStringStream& rhs);
+
+
+}; // class nsInputStringStream
+
+//========================================================================================
+class NS_COM_OBSOLETE nsInputFileStream
+// Please read the comments at the top of this file
+//========================================================================================
+: public nsRandomAccessInputStream
+, public nsFileClient
+{
+public:
+ enum { kDefaultMode = PR_RDONLY };
+ nsInputFileStream(nsIInputStream* inStream)
+ : nsRandomAccessInputStream(inStream)
+ , nsFileClient(do_QueryInterface(inStream))
+ , mFileInputStream(do_QueryInterface(inStream))
+ {
+ }
+ nsInputFileStream(
+ const nsFileSpec& inFile,
+ int nsprMode = kDefaultMode,
+ PRIntn accessMode = 00666);
+ nsInputFileStream(nsIFileSpec* inFile);
+ virtual ~nsInputFileStream();
+
+ void Open(
+ const nsFileSpec& inFile,
+ int nsprMode = kDefaultMode,
+ PRIntn accessMode = 00666)
+ {
+ if (mFile)
+ mFile->Open(inFile, nsprMode, accessMode);
+ }
+
+ // Input streamers. Unfortunately, they don't inherit!
+ nsInputStream& operator >> (char& ch)
+ { return nsInputStream::operator >>(ch); }
+ nsInputStream& operator >> (nsInputStream& (*pf)(nsInputStream&))
+ { return nsInputStream::operator >>(pf); }
+
+protected:
+ void AssignFrom(nsISupports* stream);
+
+private:
+
+ // private and unimplemented to disallow copies and assigns
+ nsInputFileStream(const nsInputFileStream& rhs);
+ nsInputFileStream& operator=(const nsInputFileStream& rhs);
+
+// DATA
+protected:
+ nsCOMPtr<nsIFileSpecInputStream> mFileInputStream;
+}; // class nsInputFileStream
+
+//========================================================================================
+class NS_COM_OBSOLETE nsRandomAccessOutputStream
+// Please read the comments at the top of this file
+//========================================================================================
+: public nsRandomAccessStoreClient
+, public nsOutputStream
+{
+public:
+ nsRandomAccessOutputStream(nsIOutputStream* inStream)
+ : nsRandomAccessStoreClient(do_QueryInterface(inStream))
+ , nsOutputStream(inStream)
+ {
+ }
+
+ // Output streamers. Unfortunately, they don't inherit!
+ nsOutputStream& operator << (const char* buf)
+ { return nsOutputStream::operator << (buf); }
+ nsOutputStream& operator << (char ch)
+ { return nsOutputStream::operator << (ch); }
+ nsOutputStream& operator << (short val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (unsigned short val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (long val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (unsigned long val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (int val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (unsigned int val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (nsOutputStream& (*pf)(nsOutputStream&))
+ { return nsOutputStream::operator << (pf); }
+
+protected:
+ nsRandomAccessOutputStream()
+ : nsOutputStream(nsnull)
+ {
+ }
+
+private:
+
+ // private and unimplemented to disallow copies and assigns
+ nsRandomAccessOutputStream(const nsRandomAccessOutputStream& rhs);
+ nsRandomAccessOutputStream& operator=(const nsRandomAccessOutputStream& rhs);
+
+}; // class nsRandomAccessOutputStream
+
+//========================================================================================
+class NS_COM_OBSOLETE nsOutputFileStream
+// Please read the comments at the top of this file
+//========================================================================================
+: public nsRandomAccessOutputStream
+, public nsFileClient
+{
+public:
+ enum { kDefaultMode = (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE) };
+
+ nsOutputFileStream() {}
+ nsOutputFileStream(nsIOutputStream* inStream)
+ {
+ AssignFrom(inStream);
+ }
+ nsOutputFileStream(
+ const nsFileSpec& inFile,
+ int nsprMode = kDefaultMode,
+ PRIntn accessMode = 00666)
+ {
+ nsISupports* stream;
+ if (NS_FAILED(NS_NewIOFileStream(
+ &stream,
+ inFile, nsprMode, accessMode)))
+ return;
+ AssignFrom(stream);
+ NS_RELEASE(stream);
+ }
+ nsOutputFileStream(nsIFileSpec* inFile);
+ virtual ~nsOutputFileStream();
+
+ virtual nsresult flush();
+ virtual void abort();
+
+ // Output streamers. Unfortunately, they don't inherit!
+ nsOutputStream& operator << (const char* buf)
+ { return nsOutputStream::operator << (buf); }
+ nsOutputStream& operator << (char ch)
+ { return nsOutputStream::operator << (ch); }
+ nsOutputStream& operator << (short val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (unsigned short val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (long val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (unsigned long val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (int val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (unsigned int val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (nsOutputStream& (*pf)(nsOutputStream&))
+ { return nsOutputStream::operator << (pf); }
+
+protected:
+ void AssignFrom(nsISupports* stream);
+
+private:
+
+ // private and unimplemented to disallow copies and assigns
+ nsOutputFileStream(const nsOutputFileStream& rhs);
+ nsOutputFileStream& operator=(const nsOutputFileStream& rhs);
+
+// DATA
+protected:
+ nsCOMPtr<nsIFileSpecOutputStream> mFileOutputStream;
+}; // class nsOutputFileStream
+
+
+//========================================================================================
+class nsIOFileStream
+// Please read the comments at the top of this file
+//========================================================================================
+: public nsInputFileStream
+, public nsOutputStream
+{
+public:
+ enum { kDefaultMode = (PR_RDWR | PR_CREATE_FILE) };
+
+ nsIOFileStream(
+ nsIInputStream* inInputStream
+ , nsIOutputStream* inOutputStream)
+ : nsInputFileStream(inInputStream)
+ , nsOutputStream(inOutputStream)
+ , mFileOutputStream(do_QueryInterface(inOutputStream))
+ {
+ }
+ nsIOFileStream(
+ const nsFileSpec& inFile,
+ int nsprMode = kDefaultMode,
+ PRIntn accessMode = 00666)
+ : nsInputFileStream((nsIInputStream*)nsnull)
+ , nsOutputStream(nsnull)
+ {
+ nsISupports* stream;
+ if (NS_FAILED(NS_NewIOFileStream(
+ &stream,
+ inFile, nsprMode, accessMode)))
+ return;
+ mFile = do_QueryInterface(stream);
+ mStore = do_QueryInterface(stream);
+ mInputStream = do_QueryInterface(stream);
+ mOutputStream = do_QueryInterface(stream);
+ mFileInputStream = do_QueryInterface(stream);
+ mFileOutputStream = do_QueryInterface(stream);
+ NS_RELEASE(stream);
+ }
+
+ virtual nsresult close()
+ {
+ // Doesn't matter which of the two we close:
+ // they're hooked up to the same file.
+ return nsInputFileStream::close();
+ }
+
+ // Output streamers. Unfortunately, they don't inherit!
+ nsOutputStream& operator << (const char* buf)
+ { return nsOutputStream::operator << (buf); }
+ nsOutputStream& operator << (char ch)
+ { return nsOutputStream::operator << (ch); }
+ nsOutputStream& operator << (short val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (unsigned short val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (long val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (unsigned long val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (int val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (unsigned int val)
+ { return nsOutputStream::operator << (val); }
+ nsOutputStream& operator << (nsOutputStream& (*pf)(nsOutputStream&))
+ { return nsOutputStream::operator << (pf); }
+
+ // Input streamers. Unfortunately, they don't inherit!
+ nsInputStream& operator >> (char& ch)
+ { return nsInputStream::operator >>(ch); }
+ nsInputStream& operator >> (nsInputStream& (*pf)(nsInputStream&))
+ { return nsInputStream::operator >>(pf); }
+
+ virtual nsresult flush() {if (mFileOutputStream) mFileOutputStream->Flush(); return error(); }
+
+
+private:
+
+ // private and unimplemented to disallow copies and assigns
+ nsIOFileStream(const nsIOFileStream& rhs);
+ nsIOFileStream& operator=(const nsIOFileStream& rhs);
+
+ // DATA
+protected:
+ nsCOMPtr<nsIFileSpecOutputStream> mFileOutputStream;
+}; // class nsIOFileStream
+
+//========================================================================================
+// Manipulators
+//========================================================================================
+
+NS_COM_OBSOLETE nsOutputStream& nsEndl(nsOutputStream& os); // outputs and FLUSHES.
+
+//========================================================================================
+#endif /* _FILESTREAM_H_ */
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsIFileSpec.idl b/src/libs/xpcom18a4/xpcom/obsolete/nsIFileSpec.idl
new file mode 100644
index 00000000..78abd9e7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsIFileSpec.idl
@@ -0,0 +1,204 @@
+/* -*- 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 INTERFACE IS DEPRECATED AND UNSUPPORTED! USE |nsIFile| and |nsILocalFile|.
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+
+// This is the only correct cross-platform way to specify a file.
+// Strings are not such a way. If you grew up on windows or unix, you
+// may think they are. Welcome to reality.
+
+#include "nsISupports.idl"
+
+%{C++
+#include "nsFileSpec.h" // for factory method
+%}
+
+interface nsIFileURL;
+interface nsIFilePath;
+interface nsIOutputStream;
+interface nsIInputStream;
+
+// Define Contractid and CID
+%{C++
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ THIS INTERFACE IS DEPRECATED AND UNSUPPORTED! USE |nsIFile| and |nsILocalFile|.
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+// {A5740FA2-146E-11d3-B00D-00C04FC2E79B}
+#define NS_FILESPEC_CID \
+{ 0xa5740fa2, 0x146e, 0x11d3, { 0xb0, 0xd, 0x0, 0xc0, 0x4f, 0xc2, 0xe7, 0x9b } }
+
+#define NS_FILESPEC_CONTRACTID "@mozilla.org/filespec;1"
+#define NS_FILESPEC_CLASSNAME "File Spec"
+
+%}
+
+ native nsFileSpec(nsFileSpec);
+[ref] native nsFileSpecRef(nsFileSpec);
+[ptr] native nsFileSpecPtr(nsFileSpec);
+
+[scriptable, uuid(d8c0a080-0868-11d3-915f-d9d889d48e3c)]
+interface nsIFileSpec : nsISupports
+{
+ void fromFileSpec([const] in nsIFileSpec original);
+
+ attribute string URLString;
+ attribute string unixStyleFilePath;
+ attribute string persistentDescriptorString;
+ attribute string nativePath;
+
+ readonly attribute string NSPRPath;
+
+ void error();
+
+ boolean isValid();
+ boolean failed();
+
+ attribute string leafName;
+
+ readonly attribute nsIFileSpec parent;
+ readonly attribute nsIInputStream inputStream;
+ readonly attribute nsIOutputStream outputStream;
+ boolean isChildOf(in nsIFileSpec possibleParent);
+ [noscript] readonly attribute nsFileSpec fileSpec;
+ [noscript] void setFromFileSpec([const] in nsFileSpecRef spec);
+
+ attribute string fileContents;
+
+ void makeUnique();
+ void makeUniqueWithSuggestedName(in string suggestedName);
+
+ readonly attribute unsigned long modDate;
+ boolean modDateChanged(in unsigned long oldStamp);
+
+ boolean isDirectory();
+ boolean isFile();
+ boolean exists();
+ boolean isHidden();
+
+ boolean equals(in nsIFileSpec spec);
+
+ readonly attribute unsigned long fileSize;
+ readonly attribute long long diskSpaceAvailable;
+
+ void appendRelativeUnixPath(in string relativePath);
+
+ void createDir();
+ void touch();
+
+ boolean isSymlink();
+ void resolveSymlink();
+
+ void delete(in boolean recursive);
+ void truncate(in long aNewLength);
+ void rename([const] in string newLeafName);
+ void copyToDir([const] in nsIFileSpec newParentDir);
+ void moveToDir([const] in nsIFileSpec newParentDir);
+ void execute([const] in string args);
+
+ void openStreamForReading();
+ void openStreamForWriting();
+ void openStreamForReadingAndWriting();
+ void closeStream();
+ boolean isStreamOpen();
+
+ boolean eof();
+ long read(inout string buffer, in long requestedCount);
+ void readLine(inout string line, in long bufferSize, out boolean wasTruncated);
+
+ /** Check eof() before each call.
+ * CAUTION: false result only indicates line was truncated
+ * to fit buffer, or an error occurred (OTHER THAN eof).
+ */
+ long write(in string data, in long requestedCount);
+ void flush();
+
+ void seek(in long offset);
+ long tell();
+ void endLine();
+ attribute AString unicodePath;
+
+};
+
+// Define Contractid and CID
+%{C++
+// {a3020981-2018-11d3-915f-a957795b7ebc}
+#define NS_DIRECTORYITERATOR_CID \
+{ 0xa3020981, 0x2018, 0x11d3, { 0x91, 0x5f, 0xa9, 0x57, 0x79, 0x5b, 0x7e, 0xbc } }
+
+#define NS_DIRECTORYITERATOR_CONTRACTID "@mozilla.org/directoryiterator;1"
+#define NS_DIRECTORYITERATOR_CLASSNAME "nsIDirectoryIterator"
+%}
+
+[scriptable, uuid(d8c0a083-0868-11d3-915f-d9d889d48e3c)]
+interface nsIDirectoryIterator : nsISupports
+{
+ void init(in nsIFileSpec parent, in boolean resolveSymlink);
+ boolean exists();
+ void next();
+ readonly attribute nsIFileSpec currentSpec;
+};
+
+%{C++
+// Factory methods if you link with xpcom
+NS_COM_OBSOLETE nsresult NS_NewFileSpecWithSpec(const nsFileSpec& aSrcFileSpec, nsIFileSpec **result);
+NS_COM_OBSOLETE nsresult NS_NewFileSpec(nsIFileSpec** result);
+NS_COM_OBSOLETE nsresult NS_NewDirectoryIterator(nsIDirectoryIterator** result);
+
+// Convert from nsIFile to nsIFileSpec
+//
+// XXX This function is here only to assist with the migration from nsIFileSpec
+// to nsIFile. This function will dissappear in future mozilla releases.
+//
+// ...ripped from nsPrefService.cpp:
+//
+// "So discouraged is the use of nsIFileSpec, nobody wanted to have this routine be
+// public - It might lead to continued use of nsIFileSpec. Right now, [mozilla] has
+// such a need for it, here it is. Let's stop having to use it though."
+//
+NS_COM_OBSOLETE nsresult NS_NewFileSpecFromIFile(nsIFile *aFile, nsIFileSpec **result);
+
+#define NS_BOOL_ACCESSOR(_method) { PRBool yes; return NS_SUCCEEDED(f->_method(&yes)) && yes; }
+inline PRBool Exists(nsIFileSpec* f) NS_BOOL_ACCESSOR(Exists)
+inline PRBool Exists(nsIDirectoryIterator* f) NS_BOOL_ACCESSOR(Exists)
+inline PRBool IsDirectory(nsIFileSpec* f) NS_BOOL_ACCESSOR(IsDirectory)
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsIFileStream.cpp b/src/libs/xpcom18a4/xpcom/obsolete/nsIFileStream.cpp
new file mode 100644
index 00000000..011bcdaa
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsIFileStream.cpp
@@ -0,0 +1,727 @@
+/* -*- 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 "nsIFileStream.h"
+#include "nsFileSpec.h"
+#include "nsCOMPtr.h"
+
+#include "prerror.h"
+
+#include "nsSegmentedBuffer.h"
+#include "nsInt64.h"
+
+#ifdef XP_MAC
+#include "pprio.h" // To get PR_ImportFile
+#else
+#include "prio.h"
+#endif
+
+#ifdef XP_MAC
+#include <Errors.h>
+#include <iostream>
+#endif
+
+//========================================================================================
+class FileImpl
+ : public nsIRandomAccessStore
+ , public nsIFileSpecOutputStream
+ , public nsIFileSpecInputStream
+ , public nsIOpenFile
+//========================================================================================
+{
+ public:
+ FileImpl(PRFileDesc* inDesc);
+ FileImpl(const nsFileSpec& inFile, int nsprMode, PRIntn accessMode);
+
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+
+ // nsIOpenFile interface
+ NS_IMETHOD Open(const nsFileSpec& inFile, int nsprMode, PRIntn accessMode);
+ NS_IMETHOD Close();
+ NS_IMETHOD GetIsOpen(PRBool* outOpen);
+
+ // nsIInputStream interface
+ NS_IMETHOD Available(PRUint32 *aLength);
+ NS_IMETHOD Read(char* aBuf, PRUint32 aCount, PRUint32 *aReadCount);
+ NS_IMETHOD ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval);
+ NS_IMETHOD IsNonBlocking(PRBool *aNonBlocking);
+
+ // nsIOutputStream interface
+ NS_IMETHOD Write(const char* aBuf, PRUint32 aCount, PRUint32 *aWriteCount);
+ NS_IMETHOD Flush();
+ NS_IMETHOD WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval);
+ NS_IMETHOD WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval);
+
+ // nsIRandomAccessStore interface
+ NS_DECL_NSISEEKABLESTREAM
+ NS_IMETHOD GetAtEOF(PRBool* outAtEOF);
+ NS_IMETHOD SetAtEOF(PRBool inAtEOF);
+
+ private:
+
+ ~FileImpl();
+
+ protected:
+
+ enum {
+ kOuputBufferSegmentSize = 4096,
+ kOuputBufferMaxSize = 4096
+ };
+
+ nsresult InternalFlush(PRBool syncFile);
+ nsresult AllocateBuffers(PRUint32 segmentSize, PRUint32 maxSize);
+
+ PRFileDesc* mFileDesc;
+ int mNSPRMode;
+ PRBool mFailed;
+ PRBool mEOF;
+ PRInt32 mLength;
+
+ PRBool mGotBuffers;
+ nsSegmentedBuffer mOutBuffer;
+ char* mWriteCursor;
+ char* mWriteLimit;
+
+}; // class FileImpl
+
+NS_IMPL_RELEASE(FileImpl)
+NS_IMPL_ADDREF(FileImpl)
+
+NS_IMPL_QUERY_HEAD(FileImpl)
+ NS_IMPL_QUERY_BODY(nsIOpenFile)
+ NS_IMPL_QUERY_BODY(nsISeekableStream)
+ NS_IMPL_QUERY_BODY(nsIRandomAccessStore)
+ NS_IMPL_QUERY_BODY(nsIOutputStream)
+ NS_IMPL_QUERY_BODY(nsIInputStream)
+ NS_IMPL_QUERY_BODY(nsIFileSpecInputStream)
+ NS_IMPL_QUERY_BODY(nsIFileSpecOutputStream)
+NS_IMPL_QUERY_TAIL(nsIOutputStream)
+
+
+//----------------------------------------------------------------------------------------
+FileImpl::FileImpl(PRFileDesc* inDesc)
+//----------------------------------------------------------------------------------------
+: mFileDesc(inDesc)
+, mNSPRMode(0)
+, mFailed(PR_FALSE)
+, mEOF(PR_FALSE)
+, mLength(-1)
+, mGotBuffers(PR_FALSE)
+{
+ mWriteCursor = nsnull;
+ mWriteLimit = nsnull;
+}
+
+
+//----------------------------------------------------------------------------------------
+FileImpl::FileImpl(const nsFileSpec& inFile, int nsprMode, PRIntn accessMode)
+//----------------------------------------------------------------------------------------
+: mFileDesc(nsnull)
+, mNSPRMode(-1)
+, mEOF(PR_FALSE)
+, mLength(-1)
+, mGotBuffers(PR_FALSE)
+{
+ mWriteCursor = nsnull;
+ mWriteLimit = nsnull;
+
+ nsresult rv = Open(inFile, nsprMode, accessMode); // this sets nsprMode
+
+ if (NS_FAILED(rv))
+ {
+ mFailed = PR_TRUE;
+#if DEBUG
+ char *fileName = inFile.GetLeafName();
+ printf("Opening file %s failed\n", fileName);
+ nsCRT::free(fileName);
+#endif
+ }
+ else
+ {
+ mFailed = PR_FALSE;
+ }
+}
+
+//----------------------------------------------------------------------------------------
+FileImpl::~FileImpl()
+//----------------------------------------------------------------------------------------
+{
+ nsresult rv = Close();
+ NS_ASSERTION(NS_SUCCEEDED(rv), "Close failed");
+}
+
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP FileImpl::Open(
+ const nsFileSpec& inFile,
+ int nsprMode,
+ PRIntn accessMode)
+//----------------------------------------------------------------------------------------
+{
+ if (mFileDesc)
+ if ((nsprMode & mNSPRMode) == nsprMode)
+ return NS_OK;
+ else
+ return NS_FILE_RESULT(PR_ILLEGAL_ACCESS_ERROR);
+
+ const int nspr_modes[]={
+ PR_WRONLY | PR_CREATE_FILE,
+ PR_WRONLY | PR_CREATE_FILE | PR_APPEND,
+ PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+ PR_RDONLY,
+ PR_RDONLY | PR_APPEND,
+ PR_RDWR | PR_CREATE_FILE,
+ PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE,
+// "wb",
+// "ab",
+// "wb",
+// "rb",
+// "r+b",
+// "w+b",
+ 0 };
+ const int* currentLegalMode = nspr_modes;
+ while (*currentLegalMode && nsprMode != *currentLegalMode)
+ ++currentLegalMode;
+ if (!*currentLegalMode)
+ return NS_FILE_RESULT(PR_ILLEGAL_ACCESS_ERROR);
+
+#ifdef XP_MAC
+ // Use the file spec to open the file, because one path can be common to
+ // several files on the Macintosh (you can have several volumes with the
+ // same name, see).
+ mFileDesc = 0;
+ OSErr err = inFile.Error();
+ if (err != noErr)
+ if (err != fnfErr || !(nsprMode & PR_CREATE_FILE))
+ return NS_FILE_RESULT(inFile.Error());
+ err = noErr;
+#if DEBUG
+ const OSType kCreator = 'CWIE';
+#else
+ const OSType kCreator = 'MOSS';
+#endif
+ // Resolve the alias to the original file.
+ nsFileSpec original = inFile;
+ PRBool ignoredResult;
+ original.ResolveSymlink(ignoredResult);
+ const FSSpec& spec = original.operator const FSSpec&();
+ if (nsprMode & PR_CREATE_FILE) {
+ // In order to get the right file type/creator, do it with an nsILocalFileMac
+ // Don't propagate any errors in doing this. If any error, just use FSpCreate.
+ FSSpec nonConstSpec = spec;
+ nsCOMPtr<nsILocalFileMac> macFile;
+ nsresult res = NS_NewLocalFileWithFSSpec(&nonConstSpec, PR_FALSE, getter_AddRefs(macFile));
+ if (NS_SUCCEEDED(res)) {
+ nsCOMPtr<nsIFile> asFile(do_QueryInterface(macFile, &res));
+ if (NS_SUCCEEDED(res)) {
+ res = asFile->Create(nsIFile::NORMAL_FILE_TYPE, 0);
+ if (res == NS_ERROR_FILE_ALREADY_EXISTS)
+ res = NS_OK;
+ }
+ }
+ if (NS_FAILED(res))
+ err = FSpCreate(&spec, kCreator, 'TEXT', 0);
+ }
+
+ if (err == dupFNErr)
+ err = noErr;
+ if (err != noErr)
+ return NS_FILE_RESULT(err);
+
+ SInt8 perm;
+ if (nsprMode & PR_RDWR)
+ perm = fsRdWrPerm;
+ else if (nsprMode & PR_WRONLY)
+ perm = fsWrPerm;
+ else
+ perm = fsRdPerm;
+
+ short refnum;
+ err = FSpOpenDF(&spec, perm, &refnum);
+
+ if (err == noErr && (nsprMode & PR_TRUNCATE))
+ err = ::SetEOF(refnum, 0);
+ if (err == noErr && (nsprMode & PR_APPEND))
+ err = SetFPos(refnum, fsFromLEOF, 0);
+ if (err != noErr)
+ return NS_FILE_RESULT(err);
+
+ if ((mFileDesc = PR_ImportFile(refnum)) == 0)
+ return NS_FILE_RESULT(PR_GetError());
+#else
+ // Platforms other than Macintosh...
+ // Another bug in NSPR: Mac PR_Open assumes a unix style path, but Win PR_Open assumes
+ // a windows path.
+ if ((mFileDesc = PR_Open((const char*)nsFileSpec(inFile), nsprMode, accessMode)) == 0)
+ return NS_FILE_RESULT(PR_GetError());
+#endif
+ mNSPRMode = nsprMode;
+ mLength = PR_Available(mFileDesc);
+ return NS_OK;
+} // FileImpl::Open
+
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP FileImpl::Available(PRUint32 *aLength)
+//----------------------------------------------------------------------------------------
+{
+ NS_PRECONDITION(aLength != nsnull, "null ptr");
+ if (!aLength)
+ return NS_ERROR_NULL_POINTER;
+ if (mLength < 0)
+ return NS_ERROR_UNEXPECTED;
+ *aLength = mLength;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP FileImpl::GetIsOpen(PRBool* outOpen)
+//----------------------------------------------------------------------------------------
+{
+ *outOpen = (mFileDesc != nsnull && !mFailed);
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP FileImpl::Seek(PRInt32 whence, PRInt64 offset)
+//----------------------------------------------------------------------------------------
+{
+ if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || !mFileDesc)
+ return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
+ mFailed = PR_FALSE; // reset on a seek.
+ mEOF = PR_FALSE; // reset on a seek.
+
+ // To avoid corruption, we flush during a seek. see bug number 18949
+ InternalFlush(PR_FALSE);
+
+ nsInt64 position = PR_Seek64(mFileDesc, 0, PR_SEEK_CUR);
+ nsInt64 available = PR_Available64(mFileDesc);
+ nsInt64 fileSize = position + available;
+ nsInt64 newPosition = offset;
+ switch (whence)
+ {
+ case NS_SEEK_CUR: newPosition += position; break;
+ case NS_SEEK_SET: ; break;
+ case NS_SEEK_END: newPosition += fileSize; break;
+ }
+ const nsInt64 zero = 0;
+ if (newPosition < zero)
+ {
+ newPosition = 0;
+ mFailed = PR_TRUE;
+ }
+ if (newPosition >= fileSize) // nb: not "else if".
+ {
+ newPosition = fileSize;
+ mEOF = PR_TRUE;
+ }
+ if (PR_Seek64(mFileDesc, newPosition, PR_SEEK_SET) < 0)
+ mFailed = PR_TRUE;
+ return NS_OK;
+} // FileImpl::Seek
+
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP FileImpl::Read(char* aBuf, PRUint32 aCount, PRUint32 *aReadCount)
+//----------------------------------------------------------------------------------------
+{
+ NS_PRECONDITION(aBuf != nsnull, "null ptr");
+ if (!aBuf)
+ return NS_ERROR_NULL_POINTER;
+ NS_PRECONDITION(aReadCount != nsnull, "null ptr");
+ if (!aReadCount)
+ return NS_ERROR_NULL_POINTER;
+ if (!mFileDesc)
+ return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
+ if (mFailed)
+ return NS_ERROR_FAILURE;
+ PRInt32 bytesRead = PR_Read(mFileDesc, aBuf, aCount);
+ if (bytesRead < 0)
+ {
+ *aReadCount = 0;
+ mFailed = PR_TRUE;
+ return NS_FILE_RESULT(PR_GetError());
+ }
+ else if (bytesRead == 0)
+ {
+ mEOF = PR_TRUE;
+ }
+ *aReadCount = bytesRead;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+FileImpl::ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval)
+{
+ NS_NOTREACHED("ReadSegments");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP FileImpl::Write(const char* aBuf, PRUint32 aCount, PRUint32 *aWriteCount)
+//----------------------------------------------------------------------------------------
+{
+ NS_PRECONDITION(aBuf != nsnull, "null ptr");
+ NS_PRECONDITION(aWriteCount != nsnull, "null ptr");
+
+ *aWriteCount = 0;
+
+#ifdef XP_MAC
+ // Calling PR_Write on stdout is sure suicide.
+ if (mFileDesc == PR_STDOUT || mFileDesc == PR_STDERR)
+ {
+ std::cout.write(aBuf, aCount);
+ *aWriteCount = aCount;
+ return NS_OK;
+ }
+#endif
+ if (!mFileDesc)
+ return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
+ if (mFailed)
+ return NS_ERROR_FAILURE;
+
+ if (!mGotBuffers)
+ {
+ nsresult rv = AllocateBuffers(kOuputBufferSegmentSize, kOuputBufferMaxSize);
+ if (NS_FAILED(rv))
+ return rv; // try to write non-buffered?
+ }
+
+ PRUint32 bufOffset = 0;
+ PRUint32 currentWrite = 0;
+ while (aCount > 0)
+ {
+ if (mWriteCursor == nsnull || mWriteCursor == mWriteLimit)
+ {
+ char* seg = mOutBuffer.AppendNewSegment();
+ if (seg == nsnull)
+ {
+ // buffer is full, try again
+ InternalFlush(PR_FALSE);
+ seg = mOutBuffer.AppendNewSegment();
+ if (seg == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ mWriteCursor = seg;
+ mWriteLimit = seg + mOutBuffer.GetSegmentSize();
+ }
+
+ // move
+ currentWrite = mWriteLimit - mWriteCursor;
+
+ if (aCount < currentWrite)
+ currentWrite = aCount;
+
+ memcpy(mWriteCursor, (aBuf + bufOffset), currentWrite);
+
+ mWriteCursor += currentWrite;
+
+ aCount -= currentWrite;
+ bufOffset += currentWrite;
+ *aWriteCount += currentWrite;
+ }
+
+ return NS_OK;
+}
+
+static NS_METHOD
+nsWriteSegmentToFile(nsIInputStream* in,
+ void* closure,
+ const char* fromRawSegment,
+ PRUint32 toOffset,
+ PRUint32 count,
+ PRUint32 *writeCount)
+{
+ NS_NOTREACHED("nsWriteSegmentToFile");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+FileImpl::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *result)
+{
+ return inStr->ReadSegments(nsWriteSegmentToFile, nsnull, count, result);
+}
+
+NS_IMETHODIMP
+FileImpl::WriteSegments(nsReadSegmentFun reader, void * closure,
+ PRUint32 count, PRUint32 *result)
+{
+ NS_NOTREACHED("WriteSegments");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+FileImpl::IsNonBlocking(PRBool *aNonBlocking)
+{
+ *aNonBlocking = PR_FALSE;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP FileImpl::Tell(PRInt64* outWhere)
+//----------------------------------------------------------------------------------------
+{
+ if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || !mFileDesc)
+ return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
+ *outWhere = PR_Seek64(mFileDesc, 0, PR_SEEK_CUR);
+ return NS_OK;
+} // FileImpl::Tell
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP FileImpl::Close()
+//----------------------------------------------------------------------------------------
+{
+ if ((mNSPRMode & PR_RDONLY) == 0)
+ InternalFlush(PR_FALSE);
+
+ if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || !mFileDesc)
+ return NS_OK;
+ if (PR_Close(mFileDesc) == PR_SUCCESS)
+ mFileDesc = 0;
+ else
+ return NS_FILE_RESULT(PR_GetError());
+ return NS_OK;
+} // FileImpl::close
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP FileImpl::Flush()
+//----------------------------------------------------------------------------------------
+{
+ // for external callers, this will do a Sync as well as flush buffers.
+ return InternalFlush(PR_TRUE);
+} // FileImpl::flush
+
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP FileImpl::GetAtEOF(PRBool* outAtEOF)
+//----------------------------------------------------------------------------------------
+{
+ *outAtEOF = mEOF;
+ return NS_OK;
+}
+
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP FileImpl::SetAtEOF(PRBool inAtEOF)
+//----------------------------------------------------------------------------------------
+{
+ mEOF = inAtEOF;
+ return NS_OK;
+}
+
+//----------------------------------------------------------------------------------------
+NS_IMETHODIMP FileImpl::SetEOF()
+//----------------------------------------------------------------------------------------
+{
+ NS_NOTYETIMPLEMENTED("FileImpl::SetEOF");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+//----------------------------------------------------------------------------------------
+nsresult FileImpl::AllocateBuffers(PRUint32 segmentSize, PRUint32 maxBufSize)
+//----------------------------------------------------------------------------------------
+{
+ nsresult rv = mOutBuffer.Init(segmentSize, maxBufSize);
+ if (NS_SUCCEEDED(rv))
+ mGotBuffers = PR_TRUE;
+
+ return rv;
+}
+
+// external callers of Flush will have sync get called,
+// but internal callers just want to flush the buffers to disk.
+nsresult FileImpl::InternalFlush(PRBool syncFile)
+{
+#ifdef XP_MAC
+ if (mFileDesc == PR_STDOUT || mFileDesc == PR_STDERR)
+ {
+ std::cout.flush();
+ return NS_OK;
+ }
+#endif
+ if (!mFileDesc)
+ return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
+
+ PRInt32 segCount = mOutBuffer.GetSegmentCount();
+ PRUint32 segSize = mOutBuffer.GetSegmentSize();
+
+ for (PRInt32 i = 0; i < segCount; i++)
+ {
+ char* seg = mOutBuffer.GetSegment(i);
+
+ // if it is the last buffer, it may not be completely full.
+ if(i == (segCount-1))
+ segSize = (mWriteCursor - seg);
+
+ PRInt32 bytesWrit = PR_Write(mFileDesc, seg, segSize);
+ if (bytesWrit != (PRInt32)segSize)
+ {
+ mFailed = PR_TRUE;
+ return NS_FILE_RESULT(PR_GetError());
+ }
+ }
+
+ if (mGotBuffers)
+ mOutBuffer.Empty();
+ mWriteCursor = nsnull;
+ mWriteLimit = nsnull;
+
+ // On unix, it seems to fail always.
+ if (syncFile && PR_Sync(mFileDesc) != PR_SUCCESS)
+ mFailed = PR_TRUE;
+
+ return NS_OK;
+}
+//----------------------------------------------------------------------------------------
+nsresult NS_NewTypicalInputFileStream(
+ nsISupports** aResult,
+ const nsFileSpec& inFile
+ /*Default nsprMode == PR_RDONLY*/
+ /*Default accessmode = 0666 (octal)*/)
+// Factory method to get an nsInputStream from a file, using most common options
+//----------------------------------------------------------------------------------------
+{
+ // This QueryInterface was needed because NS_NewIOFileStream
+ // does a cast from (void *) to (nsISupports *) thus causing a
+ // vtable problem on Windows, where we really didn't have the proper pointer
+ // to an nsIInputStream, this ensures that we do
+ nsISupports * supports;
+ nsIInputStream * inStr;
+
+ nsresult rv = NS_NewIOFileStream(&supports, inFile, PR_RDONLY, 0666);
+
+ *aResult = nsnull;
+ if (NS_SUCCEEDED(rv)) {
+ if (NS_SUCCEEDED(supports->QueryInterface(NS_GET_IID(nsIInputStream), (void**)&inStr))) {
+ *aResult = inStr;
+ }
+ NS_RELEASE(supports);
+ }
+ return rv;
+}
+
+//----------------------------------------------------------------------------------------
+nsresult NS_NewTypicalOutputFileStream(
+ nsISupports** aResult,
+ const nsFileSpec& inFile
+ /*default nsprMode= (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE)*/
+ /*Default accessMode= 0666 (octal)*/)
+// Factory method to get an nsOutputStream to a file - most common case.
+//----------------------------------------------------------------------------------------
+{
+ // This QueryInterface was needed because NS_NewIOFileStream
+ // does a cast from (void *) to (nsISupports *) thus causing a
+ // vtable problem on Windows, where we really didn't have the proper pointer
+ // to an nsIOutputStream, this ensures that we do
+#if 1
+/* nsISupports * supports;
+ nsIOutputStream * outStr;
+
+ nsresult rv = NS_NewIOFileStream(
+ &supports,
+ inFile,
+ (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE),
+ 0666);
+
+ *aResult = nsnull;
+ if (NS_SUCCEEDED(rv)) {
+ if (NS_SUCCEEDED(supports->QueryInterface(NS_GET_IID(nsIOutputStream), (void**)&outStr))) {
+ *aResult = outStr;
+ }
+ NS_RELEASE(supports);
+ }
+ return rv;
+ */
+
+ nsCOMPtr<nsISupports> supports;
+ nsIOutputStream * outStr;
+
+ nsresult rv = NS_NewIOFileStream(
+ getter_AddRefs(supports),
+ inFile,
+ (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE),
+ 0666);
+
+ *aResult = nsnull;
+ if (NS_SUCCEEDED(rv)) {
+ if (NS_SUCCEEDED(supports->QueryInterface(NS_GET_IID(nsIOutputStream), (void**)&outStr))) {
+ *aResult = outStr;
+ }
+ }
+ return rv;
+#else
+ return NS_NewIOFileStream(
+ aResult,
+ inFile,
+ (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE),
+ 0666);
+#endif
+}
+
+//----------------------------------------------------------------------------------------
+NS_COM_OBSOLETE nsresult NS_NewIOFileStream(
+ nsISupports** aResult,
+ const nsFileSpec& inFile,
+ PRInt32 nsprMode /*default = (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE)*/,
+ PRInt32 accessMode /*Default = 0666 (octal)*/)
+ // Factory method to get an object that implements both nsIInputStream
+ // and nsIOutputStream, associated with a file.
+//----------------------------------------------------------------------------------------
+{
+ NS_PRECONDITION(aResult != nsnull, "null ptr");
+ if (!aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ FileImpl* stream = new FileImpl(inFile, nsprMode, accessMode);
+ if (! stream)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(stream);
+ PRBool isOpened = PR_FALSE;
+ stream->GetIsOpen(&isOpened);
+ if (!isOpened)
+ {
+ NS_RELEASE(stream);
+ return NS_ERROR_FAILURE;
+ }
+
+ *aResult = (nsISupports*)(void*)stream;
+ return NS_OK;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsIFileStream.h b/src/libs/xpcom18a4/xpcom/obsolete/nsIFileStream.h
new file mode 100644
index 00000000..251b3ffc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsIFileStream.h
@@ -0,0 +1,157 @@
+/* -*- 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 nsIFileStream_h___
+#define nsIFileStream_h___
+
+#include "xpcomobsolete.h"
+#include "nsIInputStream.h"
+#include "nsIOutputStream.h"
+#include "nsISeekableStream.h"
+#include "prio.h"
+
+class nsFileSpec;
+
+/* a6cf90e8-15b3-11d2-932e-00805f8add32 */
+#define NS_IOPENFILE_IID \
+{ 0xa6cf90e8, 0x15b3, 0x11d2, \
+ {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} }
+
+//========================================================================================
+class nsIOpenFile
+// Represents a file, and supports Open.
+//========================================================================================
+: public nsISupports
+{
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IOPENFILE_IID)
+
+ NS_IMETHOD Open(
+ const nsFileSpec& inFile,
+ int nsprMode,
+ PRIntn accessMode) = 0;
+ // Note: Open() is only needed after
+ // an explicit Close(). All file streams
+ // are automatically opened on construction.
+ NS_IMETHOD GetIsOpen(PRBool* outOpen) = 0;
+
+}; // class nsIOpenFile
+
+/* a6cf90e8-15b3-11d2-932e-00805f8add32 */
+#define NS_IRANDOMACCESS_IID \
+{ 0xa6cf90eb, 0x15b3, 0x11d2, \
+ {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} }
+
+//========================================================================================
+class nsIRandomAccessStore
+// Supports Seek, Tell etc.
+//========================================================================================
+: public nsISeekableStream
+{
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IRANDOMACCESS_IID)
+
+/* "PROTECTED" */
+ NS_IMETHOD GetAtEOF(PRBool* outAtEOF) = 0;
+ NS_IMETHOD SetAtEOF(PRBool inAtEOF) = 0;
+}; // class nsIRandomAccessStore
+
+
+#ifndef NO_XPCOM_FILE_STREAMS // hack to work around duplicate class definitions in here
+ // and mozilla/netwerks/base/nsIFileStreams.idl
+
+/* a6cf90e6-15b3-11d2-932e-00805f8add32 */
+#define NS_IFILESPECINPUTSTREAM_IID \
+{ 0xa6cf90e6, 0x15b3, 0x11d2, \
+ {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} }
+
+//========================================================================================
+class nsIFileSpecInputStream
+// These are additional file-specific methods that files have, above what
+// nsIInputStream supports. The current implementation supports both
+// interfaces.
+//========================================================================================
+: public nsIInputStream
+{
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IFILESPECINPUTSTREAM_IID)
+}; // class nsIFileSpecInputStream
+
+/* a6cf90e7-15b3-11d2-932e-00805f8add32 */
+#define NS_IFILESPECOUTPUTSTREAM_IID \
+{ 0xa6cf90e7, 0x15b3, 0x11d2, \
+ {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} }
+
+//========================================================================================
+class nsIFileSpecOutputStream
+// These are additional file-specific methods that files have, above what
+// nsIOutputStream supports. The current implementation supports both
+// interfaces.
+//========================================================================================
+: public nsIOutputStream
+{
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IFILESPECOUTPUTSTREAM_IID)
+}; // class nsIFileSpecOutputStream
+
+#endif // NO_XPCOM_FILE_STREAMS
+
+//----------------------------------------------------------------------------------------
+nsresult NS_NewTypicalInputFileStream(
+ nsISupports** aStreamResult,
+ const nsFileSpec& inFile
+ /*Default nsprMode == PR_RDONLY*/
+ /*Default accessmode = 0700 (octal)*/);
+// Factory method to get an nsInputStream from a file, using most common options
+
+//----------------------------------------------------------------------------------------
+nsresult NS_NewTypicalOutputFileStream(
+ nsISupports** aStreamResult, // will implement all the above interfaces
+ const nsFileSpec& inFile
+ /*default nsprMode= (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE)*/
+ /*Default accessMode= 0700 (octal)*/);
+ // Factory method to get an nsOutputStream to a file - most common case.
+
+//----------------------------------------------------------------------------------------
+extern "C" NS_COM_OBSOLETE nsresult NS_NewIOFileStream(
+ nsISupports** aStreamResult, // will implement all the above interfaces
+ const nsFileSpec& inFile,
+ PRInt32 nsprMode,
+ PRInt32 accessMode);
+ // Factory method to get an object that implements both nsIInputStream
+ // and nsIOutputStream, associated with a single file.
+
+#endif /* nsIFileSpecStream_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsIRegistry.idl b/src/libs/xpcom18a4/xpcom/obsolete/nsIRegistry.idl
new file mode 100644
index 00000000..bc9990e2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsIRegistry.idl
@@ -0,0 +1,186 @@
+/* -*- 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) 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"
+#include "nsIEnumerator.idl"
+
+interface nsIFile;
+
+typedef PRUint32 nsRegistryKey;
+typedef long nsWellKnownRegistry;
+
+[scriptable,uuid(5D41A440-8E37-11d2-8059-00600811A9C3)]
+interface nsIRegistry : nsISupports
+{
+ const long None = 0;
+ const long Users = 1;
+ const long Common = 2;
+ const long CurrentUser = 3;
+
+ const long ApplicationComponentRegistry = 1;
+ const long ApplicationRegistry = 2;
+
+ // Dont use this one. This for internal use only.
+ const long ApplicationCustomRegistry = -1;
+
+ void open(in nsIFile regFile);
+ void openWellKnownRegistry(in nsWellKnownRegistry regid);
+
+ void flush();
+ boolean isOpen();
+
+ nsRegistryKey addKey(in nsRegistryKey baseKey, in wstring keyname);
+ nsRegistryKey getKey(in nsRegistryKey baseKey, in wstring keyname);
+ void removeKey(in nsRegistryKey baseKey, in wstring keyname);
+
+ wstring getString(in nsRegistryKey baseKey, in wstring valname);
+ void setString(in nsRegistryKey baseKey, in wstring valname, in wstring value);
+
+ string getStringUTF8(in nsRegistryKey baseKey, in string path);
+ void setStringUTF8(in nsRegistryKey baseKey, in string path, in string value);
+
+ void getBytesUTF8(in nsRegistryKey baseKey, in string path, out PRUint32 length, [retval, array, size_is(length)] out PRUint8 valueArray);
+ void setBytesUTF8(in nsRegistryKey baseKey, in string path, in PRUint32 length, [array, size_is(length)] in PRUint8 valueArray);
+ PRInt32 getInt(in nsRegistryKey baseKey, in string path);
+ void setInt(in nsRegistryKey baseKey, in string path, in PRInt32 value);
+ PRInt64 getLongLong(in nsRegistryKey baseKey, in string path);
+ void setLongLong(in nsRegistryKey baseKey, in string path, inout PRInt64 value);
+
+ /**
+ * addSubtree() and friends need to be renamed to addKeyUTF8().
+ * If you are using these forms make sure you pass UTF8 data
+ */
+ nsRegistryKey addSubtree(in nsRegistryKey baseKey, in string path);
+ void removeSubtree(in nsRegistryKey baseKey, in string path);
+ nsRegistryKey getSubtree(in nsRegistryKey baseKey, in string path);
+
+ nsRegistryKey addSubtreeRaw(in nsRegistryKey baseKey, in string path);
+ void removeSubtreeRaw(in nsRegistryKey baseKey, in string path);
+ nsRegistryKey getSubtreeRaw(in nsRegistryKey baseKey, in string path);
+
+ nsIEnumerator enumerateSubtrees(in nsRegistryKey baseKey);
+ nsIEnumerator enumerateAllSubtrees(in nsRegistryKey baseKey);
+ nsIEnumerator enumerateValues(in nsRegistryKey baseKey);
+
+ const unsigned long String = 1;
+ const unsigned long Int32 = 2;
+ const unsigned long Bytes = 3;
+ const unsigned long File = 4;
+
+ unsigned long getValueType(in nsRegistryKey baseKey, in string path);
+ PRUint32 getValueLength(in nsRegistryKey baseKey, in string path);
+ void deleteValue(in nsRegistryKey baseKey, in string path);
+
+ /**
+ * escapeKey() takes arbitrary binary data and converts it into
+ * valid ASCII which can be used as registry key or value names
+ */
+ void escapeKey([array, size_is(length)] in PRUint8 key, in PRUint32 terminator, inout PRUint32 length, [retval, array, size_is(length)] out PRUint8 escaped);
+ void unescapeKey([array, size_is(length)] in PRUint8 escaped, in PRUint32 terminator, inout PRUint32 length, [retval, array, size_is(length)] out PRUint8 key);
+
+ attribute string currentUserName;
+
+ void pack();
+};
+
+[scriptable, uuid(8cecf236-1dd2-11b2-893c-f9848956eaec)]
+interface nsIRegistryEnumerator : nsIEnumerator
+{
+ void currentItemInPlaceUTF8(out nsRegistryKey key,
+ [shared, retval] out string item);
+};
+
+[scriptable, uuid(D1B54831-AC07-11d2-805E-00600811A9C3)]
+interface nsIRegistryNode : nsISupports
+{
+ readonly attribute string nameUTF8;
+ readonly attribute wstring name;
+ readonly attribute nsRegistryKey key;
+};
+
+[scriptable,uuid(5316C380-B2F8-11d2-A374-0080C6F80E4B)]
+interface nsIRegistryValue : nsISupports
+{
+ readonly attribute wstring name;
+ readonly attribute string nameUTF8;
+ readonly attribute unsigned long type;
+ readonly attribute PRUint32 length;
+};
+
+[uuid(3A15FC88-7A61-4Ab4-8E58-31E95fAB3DA8)]
+/**
+ * It sucks that nsIRegistry has to always allocate and return
+ * strings. nsIRegistryGetter adds in interfaces for non allocating getters
+ * to registry values.
+ */
+interface nsIRegistryGetter : nsISupports
+{
+ /**
+ * Get a string value of attribute valname in widestring or utf8 format
+ *
+ * @return
+ * NS_OK on success.
+ * buf has the string value copied into it. length is NOT changed.
+ * NS_ERROR_REG_BUFFER_TOO_SMALL if not enough buffer space.
+ * length is updated to actual length in chars including
+ * terminating NULL and buf will be unchanged.
+ * NS_ERROR_FAILURE if an unknown error happened. state of buf and
+ * length undefined.
+ * various failure codes otherwise. buf and length wont be updated.
+ */
+ void getStringUTF8IntoBuffer(in nsRegistryKey baseKey, in string path,
+ inout char buf, inout PRUint32 length);
+
+ /**
+ * Get a a byte array value of attribute valname
+ *
+ * @return
+ * NS_OK on success. buf has the string value copied into it.
+ * length is updated to actual number of bytes copied into buf.
+ * NS_ERROR_REG_BUFFER_TOO_SMALL if not enough buffer space.
+ * length is updated to actual length in PRUint8s including
+ * terminating NULL and buf will be unchanged.
+ * NS_ERROR_FAILURE if an unknown error happened. state of buf and
+ * length undefined.
+ * various other failure codes otherwise. buf and length wont be updated.
+ */
+ void getBytesUTF8IntoBuffer(in nsRegistryKey baseKey, in string path,
+ inout PRUint8 buf, inout PRUint32 length);
+};
+
+%{ C++
+#include "nsIRegistryUtils.h"
+%}
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsIRegistryUtils.h b/src/libs/xpcom18a4/xpcom/obsolete/nsIRegistryUtils.h
new file mode 100644
index 00000000..a3d74d7a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsIRegistryUtils.h
@@ -0,0 +1,63 @@
+/* -*- 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 __nsIRegistryUtils_h
+#define __nsIRegistryUtils_h
+
+#define NS_REGISTRY_CONTRACTID "@mozilla.org/registry;1"
+#define NS_REGISTRY_CLASSNAME "Mozilla Registry"
+/* be761f00-a3b0-11d2-996c-0080c7cb1081 */
+#define NS_REGISTRY_CID \
+{ \
+ 0xbe761f00, \
+ 0xa3b0, \
+ 0x11d2, \
+ {0x99, 0x6c, 0x00, 0x80, 0xc7, 0xcb, 0x10, 0x81} \
+}
+
+/*------------------------------- Error Codes ----------------------------------
+------------------------------------------------------------------------------*/
+#define NS_ERROR_REG_BADTYPE NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 1 )
+#define NS_ERROR_REG_NO_MORE NS_ERROR_GENERATE_SUCCESS( NS_ERROR_MODULE_REG, 2 )
+#define NS_ERROR_REG_NOT_FOUND NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 3 )
+#define NS_ERROR_REG_NOFILE NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 4 )
+#define NS_ERROR_REG_BUFFER_TOO_SMALL NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 5 )
+#define NS_ERROR_REG_NAME_TOO_LONG NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 6 )
+#define NS_ERROR_REG_NO_PATH NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 7 )
+#define NS_ERROR_REG_READ_ONLY NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 8 )
+#define NS_ERROR_REG_BAD_UTF8 NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 9 )
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsSpecialSystemDirectory.cpp b/src/libs/xpcom18a4/xpcom/obsolete/nsSpecialSystemDirectory.cpp
new file mode 100644
index 00000000..f120cd43
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsSpecialSystemDirectory.cpp
@@ -0,0 +1,1189 @@
+/* -*- 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):
+ * Doug Turner <dougt@netscape.com>
+ * IBM Corp.
+ *
+ * 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 "nsSpecialSystemDirectory.h"
+#include "nsDebug.h"
+
+#ifdef XP_MAC
+#include <Folders.h>
+#include <Files.h>
+#include <Memory.h>
+#include <Processes.h>
+#include <Gestalt.h>
+#include "nsIInternetConfigService.h"
+#ifdef DEBUG
+#include "prenv.h" // For PR_Getenv
+#endif
+#elif defined(XP_WIN)
+#include <windows.h>
+#include <shlobj.h>
+#include <stdlib.h>
+#include <stdio.h>
+#elif defined(XP_OS2)
+#define MAX_PATH _MAX_PATH
+#define INCL_WINWORKPLACE
+#include <os2.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "prenv.h"
+#elif defined(XP_UNIX)
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include "prenv.h"
+#elif defined(XP_BEOS)
+#include <FindDirectory.h>
+#include <Path.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <OS.h>
+#include <image.h>
+#include "prenv.h"
+#endif
+
+#if defined(VMS)
+#include <unixlib.h>
+#endif
+
+#include "plstr.h"
+
+#include "nsHashtable.h"
+#include "prlog.h"
+
+#if defined (XP_MAC) && UNIVERSAL_INTERFACES_VERSION < 0x0340
+ enum {
+ kSystemDomain = -32766, /* Read-only system hierarchy.*/
+ kLocalDomain = -32765, /* All users of a single machine have access to these resources.*/
+ kNetworkDomain = -32764, /* All users configured to use a common network server has access to these resources.*/
+ kUserDomain = -32763, /* Read/write. Resources that are private to the user.*/
+ kClassicDomain = -32762, /* Domain referring to the currently configured Classic System Folder*/
+
+ kDomainLibraryFolderType = FOUR_CHAR_CODE('dlib')
+ };
+#endif
+
+
+class SystemDirectoriesKey : public nsHashKey {
+public:
+
+ SystemDirectoriesKey(nsSpecialSystemDirectory::SystemDirectories newKey) : sdKey(newKey) {}
+
+ virtual PRUint32 HashCode(void) const
+ {
+ return PRUint32(sdKey);
+ }
+
+ virtual PRBool Equals(const nsHashKey *aKey) const
+ {
+ nsSpecialSystemDirectory::SystemDirectories other =
+ ((SystemDirectoriesKey*)aKey)->sdKey;
+ return other == sdKey;
+ }
+
+ virtual nsHashKey *Clone(void) const
+ {
+ return new SystemDirectoriesKey(sdKey);
+ }
+
+private:
+ nsSpecialSystemDirectory::SystemDirectories sdKey; // sd for SystemDirectories
+};
+
+PR_STATIC_CALLBACK(PRBool) DeleteSystemDirKeys(nsHashKey *aKey, void *aData, void* closure)
+{
+ delete ((nsFileSpec *)aData);
+ return PR_TRUE;
+}
+
+#define NS_SYSTEMDIR_HASH_NUM (10)
+static nsHashtable *systemDirectoriesLocations = NULL;
+#if defined (XP_WIN)
+typedef BOOL (WINAPI * GetSpecialPathProc) (HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate);
+GetSpecialPathProc gGetSpecialPathProc = NULL;
+static HINSTANCE gShell32DLLInst = NULL;
+#endif
+NS_COM_OBSOLETE void StartupSpecialSystemDirectory()
+{
+#if defined (XP_WIN)
+ /* On windows, the old method to get file locations is incredibly slow.
+ As of this writing, 3 calls to GetWindowsFolder accounts for 3% of mozilla
+ startup. Replacing these older calls with a single call to SHGetSpecialFolderPath
+ effectively removes these calls from the performace radar. We need to
+ support the older way of file location lookup on systems that do not have
+ IE4. (Note: gets the ansi version: SHGetSpecialFolderPathA).
+ */
+ gShell32DLLInst = LoadLibrary("Shell32.dll");
+ if(gShell32DLLInst)
+ {
+ gGetSpecialPathProc = (GetSpecialPathProc) GetProcAddress(gShell32DLLInst,
+ "SHGetSpecialFolderPathA");
+ }
+#endif
+}
+
+NS_COM_OBSOLETE void ShutdownSpecialSystemDirectory()
+{
+ if (systemDirectoriesLocations)
+ {
+ systemDirectoriesLocations->Reset(DeleteSystemDirKeys);
+ delete systemDirectoriesLocations;
+ }
+#if defined (XP_WIN)
+ if (gShell32DLLInst)
+ {
+ FreeLibrary(gShell32DLLInst);
+ gShell32DLLInst = NULL;
+ gGetSpecialPathProc = NULL;
+ }
+#endif
+}
+
+#if defined (XP_WIN)
+
+static PRBool gGlobalOSInitialized = PR_FALSE;
+static PRBool gGlobalDBCSEnabledOS = PR_FALSE;
+
+//----------------------------------------------------------------------------------------
+static char* MakeUpperCase(char* aPath)
+//----------------------------------------------------------------------------------------
+{
+ // check if the Windows is DBCSEnabled once.
+ if (PR_FALSE == gGlobalOSInitialized) {
+ if (GetSystemMetrics(SM_DBCSENABLED))
+ gGlobalDBCSEnabledOS = PR_TRUE;
+ gGlobalOSInitialized = PR_TRUE;
+ }
+
+ // windows does not care about case. pu sh to uppercase:
+ int length = strlen(aPath);
+ int i = 0; /* C++ portability guide #20 */
+ if (!gGlobalDBCSEnabledOS) {
+ // for non-DBCS windows
+ for (i = 0; i < length; i++)
+ if (islower(aPath[i]))
+ aPath[i] = _toupper(aPath[i]);
+ }
+ else {
+ // for DBCS windows
+ for (i = 0; i < length; i++) {
+ if (IsDBCSLeadByte(aPath[i])) {
+ // begining of the double bye char
+ i++;
+ }
+ else {
+ if ( islower(aPath[i]))
+ aPath[i] = _toupper(aPath[i]);
+ }
+ } //end of for loop
+ }
+ return aPath;
+}
+
+//----------------------------------------------------------------------------------------
+static void GetWindowsFolder(int folder, nsFileSpec& outDirectory)
+//----------------------------------------------------------------------------------------
+{
+
+ if (gGetSpecialPathProc) {
+ TCHAR path[MAX_PATH];
+ HRESULT result = gGetSpecialPathProc(NULL, path, folder, true);
+
+ if (!SUCCEEDED(result))
+ return;
+
+ // Append the trailing slash
+ int len = PL_strlen(path);
+ if (len>1 && path[len-1] != '\\')
+ {
+ path[len] = '\\';
+ path[len + 1] = '\0';
+ }
+ outDirectory = path;
+ return;
+ }
+
+ LPMALLOC pMalloc = NULL;
+ LPSTR pBuffer = NULL;
+ LPITEMIDLIST pItemIDList = NULL;
+ int len;
+
+ // Get the shell's allocator.
+ if (!SUCCEEDED(SHGetMalloc(&pMalloc)))
+ return;
+
+ // Allocate a buffer
+ if ((pBuffer = (LPSTR) pMalloc->Alloc(MAX_PATH + 2)) == NULL)
+ return;
+
+ // Get the PIDL for the folder.
+ if (!SUCCEEDED(SHGetSpecialFolderLocation(
+ NULL, folder, &pItemIDList)))
+ goto Clean;
+
+ if (!SUCCEEDED(SHGetPathFromIDList(pItemIDList, pBuffer)))
+ goto Clean;
+
+ // Append the trailing slash
+ len = PL_strlen(pBuffer);
+ pBuffer[len] = '\\';
+ pBuffer[len + 1] = '\0';
+
+ // Assign the directory
+ outDirectory = pBuffer;
+
+Clean:
+ // Clean up.
+ if (pItemIDList)
+ pMalloc->Free(pItemIDList);
+ if (pBuffer)
+ pMalloc->Free(pBuffer);
+
+ pMalloc->Release();
+} // GetWindowsFolder
+#endif // XP_WIN
+
+//----------------------------------------------------------------------------------------
+static void GetCurrentWorkingDirectory(nsFileSpec& aFileSpec)
+//----------------------------------------------------------------------------------------
+{
+ aFileSpec = ".";
+ return;
+} // GetCurrentWorkingDirectory
+
+//----------------------------------------------------------------------------------------
+static void GetCurrentProcessDirectory(nsFileSpec& aFileSpec)
+//----------------------------------------------------------------------------------------
+{
+#if defined (XP_WIN)
+ char buf[MAX_PATH];
+ if ( ::GetModuleFileName(0, buf, sizeof(buf)) ) {
+ // chop of the executable name by finding the rightmost backslash
+ char* lastSlash = PL_strrchr(buf, '\\');
+ if (lastSlash)
+ *(lastSlash + 1) = '\0';
+
+ aFileSpec = buf;
+ return;
+ }
+
+#elif defined(XP_OS2)
+ PPIB ppib;
+ PTIB ptib;
+ char buffer[CCHMAXPATH];
+ DosGetInfoBlocks( &ptib, &ppib);
+ DosQueryModuleName( ppib->pib_hmte, CCHMAXPATH, buffer);
+ *strrchr( buffer, '\\') = '\0'; // XXX DBCS misery
+ aFileSpec = buffer;
+ return;
+
+
+#elif defined(XP_MAC)
+ // get info for the the current process to determine the directory
+ // its located in
+ OSErr err;
+ ProcessSerialNumber psn = {kNoProcess, kCurrentProcess};
+ ProcessInfoRec pInfo;
+ FSSpec tempSpec;
+
+ // initialize ProcessInfoRec before calling
+ // GetProcessInformation() or die horribly.
+ pInfo.processName = nil;
+ pInfo.processAppSpec = &tempSpec;
+ pInfo.processInfoLength = sizeof(ProcessInfoRec);
+
+ if (!(err = GetProcessInformation(&psn, &pInfo)))
+ {
+ FSSpec appFSSpec = *(pInfo.processAppSpec);
+ long theDirID = appFSSpec.parID;
+
+ Str255 name;
+ CInfoPBRec catInfo;
+ catInfo.dirInfo.ioCompletion = NULL;
+ catInfo.dirInfo.ioNamePtr = (StringPtr)&name;
+ catInfo.dirInfo.ioVRefNum = appFSSpec.vRefNum;
+ catInfo.dirInfo.ioDrDirID = theDirID;
+ catInfo.dirInfo.ioFDirIndex = -1; // -1 = query dir in ioDrDirID
+
+ if (!(err = PBGetCatInfoSync(&catInfo)))
+ {
+ aFileSpec = nsFileSpec(appFSSpec.vRefNum,
+ catInfo.dirInfo.ioDrParID,
+ name,
+ PR_TRUE);
+ return;
+ }
+ }
+#if defined(DEBUG)
+ else
+ {
+ // In the absence of a good way to get the executable directory let
+ // us try this for unix:
+ // - if VBOX_XPCOM_HOME is defined, that is it
+ char *moz5 = PR_GetEnv("VBOX_XPCOM_HOME");
+ if (moz5)
+ {
+ printf( "nsSpecialSystemDirectory::VBOX_XPCOM_HOME is set to %s\n", moz5 );
+ aFileSpec = moz5;
+ return;
+ }
+ else
+ {
+ static PRBool firstWarning = PR_TRUE;
+
+ if(firstWarning) {
+ // Warn that VBOX_XPCOM_HOME not set, once.
+ printf("***Warning: VBOX_XPCOM_HOME not set.\n");
+ firstWarning = PR_FALSE;
+ }
+ }
+ }
+#endif /* DEBUG */
+
+#elif defined(XP_UNIX)
+
+ // In the absence of a good way to get the executable directory let
+ // us try this for unix:
+ // - if VBOX_XPCOM_HOME is defined, that is it
+ // - else give the current directory
+ char buf[MAXPATHLEN];
+ char *moz5 = PR_GetEnv("VBOX_XPCOM_HOME");
+ if (moz5)
+ {
+ aFileSpec = moz5;
+ return;
+ }
+ else
+ {
+#if defined(DEBUG)
+ static PRBool firstWarning = PR_TRUE;
+
+ if(firstWarning) {
+ // Warn that VBOX_XPCOM_HOME not set, once.
+ printf("Warning: VBOX_XPCOM_HOME not set.\n");
+ firstWarning = PR_FALSE;
+ }
+#endif /* DEBUG */
+
+ // Fall back to current directory.
+ if (getcwd(buf, sizeof(buf)))
+ {
+ aFileSpec = buf;
+ return;
+ }
+ }
+
+#elif defined(XP_BEOS)
+
+ char *moz5 = getenv("VBOX_XPCOM_HOME");
+ if (moz5)
+ {
+ aFileSpec = moz5;
+ return;
+ }
+ else
+ {
+ static char buf[MAXPATHLEN];
+ int32 cookie = 0;
+ image_info info;
+ char *p;
+ *buf = 0;
+ if(get_next_image_info(0, &cookie, &info) == B_OK)
+ {
+ strcpy(buf, info.name);
+ if((p = strrchr(buf, '/')) != 0)
+ {
+ *p = 0;
+ aFileSpec = buf;
+ return;
+ }
+ }
+ }
+
+#endif
+
+ NS_ERROR("unable to get current process directory");
+} // GetCurrentProcessDirectory()
+
+//nsSpecialSystemDirectory::nsSpecialSystemDirectory()
+//: nsFileSpec(nsnull)
+//{
+//}
+
+//----------------------------------------------------------------------------------------
+nsSpecialSystemDirectory::nsSpecialSystemDirectory(SystemDirectories aSystemSystemDirectory)
+//----------------------------------------------------------------------------------------
+: nsFileSpec(nsnull)
+{
+ *this = aSystemSystemDirectory;
+}
+
+//----------------------------------------------------------------------------------------
+nsSpecialSystemDirectory::~nsSpecialSystemDirectory()
+//----------------------------------------------------------------------------------------
+{
+}
+
+//----------------------------------------------------------------------------------------
+void nsSpecialSystemDirectory::operator = (SystemDirectories aSystemSystemDirectory)
+//----------------------------------------------------------------------------------------
+{
+ SystemDirectoriesKey dirKey(aSystemSystemDirectory);
+ SystemDirectoriesKey mozBinDirKey(Moz_BinDirectory);
+
+ // This flag is used to tell whether or not we need to append something
+ // onto the *this. Search for needToAppend to how it's used.
+ // IT's VERY IMPORTANT that needToAppend is initialized to PR_TRUE.
+ PRBool needToAppend = PR_TRUE;
+
+#ifdef XP_MAC
+ OSErr err;
+ short vRefNum;
+ long dirID;
+#endif
+
+ *this = (const char*)nsnull;
+ switch (aSystemSystemDirectory)
+ {
+
+ case OS_DriveDirectory:
+#if defined (XP_WIN)
+ {
+ char path[_MAX_PATH];
+ PRInt32 len = GetWindowsDirectory( path, _MAX_PATH );
+ if (len)
+ {
+ if ( path[1] == ':' && path[2] == '\\' )
+ path[3] = 0;
+ }
+ *this = MakeUpperCase(path);
+ }
+#elif defined(XP_OS2)
+ {
+ // printf( "*** Warning warning OS_DriveDirectory called for");
+
+ ULONG ulBootDrive = 0;
+ char buffer[] = " :\\OS2\\";
+ DosQuerySysInfo( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE,
+ &ulBootDrive, sizeof ulBootDrive);
+ buffer[0] = 'A' - 1 + ulBootDrive; // duh, 1-based index...
+ *this = buffer;
+#ifdef DEBUG
+ printf( "Got OS_DriveDirectory: %s\n", buffer);
+#endif
+ }
+#elif defined(XP_MAC)
+ {
+ *this = kVolumeRootFolderType;
+ }
+#else
+ *this = "/";
+#endif
+ break;
+
+
+ case OS_TemporaryDirectory:
+#if defined (XP_WIN)
+ {
+ char path[_MAX_PATH];
+ DWORD len = GetTempPath(_MAX_PATH, path);
+ *this = MakeUpperCase(path);
+ }
+#elif defined(XP_OS2)
+ {
+ char buffer[CCHMAXPATH] = "";
+ char *c = getenv( "TMP");
+ if( c) strcpy( buffer, c);
+ else
+ {
+ c = getenv( "TEMP");
+ if( c) strcpy( buffer, c);
+ }
+ if( c) *this = buffer;
+ // use exe's directory if not set
+ else GetCurrentProcessDirectory(*this);
+ }
+#elif defined(XP_MAC)
+ *this = kTemporaryFolderType;
+
+#elif defined(XP_UNIX) || defined(XP_BEOS)
+ {
+ static const char *tPath = nsnull;
+ if (!tPath) {
+ tPath = PR_GetEnv("TMPDIR");
+ if (!tPath || !*tPath) {
+ tPath = PR_GetEnv("TMP");
+ if (!tPath || !*tPath) {
+ tPath = PR_GetEnv("TEMP");
+ if (!tPath || !*tPath) {
+ tPath = "/tmp/";
+ }
+ }
+ }
+ }
+
+ *this = tPath;
+ }
+#endif
+ break;
+
+ case OS_CurrentProcessDirectory:
+ GetCurrentProcessDirectory(*this);
+ break;
+
+ case OS_CurrentWorkingDirectory:
+ GetCurrentWorkingDirectory(*this);
+ break;
+
+ case XPCOM_CurrentProcessComponentRegistry:
+ {
+ nsFileSpec *dirSpec = NULL;
+
+ // if someone has called nsSpecialSystemDirectory::Set()
+ if (systemDirectoriesLocations) {
+ // look for the value for the argument key
+ if (!(dirSpec = (nsFileSpec *)systemDirectoriesLocations->Get(&dirKey))) {
+ // if not found, try Moz_BinDirectory
+ dirSpec = (nsFileSpec *)
+ systemDirectoriesLocations->Get(&mozBinDirKey);
+ }
+ else {
+ // if the value is found for the argument key,
+ // we don't need to append.
+ needToAppend = PR_FALSE;
+ }
+ }
+
+ if (dirSpec)
+ {
+ *this = *dirSpec;
+ }
+ else
+ {
+ GetCurrentProcessDirectory(*this);
+ }
+
+ if (needToAppend) {
+ // XXX We need to unify these names across all platforms
+#if defined(XP_MAC)
+ *this += "Component Registry";
+#else
+ *this += "component.reg";
+#endif /* XP_MAC */
+ }
+ }
+ break;
+
+ case XPCOM_CurrentProcessComponentDirectory:
+ {
+ nsFileSpec *dirSpec = NULL;
+ // if someone has called nsSpecialSystemDirectory::Set()
+ if (systemDirectoriesLocations) {
+ // look for the value for the argument key
+ if (!(dirSpec = (nsFileSpec *)systemDirectoriesLocations->Get(&dirKey))) {
+ // if not found, try Moz_BinDirectory
+ dirSpec = (nsFileSpec *)
+ systemDirectoriesLocations->Get(&mozBinDirKey);
+ }
+ else {
+ // if the value is found for the argument key,
+ // we don't need to append.
+ needToAppend = PR_FALSE;
+ }
+ }
+ if (dirSpec)
+ {
+ *this = *dirSpec;
+ }
+ else
+ {
+ // <exedir>/Components
+ GetCurrentProcessDirectory(*this);
+ }
+
+ if (needToAppend) {
+ // XXX We need to unify these names across all platforms
+#if defined(XP_MAC)
+ *this += "Components";
+#else
+ *this += "components";
+#endif /* XP_MAC */
+ }
+ }
+ break;
+
+ case Moz_BinDirectory:
+ {
+ nsFileSpec *dirSpec = NULL;
+ // if someone has called nsSpecialSystemDirectory::Set()
+ if (systemDirectoriesLocations) {
+ // look for the value for the argument key
+ dirSpec = (nsFileSpec *)
+ systemDirectoriesLocations->Get(&dirKey);
+ }
+ if (dirSpec) {
+ *this = *dirSpec;
+ }
+ else {
+ GetCurrentProcessDirectory(*this);
+ }
+ }
+ break;
+
+#if defined(XP_MAC)
+ case Mac_SystemDirectory:
+ *this = kSystemFolderType;
+ break;
+
+ case Mac_DesktopDirectory:
+ *this = kDesktopFolderType;
+ break;
+
+ case Mac_TrashDirectory:
+ *this = kTrashFolderType;
+ break;
+
+ case Mac_StartupDirectory:
+ *this = kStartupFolderType;
+ break;
+
+ case Mac_ShutdownDirectory:
+ *this = kShutdownFolderType;
+ break;
+
+ case Mac_AppleMenuDirectory:
+ *this = kAppleMenuFolderType;
+ break;
+
+ case Mac_ControlPanelDirectory:
+ *this = kControlPanelFolderType;
+ break;
+
+ case Mac_ExtensionDirectory:
+ *this = kExtensionFolderType;
+ break;
+
+ case Mac_FontsDirectory:
+ *this = kFontsFolderType;
+ break;
+
+ case Mac_ClassicPreferencesDirectory:
+ {
+ // whether Mac OS X or pre-Mac OS X, return Classic's Prefs folder
+ short domain;
+ long response;
+ err = ::Gestalt(gestaltSystemVersion, &response);
+ domain = (!err && response >= 0x00001000) ? kClassicDomain : kOnSystemDisk;
+ err = ::FindFolder(domain, kPreferencesFolderType, true, &vRefNum, &dirID);
+ if (!err) {
+ err = ::FSMakeFSSpec(vRefNum, dirID, "\p", &mSpec);
+ }
+ mError = NS_FILE_RESULT(err);
+ break;
+ }
+
+ case Mac_PreferencesDirectory:
+ {
+ // if Mac OS X, return Mac OS X's Prefs folder
+ // if pre-Mac OS X, return Mac OS's Prefs folder
+ err = ::FindFolder(kOnSystemDisk, kPreferencesFolderType, true, &vRefNum, &dirID);
+ if (!err) {
+ err = ::FSMakeFSSpec(vRefNum, dirID, "\p", &mSpec);
+ }
+ mError = NS_FILE_RESULT(err);
+ break;
+ }
+
+ case Mac_DocumentsDirectory:
+ *this = kDocumentsFolderType;
+ break;
+
+ case Mac_InternetSearchDirectory:
+ *this = kInternetSearchSitesFolderType;
+ break;
+
+ case Mac_DefaultDownloadDirectory:
+ *this = kDefaultDownloadFolderType;
+ break;
+
+ case Mac_UserLibDirectory:
+ {
+ err = ::FindFolder(kUserDomain, kDomainLibraryFolderType, true, &vRefNum, &dirID);
+ if (!err) {
+ err = ::FSMakeFSSpec(vRefNum, dirID, "\p", &mSpec);
+ }
+ mError = NS_FILE_RESULT(err);
+ break;
+ }
+#endif
+
+#if defined (XP_WIN)
+ case Win_SystemDirectory:
+ {
+ char path[_MAX_PATH];
+ PRInt32 len = GetSystemDirectory( path, _MAX_PATH );
+
+ // Need enough space to add the trailing backslash
+ if (len > _MAX_PATH-2)
+ break;
+ path[len] = '\\';
+ path[len+1] = '\0';
+
+ *this = MakeUpperCase(path);
+
+ break;
+ }
+
+ case Win_WindowsDirectory:
+ {
+ char path[_MAX_PATH];
+ PRInt32 len = GetWindowsDirectory( path, _MAX_PATH );
+
+ // Need enough space to add the trailing backslash
+ if (len > _MAX_PATH-2)
+ break;
+
+ path[len] = '\\';
+ path[len+1] = '\0';
+
+ *this = MakeUpperCase(path);
+ break;
+ }
+
+ case Win_HomeDirectory:
+ {
+ char path[_MAX_PATH];
+ if (GetEnvironmentVariable(TEXT("HOME"), path, _MAX_PATH) > 0)
+ {
+ PRInt32 len = PL_strlen(path);
+ // Need enough space to add the trailing backslash
+ if (len > _MAX_PATH - 2)
+ break;
+
+ path[len] = '\\';
+ path[len+1] = '\0';
+
+ *this = MakeUpperCase(path);
+ break;
+ }
+
+ if (GetEnvironmentVariable(TEXT("HOMEDRIVE"), path, _MAX_PATH) > 0)
+ {
+ char temp[_MAX_PATH];
+ if (GetEnvironmentVariable(TEXT("HOMEPATH"), temp, _MAX_PATH) > 0)
+ PL_strcatn(path, _MAX_PATH, temp);
+
+ PRInt32 len = PL_strlen(path);
+
+ // Need enough space to add the trailing backslash
+ if (len > _MAX_PATH - 2)
+ break;
+
+ path[len] = '\\';
+ path[len+1] = '\0';
+
+ *this = MakeUpperCase(path);
+ break;
+ }
+ }
+ case Win_Desktop:
+ {
+ GetWindowsFolder(CSIDL_DESKTOP, *this);
+ break;
+ }
+ case Win_Programs:
+ {
+ GetWindowsFolder(CSIDL_PROGRAMS, *this);
+ break;
+ }
+ case Win_Controls:
+ {
+ GetWindowsFolder(CSIDL_CONTROLS, *this);
+ break;
+ }
+ case Win_Printers:
+ {
+ GetWindowsFolder(CSIDL_PRINTERS, *this);
+ break;
+ }
+ case Win_Personal:
+ {
+ GetWindowsFolder(CSIDL_PERSONAL, *this);
+ break;
+ }
+ case Win_Favorites:
+ {
+ GetWindowsFolder(CSIDL_FAVORITES, *this);
+ break;
+ }
+ case Win_Startup:
+ {
+ GetWindowsFolder(CSIDL_STARTUP, *this);
+ break;
+ }
+ case Win_Recent:
+ {
+ GetWindowsFolder(CSIDL_RECENT, *this);
+ break;
+ }
+ case Win_Sendto:
+ {
+ GetWindowsFolder(CSIDL_SENDTO, *this);
+ break;
+ }
+ case Win_Bitbucket:
+ {
+ GetWindowsFolder(CSIDL_BITBUCKET, *this);
+ break;
+ }
+ case Win_Startmenu:
+ {
+ GetWindowsFolder(CSIDL_STARTMENU, *this);
+ break;
+ }
+ case Win_Desktopdirectory:
+ {
+ GetWindowsFolder(CSIDL_DESKTOPDIRECTORY, *this);
+ break;
+ }
+ case Win_Drives:
+ {
+ GetWindowsFolder(CSIDL_DRIVES, *this);
+ break;
+ }
+ case Win_Network:
+ {
+ GetWindowsFolder(CSIDL_NETWORK, *this);
+ break;
+ }
+ case Win_Nethood:
+ {
+ GetWindowsFolder(CSIDL_NETHOOD, *this);
+ break;
+ }
+ case Win_Fonts:
+ {
+ GetWindowsFolder(CSIDL_FONTS, *this);
+ break;
+ }
+ case Win_Templates:
+ {
+ GetWindowsFolder(CSIDL_TEMPLATES, *this);
+ break;
+ }
+ case Win_Common_Startmenu:
+ {
+ GetWindowsFolder(CSIDL_COMMON_STARTMENU, *this);
+ break;
+ }
+ case Win_Common_Programs:
+ {
+ GetWindowsFolder(CSIDL_COMMON_PROGRAMS, *this);
+ break;
+ }
+ case Win_Common_Startup:
+ {
+ GetWindowsFolder(CSIDL_COMMON_STARTUP, *this);
+ break;
+ }
+ case Win_Common_Desktopdirectory:
+ {
+ GetWindowsFolder(CSIDL_COMMON_DESKTOPDIRECTORY, *this);
+ break;
+ }
+ case Win_Appdata:
+ {
+ GetWindowsFolder(CSIDL_APPDATA, *this);
+ break;
+ }
+ case Win_Printhood:
+ {
+ GetWindowsFolder(CSIDL_PRINTHOOD, *this);
+ break;
+ }
+ case Win_Cookies:
+ {
+ GetWindowsFolder(CSIDL_COOKIES, *this);
+ break;
+ }
+#endif // XP_WIN
+
+#if defined(XP_UNIX)
+ case Unix_LocalDirectory:
+ *this = "/usr/local/netscape/";
+ break;
+
+ case Unix_LibDirectory:
+ *this = "/usr/local/lib/netscape/";
+ break;
+
+ case Unix_HomeDirectory:
+#ifdef VMS
+ {
+ char *pHome;
+ pHome = getenv("HOME");
+ if (*pHome == '/')
+ *this = pHome;
+ else
+ *this = decc$translate_vms(pHome);
+ }
+#else
+ *this = PR_GetEnv("HOME");
+#endif
+ break;
+
+#endif
+
+#ifdef XP_BEOS
+ case BeOS_SettingsDirectory:
+ {
+ char path[MAXPATHLEN];
+ find_directory(B_USER_SETTINGS_DIRECTORY, 0, 0, path, MAXPATHLEN);
+ // Need enough space to add the trailing backslash
+ int len = strlen(path);
+ if (len > MAXPATHLEN-2)
+ break;
+ path[len] = '/';
+ path[len+1] = '\0';
+ *this = path;
+ break;
+ }
+
+ case BeOS_HomeDirectory:
+ {
+ char path[MAXPATHLEN];
+ find_directory(B_USER_DIRECTORY, 0, 0, path, MAXPATHLEN);
+ // Need enough space to add the trailing backslash
+ int len = strlen(path);
+ if (len > MAXPATHLEN-2)
+ break;
+ path[len] = '/';
+ path[len+1] = '\0';
+ *this = path;
+ break;
+ }
+
+ case BeOS_DesktopDirectory:
+ {
+ char path[MAXPATHLEN];
+ find_directory(B_DESKTOP_DIRECTORY, 0, 0, path, MAXPATHLEN);
+ // Need enough space to add the trailing backslash
+ int len = strlen(path);
+ if (len > MAXPATHLEN-2)
+ break;
+ path[len] = '/';
+ path[len+1] = '\0';
+ *this = path;
+ break;
+ }
+
+ case BeOS_SystemDirectory:
+ {
+ char path[MAXPATHLEN];
+ find_directory(B_BEOS_DIRECTORY, 0, 0, path, MAXPATHLEN);
+ // Need enough space to add the trailing backslash
+ int len = strlen(path);
+ if (len > MAXPATHLEN-2)
+ break;
+ path[len] = '/';
+ path[len+1] = '\0';
+ *this = path;
+ break;
+ }
+#endif
+#ifdef XP_OS2
+ case OS2_SystemDirectory:
+ {
+ ULONG ulBootDrive = 0;
+ char buffer[] = " :\\OS2\\System\\";
+ DosQuerySysInfo( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE,
+ &ulBootDrive, sizeof ulBootDrive);
+ buffer[0] = 'A' - 1 + ulBootDrive; // duh, 1-based index...
+ *this = buffer;
+#ifdef DEBUG
+ printf( "Got OS2_SystemDirectory: %s\n", buffer);
+#endif
+ break;
+ }
+
+ case OS2_OS2Directory:
+ {
+ ULONG ulBootDrive = 0;
+ char buffer[] = " :\\OS2\\";
+ DosQuerySysInfo( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE,
+ &ulBootDrive, sizeof ulBootDrive);
+ buffer[0] = 'A' - 1 + ulBootDrive; // duh, 1-based index...
+ *this = buffer;
+#ifdef DEBUG
+ printf( "Got OS2_OS2Directory: %s\n", buffer);
+#endif
+ break;
+ }
+
+ case OS2_HomeDirectory:
+ {
+ char *tPath = PR_GetEnv("MOZILLA_HOME");
+ /* If MOZILLA_HOME is not set, use GetCurrentProcessDirectory */
+ /* To ensure we get a long filename system */
+ if (!tPath || !*tPath)
+ GetCurrentProcessDirectory(*this);
+ else
+ *this = tPath;
+ PrfWriteProfileString(HINI_USERPROFILE, "Mozilla", "Home", *this);
+ break;
+ }
+
+ case OS2_DesktopDirectory:
+ {
+ char szPath[CCHMAXPATH + 1];
+ BOOL fSuccess;
+ fSuccess = WinQueryActiveDesktopPathname (szPath, sizeof(szPath));
+ int len = strlen (szPath);
+ if (len > CCHMAXPATH -1)
+ break;
+ szPath[len] = '\\';
+ szPath[len + 1] = '\0';
+#ifdef DEBUG
+ if (fSuccess) {
+ printf ("Got OS2_DesktopDirectory: %s\n", szPath);
+ } else {
+ printf ("Failed getting OS2_DesktopDirectory: %s\n", szPath);
+ }
+#endif
+ break;
+ }
+
+#endif
+ default:
+ break;
+ }
+}
+
+void
+nsSpecialSystemDirectory::Set(SystemDirectories dirToSet, nsFileSpec *dirSpec)
+{
+ SystemDirectoriesKey dirKey(dirToSet);
+
+ PR_ASSERT(NULL != dirSpec);
+
+ if (NULL == systemDirectoriesLocations) {
+ systemDirectoriesLocations = new nsHashtable(NS_SYSTEMDIR_HASH_NUM);
+ }
+ PR_ASSERT(NULL != systemDirectoriesLocations);
+
+ nsFileSpec *newSpec = new nsFileSpec(*dirSpec);
+ if (NULL != newSpec) {
+ systemDirectoriesLocations->Put(&dirKey, newSpec);
+ }
+
+ return;
+}
+
+#if defined(XP_MAC)
+//----------------------------------------------------------------------------------------
+nsSpecialSystemDirectory::nsSpecialSystemDirectory(OSType folderType)
+//----------------------------------------------------------------------------------------
+{
+ *this = folderType;
+}
+
+//----------------------------------------------------------------------------------------
+void nsSpecialSystemDirectory::operator = (OSType folderType)
+//----------------------------------------------------------------------------------------
+{
+ CInfoPBRec cinfo;
+ DirInfo *dipb=(DirInfo *)&cinfo;
+
+ // hack: first check for kDefaultDownloadFolderType
+ // if it is, get Internet Config Download folder, if that's
+ // not availble use desktop folder
+ if (folderType == kDefaultDownloadFolderType)
+ {
+ nsCOMPtr<nsIInternetConfigService> icService (do_GetService(NS_INTERNETCONFIGSERVICE_CONTRACTID));
+ if (icService)
+ {
+ if (NS_SUCCEEDED(icService->GetDownloadFolder(&mSpec)))
+ return;
+ else
+ folderType = kDesktopFolderType;
+ }
+ else
+ {
+ folderType = kDesktopFolderType;
+ }
+ }
+ // Call FindFolder to fill in the vrefnum and dirid
+ for (int attempts = 0; attempts < 2; attempts++)
+ {
+ mError = NS_FILE_RESULT(
+ FindFolder(
+ kOnSystemDisk,
+ folderType,
+ true,
+ &dipb->ioVRefNum,
+ &dipb->ioDrDirID));
+ if (NS_SUCCEEDED(mError))
+ break;
+ if (attempts > 0)
+ return;
+ switch (folderType)
+ {
+ case kDocumentsFolderType:
+ // Find folder will find this, as long as it exists.
+ // The "create" parameter, however, is sadly ignored.
+ // How do we internationalize this?
+ *this = kVolumeRootFolderType;
+ *this += "Documents";
+ CreateDirectory();
+ break;
+ } // switch
+ } // for
+ StrFileName filename;
+ filename[0] = '\0';
+ dipb->ioNamePtr = (StringPtr)&filename;
+ dipb->ioFDirIndex = -1;
+
+ mError = NS_FILE_RESULT(PBGetCatInfoSync(&cinfo));
+ if (NS_SUCCEEDED(mError))
+ {
+ mError = NS_FILE_RESULT(FSMakeFSSpec(dipb->ioVRefNum, dipb->ioDrParID, filename, &mSpec));
+ }
+}
+#endif // XP_MAC
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsSpecialSystemDirectory.h b/src/libs/xpcom18a4/xpcom/obsolete/nsSpecialSystemDirectory.h
new file mode 100644
index 00000000..577cd0c0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsSpecialSystemDirectory.h
@@ -0,0 +1,167 @@
+/* -*- 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 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):
+ * Doug Turner <dougt@netscape.com>
+ * IBM Corp.
+ *
+ * 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 _NSSPECIALSYSTEMDIRECTORY_H_
+#define _NSSPECIALSYSTEMDIRECTORY_H_
+
+#include "xpcomobsolete.h"
+#include "nsFileSpec.h"
+
+#if defined(XP_MAC) || defined(XP_MACOSX)
+#include <Types.h>
+#endif
+
+
+extern NS_COM_OBSOLETE void StartupSpecialSystemDirectory();
+extern NS_COM_OBSOLETE void ShutdownSpecialSystemDirectory();
+
+
+// SEE ALSO:
+// mozilla/xpfe/appshell/public/nsFileLocations.h
+
+class NS_COM_OBSOLETE nsSpecialSystemDirectory : public nsFileSpec
+{
+
+ public:
+ enum SystemDirectories
+ {
+ OS_DriveDirectory = 1
+ , OS_TemporaryDirectory = 2
+ , OS_CurrentProcessDirectory= 3
+ , OS_CurrentWorkingDirectory= 4
+
+ , XPCOM_CurrentProcessComponentDirectory= 5
+ , XPCOM_CurrentProcessComponentRegistry= 6
+
+ , Moz_BinDirectory = 10
+
+ , Mac_SystemDirectory = 101
+ , Mac_DesktopDirectory = 102
+ , Mac_TrashDirectory = 103
+ , Mac_StartupDirectory = 104
+ , Mac_ShutdownDirectory = 105
+ , Mac_AppleMenuDirectory = 106
+ , Mac_ControlPanelDirectory = 107
+ , Mac_ExtensionDirectory = 108
+ , Mac_FontsDirectory = 109
+ , Mac_ClassicPreferencesDirectory = 110
+ , Mac_DocumentsDirectory = 111
+ , Mac_InternetSearchDirectory = 112
+ , Mac_DefaultDownloadDirectory = 113
+ , Mac_UserLibDirectory = 114
+ , Mac_PreferencesDirectory = 115
+
+ , Win_SystemDirectory = 201
+ , Win_WindowsDirectory = 202
+
+ , Win_HomeDirectory = 203
+ , Win_Desktop = 204
+ , Win_Programs = 205
+ , Win_Controls = 206
+ , Win_Printers = 207
+ , Win_Personal = 208
+ , Win_Favorites = 209
+ , Win_Startup = 210
+ , Win_Recent = 211
+ , Win_Sendto = 212
+ , Win_Bitbucket = 213
+ , Win_Startmenu = 214
+ , Win_Desktopdirectory = 215
+ , Win_Drives = 216
+ , Win_Network = 217
+ , Win_Nethood = 218
+ , Win_Fonts = 219
+ , Win_Templates = 220
+ , Win_Common_Startmenu = 221
+ , Win_Common_Programs = 222
+ , Win_Common_Startup = 223
+ , Win_Common_Desktopdirectory = 224
+ , Win_Appdata = 225
+ , Win_Printhood = 226
+ , Win_Cookies = 227
+
+ , Unix_LocalDirectory = 301
+ , Unix_LibDirectory = 302
+ , Unix_HomeDirectory = 303
+
+ , BeOS_SettingsDirectory = 401
+ , BeOS_HomeDirectory = 402
+ , BeOS_DesktopDirectory = 403
+ , BeOS_SystemDirectory = 404
+
+ , OS2_SystemDirectory = 501
+ , OS2_OS2Directory = 502
+ , OS2_DesktopDirectory = 503
+ , OS2_HomeDirectory = 504
+ };
+
+ //nsSpecialSystemDirectory();
+ nsSpecialSystemDirectory(SystemDirectories aSystemSystemDirectory);
+
+ virtual ~nsSpecialSystemDirectory();
+
+ void operator = (SystemDirectories aSystemSystemDirectory);
+
+#if defined(XP_MAC) || defined(XP_MACOSX)
+ void operator = (OSType folderType);
+ nsSpecialSystemDirectory(OSType folderType);
+ enum {
+ kDefaultDownloadFolderType = FOUR_CHAR_CODE('DfDÄ') /* Default Download Folder */
+ };
+#endif
+
+ /**
+
+ * @param: dirToSet, the value to set for this safeLocation
+
+ * @param: dirSpec, the directory specified as a filespec
+
+ */
+
+ static void Set(SystemDirectories dirToSet, nsFileSpec *dirSpec);
+
+
+private:
+ void operator = (const char* inPath) { *(nsFileSpec*)this = inPath; }
+
+}; // class NS_COM_OBSOLETE nsSpecialSystemDirectory
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/nsXPCOMObsolete.cpp b/src/libs/xpcom18a4/xpcom/obsolete/nsXPCOMObsolete.cpp
new file mode 100644
index 00000000..45391c0f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/nsXPCOMObsolete.cpp
@@ -0,0 +1,54 @@
+/* -*- 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 "nsXPCOM.h"
+#include "nsIGenericFactory.h"
+
+#include "nsFileSpecImpl.h"
+
+#define COMPONENT(NAME, Ctor) \
+ { NS_##NAME##_CLASSNAME, NS_##NAME##_CID, NS_##NAME##_CONTRACTID, Ctor }
+
+
+static const nsModuleComponentInfo components[] =
+{
+ COMPONENT(FILESPEC, nsFileSpecImpl::Create),
+ COMPONENT(DIRECTORYITERATOR, nsDirectoryIteratorImpl::Create),
+};
+
+NS_IMPL_NSGETMODULE(xpcomObsoleteModule, components)
+
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/xpcomobsolete.h b/src/libs/xpcom18a4/xpcom/obsolete/xpcomobsolete.h
new file mode 100644
index 00000000..13914115
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/xpcomobsolete.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 xpcomobsolete_h___
+#define xpcomobsolete_h___
+
+#include "nscore.h"
+
+#ifdef _IMPL_NS_COM_OBSOLETE
+#define NS_COM_OBSOLETE NS_EXPORT
+#else
+#define NS_COM_OBSOLETE NS_IMPORT
+#endif
+
+#endif /* !defined(xpcomobsolete_h___) */
diff --git a/src/libs/xpcom18a4/xpcom/obsolete/xpcomobsolete.pkg b/src/libs/xpcom18a4/xpcom/obsolete/xpcomobsolete.pkg
new file mode 100644
index 00000000..d44a8939
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/obsolete/xpcomobsolete.pkg
@@ -0,0 +1,7 @@
+[gecko xpi-bootstrap]
+#if SHARED_LIBRARY
+dist/bin/@SHARED_LIBRARY@
+#endif
+
+[gecko]
+!xpt dist/bin/components/xpcom_obsolete.xpt
diff --git a/src/libs/xpcom18a4/xpcom/proxy/.cvsignore b/src/libs/xpcom18a4/xpcom/proxy/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/proxy/Makefile.in b/src/libs/xpcom18a4/xpcom/proxy/Makefile.in
new file mode 100644
index 00000000..c30f214f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/Makefile.in
@@ -0,0 +1,49 @@
+#
+# ***** 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
+DIRS = public src
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/proxy/public/.cvsignore b/src/libs/xpcom18a4/xpcom/proxy/public/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/public/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/proxy/public/Makefile.in b/src/libs/xpcom18a4/xpcom/proxy/public/Makefile.in
new file mode 100644
index 00000000..d6950b9a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/public/Makefile.in
@@ -0,0 +1,63 @@
+#
+# ***** 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
+ifeq ($(OS_ARCH),WINNT)
+XPIDL_MODULE = proxyObject
+else
+XPIDL_MODULE = proxyObjInst
+endif
+
+EXPORTS = \
+ nsProxyEvent.h \
+ nsProxyRelease.h \
+ nsProxiedService.h \
+ $(NULL)
+
+XPIDLSRCS = nsIProxyCreateInstance.idl \
+ nsIProxyObjectManager.idl \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/proxy/public/nsIProxyCreateInstance.idl b/src/libs/xpcom18a4/xpcom/proxy/public/nsIProxyCreateInstance.idl
new file mode 100644
index 00000000..cd576f7b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/public/nsIProxyCreateInstance.idl
@@ -0,0 +1,53 @@
+/* -*- 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 "nsISupports.idl"
+
+[scriptable, uuid(948c2080-0398-11d3-915e-0000863011c4)]
+interface nsIProxyCreateInstance : nsISupports
+{
+ [noscript] void CreateInstanceByIID(in nsIIDRef cid,
+ in nsISupports aOuter,
+ in nsIIDRef iid,
+ out voidPtr result);
+
+ [noscript] void CreateInstanceByContractID(in string aContractID,
+ in nsISupports aOuter,
+ in nsIIDRef iid,
+ out voidPtr result);
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/proxy/public/nsIProxyObjectManager.idl b/src/libs/xpcom18a4/xpcom/proxy/public/nsIProxyObjectManager.idl
new file mode 100644
index 00000000..5b2cfd4d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/public/nsIProxyObjectManager.idl
@@ -0,0 +1,87 @@
+/* -*- 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):
+ * Doug Turner <dougt@netscape.com> (Original Author)
+ * Dan Mosedale <dmose@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 "nsISupports.idl"
+interface nsIEventQueue;
+
+[scriptable, uuid(eea90d43-b059-11d2-915e-c12b696c9333)]
+interface nsIProxyObjectManager : nsISupports
+{
+ void getProxyForObject(in nsIEventQueue destQueue,
+ in nsIIDRef iid,
+ in nsISupports object,
+ in PRInt32 proxyType,
+ [iid_is(iid),retval] out nsQIResult result);
+
+ void getProxy(in nsIEventQueue destQueue,
+ in nsIIDRef cid,
+ in nsISupports aOuter,
+ in nsIIDRef iid,
+ in PRInt32 proxyType,
+ [iid_is(iid),retval] out nsQIResult result);
+
+};
+
+
+%{C++
+#include "nsProxyEvent.h"
+
+#define NS_XPCOMPROXY_CONTRACTID "@mozilla.org/xpcomproxy;1"
+#define NS_XPCOMPROXY_CLASSNAME "XPCom Proxy"
+
+#define NS_PROXYEVENT_MANAGER_CID \
+{ 0xeea90d41, \
+ 0xb059, \
+ 0x11d2, \
+ {0x91, 0x5e, 0xc1, 0x2b, 0x69, 0x6c, 0x93, 0x33}\
+}
+
+/**
+ * Helper function for code that already has a link-time dependency on
+ * libxpcom and needs to get proxies in a bunch of different places.
+ * This way, the caller isn't forced to get the proxy object manager
+ * themselves every single time, thus making the calling code more
+ * readable.
+ */
+extern NS_COM nsresult
+NS_GetProxyForObject(nsIEventQueue *destQueue,
+ REFNSIID aIID,
+ nsISupports* aObj,
+ PRInt32 proxyType,
+ void** aProxyObject);
+%}
diff --git a/src/libs/xpcom18a4/xpcom/proxy/public/nsProxiedService.h b/src/libs/xpcom18a4/xpcom/proxy/public/nsProxiedService.h
new file mode 100644
index 00000000..3a39ade1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/public/nsProxiedService.h
@@ -0,0 +1,164 @@
+/* -*- 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 ***** */
+
+#ifndef __nsProxiedServiceManager_h_
+#define __nsProxiedServiceManager_h_
+
+#include "nsIServiceManager.h"
+#include "nsIProxyObjectManager.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// NS_WITH_PROXIED_SERVICE: macro to make using services that need to be proxied
+// before using them easier.
+// Now you can replace this:
+// {
+// nsresult rv;
+// nsCOMPtr<nsIMyService> pIMyService =
+// do_GetService(kMyServiceCID, &rv);
+// if(NS_FAILED(rv))
+// return;
+// nsCOMPtr<nsIProxyObjectManager> pIProxyObjectManager =
+// do_GetService(kProxyObjectManagerCID, &rv);
+// if(NS_FAILED(rv))
+// return;
+// nsIMyService pIProxiedObject = NULL;
+// rv = pIProxyObjectManager->GetProxyForObject(pIProxyQueue,
+// NS_GET_IID(nsIMyService),
+// pIMyService, PROXY_SYNC,
+// (void**)&pIProxiedObject);
+// pIProxiedObject->DoIt(...); // Executed on same thread as pIProxyQueue
+// ...
+// pIProxiedObject->Release(); // Must be done as not managed for you.
+// }
+// with this:
+// {
+// nsresult rv;
+// NS_WITH_PROXIED_SERVICE(nsIMyService, pIMyService, kMyServiceCID,
+// pIProxyQueue, &rv);
+// if(NS_FAILED(rv))
+// return;
+// pIMyService->DoIt(...); // Executed on the same thread as pIProxyQueue
+// }
+// and the automatic destructor will take care of releasing the service and
+// the proxied object for you.
+//
+// Note that this macro requires you to link with the xpcom DLL to pick up the
+// static member functions from nsServiceManager.
+
+#define NS_WITH_PROXIED_SERVICE(T, var, cid, Q, rvAddr) \
+ nsProxiedService _serv##var(cid, NS_GET_IID(T), Q, PR_FALSE, rvAddr); \
+ T* var = (T*)(nsISupports*)_serv##var;
+
+#define NS_WITH_ALWAYS_PROXIED_SERVICE(T, var, cid, Q, rvAddr) \
+ nsProxiedService _serv##var(cid, NS_GET_IID(T), Q, PR_TRUE, rvAddr); \
+ T* var = (T*)(nsISupports*)_serv##var;
+
+////////////////////////////////////////////////////////////////////////////////
+// nsProxiedService
+////////////////////////////////////////////////////////////////////////////////
+
+class nsProxiedService
+{
+ public:
+
+ nsProxiedService(const nsCID &aClass, const nsIID &aIID,
+ nsIEventQueue* pIProxyQueue, PRBool always, nsresult*rv)
+ {
+ *rv = nsServiceManager::GetService(aClass,
+ aIID,
+ getter_AddRefs(mService));
+ if (NS_FAILED(*rv)) return;
+ InitProxy(aIID, pIProxyQueue, always, rv);
+ }
+
+ nsProxiedService(const char* aContractID, const nsIID &aIID,
+ nsIEventQueue* pIProxyQueue, PRBool always, nsresult*rv)
+ {
+ *rv = nsServiceManager::GetService(aContractID,
+ aIID,
+ getter_AddRefs(mService));
+ if (NS_FAILED(*rv)) return;
+ InitProxy(aIID, pIProxyQueue, always, rv);
+ }
+
+ void InitProxy(const nsIID &aIID, nsIEventQueue* pIProxyQueue,
+ PRBool always, nsresult*rv)
+ {
+ static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID);
+
+ nsCOMPtr<nsIProxyObjectManager> pIProxyObjectManager =
+ do_GetService(kProxyObjectManagerCID, rv);
+ if (NS_FAILED(*rv)) return;
+
+ PRInt32 proxyType = PROXY_SYNC;
+ if (always) proxyType |= PROXY_ALWAYS;
+ *rv = pIProxyObjectManager->GetProxyForObject(pIProxyQueue,
+ aIID,
+ mService,
+ proxyType,
+ getter_AddRefs(mProxiedService));
+ }
+
+ ~nsProxiedService()
+ {
+ }
+
+ nsISupports* operator->() const
+ {
+ NS_PRECONDITION(mProxiedService != 0, "Your code should test the error result from the constructor.");
+ return mProxiedService;
+ }
+
+ PRBool operator==(const nsISupports* other)
+ {
+ return ((mProxiedService == other) || (mService == other));
+ }
+
+ operator nsISupports*() const
+ {
+ return mProxiedService;
+ }
+
+ protected:
+ nsCOMPtr<nsISupports> mProxiedService;
+ nsCOMPtr<nsISupports> mService;
+
+ };
+
+
+#endif //__nsProxiedServiceManager_h_
diff --git a/src/libs/xpcom18a4/xpcom/proxy/public/nsProxyEvent.h b/src/libs/xpcom18a4/xpcom/proxy/public/nsProxyEvent.h
new file mode 100644
index 00000000..c718bbdb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/public/nsProxyEvent.h
@@ -0,0 +1,183 @@
+/* -*- 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 __nsProxyEvent_h_
+#define __nsProxyEvent_h_
+
+#include "nsCOMPtr.h"
+#include "nsAutoPtr.h"
+#include "nscore.h"
+#include "nsISupports.h"
+#include "nsIFactory.h"
+
+#include "nsIEventQueueService.h"
+#include "nsIEventQueue.h"
+#include "plevent.h"
+#include "prtypes.h"
+#include "xptcall.h"
+#include "xptinfo.h"
+
+class nsProxyObjectCallInfo;
+
+#define PROXY_SYNC 0x0001 // acts just like a function call.
+#define PROXY_ASYNC 0x0002 // fire and forget. This will return immediately and you will lose all return information.
+#define PROXY_ALWAYS 0x0004 // ignore check to see if the eventQ is on the same thread as the caller, and alway return a proxied object.
+
+//#define AUTOPROXIFICATION
+
+// WARNING about PROXY_ASYNC:
+//
+// If the calling thread goes away, any function which accesses the calling stack
+// will blow up.
+//
+// example:
+//
+// myFoo->bar(&x)
+//
+// ... thread goes away ...
+//
+// bar(PRInt32 *x)
+// {
+// *x = 0; <----- You will blow up here.
+//
+//
+// So what gets saved?
+//
+// You can safely pass base types by value. You can also pass interface pointers.
+// I will make sure that the interface pointers are addrefed while they are being
+// proxied. You can also pass string and wstring. These I will copy and free.
+//
+// I do **NOT** copy arrays or strings with size. If you are using these either
+// change your interface, or contact me about this feature request.
+
+
+
+
+class nsProxyObject
+{
+public:
+ nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, nsISupports *realObject);
+ nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, const nsCID &aClass, nsISupports *aDelegate, const nsIID &aIID);
+
+ void AddRef();
+ void Release();
+
+ ~nsProxyObject();
+
+ nsresult Post( PRUint32 methodIndex,
+ nsXPTMethodInfo * info,
+ nsXPTCMiniVariant * params,
+ nsIInterfaceInfo * interfaceInfo);
+
+ nsresult PostAndWait(nsProxyObjectCallInfo *proxyInfo);
+ nsISupports* GetRealObject() const { return mRealObject; }
+ nsIEventQueue* GetQueue() const { return mDestQueue; }
+ PRInt32 GetProxyType() const { return mProxyType; }
+
+ friend class nsProxyEventObject;
+private:
+
+ nsAutoRefCnt mRefCnt;
+
+ PRInt32 mProxyType;
+
+ nsCOMPtr<nsIEventQueue> mDestQueue; /* destination queue */
+
+ nsCOMPtr<nsISupports> mRealObject; /* the non-proxy object that this event is referring to.
+ This is a strong ref. */
+ nsCOMPtr<nsIEventQueueService> mEventQService;
+
+ nsresult convertMiniVariantToVariant(nsXPTMethodInfo * methodInfo,
+ nsXPTCMiniVariant * params,
+ nsXPTCVariant **fullParam,
+ uint8 *paramCount);
+
+};
+
+
+class nsProxyObjectCallInfo
+{
+public:
+
+ nsProxyObjectCallInfo(nsProxyObject* owner,
+ nsXPTMethodInfo *methodInfo,
+ PRUint32 methodIndex,
+ nsXPTCVariant* parameterList,
+ PRUint32 parameterCount,
+ PLEvent *event);
+
+ ~nsProxyObjectCallInfo();
+
+ PRUint32 GetMethodIndex() const { return mMethodIndex; }
+ nsXPTCVariant* GetParameterList() const { return mParameterList; }
+ PRUint32 GetParameterCount() const { return mParameterCount; }
+ PLEvent* GetPLEvent() const { return mEvent; }
+ nsresult GetResult() const { return mResult; }
+ nsProxyObject* GetProxyObject() const { return mOwner; }
+
+ PRBool GetCompleted();
+ void SetCompleted();
+ void PostCompleted();
+
+ void SetResult(nsresult rv) {mResult = rv; }
+
+ nsIEventQueue* GetCallersQueue();
+ void SetCallersQueue(nsIEventQueue* queue);
+
+private:
+
+ nsresult mResult; /* this is the return result of the called function */
+ nsXPTMethodInfo *mMethodInfo;
+ PRUint32 mMethodIndex; /* which method to be called? */
+ nsXPTCVariant *mParameterList; /* marshalled in parameter buffer */
+ PRUint32 mParameterCount; /* number of params */
+ PLEvent *mEvent; /* the current plevent */
+ PRInt32 mCompleted; /* is true when the method has been called. */
+
+ nsCOMPtr<nsIEventQueue> mCallersEventQ; /* this is the eventQ that we must post a message back to
+ when we are done invoking the method (only PROXY_SYNC).
+ */
+
+ nsRefPtr<nsProxyObject> mOwner; /* this is the strong referenced nsProxyObject */
+
+ void RefCountInInterfacePointers(PRBool addRef);
+ void CopyStrings(PRBool copy);
+
+};
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/proxy/public/nsProxyRelease.h b/src/libs/xpcom18a4/xpcom/proxy/public/nsProxyRelease.h
new file mode 100644
index 00000000..413a3d0e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/public/nsProxyRelease.h
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 3 -*- */
+/* ***** 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 nsProxyRelease_h__
+#define nsProxyRelease_h__
+
+#include "nsIEventQueueService.h"
+#include "pratom.h"
+#include "prmem.h"
+
+/**
+ * Ensures that the delete of a nsISupports object occurs on the target thread.
+ *
+ * @param target
+ * the target thread where the doomed object should be released.
+ * @param doomed
+ * the doomed object; the object to be released on the target thread.
+ * @param alwaysProxy
+ * normally, if NS_ProxyRelease is called on the target thread, then the
+ * doomed object will released directly. however, if this parameter is
+ * true, then a PLEvent will always be posted to the target thread and
+ * the release will happen when that PLEvent is handled.
+ */
+NS_COM nsresult NS_ProxyRelease
+ (nsIEventTarget *target, nsISupports *doomed, PRBool alwaysProxy=PR_FALSE);
+
+
+#define NS_IMPL_PROXY_RELEASE(_class) \
+NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \
+{ \
+ NS_PRECONDITION(0 != mRefCnt, "dup release"); \
+ nsrefcnt count = PR_AtomicDecrement((PRInt32 *)&mRefCnt); \
+ NS_LOG_RELEASE(this, count, #_class); \
+ \
+ if (count == 0) \
+ { \
+ mRefCnt = 1; /* stabilize */ \
+ PRBool callDirectly = PR_TRUE; \
+ static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); \
+ nsCOMPtr<nsIEventQueueService> eventQService \
+ = do_GetService(kEventQueueServiceCID); \
+ NS_ASSERTION(eventQService, "event queue service is unavailable"); \
+ \
+ nsCOMPtr<nsIEventQueue> eventQ; \
+ if (eventQService) { \
+ eventQService->GetThreadEventQueue(NS_UI_THREAD, getter_AddRefs(eventQ)); \
+ if (eventQ) \
+ eventQ->IsOnCurrentThread(&callDirectly); \
+ } \
+ \
+ if (callDirectly) \
+ { \
+ NS_RELEASE(this); \
+ return 0; \
+ } \
+ PLEvent *event = new PLEvent; \
+ if (event == nsnull) \
+ { \
+ NS_ASSERTION(0, "Could not create a plevent. Deleting on wrong thread!"); \
+ NS_DELETEXPCOM(this); \
+ return 0; \
+ } \
+ \
+ PL_InitEvent(event, \
+ NS_STATIC_CAST(nsISupports*, this), \
+ ReleaseDestructorEventHandler, \
+ ReleaseDestructorDestroyHandler); \
+ \
+ eventQ->PostEvent(event); \
+ return 0; \
+ } \
+ return count; \
+} \
+
+
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/.cvsignore b/src/libs/xpcom18a4/xpcom/proxy/src/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/Makefile.in b/src/libs/xpcom18a4/xpcom/proxy/src/Makefile.in
new file mode 100644
index 00000000..3d46f60b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/Makefile.in
@@ -0,0 +1,67 @@
+#
+# ***** 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
+LIBRARY_NAME = xpcomproxy_s
+REQUIRES = string \
+ $(NULL)
+
+
+CPPSRCS = \
+ nsProxyEvent.cpp \
+ nsProxyEventClass.cpp \
+ nsProxyEventObject.cpp \
+ nsProxyObjectManager.cpp \
+ nsProxyRelease.cpp \
+ $(NULL)
+
+DEFINES += -D_IMPL_NS_COM -DEXPORT_XPTC_API -DEXPORT_XPTI_API
+
+# No shared lib; Force creation of static lib
+FORCE_STATIC_LIB = 1
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/nsIProxyCreateInstance.h b/src/libs/xpcom18a4/xpcom/proxy/src/nsIProxyCreateInstance.h
new file mode 100644
index 00000000..13755d74
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/nsIProxyCreateInstance.h
@@ -0,0 +1,39 @@
+/*
+ * DO NOT EDIT. THIS FILE IS GENERATED FROM nsIProxyCreateInstance.idl
+ */
+
+#ifndef __gen_nsIProxyCreateInstance_h__
+#define __gen_nsIProxyCreateInstance_h__
+
+#include "nsISupports.h" /* interface nsISupports */
+#include "nsrootidl.h" /* interface nsrootidl */
+
+#ifdef XPIDL_JS_STUBS
+#include "jsapi.h"
+#endif
+
+/* starting interface: nsIProxyCreateInstance */
+
+/* {948c2080-0398-11d3-915e-0000863011c4} */
+#define NS_IPROXYCREATEINSTANCE_IID_STR "948c2080-0398-11d3-915e-0000863011c4"
+#define NS_IPROXYCREATEINSTANCE_IID \
+ {0x948c2080, 0x0398, 0x11d3, \
+ { 0x91, 0x5e, 0x00, 0x00, 0x86, 0x30, 0x11, 0xc4 }}
+
+class nsIProxyCreateInstance : public nsISupports {
+ public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IPROXYCREATEINSTANCE_IID)
+
+ /* void CreateInstanceByIID (in nsIIDRef cid, in nsISupports aOuter, in nsIIDRef iid, out voidStar result); */
+ NS_IMETHOD CreateInstanceByIID(const nsIID & cid, nsISupports *aOuter, const nsIID & iid, void * *result) = 0;
+
+ /* void CreateInstanceByContractID (in string aContractID, in nsISupports aOuter, in nsIIDRef iid, out voidStar result); */
+ NS_IMETHOD CreateInstanceByContractID(const char *aContractID, nsISupports *aOuter, const nsIID & iid, void * *result) = 0;
+
+#ifdef XPIDL_JS_STUBS
+ static NS_EXPORT_(JSObject *) InitJSClass(JSContext *cx);
+ static NS_EXPORT_(JSObject *) GetJSObject(JSContext *cx, nsIProxyCreateInstance *priv);
+#endif
+};
+
+#endif /* __gen_nsIProxyCreateInstance_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEvent.cpp b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEvent.cpp
new file mode 100644
index 00000000..561c2fdb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEvent.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 *****
+ *
+ * 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 "nsProxyEvent.h"
+#include "nsProxyEventPrivate.h"
+#include "nsIProxyObjectManager.h"
+#include "nsCRT.h"
+
+#include "pratom.h"
+#include "prmem.h"
+#include "xptcall.h"
+
+#include "nsIComponentManager.h"
+#include "nsComponentManagerObsolete.h"
+#include "nsIServiceManager.h"
+#include "nsMemory.h"
+#include "nsIEventQueueService.h"
+#include "nsIThread.h"
+
+#include "nsIAtom.h" //hack! Need a way to define a component as threadsafe (ie. sta).
+
+/**
+ * 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
+
+static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
+
+static void* PR_CALLBACK EventHandler(PLEvent *self);
+static void PR_CALLBACK DestroyHandler(PLEvent *self);
+static void* PR_CALLBACK CompletedEventHandler(PLEvent *self);
+static void PR_CALLBACK CompletedDestroyHandler(PLEvent *self) ;
+static void* PR_CALLBACK ProxyDestructorEventHandler(PLEvent *self);
+static void PR_CALLBACK ProxyDestructorDestroyHandler(PLEvent *self) ;
+
+nsProxyObjectCallInfo::nsProxyObjectCallInfo( nsProxyObject* owner,
+ nsXPTMethodInfo *methodInfo,
+ PRUint32 methodIndex,
+ nsXPTCVariant* parameterList,
+ PRUint32 parameterCount,
+ PLEvent *event)
+{
+ NS_ASSERTION(owner, "No nsProxyObject!");
+ NS_ASSERTION(methodInfo, "No nsXPTMethodInfo!");
+ NS_ASSERTION(event, "No PLEvent!");
+
+ mCompleted = 0;
+ mMethodIndex = methodIndex;
+ mParameterList = parameterList;
+ mParameterCount = parameterCount;
+ mEvent = event;
+ mMethodInfo = methodInfo;
+ mCallersEventQ = nsnull;
+
+ mOwner = owner;
+
+ RefCountInInterfacePointers(PR_TRUE);
+ if (mOwner->GetProxyType() & PROXY_ASYNC)
+ CopyStrings(PR_TRUE);
+}
+
+
+nsProxyObjectCallInfo::~nsProxyObjectCallInfo()
+{
+ RefCountInInterfacePointers(PR_FALSE);
+ if (mOwner->GetProxyType() & PROXY_ASYNC)
+ CopyStrings(PR_FALSE);
+
+ mOwner = nsnull;
+
+ PR_FREEIF(mEvent);
+
+ if (mParameterList)
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ nsMemory::Free((void*) mParameterList);
+#else
+ free( (void*) mParameterList);
+#endif
+}
+
+void
+nsProxyObjectCallInfo::RefCountInInterfacePointers(PRBool addRef)
+{
+ for (PRUint32 i = 0; i < mParameterCount; i++)
+ {
+ nsXPTParamInfo paramInfo = mMethodInfo->GetParam(i);
+
+ if (paramInfo.GetType().IsInterfacePointer() )
+ {
+ nsISupports* anInterface = nsnull;
+
+ if (paramInfo.IsIn())
+ {
+ anInterface = ((nsISupports*)mParameterList[i].val.p);
+
+ if (anInterface)
+ {
+ if(addRef)
+ anInterface->AddRef();
+ else
+ anInterface->Release();
+
+ }
+ }
+ }
+ }
+}
+
+void
+nsProxyObjectCallInfo::CopyStrings(PRBool copy)
+{
+ for (PRUint32 i = 0; i < mParameterCount; i++)
+ {
+ const nsXPTParamInfo paramInfo = mMethodInfo->GetParam(i);
+
+ if(paramInfo.IsIn())
+ {
+ const nsXPTType& type = paramInfo.GetType();
+ uint8 type_tag = type.TagPart();
+ void *ptr = mParameterList[i].val.p;
+
+ if (!ptr)
+ continue;
+
+ if (copy)
+ {
+ switch (type_tag)
+ {
+ case nsXPTType::T_CHAR_STR:
+ mParameterList[i].val.p =
+ PL_strdup((const char *)ptr);
+ break;
+ case nsXPTType::T_WCHAR_STR:
+ mParameterList[i].val.p =
+ nsCRT::strdup((const PRUnichar *)ptr);
+ break;
+ case nsXPTType::T_DOMSTRING:
+ case nsXPTType::T_ASTRING:
+ mParameterList[i].val.p =
+ new nsString(*((nsAString*) ptr));
+ break;
+ case nsXPTType::T_CSTRING:
+ mParameterList[i].val.p =
+ new nsCString(*((nsACString*) ptr));
+ break;
+ case nsXPTType::T_UTF8STRING:
+ mParameterList[i].val.p =
+ new nsUTF8String(*((nsAUTF8String*) ptr));
+ break;
+ default:
+ // Other types are ignored
+ break;
+ }
+ }
+ else
+ {
+ switch (type_tag)
+ {
+ case nsXPTType::T_CHAR_STR:
+ case nsXPTType::T_WCHAR_STR:
+ PL_strfree((char*) ptr);
+ break;
+ case nsXPTType::T_DOMSTRING:
+ case nsXPTType::T_ASTRING:
+ delete (nsString*) ptr;
+ break;
+ case nsXPTType::T_CSTRING:
+ delete (nsCString*) ptr;
+ break;
+ case nsXPTType::T_UTF8STRING:
+ delete (nsUTF8String*) ptr;
+ break;
+ default:
+ // Other types are ignored
+ break;
+ }
+ }
+ }
+ }
+}
+
+PRBool
+nsProxyObjectCallInfo::GetCompleted()
+{
+ return (PRBool)mCompleted;
+}
+
+void
+nsProxyObjectCallInfo::SetCompleted()
+{
+ PR_AtomicSet(&mCompleted, 1);
+}
+
+void
+nsProxyObjectCallInfo::PostCompleted()
+{
+ if (mCallersEventQ)
+ {
+ PLEvent *event = PR_NEW(PLEvent);
+
+ PL_InitEvent(event,
+ this,
+ CompletedEventHandler,
+ CompletedDestroyHandler);
+
+ mCallersEventQ->PostSynchronousEvent(event, nsnull);
+ PR_FREEIF(event);
+ }
+ else
+ {
+ // caller does not have an eventQ? This is an error!
+ SetCompleted();
+ }
+}
+
+nsIEventQueue*
+nsProxyObjectCallInfo::GetCallersQueue()
+{
+ return mCallersEventQ;
+}
+void
+nsProxyObjectCallInfo::SetCallersQueue(nsIEventQueue* queue)
+{
+ mCallersEventQ = queue;
+}
+
+
+nsProxyObject::nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, nsISupports *realObject)
+{
+ mEventQService = do_GetService(kEventQueueServiceCID);
+
+ mRealObject = realObject;
+ mDestQueue = do_QueryInterface(destQueue);
+ mProxyType = proxyType;
+}
+
+
+nsProxyObject::nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, const nsCID &aClass, nsISupports *aDelegate, const nsIID &aIID)
+{
+ mEventQService = do_GetService(kEventQueueServiceCID);
+
+ nsComponentManager::CreateInstance(aClass,
+ aDelegate,
+ aIID,
+ getter_AddRefs(mRealObject));
+
+ mDestQueue = do_QueryInterface(destQueue);
+ mProxyType = proxyType;
+}
+
+nsProxyObject::~nsProxyObject()
+{
+ // I am worried about order of destruction here.
+ // do not remove assignments.
+
+ mRealObject = 0;
+ mDestQueue = 0;
+}
+
+
+void
+nsProxyObject::AddRef()
+{
+ PR_AtomicIncrement((PRInt32 *)&mRefCnt);
+ NS_LOG_ADDREF(this, mRefCnt, "nsProxyObject", sizeof(*this));
+}
+
+void
+nsProxyObject::Release(void)
+{
+ NS_PRECONDITION(0 != mRefCnt, "dup release");
+
+ nsrefcnt count = PR_AtomicDecrement((PRInt32 *)&mRefCnt);
+ NS_LOG_RELEASE(this, count, "nsProxyObject");
+
+ if (count == 0)
+ {
+ mRefCnt = 1; /* stabilize */
+
+ PRBool callDirectly;
+ mDestQueue->IsOnCurrentThread(&callDirectly);
+
+ if (callDirectly)
+ {
+ delete this;
+ return;
+ }
+
+ // need to do something special here so that
+ // the real object will always be deleted on
+ // the correct thread..
+
+ PLEvent *event = PR_NEW(PLEvent);
+ if (event == nsnull)
+ {
+ NS_ASSERTION(0, "Could not create a plevent. Leaking nsProxyObject!");
+ return; // if this happens we are going to leak.
+ }
+
+ PL_InitEvent(event,
+ this,
+ ProxyDestructorEventHandler,
+ ProxyDestructorDestroyHandler);
+
+ mDestQueue->PostEvent(event);
+ }
+}
+
+
+nsresult
+nsProxyObject::PostAndWait(nsProxyObjectCallInfo *proxyInfo)
+{
+ if (proxyInfo == nsnull || mEventQService == nsnull)
+ return NS_ERROR_NULL_POINTER;
+
+ PRBool eventLoopCreated = PR_FALSE;
+ nsresult rv;
+
+ nsCOMPtr<nsIEventQueue> eventQ;
+ rv = mEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(eventQ));
+ if (NS_FAILED(rv))
+ {
+ rv = mEventQService->CreateMonitoredThreadEventQueue();
+ eventLoopCreated = PR_TRUE;
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = mEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(eventQ));
+ }
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ proxyInfo->SetCallersQueue(eventQ);
+
+ PLEvent* event = proxyInfo->GetPLEvent();
+ if (!event)
+ return NS_ERROR_NULL_POINTER;
+
+ mDestQueue->PostEvent(event);
+
+ while (! proxyInfo->GetCompleted())
+ {
+ PLEvent *nextEvent;
+ rv = eventQ->WaitForEvent(&nextEvent);
+ if (NS_FAILED(rv)) break;
+
+ eventQ->HandleEvent(nextEvent);
+ }
+
+ if (eventLoopCreated)
+ {
+ mEventQService->DestroyThreadEventQueue();
+ eventQ = 0;
+ }
+
+ return rv;
+}
+
+
+nsresult
+nsProxyObject::convertMiniVariantToVariant(nsXPTMethodInfo *methodInfo,
+ nsXPTCMiniVariant * params,
+ nsXPTCVariant **fullParam,
+ uint8 *outParamCount)
+{
+ uint8 paramCount = methodInfo->GetParamCount();
+ *outParamCount = paramCount;
+ *fullParam = nsnull;
+
+ if (!paramCount) return NS_OK;
+
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ *fullParam = (nsXPTCVariant*)nsMemory::Alloc(sizeof(nsXPTCVariant) * paramCount);
+#else
+ *fullParam = (nsXPTCVariant*)malloc(sizeof(nsXPTCVariant) * paramCount);
+#endif
+
+ if (*fullParam == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ for (int i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& paramInfo = methodInfo->GetParam(i);
+ if ((mProxyType & PROXY_ASYNC) && paramInfo.IsDipper())
+ {
+ NS_WARNING("Async proxying of out parameters is not supported");
+ return NS_ERROR_PROXY_INVALID_OUT_PARAMETER;
+ }
+ uint8 flags = paramInfo.IsOut() ? nsXPTCVariant::PTR_IS_DATA : 0;
+ (*fullParam)[i].Init(params[i], paramInfo.GetType(), flags);
+ }
+
+ return NS_OK;
+}
+
+nsresult
+nsProxyObject::Post( PRUint32 methodIndex,
+ nsXPTMethodInfo *methodInfo,
+ nsXPTCMiniVariant * params,
+ nsIInterfaceInfo *interfaceInfo)
+{
+ nsresult rv = NS_OK;
+
+ if (! mDestQueue || ! mRealObject)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (methodInfo->IsNotXPCOM())
+ return NS_ERROR_PROXY_INVALID_IN_PARAMETER;
+
+ nsXPTCVariant *fullParam;
+ uint8 paramCount;
+ rv = convertMiniVariantToVariant(methodInfo, params, &fullParam, &paramCount);
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRBool callDirectly;
+
+ // see if we should call into the method directly. Either it is a QI function call
+ // (methodIndex == 0), or it is a sync proxy and this code is running on the same thread
+ // as the destination event queue.
+ if ( (methodIndex == 0) ||
+ (mProxyType & PROXY_SYNC &&
+ NS_SUCCEEDED(mDestQueue->IsOnCurrentThread(&callDirectly)) &&
+ callDirectly))
+ {
+
+ // invoke the magic of xptc...
+ nsresult rv = XPTC_InvokeByIndex( mRealObject,
+ methodIndex,
+ paramCount,
+ fullParam);
+
+ if (fullParam)
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ nsMemory::Free(fullParam);
+#else
+ free(fullParam);
+#endif
+ return rv;
+ }
+
+ PLEvent *event = PR_NEW(PLEvent);
+
+ if (event == nsnull) {
+ if (fullParam)
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ nsMemory::Free(fullParam);
+#else
+ free(fullParam);
+#endif
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ nsProxyObjectCallInfo *proxyInfo = new nsProxyObjectCallInfo(this,
+ methodInfo,
+ methodIndex,
+ fullParam, // will be deleted by ~()
+ paramCount,
+ event); // will be deleted by ~()
+
+ if (proxyInfo == nsnull) {
+ PR_DELETE(event);
+ if (fullParam)
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ nsMemory::Free(fullParam);
+#else
+ free(fullParam);
+#endif
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ PL_InitEvent(event,
+ proxyInfo,
+ EventHandler,
+ DestroyHandler);
+
+ if (mProxyType & PROXY_SYNC)
+ {
+ rv = PostAndWait(proxyInfo);
+
+ if (NS_SUCCEEDED(rv))
+ rv = proxyInfo->GetResult();
+ delete proxyInfo;
+ return rv;
+ }
+
+ if (mProxyType & PROXY_ASYNC)
+ {
+ mDestQueue->PostEvent(event);
+ return NS_OK;
+ }
+ return NS_ERROR_UNEXPECTED;
+}
+
+
+
+static void DestroyHandler(PLEvent *self)
+{
+ nsProxyObjectCallInfo* owner = (nsProxyObjectCallInfo*)PL_GetEventOwner(self);
+ nsProxyObject* proxyObject = owner->GetProxyObject();
+
+ if (proxyObject == nsnull)
+ return;
+
+ if (proxyObject->GetProxyType() & PROXY_ASYNC)
+ {
+ delete owner;
+ }
+ else
+ {
+ owner->PostCompleted();
+ }
+
+}
+
+static void* EventHandler(PLEvent *self)
+{
+ nsProxyObjectCallInfo *info = (nsProxyObjectCallInfo*)PL_GetEventOwner(self);
+ NS_ASSERTION(info, "No nsProxyObjectCallInfo!");
+
+ nsProxyObject *proxyObject = info->GetProxyObject();
+
+ if (proxyObject)
+ {
+ // invoke the magic of xptc...
+ nsresult rv = XPTC_InvokeByIndex( proxyObject->GetRealObject(),
+ info->GetMethodIndex(),
+ info->GetParameterCount(),
+ info->GetParameterList());
+ info->SetResult(rv);
+ }
+ else
+ {
+ info->SetResult(NS_ERROR_OUT_OF_MEMORY);
+ }
+ return NULL;
+}
+
+static void CompletedDestroyHandler(PLEvent *self)
+{
+}
+
+static void* CompletedEventHandler(PLEvent *self)
+{
+ nsProxyObjectCallInfo* owner = (nsProxyObjectCallInfo*)PL_GetEventOwner(self);
+ owner->SetCompleted();
+ return nsnull;
+}
+
+static void* ProxyDestructorEventHandler(PLEvent *self)
+{
+ nsProxyObject* owner = (nsProxyObject*) PL_GetEventOwner(self);
+ NS_DELETEXPCOM(owner);
+ return nsnull;
+}
+
+static void ProxyDestructorDestroyHandler(PLEvent *self)
+{
+ PR_DELETE(self);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventClass.cpp b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventClass.cpp
new file mode 100644
index 00000000..8e221afa
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventClass.cpp
@@ -0,0 +1,367 @@
+/* -*- 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 "nsProxyEvent.h"
+#include "nsIProxyObjectManager.h"
+#include "nsProxyEventPrivate.h"
+
+#include "nsIComponentManager.h"
+#include "nsIServiceManager.h"
+#include "nsCOMPtr.h"
+
+#include "nsMemory.h"
+#include "nsHashtable.h"
+
+#include "nsAutoLock.h"
+#include "nsIInterfaceInfoManager.h"
+#include "xptcall.h"
+
+// LIFETIME_CACHE will cache class for the entire cyle of the application.
+#define LIFETIME_CACHE
+
+static uint32 zero_methods_descriptor;
+
+
+/* ssc@netscape.com wishes he could get rid of this instance of
+ * |NS_DEFINE_IID|, but |ProxyEventClassIdentity| is not visible from
+ * here.
+ */
+static NS_DEFINE_IID(kProxyObject_Identity_Class_IID, NS_PROXYEVENT_IDENTITY_CLASS_IID);
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+// nsProxyEventClass
+//////////////////////////////////////////////////////////////////////////////////////////////////
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsProxyEventClass, nsProxyEventClass)
+
+// static
+nsProxyEventClass*
+nsProxyEventClass::GetNewOrUsedClass(REFNSIID aIID)
+{
+ /* find in our hash table */
+
+ nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance();
+ if (manager == nsnull) return nsnull;
+
+ // dont need to lock the map, because this is only called
+ // by nsProxyEventClass::GetNewOrUsed which locks it for us.
+
+ nsHashtable *iidToClassMap = manager->GetIIDToProxyClassMap();
+
+ if (iidToClassMap == nsnull)
+ {
+ return nsnull;
+ }
+
+ nsProxyEventClass* clazz = nsnull;
+ nsIDKey key(aIID);
+
+#ifdef PROXYEVENTCLASS_DEBUG
+ char* iidStr = aIID.ToString();
+ printf("GetNewOrUsedClass %s\n", iidStr);
+ nsCRT::free(iidStr);
+#endif
+
+ clazz = (nsProxyEventClass*) iidToClassMap->Get(&key);
+ if(clazz)
+ {
+ NS_ADDREF(clazz);
+#ifdef PROXYEVENTCLASS_DEBUG
+ char* iidStr = aIID.ToString();
+ printf("GetNewOrUsedClass %s hit\n", iidStr);
+ nsCRT::free(iidStr);
+#endif
+ }
+ else
+ {
+ nsCOMPtr<nsIInterfaceInfoManager> iimgr = getter_AddRefs(XPTI_GetInterfaceInfoManager());
+ if(iimgr)
+ {
+ nsCOMPtr<nsIInterfaceInfo> info;
+ if(NS_SUCCEEDED(iimgr->GetInfoForIID(&aIID, getter_AddRefs(info))))
+ {
+ /*
+ Check to see if isISupportsDescendent
+ */
+ nsCOMPtr<nsIInterfaceInfo> oldest = info;
+ nsCOMPtr<nsIInterfaceInfo> parent;
+
+ while(NS_SUCCEEDED(oldest->GetParent(getter_AddRefs(parent)))&&
+ parent)
+ {
+ oldest = parent;
+ }
+
+ PRBool isISupportsDescendent = PR_FALSE;
+ nsID* iid;
+ if(NS_SUCCEEDED(oldest->GetInterfaceIID(&iid)))
+ {
+ isISupportsDescendent = iid->Equals(NS_GET_IID(nsISupports));
+ nsMemory::Free(iid);
+ }
+
+ NS_ASSERTION(isISupportsDescendent, "!isISupportsDescendent");
+
+ if (isISupportsDescendent)
+ {
+ clazz = new nsProxyEventClass(aIID, info);
+ if(!clazz->mDescriptors)
+ NS_RELEASE(clazz); // sets clazz to NULL
+ }
+ }
+ }
+ }
+ return clazz;
+}
+
+nsProxyEventClass::nsProxyEventClass()
+{
+ NS_WARNING("This constructor should never be called");
+}
+
+nsProxyEventClass::nsProxyEventClass(REFNSIID aIID, nsIInterfaceInfo* aInfo)
+: mIID(aIID),
+ mDescriptors(NULL)
+{
+ NS_ADDREF_THIS();
+
+ mInfo = aInfo;
+
+ /* add use to the used classes */
+ nsIDKey key(aIID);
+
+ nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance();
+ if (manager == nsnull) return;
+ // dont need to lock the map, because this is only called
+ // by GetNewOrUsed which locks it for us.
+
+ nsHashtable *iidToClassMap = manager->GetIIDToProxyClassMap();
+
+ if (iidToClassMap != nsnull)
+ {
+ iidToClassMap->Put(&key, this);
+#ifdef LIFETIME_CACHE
+ // extra addref to hold it in the cache
+ NS_ADDREF_THIS();
+#endif
+#ifdef PROXYEVENTCLASS_DEBUG
+ char* iidStr = aIID.ToString();
+ printf("GetNewOrUsedClass %s put\n", iidStr);
+ nsCRT::free(iidStr);
+#endif
+ }
+
+ uint16 methodCount;
+ if(NS_SUCCEEDED(mInfo->GetMethodCount(&methodCount)))
+ {
+ if(methodCount)
+ {
+ int wordCount = (methodCount/32)+1;
+ if(NULL != (mDescriptors = new uint32[wordCount]))
+ {
+ memset(mDescriptors, 0, wordCount * sizeof(uint32));
+ }
+ }
+ else
+ {
+ mDescriptors = &zero_methods_descriptor;
+ }
+ }
+}
+
+nsProxyEventClass::~nsProxyEventClass()
+{
+ if(mDescriptors && mDescriptors != &zero_methods_descriptor)
+ delete [] mDescriptors;
+
+ if (nsProxyObjectManager::IsManagerShutdown())
+ return;
+
+#ifndef LIFETIME_CACHE
+ nsIDKey key(mIID);
+
+ nsCOMPtr<nsProxyObjectManager> manager = getter_AddRefs(nsProxyObjectManager::GetInstance());
+ if (manager == nsnull) return;
+ nsHashtable *iidToClassMap = manager->GetIIDToProxyClassMap();
+
+ if (iidToClassMap != nsnull)
+ {
+ iidToClassMap->Remove(&key);
+#ifdef PROXYEVENTCLASS_DEBUG
+ char* iidStr = mIID.ToString();
+ printf("GetNewOrUsedClass %s remove\n", iidStr);
+ nsCRT::free(iidStr);
+#endif
+ }
+#endif
+}
+
+nsresult
+nsProxyEventClass::CallQueryInterfaceOnProxy(nsProxyEventObject* self, REFNSIID aIID, nsProxyEventObject** aInstancePtr)
+{
+ NS_PRECONDITION(aInstancePtr, "Requires non-null result");
+
+ nsresult rv;
+
+ *aInstancePtr = nsnull; // in case of error.
+
+
+ // The functions we will call: QueryInterface(REFNSIID aIID, void** aInstancePtr)
+
+ nsXPTCMiniVariant var[2];
+
+ var[0].val.p = (void*)&aIID;
+ var[1].val.p = (void*)aInstancePtr;
+
+ nsCOMPtr<nsIInterfaceInfo> interfaceInfo;
+ const nsXPTMethodInfo *mi;
+
+ nsCOMPtr<nsIInterfaceInfoManager> iim = getter_AddRefs(XPTI_GetInterfaceInfoManager());
+
+ if (!iim) return NS_NOINTERFACE;
+ iim->GetInfoForName("nsISupports", getter_AddRefs(interfaceInfo));
+ interfaceInfo->GetMethodInfo(0, &mi); // 0 is QueryInterface
+
+ rv = self->CallMethod(0, mi, var);
+
+ if (NS_SUCCEEDED(rv))
+ {
+ nsISupports *aIdentificationObject;
+
+ rv = (*aInstancePtr)->QueryInterface(kProxyObject_Identity_Class_IID, (void**)&aIdentificationObject);
+
+ if (NS_FAILED(rv))
+ {
+ // okay, aInstancePtr was not a proxy. Lets create one.
+ nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance();
+ if (manager == nsnull)
+ {
+ NS_IF_RELEASE((*aInstancePtr));
+ return NS_ERROR_FAILURE;
+ }
+
+ rv = manager->GetProxyForObject(self->GetQueue(),
+ aIID,
+ self->GetRealObject(),
+ self->GetProxyType(),
+ (void**) &aIdentificationObject);
+ }
+
+ NS_IF_RELEASE((*aInstancePtr));
+ (*aInstancePtr) = NS_STATIC_CAST(nsProxyEventObject*, aIdentificationObject);
+ }
+ return rv;
+}
+
+
+/***************************************************************************/
+// This 'ProxyEventClassIdentity' class and singleton allow us to figure out if
+// any given nsISupports* is implemented by a nsProxy object. This is done
+// using a QueryInterface call on the interface pointer with our ID. If
+// that call returns NS_OK and the pointer is to a nsProxyEventObject. It must
+// be released when done.
+
+// NS_PROXYEVENT_IDENTITY_CLASS_IID defined in nsProxyEventPrivate.h
+class ProxyEventClassIdentity
+{
+ // no instance methods...
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_PROXYEVENT_IDENTITY_CLASS_IID)
+
+ static void* GetSingleton()
+ {
+ static ProxyEventClassIdentity* singleton = NULL;
+ if(!singleton)
+ singleton = new ProxyEventClassIdentity();
+ return (void*) singleton;
+ }
+};
+
+NS_IMETHODIMP
+nsProxyEventClass::DelegatedQueryInterface(nsProxyEventObject* self,
+ REFNSIID aIID,
+ void** aInstancePtr)
+{
+
+ if(aIID.Equals(NS_GET_IID(ProxyEventClassIdentity)))
+ {
+ *aInstancePtr = NS_STATIC_CAST(void*, self);
+ NS_ADDREF(self);
+ return NS_OK;
+ }
+
+ nsProxyEventObject* sibling;
+ {
+ nsProxyObjectManager* manager = nsProxyObjectManager::GetInstance();
+ nsAutoMonitor mon(manager->GetMonitor());
+
+ // This includes checking for nsISupports and the iid of self.
+ // And it also checks for other wrappers that have been constructed
+ // for this object.
+ if(nsnull != (sibling = self->LockedFind(aIID)))
+ {
+ NS_ADDREF(sibling);
+ *aInstancePtr = (void*) sibling;
+ return NS_OK;
+ }
+
+ // check if asking for an interface that we inherit from
+ nsCOMPtr<nsIInterfaceInfo> current = GetInterfaceInfo();
+ nsCOMPtr<nsIInterfaceInfo> parent;
+
+ while(NS_SUCCEEDED(current->GetParent(getter_AddRefs(parent))) && parent)
+ {
+ current = parent;
+
+ nsIID* iid;
+ if(NS_SUCCEEDED(current->GetInterfaceIID(&iid)) && iid)
+ {
+ PRBool found = aIID.Equals(*iid);
+ nsMemory::Free(iid);
+ if(found)
+ {
+ *aInstancePtr = (void*) self;
+ NS_ADDREF(self);
+ return NS_OK;
+ }
+ }
+ }
+ }
+
+ return CallQueryInterfaceOnProxy(self, aIID, (nsProxyEventObject**)aInstancePtr);
+}
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventObject.cpp b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventObject.cpp
new file mode 100644
index 00000000..d529fc05
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventObject.cpp
@@ -0,0 +1,555 @@
+/* -*- 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 "prprf.h"
+#include "prmem.h"
+
+#include "nscore.h"
+#include "nsProxyEvent.h"
+#include "nsIProxyObjectManager.h"
+#include "nsProxyEventPrivate.h"
+
+#include "nsHashtable.h"
+
+#include "nsIInterfaceInfoManager.h"
+#include "xptcall.h"
+
+#include "nsAutoLock.h"
+
+static NS_DEFINE_IID(kProxyObject_Identity_Class_IID, NS_PROXYEVENT_IDENTITY_CLASS_IID);
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+class nsProxyEventKey : public nsHashKey
+{
+public:
+ nsProxyEventKey(void* rootObjectKey, void* destQueueKey, PRInt32 proxyType)
+ : mRootObjectKey(rootObjectKey), mDestQueueKey(destQueueKey), mProxyType(proxyType) {
+ }
+
+ PRUint32 HashCode(void) const {
+ return NS_PTR_TO_INT32(mRootObjectKey) ^
+ NS_PTR_TO_INT32(mDestQueueKey) ^ mProxyType;
+ }
+
+ PRBool Equals(const nsHashKey *aKey) const {
+ const nsProxyEventKey* other = (const nsProxyEventKey*)aKey;
+ return mRootObjectKey == other->mRootObjectKey
+ && mDestQueueKey == other->mDestQueueKey
+ && mProxyType == other->mProxyType;
+ }
+
+ nsHashKey *Clone() const {
+ return new nsProxyEventKey(mRootObjectKey, mDestQueueKey, mProxyType);
+ }
+
+protected:
+ void* mRootObjectKey;
+ void* mDestQueueKey;
+ PRInt32 mProxyType;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef DEBUG_xpcom_proxy
+static PRMonitor* mon = nsnull;
+static PRUint32 totalProxyObjects = 0;
+static PRUint32 outstandingProxyObjects = 0;
+
+void
+nsProxyEventObject::DebugDump(const char * message, PRUint32 hashKey)
+{
+
+ if (mon == nsnull)
+ {
+ mon = PR_NewMonitor();
+ }
+
+ PR_EnterMonitor(mon);
+
+ if (message)
+ {
+ printf("\n-=-=-=-=-=-=-=-=-=-=-=-=-\n");
+ printf("%s\n", message);
+
+ if(strcmp(message, "Create") == 0)
+ {
+ totalProxyObjects++;
+ outstandingProxyObjects++;
+ }
+ else if(strcmp(message, "Delete") == 0)
+ {
+ outstandingProxyObjects--;
+ }
+ }
+ printf("nsProxyEventObject @ %x with mRefCnt = %d\n", this, mRefCnt);
+
+ PRBool isRoot = mRoot == nsnull;
+ printf("%s wrapper around @ %x\n", isRoot ? "ROOT":"non-root\n", GetRealObject());
+
+ nsCOMPtr<nsISupports> rootObject = do_QueryInterface(mProxyObject->mRealObject);
+ nsCOMPtr<nsISupports> rootQueue = do_QueryInterface(mProxyObject->mDestQueue);
+ nsProxyEventKey key(rootObject, rootQueue, mProxyObject->mProxyType);
+ printf("Hashkey: %d\n", key.HashCode());
+
+ char* name;
+ GetClass()->GetInterfaceInfo()->GetName(&name);
+ printf("interface name is %s\n", name);
+ if(name)
+ nsMemory::Free(name);
+ char * iid = GetClass()->GetProxiedIID().ToString();
+ printf("IID number is %s\n", iid);
+ delete iid;
+ printf("nsProxyEventClass @ %x\n", mClass);
+
+ if(mNext)
+ {
+ if(isRoot)
+ {
+ printf("Additional wrappers for this object...\n");
+ }
+ mNext->DebugDump(nsnull, 0);
+ }
+
+ printf("[proxyobjects] %d total used in system, %d outstading\n", totalProxyObjects, outstandingProxyObjects);
+
+ if (message)
+ printf("-=-=-=-=-=-=-=-=-=-=-=-=-\n");
+
+ PR_ExitMonitor(mon);
+}
+#endif
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// nsProxyEventObject
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////
+nsProxyEventObject*
+nsProxyEventObject::GetNewOrUsedProxy(nsIEventQueue *destQueue,
+ PRInt32 proxyType,
+ nsISupports *aObj,
+ REFNSIID aIID)
+{
+ nsresult rv;
+
+ if (!aObj)
+ return nsnull;
+
+ nsISupports* rawObject = aObj;
+
+ //
+ // make sure that the object pass in is not a proxy...
+ // if the object *is* a proxy, then be nice and build the proxy
+ // for the real object...
+ //
+ nsCOMPtr<nsProxyEventObject> identificationObject;
+
+ rv = rawObject->QueryInterface(kProxyObject_Identity_Class_IID,
+ getter_AddRefs(identificationObject));
+ if (NS_SUCCEEDED(rv)) {
+ //
+ // ATTENTION!!!!
+ //
+ // If you are hitting any of the assertions in this block of code,
+ // please contact dougt@netscape.com.
+ //
+
+ // if you hit this assertion, you might want to check out how
+ // you are using proxies. You shouldn't need to be creating
+ // a proxy from a proxy. -- dougt@netscape.com
+ NS_ASSERTION(0, "Someone is building a proxy from a proxy");
+
+ NS_ASSERTION(identificationObject, "where did my identification object go!");
+ if (!identificationObject) {
+ return nsnull;
+ }
+
+ // someone is asking us to create a proxy for a proxy. Lets get
+ // the real object and build aproxy for that!
+ rawObject = identificationObject->GetRealObject();
+
+ NS_ASSERTION(rawObject, "where did my real object go!");
+ if (!rawObject) {
+ return nsnull;
+ }
+ }
+
+ //
+ // Get the root nsISupports of the |real| object.
+ //
+ nsCOMPtr<nsISupports> rootObject;
+
+ rootObject = do_QueryInterface(rawObject, &rv);
+ if (NS_FAILED(rv) || !rootObject) {
+ NS_ASSERTION(NS_FAILED(rv), "where did my root object go!");
+ return nsnull;
+ }
+
+ // Get the root nsISupports of the event queue... This is used later,
+ // as part of the hashtable key...
+ nsCOMPtr<nsISupports> destQRoot = do_QueryInterface(destQueue, &rv);
+ if (NS_FAILED(rv) || !destQRoot) {
+ return nsnull;
+ }
+
+ //
+ // Enter the proxy object creation lock.
+ //
+ // This lock protects thev linked list which chains proxies together
+ // (ie. mRoot and mNext) and ensures that there is no hashtable contention
+ // between the time that a proxy is looked up (and not found) in the
+ // hashtable and then added...
+ //
+ nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance();
+ if (!manager) {
+ return nsnull;
+ }
+
+ nsAutoMonitor mon(manager->GetMonitor());
+
+ // Get the hash table containing root proxy objects...
+ nsHashtable *realToProxyMap = manager->GetRealObjectToProxyObjectMap();
+ if (!realToProxyMap) {
+ return nsnull;
+ }
+
+ // Now, lookup the root nsISupports of the raw object in the hashtable
+ // The key consists of 3 pieces of information:
+ // - root nsISupports of the raw object
+ // - event queue of the current thread
+ // - type of proxy being constructed...
+ //
+ nsProxyEventKey rootkey(rootObject.get(), destQRoot.get(), proxyType);
+
+ nsCOMPtr<nsProxyEventObject> rootProxy;
+ nsCOMPtr<nsProxyEventObject> proxy;
+ nsProxyEventObject* peo;
+
+ // find in our hash table
+ rootProxy = (nsProxyEventObject*) realToProxyMap->Get(&rootkey);
+
+ if(rootProxy) {
+ //
+ // At least one proxy has already been created for this raw object...
+ //
+ // Look for the specific interface proxy in the list off of
+ // the root proxy...
+ //
+ peo = rootProxy->LockedFind(aIID);
+
+ if(peo) {
+ // An existing proxy is available... So use it.
+ NS_ADDREF(peo);
+ return peo;
+ }
+ }
+ else {
+ // build the root proxy
+ nsCOMPtr<nsProxyEventClass> rootClazz;
+
+ rootClazz = dont_AddRef(nsProxyEventClass::GetNewOrUsedClass(
+ NS_GET_IID(nsISupports)));
+ if (!rootClazz) {
+ return nsnull;
+ }
+
+ peo = new nsProxyEventObject(destQueue,
+ proxyType,
+ rootObject,
+ rootClazz,
+ nsnull);
+ if(!peo) {
+ // Ouch... Out of memory!
+ return nsnull;
+ }
+
+ // Add this root proxy into the hash table...
+ realToProxyMap->Put(&rootkey, peo);
+
+ if(aIID.Equals(NS_GET_IID(nsISupports))) {
+ //
+ // Since the requested proxy is for the nsISupports interface of
+ // the raw object, use the new root proxy as the specific proxy
+ // too...
+ //
+ NS_ADDREF(peo);
+ return peo;
+ }
+
+ // This assignment is an owning reference to the new ProxyEventObject.
+ // So, it will automatically get deleted if any subsequent early
+ // returns are taken...
+ rootProxy = do_QueryInterface(peo);
+ }
+
+ //
+ // at this point we have a proxy for the root nsISupports (ie. rootProxy)
+ // but we need to build the specific proxy for this interface...
+ //
+ NS_ASSERTION(rootProxy, "What happened to the root proxy!");
+
+ // Get a class for this IID.
+ nsCOMPtr<nsProxyEventClass> proxyClazz;
+
+ proxyClazz = dont_AddRef(nsProxyEventClass::GetNewOrUsedClass(aIID));
+ if(!proxyClazz) {
+ return nsnull;
+ }
+
+ // Get the raw interface for this IID
+ nsCOMPtr<nsISupports> rawInterface;
+
+ rv = rawObject->QueryInterface(aIID, getter_AddRefs(rawInterface));
+ if (NS_FAILED(rv) || !rawInterface) {
+ NS_ASSERTION(NS_FAILED(rv), "where did my rawInterface object go!");
+ return nsnull;
+ }
+
+ peo = new nsProxyEventObject(destQueue,
+ proxyType,
+ rawInterface,
+ proxyClazz,
+ rootProxy);
+ if (!peo) {
+ // Ouch... Out of memory!
+ return nsnull;
+ }
+
+ //
+ // Add the new specific proxy to the head of the list of proxies hanging
+ // off of the rootProxy...
+ //
+ peo->mNext = rootProxy->mNext;
+ rootProxy->mNext = peo;
+
+ NS_ADDREF(peo);
+ return peo;
+
+}
+
+nsProxyEventObject* nsProxyEventObject::LockedFind(REFNSIID aIID)
+{
+ if(aIID.Equals(mClass->GetProxiedIID())) {
+ return this;
+ }
+
+ if(aIID.Equals(NS_GET_IID(nsISupports))) {
+ return this;
+ }
+
+ nsProxyEventObject* cur = (mRoot ? mRoot : mNext);
+ while(cur) {
+ if(aIID.Equals(cur->GetClass()->GetProxiedIID())) {
+ return cur;
+ }
+ cur = cur->mNext;
+ }
+
+ return nsnull;
+}
+
+nsProxyEventObject::nsProxyEventObject()
+: mNext(nsnull)
+{
+ NS_WARNING("This constructor should never be called");
+}
+
+nsProxyEventObject::nsProxyEventObject(nsIEventQueue *destQueue,
+ PRInt32 proxyType,
+ nsISupports* aObj,
+ nsProxyEventClass* aClass,
+ nsProxyEventObject* root)
+ : mClass(aClass),
+ mRoot(root),
+ mNext(nsnull)
+{
+ NS_IF_ADDREF(mRoot);
+
+ mProxyObject = new nsProxyObject(destQueue, proxyType, aObj);
+
+#ifdef DEBUG_xpcom_proxy
+ DebugDump("Create", 0);
+#endif
+}
+
+nsProxyEventObject::~nsProxyEventObject()
+{
+#ifdef DEBUG_xpcom_proxy
+ DebugDump("Delete", 0);
+#endif
+ if (mRoot) {
+ //
+ // This proxy is not the root interface so it must be removed
+ // from the chain of proxies...
+ //
+ nsProxyEventObject* cur = mRoot;
+ while(cur) {
+ if(cur->mNext == this) {
+ cur->mNext = mNext;
+ mNext = nsnull;
+ break;
+ }
+ cur = cur->mNext;
+ }
+ NS_ASSERTION(cur, "failed to find wrapper in its own chain");
+ }
+ else {
+ //
+ // This proxy is for the root interface. Each proxy in the chain
+ // has a strong reference to the root... So, when its refcount goes
+ // to zero, it safe to remove it because no proxies are in its chain.
+ //
+ if (! nsProxyObjectManager::IsManagerShutdown()) {
+ nsProxyObjectManager* manager = nsProxyObjectManager::GetInstance();
+ nsHashtable *realToProxyMap = manager->GetRealObjectToProxyObjectMap();
+
+ NS_ASSERTION(!mNext, "There are still proxies in the chain!");
+
+ if (realToProxyMap != nsnull) {
+ nsCOMPtr<nsISupports> rootObject = do_QueryInterface(mProxyObject->mRealObject);
+ nsCOMPtr<nsISupports> rootQueue = do_QueryInterface(mProxyObject->mDestQueue);
+ nsProxyEventKey key(rootObject, rootQueue, mProxyObject->mProxyType);
+#ifdef DEBUG_dougt
+ void* value =
+#endif
+ realToProxyMap->Remove(&key);
+#ifdef DEBUG_dougt
+ NS_ASSERTION(value, "failed to remove from realToProxyMap");
+#endif
+ }
+ }
+ }
+
+ // I am worried about ordering.
+ // do not remove assignments.
+ mProxyObject = nsnull;
+ mClass = nsnull;
+ NS_IF_RELEASE(mRoot);
+}
+
+//
+// nsISupports implementation...
+//
+
+NS_IMPL_THREADSAFE_ADDREF(nsProxyEventObject)
+
+NS_IMETHODIMP_(nsrefcnt)
+nsProxyEventObject::Release(void)
+{
+ //
+ // Be pessimistic about whether the manager or even the monitor exist...
+ // This is to protect against shutdown issues where a proxy object could
+ // be destroyed after (or while) the Proxy Manager is being destroyed...
+ //
+ nsProxyObjectManager* manager = nsProxyObjectManager::GetInstance();
+ nsAutoMonitor mon(manager ? manager->GetMonitor() : nsnull);
+
+ nsrefcnt count;
+ NS_PRECONDITION(0 != mRefCnt, "dup release");
+ // Decrement atomically - in case the Proxy Object Manager has already
+ // been deleted and the monitor is unavailable...
+ count = PR_AtomicDecrement((PRInt32 *)&mRefCnt);
+ NS_LOG_RELEASE(this, count, "nsProxyEventObject");
+ if (0 == count) {
+ mRefCnt = 1; /* stabilize */
+ //
+ // Remove the proxy from the hashtable (if necessary) or its
+ // proxy chain. This must be done inside of the proxy lock to
+ // prevent GetNewOrUsedProxy(...) from ressurecting it...
+ //
+ NS_DELETEXPCOM(this);
+ return 0;
+ }
+ return count;
+}
+
+NS_IMETHODIMP
+nsProxyEventObject::QueryInterface(REFNSIID aIID, void** aInstancePtr)
+{
+ if( aIID.Equals(GetIID()) )
+ {
+ *aInstancePtr = NS_STATIC_CAST(nsISupports*, this);
+ NS_ADDREF_THIS();
+ return NS_OK;
+ }
+
+ return mClass->DelegatedQueryInterface(this, aIID, aInstancePtr);
+}
+
+//
+// nsXPTCStubBase implementation...
+//
+
+NS_IMETHODIMP
+nsProxyEventObject::GetInterfaceInfo(nsIInterfaceInfo** info)
+{
+ NS_ENSURE_ARG_POINTER(info);
+
+ *info = mClass->GetInterfaceInfo();
+
+ NS_ASSERTION(*info, "proxy class without interface");
+ if (!*info) {
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ NS_ADDREF(*info);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsProxyEventObject::CallMethod(PRUint16 methodIndex,
+ const nsXPTMethodInfo* info,
+ nsXPTCMiniVariant * params)
+{
+ nsresult rv;
+
+ if (mProxyObject) {
+ rv = mProxyObject->Post(methodIndex,
+ (nsXPTMethodInfo*)info,
+ params,
+ mClass->GetInterfaceInfo());
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventPrivate.h b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventPrivate.h
new file mode 100644
index 00000000..ee34927e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventPrivate.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):
+ * 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 ***** */
+
+#ifndef __nsProxyEventPrivate_h_
+#define __nsProxyEventPrivate_h_
+
+#include "nscore.h"
+#include "nsISupports.h"
+#include "nsIFactory.h"
+#include "nsHashtable.h"
+
+#include "plevent.h"
+#include "xptcall.h" // defines nsXPTCVariant
+#include "nsIEventQueue.h"
+
+#include "nsProxyEvent.h"
+#include "nsIProxyObjectManager.h"
+
+class nsProxyEventObject;
+class nsProxyEventClass;
+
+#define NS_PROXYEVENT_CLASS_IID \
+{ 0xeea90d42, \
+ 0xb059, \
+ 0x11d2, \
+ {0x91, 0x5e, 0xc1, 0x2b, 0x69, 0x6c, 0x93, 0x33}\
+}
+
+#define NS_PROXYEVENT_IDENTITY_CLASS_IID \
+{ 0xeea90d45, 0xb059, 0x11d2, \
+ { 0x91, 0x5e, 0xc1, 0x2b, 0x69, 0x6c, 0x93, 0x33 } }
+
+
+#define NS_PROXYEVENT_OBJECT_IID \
+{ 0xec373590, 0x9164, 0x11d3, \
+{0x8c, 0x73, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74} }
+
+
+class nsProxyEventClass : public nsISupports
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_PROXYEVENT_CLASS_IID)
+ static nsProxyEventClass* GetNewOrUsedClass(REFNSIID aIID);
+
+ NS_IMETHOD DelegatedQueryInterface( nsProxyEventObject* self,
+ REFNSIID aIID,
+ void** aInstancePtr);
+
+
+ nsIInterfaceInfo* GetInterfaceInfo() const {return mInfo;}
+ const nsIID& GetProxiedIID() const {return mIID; }
+protected:
+ nsProxyEventClass();
+ nsProxyEventClass(REFNSIID aIID, nsIInterfaceInfo* aInfo);
+
+private:
+ ~nsProxyEventClass();
+
+ nsIID mIID;
+ nsCOMPtr<nsIInterfaceInfo> mInfo;
+ uint32* mDescriptors;
+
+ nsresult CallQueryInterfaceOnProxy(nsProxyEventObject* self,
+ REFNSIID aIID,
+ nsProxyEventObject** aInstancePtr);
+};
+
+
+
+class nsProxyEventObject : public nsXPTCStubBase
+{
+public:
+
+ NS_DECL_ISUPPORTS
+
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_PROXYEVENT_OBJECT_IID)
+
+ static nsProxyEventObject* GetNewOrUsedProxy(nsIEventQueue *destQueue,
+ PRInt32 proxyType,
+ nsISupports *aObj,
+ REFNSIID aIID);
+
+
+ NS_IMETHOD GetInterfaceInfo(nsIInterfaceInfo** info);
+
+ // call this method and return result
+ NS_IMETHOD CallMethod(PRUint16 methodIndex, const nsXPTMethodInfo* info, nsXPTCMiniVariant* params);
+
+
+ nsProxyEventClass* GetClass() const { return mClass; }
+ nsIEventQueue* GetQueue() const { return (mProxyObject ? mProxyObject->GetQueue() : nsnull);}
+ nsISupports* GetRealObject() const { return (mProxyObject ? mProxyObject->GetRealObject(): nsnull);}
+ PRInt32 GetProxyType() const { return (mProxyObject ? mProxyObject->GetProxyType() : nsnull);}
+
+ nsProxyEventObject();
+ nsProxyEventObject(nsIEventQueue *destQueue,
+ PRInt32 proxyType,
+ nsISupports* aObj,
+ nsProxyEventClass* aClass,
+ nsProxyEventObject* root);
+
+ nsProxyEventObject* LockedFind(REFNSIID aIID);
+
+#ifdef DEBUG_xpcom_proxy
+ void DebugDump(const char * message, PRUint32 hashKey);
+#endif
+
+private:
+ ~nsProxyEventObject();
+
+protected:
+ void LockedRemoveProxy();
+
+protected:
+ nsCOMPtr<nsProxyEventClass> mClass;
+ nsRefPtr<nsProxyObject> mProxyObject;
+
+ // Owning reference...
+ nsProxyEventObject *mRoot;
+
+ // Weak reference...
+ nsProxyEventObject *mNext;
+};
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// nsProxyObjectManager
+////////////////////////////////////////////////////////////////////////////////
+
+class nsProxyObjectManager: public nsIProxyObjectManager
+{
+public:
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPROXYOBJECTMANAGER
+
+
+ static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+ nsProxyObjectManager();
+
+ static nsProxyObjectManager *GetInstance();
+ static PRBool IsManagerShutdown();
+
+ static void Shutdown();
+
+ nsHashtable* GetRealObjectToProxyObjectMap() { return &mProxyObjectMap;}
+ nsHashtable* GetIIDToProxyClassMap() { return &mProxyClassMap; }
+
+ PRMonitor* GetMonitor() const { return mProxyCreationMonitor; }
+
+private:
+ ~nsProxyObjectManager();
+
+ static nsProxyObjectManager* mInstance;
+ nsHashtable mProxyObjectMap;
+ nsHashtable mProxyClassMap;
+ PRMonitor *mProxyCreationMonitor;
+};
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyObjectManager.cpp b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyObjectManager.cpp
new file mode 100644
index 00000000..0602bcd7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyObjectManager.cpp
@@ -0,0 +1,322 @@
+/* -*- 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):
+ * Doug Turner <dougt@netscape.com> (Original Author)
+ * Judson Valeski <valeski@netscape.com>
+ * Dan Matejka <danm@netscape.com>
+ * Scott Collins <scc@netscape.com>
+ * Heikki Toivonen <heiki@citec.fi>
+ * Patrick Beard <beard@netscape.com>
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ * Warren Harris <warren@netscape.com>
+ * Chris Seawood <cls@seawood.org>
+ * Chris Waterson <waterson@netscape.com>
+ * Dan Mosedale <dmose@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 "nsProxyEvent.h"
+#include "nsIProxyObjectManager.h"
+#include "nsProxyEventPrivate.h"
+
+#include "nsIProxyCreateInstance.h"
+
+#include "nsIComponentManager.h"
+#include "nsIServiceManager.h"
+#include "nsComponentManagerObsolete.h"
+#include "nsCOMPtr.h"
+
+#include "nsIEventQueueService.h"
+#include "nsIThread.h"
+
+
+static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
+
+/***************************************************************************/
+/* nsProxyCreateInstance */
+/* This private class will allow us to create Instances on another thread */
+/***************************************************************************/
+class nsProxyCreateInstance : public nsIProxyCreateInstance
+{
+ NS_DECL_ISUPPORTS
+ NS_IMETHOD CreateInstanceByIID(const nsIID & cid, nsISupports *aOuter, const nsIID & iid, void * *result);
+ NS_IMETHOD CreateInstanceByContractID(const char *aContractID, nsISupports *aOuter, const nsIID & iid, void * *result);
+
+ nsProxyCreateInstance() {}
+
+private:
+ ~nsProxyCreateInstance() {}
+};
+
+NS_IMPL_ISUPPORTS1(nsProxyCreateInstance, nsIProxyCreateInstance)
+
+NS_IMETHODIMP nsProxyCreateInstance::CreateInstanceByIID(const nsIID & cid, nsISupports *aOuter, const nsIID & iid, void * *result)
+{
+ return nsComponentManager::CreateInstance( cid,
+ aOuter,
+ iid,
+ result);
+}
+
+
+NS_IMETHODIMP nsProxyCreateInstance::CreateInstanceByContractID(const char *aContractID, nsISupports *aOuter, const nsIID & iid, void * *result)
+{
+ return nsComponentManager::CreateInstance( aContractID,
+ aOuter,
+ iid,
+ result);
+}
+
+/////////////////////////////////////////////////////////////////////////
+// nsProxyObjectManager
+/////////////////////////////////////////////////////////////////////////
+
+nsProxyObjectManager* nsProxyObjectManager::mInstance = nsnull;
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsProxyObjectManager, nsIProxyObjectManager)
+
+nsProxyObjectManager::nsProxyObjectManager()
+ : mProxyObjectMap(256, PR_TRUE),
+ mProxyClassMap(256, PR_TRUE)
+{
+ mProxyCreationMonitor = PR_NewMonitor();
+}
+
+static PRBool PurgeProxyClasses(nsHashKey *aKey, void *aData, void* closure)
+{
+ nsProxyEventClass* ptr = NS_REINTERPRET_CAST(nsProxyEventClass*, aData);
+ NS_RELEASE(ptr);
+ return PR_TRUE;
+}
+
+nsProxyObjectManager::~nsProxyObjectManager()
+{
+ mProxyClassMap.Reset((nsHashtableEnumFunc)PurgeProxyClasses, nsnull);
+
+ if (mProxyCreationMonitor) {
+ PR_DestroyMonitor(mProxyCreationMonitor);
+ }
+
+ nsProxyObjectManager::mInstance = nsnull;
+}
+
+PRBool
+nsProxyObjectManager::IsManagerShutdown()
+{
+ if (mInstance)
+ return PR_FALSE;
+ return PR_TRUE;
+}
+
+nsProxyObjectManager *
+nsProxyObjectManager::GetInstance()
+{
+ if (! mInstance)
+ {
+ mInstance = new nsProxyObjectManager();
+ }
+ return mInstance;
+}
+
+
+void
+nsProxyObjectManager::Shutdown()
+{
+ mInstance = nsnull;
+}
+
+
+// Helpers
+NS_IMETHODIMP
+nsProxyObjectManager::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
+{
+ nsProxyObjectManager *proxyObjectManager = GetInstance();
+
+ if (proxyObjectManager == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return proxyObjectManager->QueryInterface(aIID, aInstancePtr);
+}
+
+
+NS_IMETHODIMP
+nsProxyObjectManager::GetProxyForObject(nsIEventQueue *destQueue,
+ REFNSIID aIID,
+ nsISupports* aObj,
+ PRInt32 proxyType,
+ void** aProxyObject)
+{
+ if (!aObj) return NS_ERROR_NULL_POINTER;
+ if (!aProxyObject) return NS_ERROR_NULL_POINTER;
+
+ nsresult rv;
+ nsCOMPtr<nsIEventQueue> postQ;
+
+
+ *aProxyObject = nsnull;
+
+ // check to see if the destination Q is a special case.
+
+ nsCOMPtr<nsIEventQueueService> eventQService =
+ do_GetService(kEventQueueServiceCID, &rv);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = eventQService->ResolveEventQueue(destQueue, getter_AddRefs(postQ));
+ if (NS_FAILED(rv))
+ return rv;
+
+ // check to see if the eventQ is on our thread. If so, just return the real object.
+
+ if (postQ && !(proxyType & PROXY_ASYNC) && !(proxyType & PROXY_ALWAYS))
+ {
+ PRBool aResult;
+ postQ->IsOnCurrentThread(&aResult);
+
+ if (aResult)
+ {
+ return aObj->QueryInterface(aIID, aProxyObject);
+ }
+ }
+
+ // check to see if proxy is there or not.
+ *aProxyObject = nsProxyEventObject::GetNewOrUsedProxy(postQ, proxyType, aObj, aIID);
+
+ if (*aProxyObject == nsnull)
+ return NS_ERROR_NO_INTERFACE; //fix error code?
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsProxyObjectManager::GetProxy( nsIEventQueue *destQueue,
+ const nsCID &aClass,
+ nsISupports *aDelegate,
+ const nsIID &aIID,
+ PRInt32 proxyType,
+ void** aProxyObject)
+{
+ if (!aProxyObject) return NS_ERROR_NULL_POINTER;
+ *aProxyObject = nsnull;
+
+ // 1. Create a proxy for creating an instance on another thread.
+
+ nsIProxyCreateInstance* ciProxy = nsnull;
+
+ nsProxyCreateInstance* ciObject = new nsProxyCreateInstance();
+
+ if (ciObject == nsnull)
+ return NS_ERROR_NULL_POINTER;
+
+ NS_ADDREF(ciObject);
+
+ nsresult rv = GetProxyForObject(destQueue,
+ NS_GET_IID(nsIProxyCreateInstance),
+ ciObject,
+ PROXY_SYNC,
+ (void**)&ciProxy);
+
+ if (NS_FAILED(rv))
+ {
+ NS_RELEASE(ciObject);
+ return rv;
+ }
+
+ // 2. now create a new instance of the request object via our proxy.
+
+ nsISupports* aObj;
+
+ rv = ciProxy->CreateInstanceByIID(aClass,
+ aDelegate,
+ aIID,
+ (void**)&aObj);
+
+
+ // 3. Delete the create instance proxy and its real object.
+
+ NS_RELEASE(ciProxy);
+ NS_RELEASE(ciObject);
+
+ // 4. Check to see if creating the requested instance failed.
+ if ( NS_FAILED(rv))
+ {
+ return rv;
+ }
+
+ // 5. Now create a proxy object for the requested object.
+
+ rv = GetProxyForObject(destQueue, aIID, aObj, proxyType, aProxyObject);
+
+ // 6. release ownership of aObj so that aProxyObject owns it.
+
+ NS_RELEASE(aObj);
+
+ // 7. return the error returned from GetProxyForObject. Either way, we our out of here.
+
+ return rv;
+}
+
+/**
+ * Helper function for code that already has a link-time dependency on
+ * libxpcom and needs to get proxies in a bunch of different places.
+ * This way, the caller isn't forced to get the proxy object manager
+ * themselves every single time, thus making the calling code more
+ * readable.
+ */
+NS_COM nsresult
+NS_GetProxyForObject(nsIEventQueue *destQueue,
+ REFNSIID aIID,
+ nsISupports* aObj,
+ PRInt32 proxyType,
+ void** aProxyObject)
+{
+ static NS_DEFINE_CID(proxyObjMgrCID, NS_PROXYEVENT_MANAGER_CID);
+
+ nsresult rv; // temp for return value
+
+ // get the proxy object manager
+ //
+ nsCOMPtr<nsIProxyObjectManager> proxyObjMgr =
+ do_GetService(proxyObjMgrCID, &rv);
+
+ if (NS_FAILED(rv))
+ return NS_ERROR_FAILURE;
+
+ // and try to get the proxy object
+ //
+ return proxyObjMgr->GetProxyForObject(destQueue, aIID, aObj,
+ proxyType, aProxyObject);
+}
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyRelease.cpp b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyRelease.cpp
new file mode 100644
index 00000000..3ceeb667
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyRelease.cpp
@@ -0,0 +1,55 @@
+#include "nsProxyRelease.h"
+
+PR_STATIC_CALLBACK(void*)
+HandleProxyReleaseEvent(PLEvent *self)
+{
+ nsISupports* owner = (nsISupports*) self->owner;
+ NS_RELEASE(owner);
+ return nsnull;
+}
+
+PR_STATIC_CALLBACK(void)
+DestroyProxyReleaseEvent(PLEvent *self)
+{
+ delete self;
+}
+
+NS_COM nsresult
+NS_ProxyRelease(nsIEventTarget *target, nsISupports *doomed, PRBool alwaysProxy)
+{
+ nsresult rv;
+
+ if (!target) {
+ NS_RELEASE(doomed);
+ return NS_OK;
+ }
+
+ if (!alwaysProxy) {
+ PRBool onCurrentThread = PR_FALSE;
+ rv = target->IsOnCurrentThread(&onCurrentThread);
+ if (NS_SUCCEEDED(rv) && onCurrentThread) {
+ NS_RELEASE(doomed);
+ return NS_OK;
+ }
+ }
+
+ PLEvent *ev = new PLEvent;
+ if (!ev) {
+ // we do not release doomed here since it may cause a delete on the
+ // wrong thread. better to leak than crash.
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ PL_InitEvent(ev, doomed,
+ HandleProxyReleaseEvent,
+ DestroyProxyReleaseEvent);
+
+ rv = target->PostEvent(ev);
+ if (NS_FAILED(rv)) {
+ NS_WARNING("failed to post proxy release event");
+ PL_DestroyEvent(ev);
+ // again, it is better to leak the doomed object than risk crashing as
+ // a result of deleting it on the wrong thread.
+ }
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/proxy/tests/.cvsignore b/src/libs/xpcom18a4/xpcom/proxy/tests/.cvsignore
new file mode 100644
index 00000000..b7457ff6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/tests/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+proxytests
diff --git a/src/libs/xpcom18a4/xpcom/proxy/tests/Makefile.in b/src/libs/xpcom18a4/xpcom/proxy/tests/Makefile.in
new file mode 100644
index 00000000..e5e908f1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/tests/Makefile.in
@@ -0,0 +1,60 @@
+#
+# ***** 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 = proxytest
+REQUIRES = $(NULL)
+
+CPPSRCS = proxytests.cpp
+XPIDLSRCS = nsITestProxy.idl
+
+SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))
+
+LIBS = \
+ $(XPCOM_LIBS) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/proxy/tests/nsITestProxy.idl b/src/libs/xpcom18a4/xpcom/proxy/tests/nsITestProxy.idl
new file mode 100644
index 00000000..98cb3f94
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/tests/nsITestProxy.idl
@@ -0,0 +1,9 @@
+#include "nsISupports.idl"
+
+[uuid(1979e980-1cfd-11d3-915e-0000863011c4)]
+interface nsITestProxy : nsISupports
+{
+ long Test(in long p1, in long p2);
+ void Test2();
+ void Test3(in nsISupports p1, out nsISupports p2);
+};
diff --git a/src/libs/xpcom18a4/xpcom/proxy/tests/proxytests.cpp b/src/libs/xpcom18a4/xpcom/proxy/tests/proxytests.cpp
new file mode 100644
index 00000000..20693463
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/tests/proxytests.cpp
@@ -0,0 +1,553 @@
+/* -*- 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):
+ * 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 <stdio.h>
+
+#include "nsXPCOM.h"
+#include "nsIComponentManager.h"
+#include "nsIComponentRegistrar.h"
+#include "nsIServiceManager.h"
+#include "nsCOMPtr.h"
+
+#include "nscore.h"
+#include "nspr.h"
+#include "prmon.h"
+
+#include "nsITestProxy.h"
+
+#include "nsIProxyObjectManager.h"
+#include "nsIEventQueueService.h"
+
+static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
+
+/***************************************************************************/
+/* nsTestXPCFoo */
+/***************************************************************************/
+class nsTestXPCFoo : public nsITestProxy
+{
+ NS_DECL_ISUPPORTS
+ NS_IMETHOD Test(PRInt32 p1, PRInt32 p2, PRInt32* retval);
+ NS_IMETHOD Test2();
+ NS_IMETHOD Test3(nsISupports *p1, nsISupports **p2);
+
+ nsTestXPCFoo();
+};
+
+nsTestXPCFoo::nsTestXPCFoo()
+{
+ NS_ADDREF_THIS();
+}
+
+NS_IMPL_ISUPPORTS1(nsTestXPCFoo, nsITestProxy)
+
+NS_IMETHODIMP nsTestXPCFoo::Test(PRInt32 p1, PRInt32 p2, PRInt32* retval)
+{
+ printf("Thread (%d) Test Called successfully! Party on...\n", p1);
+ *retval = p1+p2;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP nsTestXPCFoo::Test2()
+{
+ printf("The quick brown netscape jumped over the old lazy ie..\n");
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsTestXPCFoo::Test3(nsISupports *p1, nsISupports **p2)
+{
+ if (p1 != nsnull)
+ {
+ nsITestProxy *test;
+
+ p1->QueryInterface(NS_GET_IID(nsITestProxy), (void**)&test);
+
+ test->Test2();
+ PRInt32 a;
+ test->Test( 1, 2, &a);
+ printf("\n1+2=%d\n",a);
+ }
+
+
+ *p2 = new nsTestXPCFoo();
+ return NS_OK;
+}
+
+/***************************************************************************/
+/* nsTestXPCFoo2 */
+/***************************************************************************/
+class nsTestXPCFoo2 : public nsITestProxy
+{
+ NS_DECL_ISUPPORTS
+ NS_IMETHOD Test(PRInt32 p1, PRInt32 p2, PRInt32* retval);
+ NS_IMETHOD Test2();
+ NS_IMETHOD Test3(nsISupports *p1, nsISupports **p2);
+
+ nsTestXPCFoo2();
+};
+
+nsTestXPCFoo2::nsTestXPCFoo2()
+{
+ NS_ADDREF_THIS();
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsTestXPCFoo2, nsITestProxy)
+
+NS_IMETHODIMP nsTestXPCFoo2::Test(PRInt32 p1, PRInt32 p2, PRInt32* retval)
+{
+printf("calling back to caller!\n\n");
+
+ nsIProxyObjectManager* manager;
+ nsITestProxy * proxyObject;
+
+ nsServiceManager::GetService( NS_XPCOMPROXY_CONTRACTID,
+ NS_GET_IID(nsIProxyObjectManager),
+ (nsISupports **)&manager);
+
+ printf("ProxyObjectManager: %p \n", manager);
+
+ PR_ASSERT(manager);
+
+ manager->GetProxyForObject((nsIEventQueue*)p1, NS_GET_IID(nsITestProxy), this, PROXY_SYNC, (void**)&proxyObject);
+ proxyObject->Test3(nsnull, nsnull);
+
+ printf("Deleting Proxy Object\n");
+ NS_RELEASE(proxyObject);
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP nsTestXPCFoo2::Test2()
+{
+ printf("nsTestXPCFoo2::Test2() called\n");
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP nsTestXPCFoo2::Test3(nsISupports *p1, nsISupports **p2)
+{
+ printf("Got called");
+ return NS_OK;
+}
+
+
+
+typedef struct _ArgsStruct
+{
+ nsIEventQueue* queue;
+ PRInt32 threadNumber;
+}ArgsStruct;
+
+
+
+// This will create two objects both descendants of a single IID.
+void TestCase_TwoClassesOneInterface(void *arg)
+{
+ ArgsStruct *argsStruct = (ArgsStruct*) arg;
+
+
+ nsIProxyObjectManager* manager;
+
+ nsServiceManager::GetService( NS_XPCOMPROXY_CONTRACTID,
+ NS_GET_IID(nsIProxyObjectManager),
+ (nsISupports **)&manager);
+
+ printf("ProxyObjectManager: %p \n", manager);
+
+ PR_ASSERT(manager);
+
+ nsITestProxy *proxyObject;
+ nsITestProxy *proxyObject2;
+
+ nsTestXPCFoo* foo = new nsTestXPCFoo();
+ nsTestXPCFoo2* foo2 = new nsTestXPCFoo2();
+
+ PR_ASSERT(foo);
+ PR_ASSERT(foo2);
+
+
+ manager->GetProxyForObject(argsStruct->queue, NS_GET_IID(nsITestProxy), foo, PROXY_SYNC, (void**)&proxyObject);
+
+ manager->GetProxyForObject(argsStruct->queue, NS_GET_IID(nsITestProxy), foo2, PROXY_SYNC, (void**)&proxyObject2);
+
+
+
+ if (proxyObject && proxyObject2)
+ {
+ // release ownership of the real object.
+
+ PRInt32 a;
+ nsresult rv;
+ PRInt32 threadNumber = argsStruct->threadNumber;
+
+ printf("Deleting real Object (%d)\n", threadNumber);
+ NS_RELEASE(foo);
+
+ printf("Deleting real Object 2 (%d)\n", threadNumber);
+ NS_RELEASE(foo2);
+
+
+ printf("Thread (%d) Prior to calling proxyObject->Test.\n", threadNumber);
+ rv = proxyObject->Test(threadNumber, 0, &a);
+ printf("Thread (%d) error: %d.\n", threadNumber, rv);
+
+
+ printf("Thread (%d) Prior to calling proxyObject->Test2.\n", threadNumber);
+ rv = proxyObject->Test2();
+ printf("Thread (%d) error: %d.\n", threadNumber, rv);
+
+ printf("Thread (%d) Prior to calling proxyObject2->Test2.\n", threadNumber);
+ rv = proxyObject2->Test2();
+ printf("Thread (%d) proxyObject2 error: %d.\n", threadNumber, rv);
+
+ printf("Deleting Proxy Object (%d)\n", threadNumber );
+ NS_RELEASE(proxyObject);
+
+ printf("Deleting Proxy Object 2 (%d)\n", threadNumber );
+ NS_RELEASE(proxyObject2);
+ }
+
+ PR_Sleep( PR_MillisecondsToInterval(1000) ); // If your thread goes away, your stack goes away. Only use ASYNC on calls that do not have out parameters
+}
+
+
+
+void TestCase_NestedLoop(void *arg)
+{
+ ArgsStruct *argsStruct = (ArgsStruct*) arg;
+
+
+ nsIProxyObjectManager* manager;
+
+ nsServiceManager::GetService( NS_XPCOMPROXY_CONTRACTID,
+ NS_GET_IID(nsIProxyObjectManager),
+ (nsISupports **)&manager);
+
+ printf("ProxyObjectManager: %p \n", manager);
+
+ PR_ASSERT(manager);
+
+ nsITestProxy *proxyObject;
+ nsTestXPCFoo2* foo = new nsTestXPCFoo2();
+
+ PR_ASSERT(foo);
+
+
+ manager->GetProxyForObject(argsStruct->queue, NS_GET_IID(nsITestProxy), foo, PROXY_SYNC, (void**)&proxyObject);
+
+ if (proxyObject)
+ {
+ // release ownership of the real object.
+
+ nsresult rv;
+ PRInt32 threadNumber = argsStruct->threadNumber;
+
+ printf("Deleting real Object (%d)\n", threadNumber);
+ NS_RELEASE(foo);
+
+ PRInt32 retval;
+
+ printf("Getting EventQueue...\n");
+
+ nsIEventQueue* eventQ;
+ nsCOMPtr<nsIEventQueueService> eventQService =
+ do_GetService(kEventQueueServiceCID, &rv);
+ if (NS_SUCCEEDED(rv))
+ {
+ rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &eventQ);
+ if (NS_FAILED(rv))
+ rv = eventQService->CreateThreadEventQueue();
+ if (NS_FAILED(rv))
+ return;
+ else
+ rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &eventQ);
+
+ printf("Thread (%d) Prior to calling proxyObject->Test.\n", threadNumber);
+ rv = proxyObject->Test(NS_PTR_TO_INT32(eventQ), 0, &retval);
+ printf("Thread (%d) proxyObject error: %d.\n", threadNumber, rv);
+
+ printf("Deleting Proxy Object (%d)\n", threadNumber );
+ NS_RELEASE(proxyObject);
+ }
+
+ PR_Sleep( PR_MillisecondsToInterval(1000) ); // If your thread goes away, your stack goes away. Only use ASYNC on calls that do not have out parameters
+ }
+}
+
+
+
+void TestCase_2(void *arg)
+{
+
+ ArgsStruct *argsStruct = (ArgsStruct*) arg;
+
+ nsIProxyObjectManager* manager;
+
+ nsServiceManager::GetService( NS_XPCOMPROXY_CONTRACTID,
+ NS_GET_IID(nsIProxyObjectManager),
+ (nsISupports **)&manager);
+
+ PR_ASSERT(manager);
+
+ nsITestProxy *proxyObject;
+
+ manager->GetProxy(argsStruct->queue,
+ NS_GET_IID(nsITestProxy), // should be CID!
+ nsnull,
+ NS_GET_IID(nsITestProxy),
+ PROXY_SYNC,
+ (void**)&proxyObject);
+
+ if (proxyObject != nsnull)
+ {
+ NS_RELEASE(proxyObject);
+ }
+}
+
+
+
+void TestCase_nsISupports(void *arg)
+{
+
+ ArgsStruct *argsStruct = (ArgsStruct*) arg;
+
+ nsIProxyObjectManager* manager;
+
+ nsServiceManager::GetService( NS_XPCOMPROXY_CONTRACTID,
+ NS_GET_IID(nsIProxyObjectManager),
+ (nsISupports **)&manager);
+
+ PR_ASSERT(manager);
+
+ nsITestProxy *proxyObject;
+ nsTestXPCFoo* foo = new nsTestXPCFoo();
+
+ PR_ASSERT(foo);
+
+ manager->GetProxyForObject(argsStruct->queue, NS_GET_IID(nsITestProxy), foo, PROXY_SYNC, (void**)&proxyObject);
+
+ if (proxyObject != nsnull)
+ {
+ nsISupports *bISupports = nsnull, *cISupports = nsnull;
+
+ proxyObject->Test3(foo, &bISupports);
+ proxyObject->Test3(bISupports, &cISupports);
+
+ nsITestProxy *test;
+ bISupports->QueryInterface(NS_GET_IID(nsITestProxy), (void**)&test);
+
+ test->Test2();
+
+ NS_RELEASE(foo);
+ NS_RELEASE(proxyObject);
+ }
+}
+
+
+
+
+
+/***************************************************************************/
+/* ProxyTest */
+/***************************************************************************/
+
+static void PR_CALLBACK ProxyTest( void *arg )
+{
+ //TestCase_TwoClassesOneInterface(arg);
+ // TestCase_2(arg);
+ //TestCase_nsISupports(arg);
+ TestCase_NestedLoop(arg);
+
+ NS_RELEASE( ((ArgsStruct*) arg)->queue);
+ free((void*) arg);
+}
+
+nsIEventQueue *gEventQueue = nsnull;
+
+static void PR_CALLBACK EventLoop( void *arg )
+{
+ nsresult rv;
+ printf("Creating EventQueue...\n");
+
+ nsIEventQueue* eventQ;
+ nsCOMPtr<nsIEventQueueService> eventQService =
+ do_GetService(kEventQueueServiceCID, &rv);
+ if (NS_SUCCEEDED(rv)) {
+ rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &eventQ);
+ if (NS_FAILED(rv))
+ rv = eventQService->CreateThreadEventQueue();
+ if (NS_FAILED(rv))
+ return;
+ else
+ rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &eventQ);
+ }
+ if (NS_FAILED(rv)) return;
+
+ rv = eventQ->QueryInterface(NS_GET_IID(nsIEventQueue), (void**)&gEventQueue);
+ if (NS_FAILED(rv)) return;
+
+
+ printf("Verifing calling Proxy on eventQ thread.\n");
+
+ nsIProxyObjectManager* manager;
+
+ nsServiceManager::GetService( NS_XPCOMPROXY_CONTRACTID,
+ NS_GET_IID(nsIProxyObjectManager),
+ (nsISupports **)&manager);
+
+ PR_ASSERT(manager);
+
+ nsITestProxy *proxyObject;
+ nsTestXPCFoo* foo = new nsTestXPCFoo();
+
+ PR_ASSERT(foo);
+
+ manager->GetProxyForObject(gEventQueue, NS_GET_IID(nsITestProxy), foo, PROXY_SYNC, (void**)&proxyObject);
+
+ PRInt32 a;
+ proxyObject->Test(1, 2, &a);
+ proxyObject->Test2();
+
+
+ NS_RELEASE(proxyObject);
+ delete foo;
+
+ printf("End of Verification calling Proxy on eventQ thread.\n");
+
+
+ printf("Looping for events.\n");
+
+ PLEvent* event = nsnull;
+
+ while ( PR_SUCCESS == PR_Sleep( PR_MillisecondsToInterval(1)) )
+ {
+ rv = gEventQueue->GetEvent(&event);
+ if (NS_FAILED(rv))
+ return;
+ gEventQueue->HandleEvent(event);
+ }
+
+ gEventQueue->ProcessPendingEvents();
+
+ printf("Closing down Event Queue.\n");
+ delete gEventQueue;
+ gEventQueue = nsnull;
+
+ printf("End looping for events.\n\n");
+}
+
+int
+main(int argc, char **argv)
+{
+ int numberOfThreads = 1;
+
+ if (argc > 1)
+ numberOfThreads = atoi(argv[1]);
+
+ nsCOMPtr<nsIServiceManager> servMan;
+ NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull);
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan);
+ NS_ASSERTION(registrar, "Null nsIComponentRegistrar");
+ registrar->AutoRegister(nsnull);
+
+ static PRThread** threads = (PRThread**) calloc(sizeof(PRThread*), numberOfThreads);
+ static PRThread* aEventThread;
+
+ aEventThread = PR_CreateThread(PR_USER_THREAD,
+ EventLoop,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0 );
+
+
+ PR_Sleep(PR_MillisecondsToInterval(1000));
+
+ NS_ASSERTION(gEventQueue, "no main event queue"); // BAD BAD BAD. EVENT THREAD DID NOT CREATE QUEUE. This may be a timing issue, set the
+ // sleep about longer, and try again.
+
+ printf("Spawn Threads:\n");
+ for (PRInt32 spawn = 0; spawn < numberOfThreads; spawn++)
+ {
+
+ ArgsStruct *args = (ArgsStruct *) malloc (sizeof(ArgsStruct));
+
+ args->queue = gEventQueue;
+ NS_ADDREF(args->queue);
+ args->threadNumber = spawn;
+
+ threads[spawn] = PR_CreateThread(PR_USER_THREAD,
+ ProxyTest,
+ args,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0 );
+
+ printf("\tThread (%d) spawned\n", spawn);
+
+ PR_Sleep( PR_MillisecondsToInterval(250) );
+ }
+
+ printf("All Threads Spawned.\n\n");
+
+
+
+ printf("Wait for threads.\n");
+ for (PRInt32 i = 0; i < numberOfThreads; i++)
+ {
+ PRStatus rv;
+ printf("Thread (%d) Join...\n", i);
+ rv = PR_JoinThread(threads[i]);
+ printf("Thread (%d) Joined. (error: %d).\n", i, rv);
+ }
+
+ PR_Interrupt(aEventThread);
+ PR_JoinThread(aEventThread);
+
+
+ printf("Calling Cleanup.\n");
+ PR_Cleanup();
+
+ printf("Return zero.\n");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/reflect/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/Makefile.in
new file mode 100644
index 00000000..171900b1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/Makefile.in
@@ -0,0 +1,49 @@
+#
+# ***** 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
+DIRS = xptinfo xptcall
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/Makefile.kup b/src/libs/xpcom18a4/xpcom/reflect/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/Makefile.kup
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptcall/.cvsignore
new file mode 100644
index 00000000..a1af50c2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/.cvsignore
@@ -0,0 +1,4 @@
+Makefile
+mk.bat
+set_env.bat
+none.pdb
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptcall/Makefile.in
new file mode 100644
index 00000000..e3173730
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/Makefile.in
@@ -0,0 +1,49 @@
+#
+# ***** 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
+DIRS = public src
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/Makefile.kup b/src/libs/xpcom18a4/xpcom/reflect/xptcall/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/Makefile.kup
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/README b/src/libs/xpcom18a4/xpcom/reflect/xptcall/README
new file mode 100644
index 00000000..0c401fe8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/README
@@ -0,0 +1,6 @@
+see:
+
+http://www.mozilla.org/scriptable/xptcall-faq.html
+and
+http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/porting.html
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/porting.html b/src/libs/xpcom18a4/xpcom/reflect/xptcall/porting.html
new file mode 100644
index 00000000..b8b204a1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/porting.html
@@ -0,0 +1,212 @@
+<html>
+<head>
+<title>xptcall Porting Guide</title>
+</head>
+<body bgcolor = "white">
+<h2><center>xptcall Porting Guide</center></h2>
+
+<h3>Overview</h3>
+
+<blockquote>
+
+<a href="http://www.mozilla.org/scriptable/xptcall-faq.html"> xptcall</a> is a
+library that supports both invoking methods on arbitrary xpcom objects and
+implementing classes whose objects can impersonate any xpcom interface. It does
+this using platform specific assembly language code. This code needs to be
+ported to all platforms that want to support xptcall (and thus mozilla).
+
+</blockquote>
+
+<h3>The tree</h3>
+
+<blockquote>
+<pre>
+<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall">mozilla/xpcom/reflect/xptcall</a>
+ +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public">public</a> // exported headers
+ +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src">src</a> // core source
+ | \--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md">md</a> // platform specific parts
+ | +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/mac">mac</a> // mac ppc
+ | +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/unix">unix</a> // all unix
+ | \--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/win32">win32</a> // win32
+ | +--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/test">test</a> // simple tests to get started
+ \--<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/tests">tests</a> // full tests via api
+</pre>
+
+Porters are free to create subdirectories under the base <code>md</code>
+directory for their given platforms and to integrate into the build system as
+appropriate for their platform.
+
+</blockquote>
+
+<h3>Theory of operation</h3>
+
+<blockquote>
+
+There are really two pieces of functionality: <i>invoke</i> and <i>stubs</i>...
+
+<p>
+
+The <b><i>invoke</i></b> functionality requires the implementation of the
+following on each platform (from <a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public/xptcall.h#131">xptcall/public/xptcall.h</a>):
+
+<pre>
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+</pre>
+
+Calling code is expected to supply an array of <code>nsXPTCVariant</code>
+structs. These are discriminated unions describing the type and value of each
+parameter of the target function. The platform specific code then builds a call
+frame and invokes the method indicated by the index <code>methodIndex</code> on
+the xpcom interface <code>that</code>.
+
+<p>
+
+Here are examples of this implementation for
+<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/win32/xptcinvoke.cpp">Win32</a>
+and
+<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_unixish_x86.cpp">Linux x86, NetBSD x86, and FreeBSD</a>.
+
+Both of these implementations use the basic strategy of: figure out how much
+stack space is needed for the params, make the space in a new frame, copy the
+params to that space, invoke the method, cleanup and return. C++ is used where
+appropriate, Assembly language is used where necessary. Inline assembly language is used here,
+but it is equally valid to use separate assembly language source files. Porters
+can decide how best to do this for their platforms.
+
+<p>
+
+The <b><i>stubs</i></b> functionality is more complex. The goal here is a class
+whose vtbl can look like the vtbl of any arbitrary xpcom interface. Objects of
+this class can then be built to impersonate any xpcom object. The base interface
+for this is (from <a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public/xptcall.h#109">xptcall/public/xptcall.h</a>):
+
+<pre>
+class nsXPTCStubBase : public nsISupports
+{
+public:
+ // Include generated vtbl stub declarations.
+ // These are virtual and *also* implemented by this class..
+#include "xptcstubsdecl.inc"
+
+ // The following methods must be provided by inheritor of this class.
+
+ // return a refcounted pointer to the InterfaceInfo for this object
+ // NOTE: on some platforms this MUST not fail or we crash!
+ NS_IMETHOD GetInterfaceInfo(nsIInterfaceInfo** info) = 0;
+
+ // call this method and return result
+ NS_IMETHOD CallMethod(PRUint16 methodIndex,
+ const nsXPTMethodInfo* info,
+ nsXPTCMiniVariant* params) = 0;
+};
+</pre>
+
+Code that wishes to make use of this <i>stubs</i> functionality (such as
+<a href="http://www.mozilla.org/scriptable/">XPConnect</a>) implement a class
+which inherits from <code>nsXPTCStubBase</code> and implements the
+<code>GetInterfaceInfo</code> and <code>CallMethod</code> to let the
+platform specific code know how to get interface information and how to dispatch methods
+once their parameters have been pulled out of the platform specific calling
+frame.
+
+<p>
+
+Porters of this functionality implement the platform specific code for the
+<i>stub</i> methods that fill the vtbl for this class. The idea here is that the
+class has a vtbl full of a large number of generic stubs. All instances of this
+class share that vtbl and the same stubs. The stubs forward calls to a platform
+specific method that uses the interface information supplied by
+the overridden <code>GetInterfaceInfo</code> to extract the parameters and build
+an array of platform independent <code>nsXPTCMiniVariant</code> structs which
+are in turn passed on to the overridden <code>CallMethod</code>. The
+platform dependent code is responsible for doing any cleanup and returning.
+
+<p>
+
+The stub methods are declared in <a
+href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public/xptcstubsdecl.inc">xptcall/public/xptcstubsdecl.inc</a>.
+These are '#included' into the declaration of <code>nsXPTCStubBase</code>. A
+similar include file (<a
+href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public/xptcstubsdef.inc">xptcall/public/xptcstubsdef.inc</a>)
+is expanded using platform specific macros to define the stub functions. These
+'.inc' files are checked into cvs. However, they can be regenerated as necessary
+(i.e. to change the number of stubs or to change their specific declaration)
+using the Perl script <a
+href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/public/genstubs.pl">xptcall/public/genstubs.pl</a>.
+
+<p>
+
+Here are examples of this implementation for <a
+href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/win32/xptcstubs.cpp">Win32</a>
+and <a
+href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/unix/xptcstubs_unixish_x86.cpp">Linux x86, NetBSD x86, and FreeBSD</a>.
+Both of these examples use inline assembly language. That is just how I
+decided to do it. You can do it as you choose.
+
+<p>
+
+The Win32 version is somewhat tighter because the __declspec(naked) feature
+allows for very small stubs. However, the __stdcall requires the callee to clean
+up the stack, so it is imperative that the interface information scheme allow
+the code to determine the correct stack pointer fixup for return without fail,
+else the process will crash.
+
+<p>
+
+I opted to use inline assembler for the gcc Linux x86 port. I ended up with
+larger stubs than I would have preferred rather than battle the compiler over
+what would happen to the stack before my asm code began running.
+
+<p>
+
+I believe that the non-assembly parts of these files can be copied and reused
+with minimal (but not zero) platform specific tweaks. Feel free to copy and
+paste as necessary. Please remember that safety and reliability are more
+important than speed optimizations. This code is primarily used to connect XPCOM
+components with JavaScript; function call overhead is a <b>tiny</b> part of the
+time involved.
+
+<p>
+
+I put together
+<a
+href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/test">xptcall/src/md/test
+</a> as a place to evolve the basic functionality as a port is coming together.
+Not all of the functionality is exercised, but it is a place to get started.
+<a
+href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/tests">xptcall/tests
+</a> has an api level test for <code>XPTC_InvokeByIndex</code>, but no tests for
+the <i>stubs</i> functionality. Such a test ought to be written, but this has not
+yet been done.
+
+<p>
+
+A full 'test' at this point requires building the client and running the
+XPConnect test called <i>TestXPC</i> in
+<a
+href="http://lxr.mozilla.org/mozilla/source/js/src/xpconnect/tests">mozilla/js/src/xpconnect/tests
+</a>.
+
+<p>
+
+Getting these ports done is very important. Please let <a
+href="mailto:jband@netscape.com">me</a> know if you are interested in doing one.
+I'll answer any questions as I get them.
+
+<p>
+
+<a
+href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/status.html">
+Porting Status
+</a>
+
+</blockquote>
+
+<hr>
+<b>Author:</b> <a href="mailto:jband@netscape.com">John Bandhauer &lt;jband@netscape.com&gt;</a><br>
+<b>Last modified:</b> 31 May 1999
+
+</body>
+</html>
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/Makefile.in
new file mode 100644
index 00000000..ac8432af
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/Makefile.in
@@ -0,0 +1,54 @@
+#
+# ***** 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
+
+EXPORTS = \
+ xptcall.h \
+ xptcstubsdecl.inc \
+ xptcstubsdef.inc \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/genstubs.pl b/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/genstubs.pl
new file mode 100755
index 00000000..b8962930
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/genstubs.pl
@@ -0,0 +1,78 @@
+#!/usr/local/bin/perl
+
+# This is used to generate stub entry points. We generate a file to
+# be included in the declaraion and a file to be used for expanding macros
+# to represent the implementation of the stubs.
+
+#
+# if "$entry_count" is ever changed and the .inc files regenerated then
+# the following issues need to be addressed:
+#
+# 1) Alpha NT has a .def file that lists exports by symbol. It will need
+# updating.
+# 2) The current Linux ARM code has a limitation of only having 256-3 stubs
+#
+# more dependencies???
+#
+
+# 3 entries are already 'used' by the 3 methods of nsISupports.
+# 3+247+5=255 This should get us in under the Linux ARM limitation
+$entry_count = 247;
+$sentinel_count = 5;
+
+$decl_name = "xptcstubsdecl.inc";
+$def_name = "xptcstubsdef.inc";
+
+##
+## Write the declarations include file
+##
+
+die "Can't open $decl_name" if !open(OUTFILE, ">$decl_name");
+
+print OUTFILE "/* generated file - DO NOT EDIT */\n\n";
+print OUTFILE "/* includes ",$entry_count," stub entries, and ",
+ $sentinel_count," sentinel entries */\n\n";
+print OUTFILE "/*\n";
+print OUTFILE "* declarations of normal stubs...\n";
+print OUTFILE "* 0 is QueryInterface\n";
+print OUTFILE "* 1 is AddRef\n";
+print OUTFILE "* 2 is Release\n";
+print OUTFILE "*/\n";
+print OUTFILE "#if !defined(__ia64) || (!defined(__hpux) && !defined(__linux__))\n";
+for($i = 0; $i < $entry_count; $i++) {
+ print OUTFILE "NS_IMETHOD Stub",$i+3,"();\n";
+}
+print OUTFILE "#else\n";
+for($i = 0; $i < $entry_count; $i++) {
+ print OUTFILE "NS_IMETHOD Stub",$i+3,"(PRUint64,\n";
+ print OUTFILE " PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);\n";
+
+}
+print OUTFILE "#endif\n";
+
+print OUTFILE "\n/* declarations of sentinel stubs */\n";
+
+for($i = 0; $i < $sentinel_count; $i++) {
+ print OUTFILE "NS_IMETHOD Sentinel",$i,"();\n";
+}
+close(OUTFILE);
+
+
+##
+## Write the definitions include file. This assumes a macro will be used to
+## expand the entries written...
+##
+
+die "Can't open $def_name" if !open(OUTFILE, ">$def_name");
+
+print OUTFILE "/* generated file - DO NOT EDIT */\n\n";
+print OUTFILE "/* includes ",$entry_count," stub entries, and ",
+ $sentinel_count," sentinel entries */\n\n";
+
+for($i = 0; $i < $entry_count; $i++) {
+ print OUTFILE "STUB_ENTRY(",$i+3,")\n";
+}
+
+for($i = 0; $i < $sentinel_count; $i++) {
+ print OUTFILE "SENTINEL_ENTRY(",$i,")\n";
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/xptcall.h b/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/xptcall.h
new file mode 100644
index 00000000..153a047e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/xptcall.h
@@ -0,0 +1,271 @@
+/* -*- 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) 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 ***** */
+
+/* Public declarations for xptcall. */
+
+#ifndef xptcall_h___
+#define xptcall_h___
+
+#include "prtypes.h"
+#include "nscore.h"
+#include "nsISupports.h"
+#include "xpt_struct.h"
+#include "xptinfo.h"
+#include "nsIInterfaceInfo.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define XPTC_InvokeByIndex VBoxNsxpXPTC_InvokeByIndex
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+/***************************************************************************/
+/*
+ * The linkage of XPTC API functions differs depending on whether the file is
+ * used within the XPTC library or not. Any source file within the XPTC
+ * library should define EXPORT_XPTC_API whereas any client of the library
+ * should not.
+ */
+#ifdef EXPORT_XPTC_API
+#define XPTC_PUBLIC_API(t) PR_IMPLEMENT(t)
+#define XPTC_PUBLIC_DATA(t) PR_IMPLEMENT_DATA(t)
+#if defined(_WIN32)
+# define XPTC_EXPORT __declspec(dllexport)
+#elif defined(XP_OS2) && defined(__declspec)
+# define XPTC_EXPORT __declspec(dllexport)
+#elif defined(XP_OS2_VACPP)
+# define XPTC_EXPORT extern
+#else
+# ifdef VBOX_HAVE_VISIBILITY_HIDDEN
+# define XPTC_EXPORT __attribute__((visibility("default")))
+# else
+# define XPTC_EXPORT
+# endif
+#endif
+#else
+#if defined(_WIN32)
+# define XPTC_PUBLIC_API(t) __declspec(dllimport) t
+# define XPTC_PUBLIC_DATA(t) __declspec(dllimport) t
+# define XPTC_EXPORT __declspec(dllimport)
+#elif defined(XP_OS2) && defined(__declspec)
+# define XPTC_PUBLIC_API(t) __declspec(dllimport) t
+# define XPTC_PUBLIC_DATA(t) __declspec(dllimport) t
+# define XPTC_EXPORT __declspec(dllimport)
+#elif defined(XP_OS2_VACPP)
+# define XPTC_PUBLIC_API(t) extern t
+# define XPTC_PUBLIC_DATA(t) extern t
+# define XPTC_EXPORT extern
+#else
+# define XPTC_PUBLIC_API(t) PR_IMPLEMENT(t)
+# define XPTC_PUBLIC_DATA(t) t
+# define XPTC_EXPORT
+#endif
+#endif
+#define XPTC_FRIEND_API(t) XPTC_PUBLIC_API(t)
+#define XPTC_FRIEND_DATA(t) XPTC_PUBLIC_DATA(t)
+/***************************************************************************/
+
+struct nsXPTCMiniVariant
+{
+// No ctors or dtors so that we can use arrays of these on the stack
+// with no penalty.
+ union
+ {
+ PRInt8 i8;
+ PRInt16 i16;
+ PRInt32 i32;
+ PRInt64 i64;
+ PRUint8 u8;
+ PRUint16 u16;
+ PRUint32 u32;
+ PRUint64 u64;
+ float f;
+ double d;
+ PRBool b;
+ char c;
+ PRUnichar wc;
+ void* p;
+ } val;
+};
+
+struct nsXPTCVariant : public nsXPTCMiniVariant
+{
+// No ctors or dtors so that we can use arrays of these on the stack
+// with no penalty.
+
+ // inherits 'val' here
+ void* ptr;
+ nsXPTType type;
+ PRUint8 flags;
+
+ enum
+ {
+ // these are bitflags!
+ PTR_IS_DATA = 0x1, // ptr points to 'real' data in val
+ VAL_IS_ALLOCD = 0x2, // val.p holds alloc'd ptr that must be freed
+ VAL_IS_IFACE = 0x4, // val.p holds interface ptr that must be released
+ VAL_IS_ARRAY = 0x8, // val.p holds a pointer to an array needing cleanup
+ VAL_IS_DOMSTR = 0x10, // val.p holds a pointer to domstring needing cleanup
+ VAL_IS_UTF8STR = 0x20, // val.p holds a pointer to utf8string needing cleanup
+ VAL_IS_CSTR = 0x40 // val.p holds a pointer to cstring needing cleanup
+ };
+
+ /* VBox: Added to prevent -Wclass-memaccess warnings (nsXPTType has a constructor) in python/src/VariantUtils.cpp */
+ nsXPTCVariant() : ptr(NULL), flags(0)
+ {
+ val.p = NULL;
+ type.flags = 0; /* stupid nsXPTType constructor only do random bytes (documented) */
+ }
+
+ void ClearFlags() {flags = 0;}
+ void SetPtrIsData() {flags |= PTR_IS_DATA;}
+ void SetValIsAllocated() {flags |= VAL_IS_ALLOCD;}
+ void SetValIsInterface() {flags |= VAL_IS_IFACE;}
+ void SetValIsArray() {flags |= VAL_IS_ARRAY;}
+ void SetValIsDOMString() {flags |= VAL_IS_DOMSTR;}
+ void SetValIsUTF8String() {flags |= VAL_IS_UTF8STR;}
+ void SetValIsCString() {flags |= VAL_IS_CSTR;}
+
+ PRBool IsPtrData() const {return 0 != (flags & PTR_IS_DATA);}
+ PRBool IsValAllocated() const {return 0 != (flags & VAL_IS_ALLOCD);}
+ PRBool IsValInterface() const {return 0 != (flags & VAL_IS_IFACE);}
+ PRBool IsValArray() const {return 0 != (flags & VAL_IS_ARRAY);}
+ PRBool IsValDOMString() const {return 0 != (flags & VAL_IS_DOMSTR);}
+ PRBool IsValUTF8String() const {return 0 != (flags & VAL_IS_UTF8STR);}
+ PRBool IsValCString() const {return 0 != (flags & VAL_IS_CSTR);}
+#ifdef VBOX
+ PRBool MustFreeVal() const {return 0 != (flags & ( VAL_IS_ALLOCD
+ | VAL_IS_IFACE
+ | VAL_IS_DOMSTR
+ | VAL_IS_UTF8STR
+ | VAL_IS_CSTR)); }
+#endif
+
+ void Init(const nsXPTCMiniVariant& mv, const nsXPTType& t, PRUint8 f)
+ {
+ type = t;
+ flags = f;
+
+ if(f & PTR_IS_DATA)
+ {
+ ptr = mv.val.p;
+ val.p = nsnull;
+ }
+ else
+ {
+ ptr = nsnull;
+ switch(t.TagPart()) {
+ case nsXPTType::T_I8: val.i8 = mv.val.i8; break;
+ case nsXPTType::T_I16: val.i16 = mv.val.i16; break;
+ case nsXPTType::T_I32: val.i32 = mv.val.i32; break;
+ case nsXPTType::T_I64: val.i64 = mv.val.i64; break;
+ case nsXPTType::T_U8: val.u8 = mv.val.u8; break;
+ case nsXPTType::T_U16: val.u16 = mv.val.u16; break;
+ case nsXPTType::T_U32: val.u32 = mv.val.u32; break;
+ case nsXPTType::T_U64: val.u64 = mv.val.u64; break;
+ case nsXPTType::T_FLOAT: val.f = mv.val.f; break;
+ case nsXPTType::T_DOUBLE: val.d = mv.val.d; break;
+ case nsXPTType::T_BOOL: val.b = mv.val.b; break;
+ case nsXPTType::T_CHAR: val.c = mv.val.c; break;
+ case nsXPTType::T_WCHAR: val.wc = mv.val.wc; break;
+ case nsXPTType::T_VOID: /* fall through */
+ case nsXPTType::T_IID: /* fall through */
+ case nsXPTType::T_DOMSTRING: /* fall through */
+ case nsXPTType::T_CHAR_STR: /* fall through */
+ case nsXPTType::T_WCHAR_STR: /* fall through */
+ case nsXPTType::T_INTERFACE: /* fall through */
+ case nsXPTType::T_INTERFACE_IS: /* fall through */
+ case nsXPTType::T_ARRAY: /* fall through */
+ case nsXPTType::T_PSTRING_SIZE_IS: /* fall through */
+ case nsXPTType::T_PWSTRING_SIZE_IS: /* fall through */
+ case nsXPTType::T_UTF8STRING: /* fall through */
+ case nsXPTType::T_CSTRING: /* fall through */
+ default: val.p = mv.val.p; break;
+ }
+ }
+ }
+};
+
+/***************************************************************************/
+
+#undef IMETHOD_VISIBILITY
+#define IMETHOD_VISIBILITY NS_VISIBILITY_DEFAULT
+
+class XPTC_EXPORT nsXPTCStubBase : public nsISupports
+{
+public:
+ // We are going to implement this to force the compiler to generate a
+ // vtbl for this class. Since this is overridden in the inheriting class
+ // we expect it to never be called.
+ // *This is needed by the Irix implementation.*
+ NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
+
+ // Implement dummy constructor, destructor to workaround Solaris gcc 4.8.2
+ // linking issue (see @bugref{5838}).
+ nsXPTCStubBase() {}
+ ~nsXPTCStubBase() {}
+
+ // Include generated vtbl stub declarations.
+ // These are virtual and *also* implemented by this class..
+#include "xptcstubsdecl.inc"
+
+ // The following methods must be provided by inheritor of this class.
+
+ // return a refcounted pointer to the InterfaceInfo for this object
+ // NOTE: on some platforms this MUST not fail or we crash!
+ NS_IMETHOD GetInterfaceInfo(nsIInterfaceInfo** info) = 0;
+
+ // call this method and return result
+ NS_IMETHOD CallMethod(PRUint16 methodIndex,
+ const nsXPTMethodInfo* info,
+ nsXPTCMiniVariant* params) = 0;
+};
+
+#undef IMETHOD_VISIBILITY
+#define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN
+
+PR_BEGIN_EXTERN_C
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+// Used to force linking of these obj for the static library into the dll
+extern void xptc_dummy();
+extern void xptc_dummy2();
+
+PR_END_EXTERN_C
+
+#endif /* xptcall_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/xptcstubsdecl.inc b/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/xptcstubsdecl.inc
new file mode 100644
index 00000000..99116d68
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/xptcstubsdecl.inc
@@ -0,0 +1,761 @@
+/* generated file - DO NOT EDIT */
+
+/* includes 247 stub entries, and 5 sentinel entries */
+
+/*
+* declarations of normal stubs...
+* 0 is QueryInterface
+* 1 is AddRef
+* 2 is Release
+*/
+#if !defined(__ia64) || (!defined(__hpux) && !defined(__linux__))
+NS_IMETHOD Stub3();
+NS_IMETHOD Stub4();
+NS_IMETHOD Stub5();
+NS_IMETHOD Stub6();
+NS_IMETHOD Stub7();
+NS_IMETHOD Stub8();
+NS_IMETHOD Stub9();
+NS_IMETHOD Stub10();
+NS_IMETHOD Stub11();
+NS_IMETHOD Stub12();
+NS_IMETHOD Stub13();
+NS_IMETHOD Stub14();
+NS_IMETHOD Stub15();
+NS_IMETHOD Stub16();
+NS_IMETHOD Stub17();
+NS_IMETHOD Stub18();
+NS_IMETHOD Stub19();
+NS_IMETHOD Stub20();
+NS_IMETHOD Stub21();
+NS_IMETHOD Stub22();
+NS_IMETHOD Stub23();
+NS_IMETHOD Stub24();
+NS_IMETHOD Stub25();
+NS_IMETHOD Stub26();
+NS_IMETHOD Stub27();
+NS_IMETHOD Stub28();
+NS_IMETHOD Stub29();
+NS_IMETHOD Stub30();
+NS_IMETHOD Stub31();
+NS_IMETHOD Stub32();
+NS_IMETHOD Stub33();
+NS_IMETHOD Stub34();
+NS_IMETHOD Stub35();
+NS_IMETHOD Stub36();
+NS_IMETHOD Stub37();
+NS_IMETHOD Stub38();
+NS_IMETHOD Stub39();
+NS_IMETHOD Stub40();
+NS_IMETHOD Stub41();
+NS_IMETHOD Stub42();
+NS_IMETHOD Stub43();
+NS_IMETHOD Stub44();
+NS_IMETHOD Stub45();
+NS_IMETHOD Stub46();
+NS_IMETHOD Stub47();
+NS_IMETHOD Stub48();
+NS_IMETHOD Stub49();
+NS_IMETHOD Stub50();
+NS_IMETHOD Stub51();
+NS_IMETHOD Stub52();
+NS_IMETHOD Stub53();
+NS_IMETHOD Stub54();
+NS_IMETHOD Stub55();
+NS_IMETHOD Stub56();
+NS_IMETHOD Stub57();
+NS_IMETHOD Stub58();
+NS_IMETHOD Stub59();
+NS_IMETHOD Stub60();
+NS_IMETHOD Stub61();
+NS_IMETHOD Stub62();
+NS_IMETHOD Stub63();
+NS_IMETHOD Stub64();
+NS_IMETHOD Stub65();
+NS_IMETHOD Stub66();
+NS_IMETHOD Stub67();
+NS_IMETHOD Stub68();
+NS_IMETHOD Stub69();
+NS_IMETHOD Stub70();
+NS_IMETHOD Stub71();
+NS_IMETHOD Stub72();
+NS_IMETHOD Stub73();
+NS_IMETHOD Stub74();
+NS_IMETHOD Stub75();
+NS_IMETHOD Stub76();
+NS_IMETHOD Stub77();
+NS_IMETHOD Stub78();
+NS_IMETHOD Stub79();
+NS_IMETHOD Stub80();
+NS_IMETHOD Stub81();
+NS_IMETHOD Stub82();
+NS_IMETHOD Stub83();
+NS_IMETHOD Stub84();
+NS_IMETHOD Stub85();
+NS_IMETHOD Stub86();
+NS_IMETHOD Stub87();
+NS_IMETHOD Stub88();
+NS_IMETHOD Stub89();
+NS_IMETHOD Stub90();
+NS_IMETHOD Stub91();
+NS_IMETHOD Stub92();
+NS_IMETHOD Stub93();
+NS_IMETHOD Stub94();
+NS_IMETHOD Stub95();
+NS_IMETHOD Stub96();
+NS_IMETHOD Stub97();
+NS_IMETHOD Stub98();
+NS_IMETHOD Stub99();
+NS_IMETHOD Stub100();
+NS_IMETHOD Stub101();
+NS_IMETHOD Stub102();
+NS_IMETHOD Stub103();
+NS_IMETHOD Stub104();
+NS_IMETHOD Stub105();
+NS_IMETHOD Stub106();
+NS_IMETHOD Stub107();
+NS_IMETHOD Stub108();
+NS_IMETHOD Stub109();
+NS_IMETHOD Stub110();
+NS_IMETHOD Stub111();
+NS_IMETHOD Stub112();
+NS_IMETHOD Stub113();
+NS_IMETHOD Stub114();
+NS_IMETHOD Stub115();
+NS_IMETHOD Stub116();
+NS_IMETHOD Stub117();
+NS_IMETHOD Stub118();
+NS_IMETHOD Stub119();
+NS_IMETHOD Stub120();
+NS_IMETHOD Stub121();
+NS_IMETHOD Stub122();
+NS_IMETHOD Stub123();
+NS_IMETHOD Stub124();
+NS_IMETHOD Stub125();
+NS_IMETHOD Stub126();
+NS_IMETHOD Stub127();
+NS_IMETHOD Stub128();
+NS_IMETHOD Stub129();
+NS_IMETHOD Stub130();
+NS_IMETHOD Stub131();
+NS_IMETHOD Stub132();
+NS_IMETHOD Stub133();
+NS_IMETHOD Stub134();
+NS_IMETHOD Stub135();
+NS_IMETHOD Stub136();
+NS_IMETHOD Stub137();
+NS_IMETHOD Stub138();
+NS_IMETHOD Stub139();
+NS_IMETHOD Stub140();
+NS_IMETHOD Stub141();
+NS_IMETHOD Stub142();
+NS_IMETHOD Stub143();
+NS_IMETHOD Stub144();
+NS_IMETHOD Stub145();
+NS_IMETHOD Stub146();
+NS_IMETHOD Stub147();
+NS_IMETHOD Stub148();
+NS_IMETHOD Stub149();
+NS_IMETHOD Stub150();
+NS_IMETHOD Stub151();
+NS_IMETHOD Stub152();
+NS_IMETHOD Stub153();
+NS_IMETHOD Stub154();
+NS_IMETHOD Stub155();
+NS_IMETHOD Stub156();
+NS_IMETHOD Stub157();
+NS_IMETHOD Stub158();
+NS_IMETHOD Stub159();
+NS_IMETHOD Stub160();
+NS_IMETHOD Stub161();
+NS_IMETHOD Stub162();
+NS_IMETHOD Stub163();
+NS_IMETHOD Stub164();
+NS_IMETHOD Stub165();
+NS_IMETHOD Stub166();
+NS_IMETHOD Stub167();
+NS_IMETHOD Stub168();
+NS_IMETHOD Stub169();
+NS_IMETHOD Stub170();
+NS_IMETHOD Stub171();
+NS_IMETHOD Stub172();
+NS_IMETHOD Stub173();
+NS_IMETHOD Stub174();
+NS_IMETHOD Stub175();
+NS_IMETHOD Stub176();
+NS_IMETHOD Stub177();
+NS_IMETHOD Stub178();
+NS_IMETHOD Stub179();
+NS_IMETHOD Stub180();
+NS_IMETHOD Stub181();
+NS_IMETHOD Stub182();
+NS_IMETHOD Stub183();
+NS_IMETHOD Stub184();
+NS_IMETHOD Stub185();
+NS_IMETHOD Stub186();
+NS_IMETHOD Stub187();
+NS_IMETHOD Stub188();
+NS_IMETHOD Stub189();
+NS_IMETHOD Stub190();
+NS_IMETHOD Stub191();
+NS_IMETHOD Stub192();
+NS_IMETHOD Stub193();
+NS_IMETHOD Stub194();
+NS_IMETHOD Stub195();
+NS_IMETHOD Stub196();
+NS_IMETHOD Stub197();
+NS_IMETHOD Stub198();
+NS_IMETHOD Stub199();
+NS_IMETHOD Stub200();
+NS_IMETHOD Stub201();
+NS_IMETHOD Stub202();
+NS_IMETHOD Stub203();
+NS_IMETHOD Stub204();
+NS_IMETHOD Stub205();
+NS_IMETHOD Stub206();
+NS_IMETHOD Stub207();
+NS_IMETHOD Stub208();
+NS_IMETHOD Stub209();
+NS_IMETHOD Stub210();
+NS_IMETHOD Stub211();
+NS_IMETHOD Stub212();
+NS_IMETHOD Stub213();
+NS_IMETHOD Stub214();
+NS_IMETHOD Stub215();
+NS_IMETHOD Stub216();
+NS_IMETHOD Stub217();
+NS_IMETHOD Stub218();
+NS_IMETHOD Stub219();
+NS_IMETHOD Stub220();
+NS_IMETHOD Stub221();
+NS_IMETHOD Stub222();
+NS_IMETHOD Stub223();
+NS_IMETHOD Stub224();
+NS_IMETHOD Stub225();
+NS_IMETHOD Stub226();
+NS_IMETHOD Stub227();
+NS_IMETHOD Stub228();
+NS_IMETHOD Stub229();
+NS_IMETHOD Stub230();
+NS_IMETHOD Stub231();
+NS_IMETHOD Stub232();
+NS_IMETHOD Stub233();
+NS_IMETHOD Stub234();
+NS_IMETHOD Stub235();
+NS_IMETHOD Stub236();
+NS_IMETHOD Stub237();
+NS_IMETHOD Stub238();
+NS_IMETHOD Stub239();
+NS_IMETHOD Stub240();
+NS_IMETHOD Stub241();
+NS_IMETHOD Stub242();
+NS_IMETHOD Stub243();
+NS_IMETHOD Stub244();
+NS_IMETHOD Stub245();
+NS_IMETHOD Stub246();
+NS_IMETHOD Stub247();
+NS_IMETHOD Stub248();
+NS_IMETHOD Stub249();
+#else
+NS_IMETHOD Stub3(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub4(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub5(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub6(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub7(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub8(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub9(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub10(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub11(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub12(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub13(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub14(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub15(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub16(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub17(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub18(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub19(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub20(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub21(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub22(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub23(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub24(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub25(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub26(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub27(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub28(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub29(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub30(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub31(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub32(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub33(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub34(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub35(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub36(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub37(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub38(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub39(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub40(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub41(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub42(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub43(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub44(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub45(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub46(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub47(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub48(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub49(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub50(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub51(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub52(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub53(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub54(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub55(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub56(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub57(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub58(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub59(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub60(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub61(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub62(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub63(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub64(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub65(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub66(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub67(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub68(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub69(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub70(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub71(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub72(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub73(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub74(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub75(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub76(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub77(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub78(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub79(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub80(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub81(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub82(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub83(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub84(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub85(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub86(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub87(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub88(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub89(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub90(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub91(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub92(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub93(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub94(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub95(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub96(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub97(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub98(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub99(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub100(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub101(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub102(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub103(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub104(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub105(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub106(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub107(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub108(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub109(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub110(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub111(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub112(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub113(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub114(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub115(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub116(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub117(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub118(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub119(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub120(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub121(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub122(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub123(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub124(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub125(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub126(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub127(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub128(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub129(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub130(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub131(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub132(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub133(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub134(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub135(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub136(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub137(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub138(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub139(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub140(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub141(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub142(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub143(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub144(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub145(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub146(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub147(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub148(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub149(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub150(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub151(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub152(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub153(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub154(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub155(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub156(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub157(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub158(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub159(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub160(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub161(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub162(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub163(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub164(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub165(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub166(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub167(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub168(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub169(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub170(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub171(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub172(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub173(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub174(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub175(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub176(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub177(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub178(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub179(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub180(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub181(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub182(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub183(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub184(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub185(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub186(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub187(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub188(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub189(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub190(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub191(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub192(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub193(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub194(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub195(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub196(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub197(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub198(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub199(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub200(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub201(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub202(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub203(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub204(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub205(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub206(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub207(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub208(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub209(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub210(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub211(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub212(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub213(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub214(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub215(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub216(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub217(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub218(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub219(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub220(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub221(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub222(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub223(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub224(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub225(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub226(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub227(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub228(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub229(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub230(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub231(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub232(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub233(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub234(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub235(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub236(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub237(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub238(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub239(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub240(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub241(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub242(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub243(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub244(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub245(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub246(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub247(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub248(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+NS_IMETHOD Stub249(PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+#endif
+
+/* declarations of sentinel stubs */
+NS_IMETHOD Sentinel0();
+NS_IMETHOD Sentinel1();
+NS_IMETHOD Sentinel2();
+NS_IMETHOD Sentinel3();
+NS_IMETHOD Sentinel4();
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/xptcstubsdef.inc b/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/xptcstubsdef.inc
new file mode 100644
index 00000000..780e2f52
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/public/xptcstubsdef.inc
@@ -0,0 +1,256 @@
+/* generated file - DO NOT EDIT */
+
+/* includes 247 stub entries, and 5 sentinel entries */
+
+STUB_ENTRY(3)
+STUB_ENTRY(4)
+STUB_ENTRY(5)
+STUB_ENTRY(6)
+STUB_ENTRY(7)
+STUB_ENTRY(8)
+STUB_ENTRY(9)
+STUB_ENTRY(10)
+STUB_ENTRY(11)
+STUB_ENTRY(12)
+STUB_ENTRY(13)
+STUB_ENTRY(14)
+STUB_ENTRY(15)
+STUB_ENTRY(16)
+STUB_ENTRY(17)
+STUB_ENTRY(18)
+STUB_ENTRY(19)
+STUB_ENTRY(20)
+STUB_ENTRY(21)
+STUB_ENTRY(22)
+STUB_ENTRY(23)
+STUB_ENTRY(24)
+STUB_ENTRY(25)
+STUB_ENTRY(26)
+STUB_ENTRY(27)
+STUB_ENTRY(28)
+STUB_ENTRY(29)
+STUB_ENTRY(30)
+STUB_ENTRY(31)
+STUB_ENTRY(32)
+STUB_ENTRY(33)
+STUB_ENTRY(34)
+STUB_ENTRY(35)
+STUB_ENTRY(36)
+STUB_ENTRY(37)
+STUB_ENTRY(38)
+STUB_ENTRY(39)
+STUB_ENTRY(40)
+STUB_ENTRY(41)
+STUB_ENTRY(42)
+STUB_ENTRY(43)
+STUB_ENTRY(44)
+STUB_ENTRY(45)
+STUB_ENTRY(46)
+STUB_ENTRY(47)
+STUB_ENTRY(48)
+STUB_ENTRY(49)
+STUB_ENTRY(50)
+STUB_ENTRY(51)
+STUB_ENTRY(52)
+STUB_ENTRY(53)
+STUB_ENTRY(54)
+STUB_ENTRY(55)
+STUB_ENTRY(56)
+STUB_ENTRY(57)
+STUB_ENTRY(58)
+STUB_ENTRY(59)
+STUB_ENTRY(60)
+STUB_ENTRY(61)
+STUB_ENTRY(62)
+STUB_ENTRY(63)
+STUB_ENTRY(64)
+STUB_ENTRY(65)
+STUB_ENTRY(66)
+STUB_ENTRY(67)
+STUB_ENTRY(68)
+STUB_ENTRY(69)
+STUB_ENTRY(70)
+STUB_ENTRY(71)
+STUB_ENTRY(72)
+STUB_ENTRY(73)
+STUB_ENTRY(74)
+STUB_ENTRY(75)
+STUB_ENTRY(76)
+STUB_ENTRY(77)
+STUB_ENTRY(78)
+STUB_ENTRY(79)
+STUB_ENTRY(80)
+STUB_ENTRY(81)
+STUB_ENTRY(82)
+STUB_ENTRY(83)
+STUB_ENTRY(84)
+STUB_ENTRY(85)
+STUB_ENTRY(86)
+STUB_ENTRY(87)
+STUB_ENTRY(88)
+STUB_ENTRY(89)
+STUB_ENTRY(90)
+STUB_ENTRY(91)
+STUB_ENTRY(92)
+STUB_ENTRY(93)
+STUB_ENTRY(94)
+STUB_ENTRY(95)
+STUB_ENTRY(96)
+STUB_ENTRY(97)
+STUB_ENTRY(98)
+STUB_ENTRY(99)
+STUB_ENTRY(100)
+STUB_ENTRY(101)
+STUB_ENTRY(102)
+STUB_ENTRY(103)
+STUB_ENTRY(104)
+STUB_ENTRY(105)
+STUB_ENTRY(106)
+STUB_ENTRY(107)
+STUB_ENTRY(108)
+STUB_ENTRY(109)
+STUB_ENTRY(110)
+STUB_ENTRY(111)
+STUB_ENTRY(112)
+STUB_ENTRY(113)
+STUB_ENTRY(114)
+STUB_ENTRY(115)
+STUB_ENTRY(116)
+STUB_ENTRY(117)
+STUB_ENTRY(118)
+STUB_ENTRY(119)
+STUB_ENTRY(120)
+STUB_ENTRY(121)
+STUB_ENTRY(122)
+STUB_ENTRY(123)
+STUB_ENTRY(124)
+STUB_ENTRY(125)
+STUB_ENTRY(126)
+STUB_ENTRY(127)
+STUB_ENTRY(128)
+STUB_ENTRY(129)
+STUB_ENTRY(130)
+STUB_ENTRY(131)
+STUB_ENTRY(132)
+STUB_ENTRY(133)
+STUB_ENTRY(134)
+STUB_ENTRY(135)
+STUB_ENTRY(136)
+STUB_ENTRY(137)
+STUB_ENTRY(138)
+STUB_ENTRY(139)
+STUB_ENTRY(140)
+STUB_ENTRY(141)
+STUB_ENTRY(142)
+STUB_ENTRY(143)
+STUB_ENTRY(144)
+STUB_ENTRY(145)
+STUB_ENTRY(146)
+STUB_ENTRY(147)
+STUB_ENTRY(148)
+STUB_ENTRY(149)
+STUB_ENTRY(150)
+STUB_ENTRY(151)
+STUB_ENTRY(152)
+STUB_ENTRY(153)
+STUB_ENTRY(154)
+STUB_ENTRY(155)
+STUB_ENTRY(156)
+STUB_ENTRY(157)
+STUB_ENTRY(158)
+STUB_ENTRY(159)
+STUB_ENTRY(160)
+STUB_ENTRY(161)
+STUB_ENTRY(162)
+STUB_ENTRY(163)
+STUB_ENTRY(164)
+STUB_ENTRY(165)
+STUB_ENTRY(166)
+STUB_ENTRY(167)
+STUB_ENTRY(168)
+STUB_ENTRY(169)
+STUB_ENTRY(170)
+STUB_ENTRY(171)
+STUB_ENTRY(172)
+STUB_ENTRY(173)
+STUB_ENTRY(174)
+STUB_ENTRY(175)
+STUB_ENTRY(176)
+STUB_ENTRY(177)
+STUB_ENTRY(178)
+STUB_ENTRY(179)
+STUB_ENTRY(180)
+STUB_ENTRY(181)
+STUB_ENTRY(182)
+STUB_ENTRY(183)
+STUB_ENTRY(184)
+STUB_ENTRY(185)
+STUB_ENTRY(186)
+STUB_ENTRY(187)
+STUB_ENTRY(188)
+STUB_ENTRY(189)
+STUB_ENTRY(190)
+STUB_ENTRY(191)
+STUB_ENTRY(192)
+STUB_ENTRY(193)
+STUB_ENTRY(194)
+STUB_ENTRY(195)
+STUB_ENTRY(196)
+STUB_ENTRY(197)
+STUB_ENTRY(198)
+STUB_ENTRY(199)
+STUB_ENTRY(200)
+STUB_ENTRY(201)
+STUB_ENTRY(202)
+STUB_ENTRY(203)
+STUB_ENTRY(204)
+STUB_ENTRY(205)
+STUB_ENTRY(206)
+STUB_ENTRY(207)
+STUB_ENTRY(208)
+STUB_ENTRY(209)
+STUB_ENTRY(210)
+STUB_ENTRY(211)
+STUB_ENTRY(212)
+STUB_ENTRY(213)
+STUB_ENTRY(214)
+STUB_ENTRY(215)
+STUB_ENTRY(216)
+STUB_ENTRY(217)
+STUB_ENTRY(218)
+STUB_ENTRY(219)
+STUB_ENTRY(220)
+STUB_ENTRY(221)
+STUB_ENTRY(222)
+STUB_ENTRY(223)
+STUB_ENTRY(224)
+STUB_ENTRY(225)
+STUB_ENTRY(226)
+STUB_ENTRY(227)
+STUB_ENTRY(228)
+STUB_ENTRY(229)
+STUB_ENTRY(230)
+STUB_ENTRY(231)
+STUB_ENTRY(232)
+STUB_ENTRY(233)
+STUB_ENTRY(234)
+STUB_ENTRY(235)
+STUB_ENTRY(236)
+STUB_ENTRY(237)
+STUB_ENTRY(238)
+STUB_ENTRY(239)
+STUB_ENTRY(240)
+STUB_ENTRY(241)
+STUB_ENTRY(242)
+STUB_ENTRY(243)
+STUB_ENTRY(244)
+STUB_ENTRY(245)
+STUB_ENTRY(246)
+STUB_ENTRY(247)
+STUB_ENTRY(248)
+STUB_ENTRY(249)
+SENTINEL_ENTRY(0)
+SENTINEL_ENTRY(1)
+SENTINEL_ENTRY(2)
+SENTINEL_ENTRY(3)
+SENTINEL_ENTRY(4)
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/Makefile.in
new file mode 100644
index 00000000..987fc505
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/Makefile.in
@@ -0,0 +1,62 @@
+#
+# ***** 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
+LIBRARY_NAME = xptcall
+
+
+DIRS = md
+
+CPPSRCS = xptcall.cpp
+
+# 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 += -DEXPORT_XPTC_API -D_IMPL_NS_COM -D_IMPL_NS_BASE
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/Makefile.kup b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/Makefile.kup
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/Makefile.in
new file mode 100644
index 00000000..dd70cabf
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/Makefile.in
@@ -0,0 +1,56 @@
+#
+# ***** 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
+
+ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
+DIRS = os2
+else
+ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
+DIRS = win32
+else
+DIRS = unix
+endif
+endif
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/Makefile.kup b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/Makefile.kup
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcinvoke_mac.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcinvoke_mac.cpp
new file mode 100644
index 00000000..29343c08
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcinvoke_mac.cpp
@@ -0,0 +1,148 @@
+/* -*- 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 ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#ifndef XP_MAC
+#error "This code is for Macintosh only"
+#endif
+
+extern "C" uint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ PRUint32 result = 0;
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ return result;
+}
+
+extern "C" void
+invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPTCVariant* s, double *fprData)
+{
+ PRUint32 fpCount = 0;
+ for(PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((PRInt32*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((PRInt32*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((PRInt32*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((PRInt64*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((PRUint32*) d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((PRUint32*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((PRUint32*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((PRUint64*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f;
+ if (fpCount < 13)
+ fprData[fpCount++] = s->val.f;
+ break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++;
+ if (fpCount < 13)
+ fprData[fpCount++] = s->val.d;
+ break;
+ case nsXPTType::T_BOOL : *((PRBool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((PRInt32*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((PRUint32*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+}
+
+#pragma export on
+
+extern "C" nsresult _XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+extern "C"
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ return _XPTC_InvokeByIndex(that, methodIndex, paramCount, params);
+}
+
+#pragma export off
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcinvoke_mac.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcinvoke_mac.s
new file mode 100644
index 00000000..47544dd3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcinvoke_mac.s
@@ -0,0 +1,128 @@
+ #
+ # -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ #
+ # The contents of this file are subject to the Netscape 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/NPL/
+ #
+ # 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 Netscape are
+ # Copyright (C) 1999 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s):
+ #
+
+ csect CODE{PR}
+#
+# XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+# PRUint32 paramCount, nsXPTCVariant* params)
+#
+
+ import .invoke_count_words
+ import .invoke_copy_to_stack
+ import .__ptr_glue
+
+._XPTC_InvokeByIndex:
+ mflr r0
+ stw r31,-4(sp)
+#
+# save off the incoming values in the caller's parameter area
+#
+ stw r3,24(sp) # that
+ stw r4,28(sp) # methodIndex
+ stw r5,32(sp) # paramCount
+ stw r6,36(sp) # params
+ stw r0,8(sp)
+ stwu sp,-144(sp) # = 24 for linkage area, 8 * 13 for fprData area, 8 for saved registers,
+ # 8 to keep stack 16-byte aligned.
+
+# set up for and call 'invoke_count_words' to get new stack size
+#
+ mr r3,r5
+ mr r4,r6
+ bl .invoke_count_words
+ nop
+
+# prepare args for 'invoke_copy_to_stack' call
+#
+ lwz r4,176(sp) # paramCount
+ lwz r5,180(sp) # params
+# addi r6,sp,128 # fprData
+ mr r6,sp # fprData
+ slwi r3,r3,2 # number of bytes of stack required
+ addi r3,r3,28 # linkage area
+ mr r31,sp # save original stack top
+ sub sp,sp,r3 # bump the stack
+ clrrwi sp,sp,4 # keep the stack 16-byte aligned.
+ lwz r3,0(r31) # act like real alloca, so 0(sp) always points back to
+ stw r3,0(sp) # previous stack frame.
+ addi r3,sp,28 # parameter pointer excludes linkage area size + 'this'
+
+ bl .invoke_copy_to_stack
+ nop
+
+ lfd f1,0(r31)
+ lfd f2,8(r31)
+ lfd f3,16(r31)
+ lfd f4,24(r31)
+ lfd f5,32(r31)
+ lfd f6,40(r31)
+ lfd f7,48(r31)
+ lfd f8,56(r31)
+ lfd f9,64(r31)
+ lfd f10,72(r31)
+ lfd f11,80(r31)
+ lfd f12,88(r31)
+ lfd f13,96(r31)
+
+ lwz r3,168(r31) # that
+ lwz r4,0(r3) # get vTable from 'that'
+ lwz r5,172(r31) # methodIndex
+ slwi r5,r5,2 # methodIndex * 4
+ addi r5,r5,8 # step over junk at start of vTable !
+ lwzx r12,r5,r4 # get function pointer
+
+ lwz r4,28(sp)
+ lwz r5,32(sp)
+ lwz r6,36(sp)
+ lwz r7,40(sp)
+ lwz r8,44(sp)
+ lwz r9,48(sp)
+ lwz r10,52(sp)
+
+ bl .__ptr_glue
+ nop
+
+
+ mr sp,r31
+ lwz r0,152(sp)
+ addi sp,sp,144
+ mtlr r0
+ lwz r31,-4(sp)
+ blr
+
+# traceback table.
+ traceback:
+ dc.l 0
+ dc.l 0x00002040
+ dc.l 0
+ dc.l (traceback - ._XPTC_InvokeByIndex) # size of the code.
+ dc.w 20 # short length of identifier.
+ dc.b '._XPTC_InvokeByIndex'
+
+ csect DATA
+ import TOC
+ export ._XPTC_InvokeByIndex
+
+ dc.l ._XPTC_InvokeByIndex
+ dc.l TOC
+ \ No newline at end of file
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcstubs_mac.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcstubs_mac.cpp
new file mode 100644
index 00000000..3fea7d51
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcstubs_mac.cpp
@@ -0,0 +1,265 @@
+/* -*- 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) 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 ***** */
+
+/* Implement shared vtbl methods. */
+
+#pragma export on
+
+#include "xptcprivate.h"
+
+#if defined(XP_MAC)
+
+/*
+ For mac, the first 8 integral and the first 13 f.p. parameters arrive
+ in a separate chunk of data that has been loaded from the registers. The
+ args pointer has been set to the start of the parameters BEYOND the ones
+ arriving in registers
+*/
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, PRUint32 methodIndex, PRUint32* args, PRUint32 *gprData, double *fprData)
+{
+#define PARAM_BUFFER_COUNT 16
+#define PARAM_GPR_COUNT 7
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ PRUint32 iCount = 0;
+ PRUint32 fpCount = 0;
+ for(i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.p = (void*) gprData[iCount++];
+ else
+ dp->val.p = (void*) *ap++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (PRInt8) gprData[iCount++];
+ else
+ dp->val.i8 = (PRInt8) *ap++;
+ break;
+ case nsXPTType::T_I16 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (PRInt16) gprData[iCount++];
+ else
+ dp->val.i16 = (PRInt16) *ap++;
+ break;
+ case nsXPTType::T_I32 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (PRInt32) gprData[iCount++];
+ else
+ dp->val.i32 = (PRInt32) *ap++;
+ break;
+ case nsXPTType::T_I64 :
+#ifdef HAVE_LONG_LONG
+ PRUint64 tempu64;
+ if (iCount & 1) iCount++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ if ((iCount + 1) < PARAM_GPR_COUNT)
+ {
+ tempu64 = *(PRUint64*) &gprData[iCount];
+ iCount += 2;
+ }
+ else
+ {
+ if ((PRUint32) ap & 4) ap++; // longlongs are 8-byte aligned on stack
+ tempu64 = *(PRUint64*) ap;
+ ap += 2;
+ }
+ dp->val.i64 = (PRUint64)tempu64;
+#else
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64.hi = (PRInt32) gprData[iCount++];
+ else
+ dp->val.i64.hi = (PRInt32) *ap++;
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64.lo = (PRUint32) gprData[iCount++];
+ else
+ dp->val.i64.lo = (PRUint32) *ap++;
+#endif
+ break;
+ case nsXPTType::T_U8 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (PRUint8) gprData[iCount++];
+ else
+ dp->val.i8 = (PRUint8) *ap++;
+ break;
+ case nsXPTType::T_U16 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (PRUint16) gprData[iCount++];
+ else
+ dp->val.i16 = (PRUint16) *ap++;
+ break;
+ case nsXPTType::T_U32 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (PRUint32) gprData[iCount++];
+ else
+ dp->val.i32 = (PRUint32) *ap++;
+ break;
+ case nsXPTType::T_U64 :
+#ifdef HAVE_LONG_LONG
+ // PRUint64 tempu64; // declared above and still in scope
+ if (iCount & 1) iCount++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ if ((iCount + 1) < PARAM_GPR_COUNT)
+ {
+ tempu64 = *(PRUint64*) &gprData[iCount];
+ iCount += 2;
+ }
+ else
+ {
+ if ((PRUint32) ap & 4) ap++; // longlongs are 8-byte aligned on stack
+ tempu64 = *(PRUint64*) ap;
+ ap += 2;
+ }
+ dp->val.i64 = (PRUint64)tempu64;
+#else
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64.hi = (PRUint32) gprData[iCount++];
+ else
+ dp->val.i64.hi = (PRUint32) *ap++;
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64.lo = (PRUint32) gprData[iCount++];
+ else
+ dp->val.i64.lo = (PRUint32) *ap++;
+#endif
+ break;
+ case nsXPTType::T_FLOAT : if (fpCount < 13) {
+ dp->val.f = (float) fprData[fpCount++];
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ }
+ else
+ dp->val.f = *((float*) ap++);
+ break;
+ case nsXPTType::T_DOUBLE : if (fpCount < 13) {
+ dp->val.d = (double) fprData[fpCount++];
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ }
+ else {
+ dp->val.f = *((double*) ap);
+ ap += 2;
+ }
+ break;
+ case nsXPTType::T_BOOL : if (iCount < PARAM_GPR_COUNT)
+ dp->val.b = (PRBool) gprData[iCount++];
+ else
+ dp->val.b = (PRBool) *ap++;
+ break;
+ case nsXPTType::T_CHAR : if (iCount < PARAM_GPR_COUNT)
+ dp->val.c = (char) gprData[iCount++];
+ else
+ dp->val.c = (char) *ap++;
+ break;
+ case nsXPTType::T_WCHAR : if (iCount < PARAM_GPR_COUNT)
+ dp->val.wc = (wchar_t) gprData[iCount++];
+ else
+ dp->val.wc = (wchar_t) *ap++;
+ break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" void SharedStub();
+
+#define STUB_ENTRY(n) \
+asm nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ addi r12,r0,n; \
+ b SharedStub \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+
+#include "xptcstubsdef.inc"
+
+#pragma export off
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcstubs_mac.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcstubs_mac.s
new file mode 100644
index 00000000..d2f7185b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/mac/xptcstubs_mac.s
@@ -0,0 +1,78 @@
+ #
+ # -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ #
+ # The contents of this file are subject to the Netscape 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/NPL/
+ #
+ # 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 Netscape are
+ # Copyright (C) 1999 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s):
+ #
+
+ csect CODE{PR}
+#
+# on entry SharedStub has the method selector in r12, the rest of the original
+# parameters are in r3 thru r10 and f1 thru f13
+#
+ import .PrepareAndDispatch
+
+.SharedStub:
+ mflr r0
+ stw r0,8(sp)
+
+ stwu sp,-176(sp) # room for linkage (24), fprData (104), gprData(28)
+ # outgoing params to PrepareAndDispatch (20)
+
+ stw r4,44(sp)
+ stw r5,48(sp)
+ stw r6,52(sp)
+ stw r7,56(sp)
+ stw r8,60(sp)
+ stw r9,64(sp)
+ stw r10,68(sp)
+ stfd f1,72(sp)
+ stfd f2,80(sp)
+ stfd f3,88(sp)
+ stfd f4,96(sp)
+ stfd f5,104(sp)
+ stfd f6,112(sp)
+ stfd f7,120(sp)
+ stfd f8,128(sp)
+ stfd f9,136(sp)
+ stfd f10,144(sp)
+ stfd f11,152(sp)
+ stfd f12,156(sp)
+ stfd f13,164(sp)
+
+ addi r6,sp,44 # gprData
+ addi r7,sp,72 # fprData
+ # r3 has the 'self' pointer already
+ mr r4,r12 # methodIndex selector
+ addi r5,sp,232 # pointer to callers args area, beyond r3-r10 mapped range
+
+ bl .PrepareAndDispatch
+ nop
+
+ lwz r0,184(sp)
+ addi sp,sp,176
+ mtlr r0
+ blr
+
+ csect DATA
+ import TOC
+ export .SharedStub
+
+ dc.l .SharedStub
+ dc.l TOC
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/Makefile.in
new file mode 100644
index 00000000..cfd57c83
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/Makefile.in
@@ -0,0 +1,72 @@
+#
+# ***** 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
+LIBRARY_NAME = xptcmd
+
+ifdef GNU_CXX
+CPPSRCS = \
+ ../unix/xptcinvoke_gcc_x86_unix.cpp \
+ ../unix/xptcstubs_gcc_x86_unix.cpp \
+ $(NULL)
+LOCAL_INCLUDES = -I$(srcdir)/../unix
+DEFINES += -DMOZ_NEED_LEADING_UNDERSCORE
+else
+CPPSRCS = xptcstubs_os2.cpp
+ASFILES = xptcinvoke_vacpp.asm xptcstubs_vacpp.asm
+endif
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+include $(topsrcdir)/config/config.mk
+
+# we don't want the shared lib, but we want to force the creation of a static lib.
+FORCE_STATIC_LIB = 1
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -DEXPORT_XPTC_API
+
+INCLUDES += -I$(srcdir)/../..
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcinvoke_emx.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcinvoke_emx.cpp
new file mode 100644
index 00000000..17fcadfe
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcinvoke_emx.cpp
@@ -0,0 +1,185 @@
+/* -*- 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):
+ * John Fairhurst <john_fairhurst@iname.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 *****
+ *
+ * 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
+ * 03/22/2000 IBM Corp. Fixed multiple inheritance bug in XPTC_InvokeByIndex to adjust the
+ * "that" (this) pointer appropriately.
+ */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+// This is 80% copied directly from other platforms; the assembler
+// stuff is all my fault, though. (jmf)
+
+#if !defined(__EMX__)
+#error "This code is for OS/2 EMX only"
+#endif
+
+#include "xptcprivate.h"
+
+// Remember that these 'words' are 32-bit DWORDs
+static PRUint32
+invoke_count_words( PRUint32 paramCount, nsXPTCVariant* s)
+{
+ PRUint32 result = 0;
+
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ result++;
+
+ else {
+
+ switch(s->type)
+ {
+ // 64-bit types
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+
+ // all others are dwords
+ default:
+ result++;
+ break;
+ }
+ }
+ }
+ return result;
+}
+
+
+static void
+invoke_copy_to_stack( PRUint32* d, uint32 paramCount, nsXPTCVariant* s)
+{
+ for( PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ *((void**)d) = s->ptr;
+
+ else {
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((int8*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((int16*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((int64*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((uint8*) d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint16*) d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32*) d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((uint64*) d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ case nsXPTType::T_BOOL : *((PRBool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((wchar_t*)d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+ }
+}
+
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex( nsISupports *that, PRUint32 index,
+ PRUint32 paramcount, nsXPTCVariant* params)
+{
+ int ibytes;
+ void *pStack;
+ int result = NS_OK;
+
+ // Find size in bytes necessary for call
+ ibytes = 4 * invoke_count_words( paramcount, params);
+
+ __asm__ __volatile__(
+ "movl %1, %%eax\n" /* load |ibytes| into eax */
+ "subl %%eax, %%esp\n" /* make room on stack */
+ "movl %%esp, %0" /* store base in |pStack| */
+ : "=g" (pStack) /* %0 */
+ : "g" (ibytes) /* %1 */
+ : "ax", "memory", "sp"
+ );
+
+ // Fill in that gap in the stack with the params to the method
+ invoke_copy_to_stack( (PRUint32*) pStack, paramcount, params);
+
+ // push the hidden 'this' parameter, traverse the vtable,
+ // and then call the method.
+
+ __asm__ __volatile__(
+ "movl %2, %%eax\n" /* |that| ptr -> eax */
+ "movl (%%eax), %%edx\n" /* vptr -> edx */
+ "movl %3, %%ebx\n"
+ "shl $3, %%ebx\n" /* 8 bytes per method.. */
+ "addl $8, %%ebx\n" /* ..plus 8 to skip over 1st 8 bytes of vtbl */
+
+ "addl %%ebx, %%edx\n" /* find appropriate vtbl entry */
+ "movswl (%%edx),%%ecx\n" /* get possible |that| ptr adjustment value */
+ "addl %%ecx, %%eax\n" /* adjust the |that| ptr (needed for multiple inheritance) */
+ "pushl %%eax\n" /* enstack the possibly-adjusted |that| */
+
+ "addl $4, %%edx\n" /* ..add 4 more to get to the method's entry point */
+
+ "call (%%edx)\n" /* call method */
+ "movl %%eax, %0\n" /* save rc in |result| */
+ "movl %1, %%ebx\n" /* clear up stack */
+ "addl $4, %%ebx\n"
+ "addl %%ebx, %%esp"
+ : "=g" (result) /* %0 */
+ : "g" (ibytes), /* %1 */
+ "g" (that), /* %2 */
+ "g" (index) /* %3 */
+ : "ax", "bx", "dx", "memory", "sp"
+ );
+
+ return result;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcinvoke_gcc_x86_os2.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcinvoke_gcc_x86_os2.cpp
new file mode 100644
index 00000000..6bbb93b0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcinvoke_gcc_x86_os2.cpp
@@ -0,0 +1,159 @@
+/* -*- 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 ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+/* This file is basically a copy of xptcinvoke_gcc_x86_unix.cpp with some
+ * irrelevant parts stipped off and some OS/2 specific modifications added,
+ * so it needs to be kept in sync with the original. */
+
+#include "xptcprivate.h"
+#include "xptc_platforms_unixish_x86.h"
+#include "xptc_gcc_x86_unix.h"
+
+extern "C" {
+static
+void ATTRIBUTE_USED __attribute__ ((regparm(3)))
+invoke_copy_to_stack(PRUint32 paramCount, nsXPTCVariant* s, PRUint32* d)
+{
+ for(PRUint32 i = paramCount; i >0; i--, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I64 : *((PRInt64*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U64 : *((PRUint64*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ default : *((void**)d) = s->val.p; break;
+ }
+ }
+}
+} // extern "C"
+
+/*
+ XPTC_PUBLIC_API(nsresult)
+ XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+ Each param takes at most two 4-byte words.
+ It doesn't matter if we push too many words, and calculating the exact
+ amount takes time.
+
+ that = ebp + 0x08
+ methodIndex = ebp + 0x0c
+ paramCount = ebp + 0x10
+ params = ebp + 0x14
+
+ NOTE NOTE NOTE:
+ As of 2002-04-29 this function references no global variables nor does
+ it call non-static functions so preserving and loading the PIC register
+ is unnecessary. Define MOZ_PRESERVE_PIC if this changes. See mozilla
+ bug 140412 for details. However, avoid this if you can. It's slower.
+*/
+
+#if defined(__declspec)
+#define SYMBOL_EXPORT(sym) \
+ ".stabs \"" sym ",0=" sym ",code\", 0x6c,0,0,-42\n\t"
+#else
+#define SYMBOL_EXPORT(sym)
+#endif
+
+__asm__ (
+ ".text\n\t"
+/* alignment here seems unimportant here; this was 16, now it's 2 which
+ is what xptcstubs uses. */
+ ".align 2\n\t"
+ ".globl " SYMBOL_UNDERSCORE "XPTC_InvokeByIndex\n\t"
+ ".type " SYMBOL_UNDERSCORE "XPTC_InvokeByIndex,@function\n"
+ SYMBOL_EXPORT(SYMBOL_UNDERSCORE "XPTC_InvokeByIndex")
+ SYMBOL_UNDERSCORE "XPTC_InvokeByIndex:\n\t"
+ "pushl %ebp\n\t"
+ "movl %esp, %ebp\n\t"
+#ifdef MOZ_PRESERVE_PIC
+ "pushl %ebx\n\t"
+ "call 0f\n\t"
+ ".subsection 1\n"
+ "0:\n\t"
+ "movl (%esp), %ebx\n\t"
+ "ret\n\t"
+ ".previous\n\t"
+ "addl $_GLOBAL_OFFSET_TABLE_, %ebx\n\t"
+#endif
+ "movl 0x10(%ebp), %eax\n\t"
+ "leal 0(,%eax,8),%edx\n\t"
+ "movl %esp, %ecx\n\t"
+ "subl %edx, %ecx\n\t"
+/* Since there may be 64-bit data, it occurs to me that aligning this
+ space might be a performance gain. However, I don't think the rest
+ of mozilla worries about such things. In any event, do it here.
+ "andl $0xfffffff8, %ecx\n\t"
+ */
+ "movl %ecx, %esp\n\t" /* make stack space */
+ "movl 0x14(%ebp), %edx\n\t"
+ "call " SYMBOL_UNDERSCORE "invoke_copy_to_stack\n\t"
+ "movl 0x08(%ebp), %ecx\n\t" /* 'that' */
+#ifdef CFRONT_STYLE_THIS_ADJUST
+ "movl (%ecx), %edx\n\t"
+ "movl 0x0c(%ebp), %eax\n\t" /* function index */
+ "shll $3, %eax\n\t" /* *= 8 */
+ "addl $8, %eax\n\t" /* += 8 skip first entry */
+ "addl %eax, %edx\n\t"
+ "movswl (%edx), %eax\n\t" /* 'this' offset */
+ "addl %eax, %ecx\n\t"
+ "pushl %ecx\n\t"
+ "addl $4, %edx\n\t" /* += 4, method pointer */
+#else /* THUNK_BASED_THIS_ADJUST */
+ "pushl %ecx\n\t"
+ "movl (%ecx), %edx\n\t"
+ "movl 0x0c(%ebp), %eax\n\t" /* function index */
+ "leal (%edx,%eax,4), %edx\n\t"
+#endif
+ "call *(%edx)\n\t"
+#ifdef MOZ_PRESERVE_PIC
+ "movl -4(%ebp), %ebx\n\t"
+#endif
+ "movl %ebp, %esp\n\t"
+ "popl %ebp\n\t"
+ "ret\n"
+ ".size " SYMBOL_UNDERSCORE "XPTC_InvokeByIndex, . -" SYMBOL_UNDERSCORE "XPTC_InvokeByIndex\n\t"
+);
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcinvoke_vacpp.asm b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcinvoke_vacpp.asm
new file mode 100644
index 00000000..4d013fdb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcinvoke_vacpp.asm
@@ -0,0 +1,268 @@
+COMMENT | -*- Mode: asm; tab-width: 8; 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
+ the Initial Developer. All Rights Reserved.
+
+ Contributor(s):
+ Henry Sobotka <sobotka@axess.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 *****
+ Version 1.0 (the "NPL"); you may not use this file except in
+ compliance with the NPL. You may obtain a copy of the NPL at
+ http://www.mozilla.org/NPL/
+
+ Software distributed under the NPL is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ for the specific language governing rights and limitations under the
+ NPL.
+
+ The Initial Developer of this code under the NPL is Netscape
+ Communications Corporation. Portions created by Netscape are
+ Copyright (C) 1999 Netscape Communications Corporation. All Rights
+ Reserved.
+
+ Contributor: Henry Sobotka <sobotka@axess.com>
+
+ 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
+ 03/23/2000 IBM Corp. Various fixes for parameter passing and adjusting the 'this'
+ pointer for multiply inherited objects.
+
+ xptcall_vacpp.asm: ALP assembler procedures for VAC++ build of xptcall
+
+ We use essentially the same algorithm as the other platforms, except
+ Optlink as calling convention. This means loading the three leftmost
+ conforming (<= 4 bytes, enum or pointer) parameters into eax, edx and ecx,
+ and the four leftmost float types atop the FP stack. As "this" goes into
+ eax, we only have to load edx and ecx (if there are two parameters).
+ Nonconforming parameters go on the stack. As the right-size space has
+ to be allocated at the proper place (order of parameters) in the stack
+ for each conforming parameter, we simply copy them all. |
+
+
+ .486P
+ .MODEL FLAT, OPTLINK
+ .STACK
+
+ .CODE
+
+t_Int4Bytes equ 001004h
+t_Int8Bytes equ 001008h
+t_Float4Bytes equ 000104h
+t_Float8Bytes equ 000108h
+
+TypesArray dd t_Int4Bytes ; nsXPTType::T_I8
+ dd t_Int4Bytes ; nsXPTType::T_I16
+ dd t_Int4Bytes ; nsXPTType::T_I32
+ dd t_Int8Bytes ; nsXPTType::T_I64 (***)
+ dd t_Int4Bytes ; nsXPTType::T_U8
+ dd t_Int4Bytes ; nsXPTType::T_U16
+ dd t_Int4Bytes ; nsXPTType::T_U32
+ dd t_Int8Bytes ; nsXPTType::T_U64 (***)
+ dd t_Float4Bytes ; nsXPTType::T_FLOAT (***)
+ dd t_Float8Bytes ; nsXPTType::T_DOUBLE (***)
+ dd t_Int4Bytes ; nsXPTType::T_BOOL
+ dd t_Int4Bytes ; nsXPTType::T_CHAR
+ dd t_Int4Bytes ; nsXPTType::T_WCHAR
+ dd t_Int4Bytes ; TD_VOID
+ dd t_Int4Bytes ; TD_PNSIID
+ dd t_Int4Bytes ; TD_DOMSTRING
+ dd t_Int4Bytes ; TD_PSTRING
+ dd t_Int4Bytes ; TD_PWSTRING
+ dd t_Int4Bytes ; TD_INTERFACE_TYPE
+ dd t_Int4Bytes ; TD_INTERFACE_IS_TYPE
+ dd t_Int4Bytes ; TD_ARRAY
+ dd t_Int4Bytes ; TD_PSTRING_SIZE_IS
+ dd t_Int4Bytes ; TD_PWSTRING_SIZE_IS
+ dd t_Int4Bytes ; TD_UTF8STRING
+ dd t_Int4Bytes ; TD_CSTRING
+ dd t_Int4Bytes ; TD_ASTRING
+ ; All other values default to 4 byte int/ptr
+
+
+
+ ; Optlink puts 'that' in eax, 'index' in edx, 'paramcount' in ecx
+ ; 'params' is on the stack...
+XPTC_InvokeByIndex PROC OPTLINK EXPORT USES ebx edi esi, that, index, paramcount, params
+
+ LOCAL cparams:dword, fparams:dword, reg_edx:dword, reg_ecx:dword, count:dword
+
+ mov dword ptr [that], eax ; that
+ mov dword ptr [index], edx ; index
+ mov dword ptr [paramcount], ecx ; paramcount
+ mov dword ptr [count], ecx ; save a copy of count
+
+; #define FOURBYTES 4
+; #define EIGHTBYTES 8
+; #define FLOAT 0x00000100
+; #define INT 0x00001000
+; #define LENGTH 0x000000ff
+;
+;types[ ] = {
+; FOURBYES | INT, // int/uint/ptr/etc
+; EIGHTBYTES | INT, // long long
+; FOURBYES | FLOAT, // float
+; EIGHTBYTES | FLOAT // double
+;};
+; params+00h = val // double
+; params+08h = ptr
+; params+0ch = type
+; params+0dh = flags
+; PTR_IS_DATA = 0x01
+; ecx = params
+; edx = src
+; edi = dst
+; ebx = type (bh = int/float, bl = byte count)
+
+ xor eax, eax
+ mov dword ptr [cparams],eax ; cparams = 0;
+ mov dword ptr [fparams],eax ; fparams = 0;
+
+ shl ecx, 03h
+ sub esp, ecx ; dst/esp = add esp, paramCount * 8
+ mov edi, esp
+
+ push eax ; push 0 // "end" of floating point register stack...
+
+ mov ecx, dword ptr [params] ; // params is a "register" variable
+@While1:
+ mov eax, dword ptr [count] ; while( count-- )
+ or eax, eax ; // (test for zero)
+ je @EndWhile1
+ dec eax
+ mov dword ptr [count], eax
+ ; {
+
+ test byte ptr [ecx+0dh],01h ; if ( params->flags & PTR_IS_DATA ) {
+ je @IfElse1
+ lea edx, dword ptr [ecx+08h] ; src = &params->ptr;
+ mov ebx, 01004h ; type = INT | FOURBYTES;
+ jmp @EndIf1
+@IfElse1: ; } else {
+ mov edx, ecx ; src = &params->val
+ movzx eax, byte ptr [ecx+0ch] ; type = types[params->type];
+ cmp eax, 22 ; // range check params->type... (0 to 22)
+ jle @TypeOK
+ mov eax,2 ; // all others default to 4 byte int
+@TypeOK:
+ mov ebx, dword ptr [TypesArray+eax*4]
+@EndIf1: ; }
+
+ test bh, 001h ; if ( type & FLOAT ) {
+ je @EndIf2
+ cmp dword ptr [fparams], 4 ; if ( fparams < 4 ) {
+ jge @EndIf3
+ push edx ; push src;
+ push ebx ; push type
+ inc dword ptr [fparams] ; fparams++;
+;;; movzx eax, bl ; // dst += (type & LENGTH);
+;;; add edi, eax ;
+;;; xor ebx, ebx ; // type = 0; // "handled"
+@EndIf3: ; }
+@EndIf2: ; }
+
+ ; // copy bytes...
+@While2: or bl, bl ; while( type & LENGTH ) {
+ je @EndWhile2
+ test bh, 010h ; if( type & INT ) {
+ je @EndIf4
+ cmp dword ptr [cparams], 8 ; if( cparams < 8 ) {
+ jge @EndIf5
+ lea eax, dword ptr [reg_edx] ; (&reg_edx)[cparams] = *src;
+ sub eax, dword ptr [cparams]
+ mov esi, dword ptr [edx]
+ mov dword ptr [eax], esi
+ add dword ptr [cparams], 4 ; cparams += 4;
+;;; jmp @NoCopy ; // goto nocopy;
+@EndIf5: ; }
+@EndIf4: ; }
+ mov eax, dword ptr [edx] ; *dst = *src;
+ mov dword ptr [edi], eax
+@NoCopy: ;nocopy:
+ add edi, 4 ; dst++;
+ add edx, 4 ; src++;
+ sub bl, 4 ; type -= 4;
+ jmp @While2
+@EndWhile2: ; }
+ add ecx, 010h ; params++;
+ jmp @While1
+@EndWhile1: ; }
+
+ ; // Set up fpu and regs can make the call...
+@While3: pop ebx ; while ( pop type ) {
+ or ebx, ebx
+ je @EndWhile3
+ pop edx ; pop src
+ cmp bl, 08h ; if( type & EIGHTBYTES ) {
+ jne @IfElse6
+ fld qword ptr [edx] ; fld qword ptr [src]
+ jmp @EndIf6
+@IfElse6: ; } else {
+ fld dword ptr [edx] ; fld dword ptr [src]
+@EndIf6: ; }
+ jmp @While3
+@EndWhile3: ; }
+
+ ; make the call
+ mov eax, dword ptr [that] ; get 'that' ("this" ptr)
+ mov ebx, dword ptr [index] ; get index
+ shl ebx, 03h ; index *= 8 bytes per method
+ add ebx, 08h ; += 8 at head of vtable
+ add ebx, [eax] ; calculate address
+
+ mov ecx, dword ptr [ebx+04h]
+ add eax, ecx
+ sub esp, 04h ; make room for 'this' ptr on stack
+
+ mov edx, dword ptr [reg_edx]
+ mov ecx, dword ptr [reg_ecx]
+
+ call dword ptr [ebx] ; call method
+
+ mov ecx, dword ptr [paramcount]
+ shl ecx, 03h
+ add esp, ecx ; remove space on stack for params
+ add esp, 04h ; remove space on stack for 'this' ptr
+ ret
+
+ ENDP
+
+ END
+
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_emx.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_emx.cpp
new file mode 100644
index 00000000..6cde9231
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_emx.cpp
@@ -0,0 +1,153 @@
+/* -*- 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) 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 ***** */
+
+/* Implement shared vtbl methods */
+
+// This is a 98% copy of other implementations; see comment at top of
+// xptcinvoke_emx.cpp for why this file exists.
+//
+
+#include "xptcprivate.h"
+
+#if !defined(__EMX__)
+#error "This code is for OS/2 EMX only"
+#endif
+
+static nsresult
+PrepareAndDispatch( nsXPTCStubBase *self, PRUint32 methodIndex,
+ PRUint32 *args)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ // If anything fails before stackBytesToPop can be set then
+ // the failure is completely catastrophic!
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((PRInt8*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((PRInt16*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((PRInt64*) ap); ap++; break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((PRUint8*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((PRUint16*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((PRUint32*)ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((PRUint64*)ap); ap++; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((PRBool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ register void* method = PrepareAndDispatch; \
+ register nsresult result; \
+ __asm__ __volatile__( \
+ "leal 0x0c(%%ebp), %%ecx\n\t" /* args */ \
+ "pushl %%ecx\n\t" \
+ "pushl $"#n"\n\t" /* method index */ \
+ "movl 0x08(%%ebp), %%ecx\n\t" /* this */ \
+ "pushl %%ecx\n\t" \
+ "call *%%edx" /* PrepareAndDispatch */ \
+ : "=a" (result) /* %0 */ \
+ : "d" (method) /* %1 */ \
+ : "ax", "dx", "cx", "memory" ); \
+ return result; \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPCWrappedJS::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_gcc_x86_os2.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_gcc_x86_os2.cpp
new file mode 100644
index 00000000..6304b67a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_gcc_x86_os2.cpp
@@ -0,0 +1,180 @@
+/* -*- 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) 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 ***** */
+
+/* Implement shared vtbl methods. */
+
+/* This file is basically a copy of xptcinvoke_gcc_x86_unix.cpp with some
+ * irrelevant parts stipped off and some OS/2 specific modifications added,
+ * so it needs to be kept in sync with the original. */
+
+#include "xptcprivate.h"
+#include "xptc_platforms_unixish_x86.h"
+#include "xptc_gcc_x86_unix.h"
+
+extern "C" {
+static nsresult ATTRIBUTE_USED
+__attribute__ ((regparm (3)))
+PrepareAndDispatch(uint32 methodIndex, nsXPTCStubBase* self, PRUint32* args)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info = NULL;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+ if (!iface_info)
+ return NS_ERROR_UNEXPECTED;
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (!info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ dp->val.p = (void*) *ap;
+ switch(type)
+ {
+ case nsXPTType::T_I64 : dp->val.i64 = *((PRInt64*) ap); ap++; break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((PRUint64*)ap); ap++; break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+} // extern "C"
+
+#if defined(__declspec)
+#define SYMBOL_EXPORT(sym) \
+ ".stabs \"" sym ",0=" sym ",code\", 0x6c,0,0,-42\n\t"
+#else
+#define SYMBOL_EXPORT(sym)
+#endif
+
+#define STUB_ENTRY(n) \
+asm(".text\n\t" \
+ ".align 2\n\t" \
+ ".if " #n " < 10\n\t" \
+ ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \
+ ".type " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev,@function\n" \
+ SYMBOL_EXPORT(SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev") \
+ SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 100\n\t" \
+ ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \
+ ".type " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev,@function\n" \
+ SYMBOL_EXPORT(SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev") \
+ SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 1000\n\t" \
+ ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \
+ ".type " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev,@function\n" \
+ SYMBOL_EXPORT(SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev") \
+ SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev:\n\t" \
+ ".else\n\t" \
+ ".err \"stub number " #n " >= 1000 not yet supported\"\n\t" \
+ ".endif\n\t" \
+ "movl $" #n ", %eax\n\t" \
+ "jmp " SYMBOL_UNDERSCORE "SharedStub\n\t" \
+ ".if " #n " < 10\n\t" \
+ ".size " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev,.-" SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \
+ ".elseif " #n " < 100\n\t" \
+ ".size " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev,.-" SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \
+ ".else\n\t" \
+ ".size " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev,.-" SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \
+ ".endif");
+
+// static nsresult SharedStub(PRUint32 methodIndex) __attribute__((regparm(1)))
+asm(".text\n\t"
+ ".align 2\n\t"
+ ".type " SYMBOL_UNDERSCORE "SharedStub,@function\n\t"
+ SYMBOL_UNDERSCORE "SharedStub:\n\t"
+ "leal 0x08(%esp), %ecx\n\t"
+ "movl 0x04(%esp), %edx\n\t"
+ "jmp " SYMBOL_UNDERSCORE "PrepareAndDispatch\n\t"
+ ".size " SYMBOL_UNDERSCORE "SharedStub,.-" SYMBOL_UNDERSCORE "SharedStub");
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+void
+xptc_dummy()
+{
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_os2.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_os2.cpp
new file mode 100644
index 00000000..33e8574a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_os2.cpp
@@ -0,0 +1,195 @@
+/* -*- 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) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * John Fairhurst <john_fairhurst@iname.com>
+ * Henry Sobotka <sobotka@axess.com> added VAC++ support
+ * and fixed emx asm to work with gcc 2.95.2 (Jan. 2000)
+ *
+ * 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 ***** */
+
+/* Implement shared vtbl methods */
+
+#include "xptcprivate.h"
+
+#if !defined (__EMX__) && !defined(__IBMCPP__)
+#error "This code is only for OS/2"
+#endif
+
+// Procedure in xptcall_vacpp.asm
+#ifdef XP_OS2_VACPP
+extern nsresult SetEntryFromIndex(int stubidx);
+#endif
+
+#ifdef XP_OS2_VACPP
+nsresult
+PrepareAndDispatch( nsXPTCStubBase *self, PRUint32 methodIndex,
+ PRUint32 *args)
+#else
+static nsresult
+PrepareAndDispatch( nsXPTCStubBase *self, PRUint32 methodIndex,
+ PRUint32 *args)
+#endif
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ // If anything fails before stackBytesToPop can be set then
+ // the failure is completely catastrophic!
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+#ifdef XP_OS2_VACPP
+ /* If paramCount is > 0, write out the EDX pointer to the
+ space on the stack args[0]. args[-4] is the space on
+ the stack where it was pushed */
+ if (paramCount) {
+ args[0] = args[-4];
+
+ /* If this is the second parameter, or if the first parameter is an
+ 8 byte long long, write out the ECX pointer to the space on the
+ stack args[1]. args[-3] is the space on the stack where it was
+ pushed */
+ nsXPTType type = info->GetParam(0).GetType();
+ if( paramCount > 1 ||
+ type == nsXPTType::T_I64 || type == nsXPTType::T_U64 )
+ {
+ args[1] = args[-3];
+ }
+ }
+#endif
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((PRInt8*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((PRInt16*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((PRInt64*) ap); ap++; break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((PRUint8*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((PRUint16*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((PRUint32*)ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((PRUint64*)ap); ap++; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((PRBool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#ifdef XP_OS2_VACPP
+
+#define STUB_ENTRY(n)
+
+#else
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ register nsresult (*method) (nsXPTCStubBase *, PRUint32, PRUint32 *) = PrepareAndDispatch; \
+ int temp0, temp1; \
+ register nsresult result; \
+ __asm__ __volatile__( \
+ "leal 0x0c(%%ebp), %%ecx\n\t" /* args */ \
+ "pushl %%ecx\n\t" \
+ "pushl $"#n"\n\t" /* method index */ \
+ "movl 0x08(%%ebp), %%ecx\n\t" /* this */ \
+ "pushl %%ecx\n\t" \
+ "call *%%edx\n\t" /* PrepareAndDispatch */ \
+ "addl $12, %%esp" \
+ : "=a" (result), /* %0 */ \
+ "=&c" (temp0), /* %1 */ \
+ "=d" (temp1) /* %2 */ \
+ : "2" (method) /* %2 */ \
+ : "memory" ); \
+ return result; \
+}
+#endif
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPCWrappedJS::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_vacpp.asm b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_vacpp.asm
new file mode 100644
index 00000000..3464a1f9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/os2/xptcstubs_vacpp.asm
@@ -0,0 +1,1563 @@
+COMMENT | -*- Mode: asm; tab-width: 8; 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
+ the Initial Developer. All Rights Reserved.
+
+ Contributor(s):
+ John Fairhurst <john_fairhurst@iname.com>
+ Henry Sobotka <sobotka@axess.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 *****
+ Version 1.0 (the "NPL"); you may not use this file except in
+ compliance with the NPL. You may obtain a copy of the NPL at
+ http://www.mozilla.org/NPL/
+
+ Software distributed under the NPL is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ for the specific language governing rights and limitations under the
+ NPL.
+
+ The Initial Developer of this code under the NPL is Netscape
+ Communications Corporation. Portions created by Netscape are
+ Copyright (C) 1999 Netscape Communications Corporation. All Rights
+ Reserved.
+
+ Contributor: Henry Sobotka <sobotka@axess.com>
+
+ xptcallstub_vacpp.asm: ALP assembler procedure for VAC++ build of xptcall
+ |
+
+ .486P
+ .MODEL FLAT, OPTLINK
+ .STACK
+
+ .CODE
+
+ EXTERN OPTLINK PrepareAndDispatch__FP14nsXPTCStubBaseUiPUi:PROC
+
+setentidx MACRO index
+
+ push ecx ; Save parameters
+ push edx ; Save parameters - don't need to save eax - it is the "this" ptr
+ lea ecx, dword ptr [esp+10h] ; Load pointer to "args" into ecx
+ mov edx, index ; Move vtable index into edx
+ sub esp, 0ch ; Make room for three parameters on the stack
+ call PrepareAndDispatch__FP14nsXPTCStubBaseUiPUi
+ add esp, 14h ; Reset stack pointer
+ ret
+ ENDM
+
+; 251 STUB_ENTRY(249)
+
+Stub249__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0f9h
+Stub249__14nsXPTCStubBaseFv endp
+
+; 250 STUB_ENTRY(248)
+
+Stub248__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0f8h
+Stub248__14nsXPTCStubBaseFv endp
+
+; 249 STUB_ENTRY(247)
+
+Stub247__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0f7h
+Stub247__14nsXPTCStubBaseFv endp
+
+; 248 STUB_ENTRY(246)
+
+Stub246__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0f6h
+Stub246__14nsXPTCStubBaseFv endp
+
+; 247 STUB_ENTRY(245)
+
+Stub245__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0f5h
+Stub245__14nsXPTCStubBaseFv endp
+
+; 246 STUB_ENTRY(244)
+
+Stub244__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0f4h
+Stub244__14nsXPTCStubBaseFv endp
+
+; 245 STUB_ENTRY(243)
+
+Stub243__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0f3h
+Stub243__14nsXPTCStubBaseFv endp
+
+; 244 STUB_ENTRY(242)
+
+Stub242__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0f2h
+Stub242__14nsXPTCStubBaseFv endp
+
+; 243 STUB_ENTRY(241)
+
+Stub241__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0f1h
+Stub241__14nsXPTCStubBaseFv endp
+
+; 242 STUB_ENTRY(240)
+
+Stub240__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0f0h
+Stub240__14nsXPTCStubBaseFv endp
+
+; 241 STUB_ENTRY(239)
+
+Stub239__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0efh
+Stub239__14nsXPTCStubBaseFv endp
+
+; 240 STUB_ENTRY(238)
+
+Stub238__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0eeh
+Stub238__14nsXPTCStubBaseFv endp
+
+; 239 STUB_ENTRY(237)
+
+Stub237__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0edh
+Stub237__14nsXPTCStubBaseFv endp
+
+; 238 STUB_ENTRY(236)
+
+Stub236__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0ech
+Stub236__14nsXPTCStubBaseFv endp
+
+; 237 STUB_ENTRY(235)
+
+Stub235__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0ebh
+Stub235__14nsXPTCStubBaseFv endp
+
+; 236 STUB_ENTRY(234)
+
+Stub234__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0eah
+Stub234__14nsXPTCStubBaseFv endp
+
+; 235 STUB_ENTRY(233)
+
+Stub233__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0e9h
+Stub233__14nsXPTCStubBaseFv endp
+
+; 234 STUB_ENTRY(232)
+
+Stub232__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0e8h
+Stub232__14nsXPTCStubBaseFv endp
+
+; 233 STUB_ENTRY(231)
+
+Stub231__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0e7h
+Stub231__14nsXPTCStubBaseFv endp
+
+; 232 STUB_ENTRY(230)
+
+Stub230__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0e6h
+Stub230__14nsXPTCStubBaseFv endp
+
+; 231 STUB_ENTRY(229)
+
+Stub229__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0e5h
+Stub229__14nsXPTCStubBaseFv endp
+
+; 230 STUB_ENTRY(228)
+
+Stub228__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0e4h
+Stub228__14nsXPTCStubBaseFv endp
+
+; 229 STUB_ENTRY(227)
+
+Stub227__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0e3h
+Stub227__14nsXPTCStubBaseFv endp
+
+; 228 STUB_ENTRY(226)
+
+Stub226__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0e2h
+Stub226__14nsXPTCStubBaseFv endp
+
+; 227 STUB_ENTRY(225)
+
+Stub225__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0e1h
+Stub225__14nsXPTCStubBaseFv endp
+
+; 226 STUB_ENTRY(224)
+
+Stub224__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0e0h
+Stub224__14nsXPTCStubBaseFv endp
+
+; 225 STUB_ENTRY(223)
+
+Stub223__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0dfh
+Stub223__14nsXPTCStubBaseFv endp
+
+; 224 STUB_ENTRY(222)
+
+Stub222__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0deh
+Stub222__14nsXPTCStubBaseFv endp
+
+; 223 STUB_ENTRY(221)
+
+Stub221__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0ddh
+Stub221__14nsXPTCStubBaseFv endp
+
+; 222 STUB_ENTRY(220)
+
+Stub220__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0dch
+Stub220__14nsXPTCStubBaseFv endp
+
+; 221 STUB_ENTRY(219)
+
+Stub219__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0dbh
+Stub219__14nsXPTCStubBaseFv endp
+
+; 220 STUB_ENTRY(218)
+
+Stub218__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0dah
+Stub218__14nsXPTCStubBaseFv endp
+
+; 219 STUB_ENTRY(217)
+
+Stub217__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0d9h
+Stub217__14nsXPTCStubBaseFv endp
+
+; 218 STUB_ENTRY(216)
+
+Stub216__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0d8h
+Stub216__14nsXPTCStubBaseFv endp
+
+; 217 STUB_ENTRY(215)
+
+Stub215__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0d7h
+Stub215__14nsXPTCStubBaseFv endp
+
+; 216 STUB_ENTRY(214)
+
+Stub214__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0d6h
+Stub214__14nsXPTCStubBaseFv endp
+
+; 215 STUB_ENTRY(213)
+
+Stub213__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0d5h
+Stub213__14nsXPTCStubBaseFv endp
+
+; 214 STUB_ENTRY(212)
+
+Stub212__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0d4h
+Stub212__14nsXPTCStubBaseFv endp
+
+; 213 STUB_ENTRY(211)
+
+Stub211__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0d3h
+Stub211__14nsXPTCStubBaseFv endp
+
+; 212 STUB_ENTRY(210)
+
+Stub210__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0d2h
+Stub210__14nsXPTCStubBaseFv endp
+
+; 211 STUB_ENTRY(209)
+
+Stub209__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0d1h
+Stub209__14nsXPTCStubBaseFv endp
+
+; 210 STUB_ENTRY(208)
+
+Stub208__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0d0h
+Stub208__14nsXPTCStubBaseFv endp
+
+; 209 STUB_ENTRY(207)
+
+Stub207__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0cfh
+Stub207__14nsXPTCStubBaseFv endp
+
+; 208 STUB_ENTRY(206)
+
+Stub206__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0ceh
+Stub206__14nsXPTCStubBaseFv endp
+
+; 207 STUB_ENTRY(205)
+
+Stub205__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0cdh
+Stub205__14nsXPTCStubBaseFv endp
+
+; 206 STUB_ENTRY(204)
+
+Stub204__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0cch
+Stub204__14nsXPTCStubBaseFv endp
+
+; 205 STUB_ENTRY(203)
+
+Stub203__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0cbh
+Stub203__14nsXPTCStubBaseFv endp
+
+; 204 STUB_ENTRY(202)
+
+Stub202__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0cah
+Stub202__14nsXPTCStubBaseFv endp
+
+; 203 STUB_ENTRY(201)
+
+Stub201__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0c9h
+Stub201__14nsXPTCStubBaseFv endp
+
+; 202 STUB_ENTRY(200)
+
+Stub200__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0c8h
+Stub200__14nsXPTCStubBaseFv endp
+
+; 201 STUB_ENTRY(199)
+
+Stub199__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0c7h
+Stub199__14nsXPTCStubBaseFv endp
+
+; 200 STUB_ENTRY(198)
+
+Stub198__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0c6h
+Stub198__14nsXPTCStubBaseFv endp
+
+; 199 STUB_ENTRY(197)
+
+Stub197__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0c5h
+Stub197__14nsXPTCStubBaseFv endp
+
+; 198 STUB_ENTRY(196)
+
+Stub196__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0c4h
+Stub196__14nsXPTCStubBaseFv endp
+
+; 197 STUB_ENTRY(195)
+
+Stub195__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0c3h
+Stub195__14nsXPTCStubBaseFv endp
+
+; 196 STUB_ENTRY(194)
+
+Stub194__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0c2h
+Stub194__14nsXPTCStubBaseFv endp
+
+; 195 STUB_ENTRY(193)
+
+Stub193__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0c1h
+Stub193__14nsXPTCStubBaseFv endp
+
+; 194 STUB_ENTRY(192)
+
+Stub192__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0c0h
+Stub192__14nsXPTCStubBaseFv endp
+
+; 193 STUB_ENTRY(191)
+
+Stub191__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0bfh
+Stub191__14nsXPTCStubBaseFv endp
+
+; 192 STUB_ENTRY(190)
+
+Stub190__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0beh
+Stub190__14nsXPTCStubBaseFv endp
+
+; 191 STUB_ENTRY(189)
+
+Stub189__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0bdh
+Stub189__14nsXPTCStubBaseFv endp
+
+; 190 STUB_ENTRY(188)
+
+Stub188__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0bch
+Stub188__14nsXPTCStubBaseFv endp
+
+; 189 STUB_ENTRY(187)
+
+Stub187__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0bbh
+Stub187__14nsXPTCStubBaseFv endp
+
+; 188 STUB_ENTRY(186)
+
+Stub186__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0bah
+Stub186__14nsXPTCStubBaseFv endp
+
+; 187 STUB_ENTRY(185)
+
+Stub185__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0b9h
+Stub185__14nsXPTCStubBaseFv endp
+
+; 186 STUB_ENTRY(184)
+
+Stub184__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0b8h
+Stub184__14nsXPTCStubBaseFv endp
+
+; 185 STUB_ENTRY(183)
+
+Stub183__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0b7h
+Stub183__14nsXPTCStubBaseFv endp
+
+; 184 STUB_ENTRY(182)
+
+Stub182__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0b6h
+Stub182__14nsXPTCStubBaseFv endp
+
+; 183 STUB_ENTRY(181)
+
+Stub181__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0b5h
+Stub181__14nsXPTCStubBaseFv endp
+
+; 182 STUB_ENTRY(180)
+
+Stub180__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0b4h
+Stub180__14nsXPTCStubBaseFv endp
+
+; 181 STUB_ENTRY(179)
+
+Stub179__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0b3h
+Stub179__14nsXPTCStubBaseFv endp
+
+; 180 STUB_ENTRY(178)
+
+Stub178__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0b2h
+Stub178__14nsXPTCStubBaseFv endp
+
+; 179 STUB_ENTRY(177)
+
+Stub177__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0b1h
+Stub177__14nsXPTCStubBaseFv endp
+
+; 178 STUB_ENTRY(176)
+
+Stub176__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0b0h
+Stub176__14nsXPTCStubBaseFv endp
+
+; 177 STUB_ENTRY(175)
+
+Stub175__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0afh
+Stub175__14nsXPTCStubBaseFv endp
+
+; 176 STUB_ENTRY(174)
+
+Stub174__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0aeh
+Stub174__14nsXPTCStubBaseFv endp
+
+; 175 STUB_ENTRY(173)
+
+Stub173__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0adh
+Stub173__14nsXPTCStubBaseFv endp
+
+; 174 STUB_ENTRY(172)
+
+Stub172__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0ach
+Stub172__14nsXPTCStubBaseFv endp
+
+; 173 STUB_ENTRY(171)
+
+Stub171__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0abh
+Stub171__14nsXPTCStubBaseFv endp
+
+; 172 STUB_ENTRY(170)
+
+Stub170__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0aah
+Stub170__14nsXPTCStubBaseFv endp
+
+; 171 STUB_ENTRY(169)
+
+Stub169__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0a9h
+Stub169__14nsXPTCStubBaseFv endp
+
+; 170 STUB_ENTRY(168)
+
+Stub168__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0a8h
+Stub168__14nsXPTCStubBaseFv endp
+
+; 169 STUB_ENTRY(167)
+
+Stub167__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0a7h
+Stub167__14nsXPTCStubBaseFv endp
+
+; 168 STUB_ENTRY(166)
+
+Stub166__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0a6h
+Stub166__14nsXPTCStubBaseFv endp
+
+; 167 STUB_ENTRY(165)
+
+Stub165__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0a5h
+Stub165__14nsXPTCStubBaseFv endp
+
+; 166 STUB_ENTRY(164)
+
+Stub164__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0a4h
+Stub164__14nsXPTCStubBaseFv endp
+
+; 165 STUB_ENTRY(163)
+
+Stub163__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0a3h
+Stub163__14nsXPTCStubBaseFv endp
+
+; 164 STUB_ENTRY(162)
+
+Stub162__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0a2h
+Stub162__14nsXPTCStubBaseFv endp
+
+; 163 STUB_ENTRY(161)
+
+Stub161__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0a1h
+Stub161__14nsXPTCStubBaseFv endp
+
+; 162 STUB_ENTRY(160)
+
+Stub160__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0a0h
+Stub160__14nsXPTCStubBaseFv endp
+
+; 161 STUB_ENTRY(159)
+
+Stub159__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 09fh
+Stub159__14nsXPTCStubBaseFv endp
+
+; 160 STUB_ENTRY(158)
+
+Stub158__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 09eh
+Stub158__14nsXPTCStubBaseFv endp
+
+; 159 STUB_ENTRY(157)
+
+Stub157__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 09dh
+Stub157__14nsXPTCStubBaseFv endp
+
+; 158 STUB_ENTRY(156)
+
+Stub156__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 09ch
+Stub156__14nsXPTCStubBaseFv endp
+
+; 157 STUB_ENTRY(155)
+
+Stub155__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 09bh
+Stub155__14nsXPTCStubBaseFv endp
+
+; 156 STUB_ENTRY(154)
+
+Stub154__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 09ah
+Stub154__14nsXPTCStubBaseFv endp
+
+; 155 STUB_ENTRY(153)
+
+Stub153__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 099h
+Stub153__14nsXPTCStubBaseFv endp
+
+; 154 STUB_ENTRY(152)
+
+Stub152__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 098h
+Stub152__14nsXPTCStubBaseFv endp
+
+; 153 STUB_ENTRY(151)
+
+Stub151__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 097h
+Stub151__14nsXPTCStubBaseFv endp
+
+; 152 STUB_ENTRY(150)
+
+Stub150__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 096h
+Stub150__14nsXPTCStubBaseFv endp
+
+; 151 STUB_ENTRY(149)
+
+Stub149__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 095h
+Stub149__14nsXPTCStubBaseFv endp
+
+; 150 STUB_ENTRY(148)
+
+Stub148__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 094h
+Stub148__14nsXPTCStubBaseFv endp
+
+; 149 STUB_ENTRY(147)
+
+Stub147__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 093h
+Stub147__14nsXPTCStubBaseFv endp
+
+; 148 STUB_ENTRY(146)
+
+Stub146__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 092h
+Stub146__14nsXPTCStubBaseFv endp
+
+; 147 STUB_ENTRY(145)
+
+Stub145__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 091h
+Stub145__14nsXPTCStubBaseFv endp
+
+; 146 STUB_ENTRY(144)
+
+Stub144__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 090h
+Stub144__14nsXPTCStubBaseFv endp
+
+; 145 STUB_ENTRY(143)
+
+Stub143__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 08fh
+Stub143__14nsXPTCStubBaseFv endp
+
+; 144 STUB_ENTRY(142)
+
+Stub142__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 08eh
+Stub142__14nsXPTCStubBaseFv endp
+
+; 143 STUB_ENTRY(141)
+
+Stub141__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 08dh
+Stub141__14nsXPTCStubBaseFv endp
+
+; 142 STUB_ENTRY(140)
+
+Stub140__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 08ch
+Stub140__14nsXPTCStubBaseFv endp
+
+; 141 STUB_ENTRY(139)
+
+Stub139__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 08bh
+Stub139__14nsXPTCStubBaseFv endp
+
+; 140 STUB_ENTRY(138)
+
+Stub138__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 08ah
+Stub138__14nsXPTCStubBaseFv endp
+
+; 139 STUB_ENTRY(137)
+
+Stub137__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 089h
+Stub137__14nsXPTCStubBaseFv endp
+
+; 138 STUB_ENTRY(136)
+
+Stub136__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 088h
+Stub136__14nsXPTCStubBaseFv endp
+
+; 137 STUB_ENTRY(135)
+
+Stub135__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 087h
+Stub135__14nsXPTCStubBaseFv endp
+
+; 136 STUB_ENTRY(134)
+
+Stub134__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 086h
+Stub134__14nsXPTCStubBaseFv endp
+
+; 135 STUB_ENTRY(133)
+
+Stub133__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 085h
+Stub133__14nsXPTCStubBaseFv endp
+
+; 134 STUB_ENTRY(132)
+
+Stub132__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 084h
+Stub132__14nsXPTCStubBaseFv endp
+
+; 133 STUB_ENTRY(131)
+
+Stub131__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 083h
+Stub131__14nsXPTCStubBaseFv endp
+
+; 132 STUB_ENTRY(130)
+
+Stub130__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 082h
+Stub130__14nsXPTCStubBaseFv endp
+
+; 131 STUB_ENTRY(129)
+
+Stub129__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 081h
+Stub129__14nsXPTCStubBaseFv endp
+
+; 130 STUB_ENTRY(128)
+
+Stub128__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 080h
+Stub128__14nsXPTCStubBaseFv endp
+
+; 129 STUB_ENTRY(127)
+
+Stub127__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 07fh
+Stub127__14nsXPTCStubBaseFv endp
+
+; 128 STUB_ENTRY(126)
+
+Stub126__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 07eh
+Stub126__14nsXPTCStubBaseFv endp
+
+; 127 STUB_ENTRY(125)
+
+Stub125__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 07dh
+Stub125__14nsXPTCStubBaseFv endp
+
+; 126 STUB_ENTRY(124)
+
+Stub124__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 07ch
+Stub124__14nsXPTCStubBaseFv endp
+
+; 125 STUB_ENTRY(123)
+
+Stub123__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 07bh
+Stub123__14nsXPTCStubBaseFv endp
+
+; 124 STUB_ENTRY(122)
+
+Stub122__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 07ah
+Stub122__14nsXPTCStubBaseFv endp
+
+; 123 STUB_ENTRY(121)
+
+Stub121__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 079h
+Stub121__14nsXPTCStubBaseFv endp
+
+; 122 STUB_ENTRY(120)
+
+Stub120__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 078h
+Stub120__14nsXPTCStubBaseFv endp
+
+; 121 STUB_ENTRY(119)
+
+Stub119__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 077h
+Stub119__14nsXPTCStubBaseFv endp
+
+; 120 STUB_ENTRY(118)
+
+Stub118__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 076h
+Stub118__14nsXPTCStubBaseFv endp
+
+; 119 STUB_ENTRY(117)
+
+Stub117__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 075h
+Stub117__14nsXPTCStubBaseFv endp
+
+; 118 STUB_ENTRY(116)
+
+Stub116__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 074h
+Stub116__14nsXPTCStubBaseFv endp
+
+; 117 STUB_ENTRY(115)
+
+Stub115__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 073h
+Stub115__14nsXPTCStubBaseFv endp
+
+; 116 STUB_ENTRY(114)
+
+Stub114__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 072h
+Stub114__14nsXPTCStubBaseFv endp
+
+; 115 STUB_ENTRY(113)
+
+Stub113__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 071h
+Stub113__14nsXPTCStubBaseFv endp
+
+; 114 STUB_ENTRY(112)
+
+Stub112__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 070h
+Stub112__14nsXPTCStubBaseFv endp
+
+; 113 STUB_ENTRY(111)
+
+Stub111__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 06fh
+Stub111__14nsXPTCStubBaseFv endp
+
+; 112 STUB_ENTRY(110)
+
+Stub110__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 06eh
+Stub110__14nsXPTCStubBaseFv endp
+
+; 111 STUB_ENTRY(109)
+
+Stub109__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 06dh
+Stub109__14nsXPTCStubBaseFv endp
+
+; 110 STUB_ENTRY(108)
+
+Stub108__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 06ch
+Stub108__14nsXPTCStubBaseFv endp
+
+; 109 STUB_ENTRY(107)
+
+Stub107__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 06bh
+Stub107__14nsXPTCStubBaseFv endp
+
+; 108 STUB_ENTRY(106)
+
+Stub106__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 06ah
+Stub106__14nsXPTCStubBaseFv endp
+
+; 107 STUB_ENTRY(105)
+
+Stub105__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 069h
+Stub105__14nsXPTCStubBaseFv endp
+
+; 106 STUB_ENTRY(104)
+
+Stub104__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 068h
+Stub104__14nsXPTCStubBaseFv endp
+
+; 105 STUB_ENTRY(103)
+
+Stub103__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 067h
+Stub103__14nsXPTCStubBaseFv endp
+
+; 104 STUB_ENTRY(102)
+
+Stub102__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 066h
+Stub102__14nsXPTCStubBaseFv endp
+
+; 103 STUB_ENTRY(101)
+
+Stub101__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 065h
+Stub101__14nsXPTCStubBaseFv endp
+
+; 102 STUB_ENTRY(100)
+
+Stub100__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 064h
+Stub100__14nsXPTCStubBaseFv endp
+
+; 101 STUB_ENTRY(99)
+
+Stub99__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 063h
+Stub99__14nsXPTCStubBaseFv endp
+
+; 100 STUB_ENTRY(98)
+
+Stub98__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 062h
+Stub98__14nsXPTCStubBaseFv endp
+
+; 99 STUB_ENTRY(97)
+
+Stub97__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 061h
+Stub97__14nsXPTCStubBaseFv endp
+
+; 98 STUB_ENTRY(96)
+
+Stub96__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 060h
+Stub96__14nsXPTCStubBaseFv endp
+
+; 97 STUB_ENTRY(95)
+
+Stub95__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 05fh
+Stub95__14nsXPTCStubBaseFv endp
+
+; 96 STUB_ENTRY(94)
+
+Stub94__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 05eh
+Stub94__14nsXPTCStubBaseFv endp
+
+; 95 STUB_ENTRY(93)
+
+Stub93__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 05dh
+Stub93__14nsXPTCStubBaseFv endp
+
+; 94 STUB_ENTRY(92)
+
+Stub92__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 05ch
+Stub92__14nsXPTCStubBaseFv endp
+
+; 93 STUB_ENTRY(91)
+
+Stub91__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 05bh
+Stub91__14nsXPTCStubBaseFv endp
+
+; 92 STUB_ENTRY(90)
+
+Stub90__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 05ah
+Stub90__14nsXPTCStubBaseFv endp
+
+; 91 STUB_ENTRY(89)
+
+Stub89__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 059h
+Stub89__14nsXPTCStubBaseFv endp
+
+; 90 STUB_ENTRY(88)
+
+Stub88__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 058h
+Stub88__14nsXPTCStubBaseFv endp
+
+; 89 STUB_ENTRY(87)
+
+Stub87__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 057h
+Stub87__14nsXPTCStubBaseFv endp
+
+; 88 STUB_ENTRY(86)
+
+Stub86__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 056h
+Stub86__14nsXPTCStubBaseFv endp
+
+; 87 STUB_ENTRY(85)
+
+Stub85__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 055h
+Stub85__14nsXPTCStubBaseFv endp
+
+; 86 STUB_ENTRY(84)
+
+Stub84__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 054h
+Stub84__14nsXPTCStubBaseFv endp
+
+; 85 STUB_ENTRY(83)
+
+Stub83__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 053h
+Stub83__14nsXPTCStubBaseFv endp
+
+; 84 STUB_ENTRY(82)
+
+Stub82__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 052h
+Stub82__14nsXPTCStubBaseFv endp
+
+; 83 STUB_ENTRY(81)
+
+Stub81__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 051h
+Stub81__14nsXPTCStubBaseFv endp
+
+; 82 STUB_ENTRY(80)
+
+Stub80__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 050h
+Stub80__14nsXPTCStubBaseFv endp
+
+; 81 STUB_ENTRY(79)
+
+Stub79__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 04fh
+Stub79__14nsXPTCStubBaseFv endp
+
+; 80 STUB_ENTRY(78)
+
+Stub78__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 04eh
+Stub78__14nsXPTCStubBaseFv endp
+
+; 79 STUB_ENTRY(77)
+
+Stub77__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 04dh
+Stub77__14nsXPTCStubBaseFv endp
+
+; 78 STUB_ENTRY(76)
+
+Stub76__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 04ch
+Stub76__14nsXPTCStubBaseFv endp
+
+; 77 STUB_ENTRY(75)
+
+Stub75__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 04bh
+Stub75__14nsXPTCStubBaseFv endp
+
+; 76 STUB_ENTRY(74)
+
+Stub74__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 04ah
+Stub74__14nsXPTCStubBaseFv endp
+
+; 75 STUB_ENTRY(73)
+
+Stub73__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 049h
+Stub73__14nsXPTCStubBaseFv endp
+
+; 74 STUB_ENTRY(72)
+
+Stub72__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 048h
+Stub72__14nsXPTCStubBaseFv endp
+
+; 73 STUB_ENTRY(71)
+
+Stub71__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 047h
+Stub71__14nsXPTCStubBaseFv endp
+
+; 72 STUB_ENTRY(70)
+
+Stub70__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 046h
+Stub70__14nsXPTCStubBaseFv endp
+
+; 71 STUB_ENTRY(69)
+
+Stub69__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 045h
+Stub69__14nsXPTCStubBaseFv endp
+
+; 70 STUB_ENTRY(68)
+
+Stub68__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 044h
+Stub68__14nsXPTCStubBaseFv endp
+
+; 69 STUB_ENTRY(67)
+
+Stub67__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 043h
+Stub67__14nsXPTCStubBaseFv endp
+
+; 68 STUB_ENTRY(66)
+
+Stub66__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 042h
+Stub66__14nsXPTCStubBaseFv endp
+
+; 67 STUB_ENTRY(65)
+
+Stub65__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 041h
+Stub65__14nsXPTCStubBaseFv endp
+
+; 66 STUB_ENTRY(64)
+
+Stub64__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 040h
+Stub64__14nsXPTCStubBaseFv endp
+
+; 65 STUB_ENTRY(63)
+
+Stub63__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 03fh
+Stub63__14nsXPTCStubBaseFv endp
+
+; 64 STUB_ENTRY(62)
+
+Stub62__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 03eh
+Stub62__14nsXPTCStubBaseFv endp
+
+; 63 STUB_ENTRY(61)
+
+Stub61__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 03dh
+Stub61__14nsXPTCStubBaseFv endp
+
+; 62 STUB_ENTRY(60)
+
+Stub60__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 03ch
+Stub60__14nsXPTCStubBaseFv endp
+
+; 61 STUB_ENTRY(59)
+
+Stub59__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 03bh
+Stub59__14nsXPTCStubBaseFv endp
+
+; 60 STUB_ENTRY(58)
+
+Stub58__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 03ah
+Stub58__14nsXPTCStubBaseFv endp
+
+; 59 STUB_ENTRY(57)
+
+Stub57__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 039h
+Stub57__14nsXPTCStubBaseFv endp
+
+; 58 STUB_ENTRY(56)
+
+Stub56__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 038h
+Stub56__14nsXPTCStubBaseFv endp
+
+; 57 STUB_ENTRY(55)
+
+Stub55__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 037h
+Stub55__14nsXPTCStubBaseFv endp
+
+; 56 STUB_ENTRY(54)
+
+Stub54__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 036h
+Stub54__14nsXPTCStubBaseFv endp
+
+; 55 STUB_ENTRY(53)
+
+Stub53__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 035h
+Stub53__14nsXPTCStubBaseFv endp
+
+; 54 STUB_ENTRY(52)
+
+Stub52__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 034h
+Stub52__14nsXPTCStubBaseFv endp
+
+; 53 STUB_ENTRY(51)
+
+Stub51__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 033h
+Stub51__14nsXPTCStubBaseFv endp
+
+; 52 STUB_ENTRY(50)
+
+Stub50__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 032h
+Stub50__14nsXPTCStubBaseFv endp
+
+; 51 STUB_ENTRY(49)
+
+Stub49__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 031h
+Stub49__14nsXPTCStubBaseFv endp
+
+; 50 STUB_ENTRY(48)
+
+Stub48__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 030h
+Stub48__14nsXPTCStubBaseFv endp
+
+; 49 STUB_ENTRY(47)
+
+Stub47__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 02fh
+Stub47__14nsXPTCStubBaseFv endp
+
+; 48 STUB_ENTRY(46)
+
+Stub46__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 02eh
+Stub46__14nsXPTCStubBaseFv endp
+
+; 47 STUB_ENTRY(45)
+
+Stub45__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 02dh
+Stub45__14nsXPTCStubBaseFv endp
+
+; 46 STUB_ENTRY(44)
+
+Stub44__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 02ch
+Stub44__14nsXPTCStubBaseFv endp
+
+; 45 STUB_ENTRY(43)
+
+Stub43__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 02bh
+Stub43__14nsXPTCStubBaseFv endp
+
+; 44 STUB_ENTRY(42)
+
+Stub42__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 02ah
+Stub42__14nsXPTCStubBaseFv endp
+
+; 43 STUB_ENTRY(41)
+
+Stub41__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 029h
+Stub41__14nsXPTCStubBaseFv endp
+
+; 42 STUB_ENTRY(40)
+
+Stub40__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 028h
+Stub40__14nsXPTCStubBaseFv endp
+
+; 41 STUB_ENTRY(39)
+
+Stub39__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 027h
+Stub39__14nsXPTCStubBaseFv endp
+
+; 40 STUB_ENTRY(38)
+
+Stub38__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 026h
+Stub38__14nsXPTCStubBaseFv endp
+
+; 39 STUB_ENTRY(37)
+
+Stub37__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 025h
+Stub37__14nsXPTCStubBaseFv endp
+
+; 38 STUB_ENTRY(36)
+
+Stub36__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 024h
+Stub36__14nsXPTCStubBaseFv endp
+
+; 37 STUB_ENTRY(35)
+
+Stub35__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 023h
+Stub35__14nsXPTCStubBaseFv endp
+
+; 36 STUB_ENTRY(34)
+
+Stub34__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 022h
+Stub34__14nsXPTCStubBaseFv endp
+
+; 35 STUB_ENTRY(33)
+
+Stub33__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 021h
+Stub33__14nsXPTCStubBaseFv endp
+
+; 34 STUB_ENTRY(32)
+
+Stub32__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 020h
+Stub32__14nsXPTCStubBaseFv endp
+
+; 33 STUB_ENTRY(31)
+
+Stub31__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 01fh
+Stub31__14nsXPTCStubBaseFv endp
+
+; 32 STUB_ENTRY(30)
+
+Stub30__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 01eh
+Stub30__14nsXPTCStubBaseFv endp
+
+; 31 STUB_ENTRY(29)
+
+Stub29__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 01dh
+Stub29__14nsXPTCStubBaseFv endp
+
+; 30 STUB_ENTRY(28)
+
+Stub28__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 01ch
+Stub28__14nsXPTCStubBaseFv endp
+
+; 29 STUB_ENTRY(27)
+
+Stub27__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 01bh
+Stub27__14nsXPTCStubBaseFv endp
+
+; 28 STUB_ENTRY(26)
+
+Stub26__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 01ah
+Stub26__14nsXPTCStubBaseFv endp
+
+; 27 STUB_ENTRY(25)
+
+Stub25__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 019h
+Stub25__14nsXPTCStubBaseFv endp
+
+; 26 STUB_ENTRY(24)
+
+Stub24__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 018h
+Stub24__14nsXPTCStubBaseFv endp
+
+; 25 STUB_ENTRY(23)
+
+Stub23__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 017h
+Stub23__14nsXPTCStubBaseFv endp
+
+; 24 STUB_ENTRY(22)
+
+Stub22__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 016h
+Stub22__14nsXPTCStubBaseFv endp
+
+; 23 STUB_ENTRY(21)
+
+Stub21__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 015h
+Stub21__14nsXPTCStubBaseFv endp
+
+; 22 STUB_ENTRY(20)
+
+Stub20__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 014h
+Stub20__14nsXPTCStubBaseFv endp
+
+; 21 STUB_ENTRY(19)
+
+Stub19__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 013h
+Stub19__14nsXPTCStubBaseFv endp
+
+; 20 STUB_ENTRY(18)
+
+Stub18__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 012h
+Stub18__14nsXPTCStubBaseFv endp
+
+; 19 STUB_ENTRY(17)
+
+Stub17__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 011h
+Stub17__14nsXPTCStubBaseFv endp
+
+; 18 STUB_ENTRY(16)
+
+Stub16__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 010h
+Stub16__14nsXPTCStubBaseFv endp
+
+; 17 STUB_ENTRY(15)
+
+Stub15__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0fh
+Stub15__14nsXPTCStubBaseFv endp
+
+; 16 STUB_ENTRY(14)
+
+Stub14__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0eh
+Stub14__14nsXPTCStubBaseFv endp
+
+; 15 STUB_ENTRY(13)
+
+Stub13__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0dh
+Stub13__14nsXPTCStubBaseFv endp
+
+; 14 STUB_ENTRY(12)
+
+Stub12__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0ch
+Stub12__14nsXPTCStubBaseFv endp
+
+; 13 STUB_ENTRY(11)
+
+Stub11__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0bh
+Stub11__14nsXPTCStubBaseFv endp
+
+; 12 STUB_ENTRY(10)
+
+Stub10__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 0ah
+Stub10__14nsXPTCStubBaseFv endp
+
+; 11 STUB_ENTRY(9)
+
+Stub9__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 09h
+Stub9__14nsXPTCStubBaseFv endp
+
+; 10 STUB_ENTRY(8)
+
+Stub8__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 08h
+Stub8__14nsXPTCStubBaseFv endp
+
+; 9 STUB_ENTRY(7)
+
+Stub7__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 07h
+Stub7__14nsXPTCStubBaseFv endp
+
+; 8 STUB_ENTRY(6)
+
+Stub6__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 06h
+Stub6__14nsXPTCStubBaseFv endp
+
+; 7 STUB_ENTRY(5)
+
+Stub5__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 05h
+Stub5__14nsXPTCStubBaseFv endp
+
+; 6 STUB_ENTRY(4)
+
+Stub4__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 04h
+Stub4__14nsXPTCStubBaseFv endp
+
+; 5 STUB_ENTRY(3)
+
+Stub3__14nsXPTCStubBaseFv PROC OPTLINK EXPORT
+ setentidx 03h
+Stub3__14nsXPTCStubBaseFv endp
+
+
+ END
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/.cvsignore
new file mode 100644
index 00000000..055e647f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+invoke_test
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/Makefile.in
new file mode 100644
index 00000000..dbf0f64d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/Makefile.in
@@ -0,0 +1,50 @@
+#
+# ***** 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
+CPPSRCS = stub_test.cpp #invoke_test.cpp
+SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/README b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/README
new file mode 100644
index 00000000..04850b2e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/README
@@ -0,0 +1,6 @@
+These are just simple test programs in which stripped down versions of the
+XPConnect invoke and stubs code can be built and tested as the code is brought
+up on various platforms. These probrams do not test the param sizing and copying
+functionality of the routines. However, they do supply a place where the lowest
+level assembly language code can be developed and debugged in the simplest of
+contexts before it is moved into the real routines. \ No newline at end of file
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/clean.bat b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/clean.bat
new file mode 100644
index 00000000..f320e222
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/clean.bat
@@ -0,0 +1,5 @@
+@echo off
+echo deleting intermediate files
+if exist *.obj del *.obj > NUL
+if exist *.ilk del *.ilk > NUL
+if exist *.pdb del *.pdb > NUL \ No newline at end of file
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/invoke_test.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/invoke_test.cpp
new file mode 100644
index 00000000..376ba58f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/invoke_test.cpp
@@ -0,0 +1,239 @@
+/* -*- 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 <stdio.h>
+
+typedef unsigned nsresult;
+typedef unsigned PRUint32;
+typedef unsigned nsXPCVariant;
+
+
+#if defined(WIN32)
+#define NS_IMETHOD virtual nsresult __stdcall
+#define NS_IMETHODIMP nsresult __stdcall
+#else
+#define NS_IMETHOD virtual nsresult
+#define NS_IMETHODIMP nsresult
+#endif
+
+
+class base{
+public:
+ NS_IMETHOD ignored() = 0;
+};
+
+class foo : public base {
+public:
+ NS_IMETHOD callme1(int i, int j) = 0;
+ NS_IMETHOD callme2(int i, int j) = 0;
+ NS_IMETHOD callme3(int i, int j) = 0;
+};
+
+class bar : public foo{
+public:
+ NS_IMETHOD ignored();
+ NS_IMETHOD callme1(int i, int j);
+ NS_IMETHOD callme2(int i, int j);
+ NS_IMETHOD callme3(int i, int j);
+};
+
+/*
+class baz : public base {
+public:
+ NS_IMETHOD ignored();
+ NS_IMETHOD callme1();
+ NS_IMETHOD callme2();
+ NS_IMETHOD callme3();
+ void setfoo(foo* f) {other = f;}
+
+ foo* other;
+};
+NS_IMETHODIMP baz::ignored(){return 0;}
+*/
+
+NS_IMETHODIMP bar::ignored(){return 0;}
+
+NS_IMETHODIMP bar::callme1(int i, int j)
+{
+ printf("called bar::callme1 with: %d %d\n", i, j);
+ return 5;
+}
+
+NS_IMETHODIMP bar::callme2(int i, int j)
+{
+ printf("called bar::callme2 with: %d %d\n", i, j);
+ return 5;
+}
+
+NS_IMETHODIMP bar::callme3(int i, int j)
+{
+ printf("called bar::callme3 with: %d %d\n", i, j);
+ return 5;
+}
+
+void docall(foo* f, int i, int j){
+ f->callme1(i, j);
+}
+
+/***************************************************************************/
+#if defined(WIN32)
+
+static PRUint32 __stdcall
+invoke_count_words(PRUint32 paramCount, nsXPCVariant* s)
+{
+ return paramCount;
+}
+
+static void __stdcall
+invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPCVariant* s)
+{
+ for(PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ *((PRUint32*)d) = *((PRUint32*)s);
+ }
+}
+
+static nsresult __stdcall
+DoInvoke(void* that, PRUint32 index,
+ PRUint32 paramCount, nsXPCVariant* params)
+{
+ __asm {
+ push params
+ push paramCount
+ call invoke_count_words // stdcall, result in eax
+ shl eax,2 // *= 4
+ sub esp,eax // make space for params
+ mov edx,esp
+ push params
+ push paramCount
+ push edx
+ call invoke_copy_to_stack // stdcall
+ mov ecx,that // instance in ecx
+ push ecx // push this
+ mov edx,[ecx] // vtable in edx
+ mov eax,index
+ shl eax,2 // *= 4
+ add edx,eax
+ call [edx] // stdcall, i.e. callee cleans up stack.
+ }
+}
+
+#else
+/***************************************************************************/
+// just Linux_x86 now. Add other later...
+
+static PRUint32
+invoke_count_words(PRUint32 paramCount, nsXPCVariant* s)
+{
+ return paramCount;
+}
+
+static void
+invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPCVariant* s)
+{
+ for(PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ *((PRUint32*)d) = *((PRUint32*)s);
+ }
+}
+
+static nsresult
+DoInvoke(void* that, PRUint32 index,
+ PRUint32 paramCount, nsXPCVariant* params)
+{
+ PRUint32 result;
+ void* fn_count = invoke_count_words;
+ void* fn_copy = invoke_copy_to_stack;
+
+ __asm__ __volatile__(
+ "pushl %4\n\t"
+ "pushl %3\n\t"
+ "movl %5, %%eax\n\t"
+ "call *%%eax\n\t" /* count words */
+ "addl $0x8, %%esp\n\t"
+ "shl $2, %%eax\n\t" /* *= 4 */
+ "subl %%eax, %%esp\n\t" /* make room for params */
+ "movl %%esp, %%edx\n\t"
+ "pushl %4\n\t"
+ "pushl %3\n\t"
+ "pushl %%edx\n\t"
+ "movl %6, %%eax\n\t"
+ "call *%%eax\n\t" /* copy params */
+ "addl $0xc, %%esp\n\t"
+ "movl %1, %%ecx\n\t"
+ "pushl %%ecx\n\t"
+ "movl (%%ecx), %%edx\n\t"
+ "movl %2, %%eax\n\t" /* function index */
+ "shl $2, %%eax\n\t" /* *= 4 */
+ "addl $8, %%eax\n\t" /* += 8 */
+ "addl %%eax, %%edx\n\t"
+ "call *(%%edx)\n\t" /* safe to not cleanup esp */
+ "movl %%eax, %0"
+ : "=g" (result) /* %0 */
+ : "g" (that), /* %1 */
+ "g" (index), /* %2 */
+ "g" (paramCount), /* %3 */
+ "g" (params), /* %4 */
+ "g" (fn_count), /* %5 */
+ "g" (fn_copy) /* %6 */
+ : "ax", "cx", "dx", "memory"
+ );
+
+ return result;
+}
+
+#endif
+/***************************************************************************/
+
+int main()
+{
+ nsXPCVariant params1[2] = {1,2};
+ nsXPCVariant params2[2] = {2,4};
+ nsXPCVariant params3[2] = {3,6};
+
+ foo* a = new bar();
+
+// printf("calling via C++...\n");
+// docall(a, 12, 24);
+
+ printf("calling via ASM...\n");
+ DoInvoke(a, 1, 2, params1);
+ DoInvoke(a, 2, 2, params2);
+ DoInvoke(a, 3, 2, params3);
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/mk_invoke.bat b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/mk_invoke.bat
new file mode 100644
index 00000000..10a9be51
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/mk_invoke.bat
@@ -0,0 +1,9 @@
+@echo off
+@echo deleing old output
+if exist invoke_test.obj del invoke_test.obj > NUL
+if exist invoke_test.ilk del invoke_test.ilk > NUL
+if exist *.pdb del *.pdb > NUL
+if exist invoke_test.exe del invoke_test.exe > NUL
+
+@echo building...
+cl /nologo -Zi -DWIN32 invoke_test.cpp \ No newline at end of file
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/mk_stub.bat b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/mk_stub.bat
new file mode 100644
index 00000000..f9af17af
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/mk_stub.bat
@@ -0,0 +1,9 @@
+@echo off
+@echo deleing old output
+if exist stub_test.obj del stub_test.obj > NUL
+if exist stub_test.ilk del stub_test.ilk > NUL
+if exist *.pdb del *.pdb > NUL
+if exist stub_test.exe del stub_test.exe > NUL
+
+@echo building...
+cl /nologo -Zi -DWIN32 stub_test.cpp \ No newline at end of file
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/stub_test.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/stub_test.cpp
new file mode 100644
index 00000000..10935299
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/test/stub_test.cpp
@@ -0,0 +1,210 @@
+
+#include <stdio.h>
+
+typedef unsigned nsresult;
+typedef unsigned PRUint32;
+typedef unsigned nsXPCVariant;
+
+
+#if defined(WIN32)
+#define NS_IMETHOD virtual nsresult __stdcall
+#define NS_IMETHODIMP nsresult __stdcall
+#else
+#define NS_IMETHOD virtual nsresult
+#define NS_IMETHODIMP nsresult
+#endif
+
+
+class base{
+public:
+ NS_IMETHOD ignored() = 0;
+};
+
+class foo : public base {
+public:
+ NS_IMETHOD callme1(int i, int j) = 0;
+ NS_IMETHOD callme2(int i, int j) = 0;
+ NS_IMETHOD callme3(int i, int j) = 0;
+};
+
+class bar : public foo{
+public:
+ NS_IMETHOD ignored();
+ NS_IMETHOD callme1(int i, int j);
+ NS_IMETHOD callme2(int i, int j);
+ NS_IMETHOD callme3(int i, int j);
+};
+
+class baz : public base {
+public:
+ NS_IMETHOD ignored();
+ NS_IMETHOD callme1();
+ NS_IMETHOD callme2();
+ NS_IMETHOD callme3();
+ void setfoo(foo* f) {other = f;}
+
+ foo* other;
+};
+NS_IMETHODIMP baz::ignored(){return 0;}
+
+NS_IMETHODIMP bar::ignored(){return 0;}
+
+NS_IMETHODIMP bar::callme1(int i, int j)
+{
+ printf("called bar::callme1 with: %d %d\n", i, j);
+ return 15;
+}
+
+NS_IMETHODIMP bar::callme2(int i, int j)
+{
+ printf("called bar::callme2 with: %d %d\n", i, j);
+ return 25;
+}
+
+NS_IMETHODIMP bar::callme3(int i, int j)
+{
+ printf("called bar::callme3 with: %d %d\n", i, j);
+ return 35;
+}
+
+void docall(foo* f, int i, int j){
+ f->callme1(i, j);
+}
+
+/***************************************************************************/
+#if defined(WIN32)
+
+static int __stdcall
+PrepareAndDispatch(baz* self, PRUint32 methodIndex,
+ PRUint32* args, PRUint32* stackBytesToPop)
+{
+ fprintf(stdout, "PrepareAndDispatch (%p, %d, %p)\n",
+ (void*)self, methodIndex, (void*)args);
+ foo* a = self->other;
+ int p1 = (int) *args;
+ int p2 = (int) *(args+1);
+ int out = 0;
+ switch(methodIndex)
+ {
+ case 1: out = a->callme1(p1, p2); break;
+ case 2: out = a->callme2(p1, p2); break;
+ case 3: out = a->callme3(p1, p2); break;
+ }
+ *stackBytesToPop = 2*4;
+ return out;
+}
+
+#ifndef __GNUC__
+static __declspec(naked) void SharedStub(void)
+{
+ __asm {
+ push ebp // set up simple stack frame
+ mov ebp, esp // stack has: ebp/vtbl_index/retaddr/this/args
+ push ecx // make room for a ptr
+ lea eax, [ebp-4] // pointer to stackBytesToPop
+ push eax
+ lea ecx, [ebp+16] // pointer to args
+ push ecx
+ mov edx, [ebp+4] // vtbl_index
+ push edx
+ mov eax, [ebp+12] // this
+ push eax
+ call PrepareAndDispatch
+ mov edx, [ebp+8] // return address
+ mov ecx, [ebp-4] // stackBytesToPop
+ add ecx, 12 // for this, the index, and ret address
+ mov esp, ebp
+ pop ebp
+ add esp, ecx // fix up stack pointer
+ jmp edx // simulate __stdcall return
+ }
+}
+
+// these macros get expanded (many times) in the file #included below
+#define STUB_ENTRY(n) \
+__declspec(naked) nsresult __stdcall baz::callme##n() \
+{ __asm push n __asm jmp SharedStub }
+
+#else /* __GNUC__ */
+
+#define STUB_ENTRY(n) \
+nsresult __stdcall baz::callme##n() \
+{ \
+ PRUint32 *args, stackBytesToPop; \
+ int result = 0; \
+ baz *obj; \
+ __asm__ __volatile__ ( \
+ "leal 0x0c(%%ebp), %0\n\t" /* args */ \
+ "movl 0x08(%%ebp), %1\n\t" /* this */ \
+ : "=r" (args), \
+ "=r" (obj)); \
+ result = PrepareAndDispatch(obj, n, args,&stackBytesToPop); \
+ fprintf(stdout, "stub returning: %d\n", result); \
+ fprintf(stdout, "bytes to pop: %d\n", stackBytesToPop); \
+ return result; \
+}
+
+#endif /* ! __GNUC__ */
+
+#else
+/***************************************************************************/
+// just Linux_x86 now. Add other later...
+
+static int
+PrepareAndDispatch(baz* self, PRUint32 methodIndex, PRUint32* args)
+{
+ foo* a = self->other;
+ int p1 = (int) *args;
+ int p2 = (int) *(args+1);
+ switch(methodIndex)
+ {
+ case 1: a->callme1(p1, p2); break;
+ case 2: a->callme2(p1, p2); break;
+ case 3: a->callme3(p1, p2); break;
+ }
+ return 1;
+}
+
+#define STUB_ENTRY(n) \
+nsresult baz::callme##n() \
+{ \
+ register void* method = PrepareAndDispatch; \
+ register nsresult result; \
+ __asm__ __volatile__( \
+ "leal 0x0c(%%ebp), %%ecx\n\t" /* args */ \
+ "pushl %%ecx\n\t" \
+ "pushl $"#n"\n\t" /* method index */ \
+ "movl 0x08(%%ebp), %%ecx\n\t" /* this */ \
+ "pushl %%ecx\n\t" \
+ "call *%%edx" /* PrepareAndDispatch */ \
+ : "=a" (result) /* %0 */ \
+ : "d" (method) /* %1 */ \
+ : "memory" ); \
+ return result; \
+}
+
+#endif
+/***************************************************************************/
+
+STUB_ENTRY(1)
+STUB_ENTRY(2)
+STUB_ENTRY(3)
+
+int main()
+{
+ foo* a = new bar();
+ baz* b = new baz();
+
+ /* here we make the global 'check for alloc failure' checker happy */
+ if(!a || !b)
+ return 1;
+
+ foo* c = (foo*)b;
+
+ b->setfoo(a);
+ c->callme1(1,2);
+ c->callme2(2,4);
+ c->callme3(3,6);
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/.cvsignore
new file mode 100644
index 00000000..ff6fd9bc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+xptcstubs_asm_mips.s
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/Makefile.in
new file mode 100644
index 00000000..78bf1f92
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/Makefile.in
@@ -0,0 +1,416 @@
+#
+# ***** 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
+LIBRARY_NAME = xptcmd
+
+#
+# The default is this buildable, but non-functioning code.
+#
+CPPSRCS := xptcinvoke_unsupported.cpp xptcstubs_unsupported.cpp
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+include $(topsrcdir)/config/config.mk
+
+######################################################################
+# i386 and beyond
+######################################################################
+#
+# Lots of Unixish x86 flavors
+#
+ifneq (,$(filter FreeBSD NetBSD OpenBSD BSD_OS Darwin,$(OS_ARCH)))
+ifeq (86,$(findstring 86,$(OS_TEST)))
+CPPSRCS := xptcinvoke_unixish_x86.cpp xptcstubs_unixish_x86.cpp
+endif
+endif
+#
+# New code for Linux, et. al., with gcc
+# Migrate other platforms here after testing
+#
+ifneq (,$(filter Linux,$(OS_ARCH)))
+# Linux/x86-64
+ifeq (x86_64,$(OS_TEST))
+CPPSRCS := xptcinvoke_x86_64_linux.cpp xptcstubs_x86_64_linux.cpp
+else
+ifeq (86,$(findstring 86,$(OS_TEST)))
+CPPSRCS := xptcinvoke_gcc_x86_unix.cpp xptcstubs_gcc_x86_unix.cpp
+endif
+endif
+endif
+# IA64 Linux
+ifneq (,$(filter Linux,$(OS_ARCH)))
+ifneq (,$(findstring ia64,$(OS_TEST)))
+CPPSRCS := xptcinvoke_ipf64.cpp xptcstubs_ipf64.cpp
+ASFILES := xptcstubs_asm_ipf64.s xptcinvoke_asm_ipf64.s
+endif
+endif
+#
+# BeOS/Intel (uses the same unixish_x86 code)
+#
+ifeq ($(OS_ARCH)$(OS_TEST),BeOSBePC)
+CPPSRCS := xptcinvoke_unixish_x86.cpp xptcstubs_unixish_x86.cpp
+endif
+#
+# Neutrino/Intel (uses the same unixish_x86 code)
+#
+ifeq ($(OS_TARGET)$(OS_TEST),NTOx86)
+CPPSRCS := xptcinvoke_unixish_x86.cpp xptcstubs_unixish_x86.cpp
+endif
+
+######################################################################
+# Solaris/Intel
+######################################################################
+#
+# Solaris/Intel
+#
+ifeq ($(OS_ARCH),SunOS)
+ifeq ($(OS_TEST),i86pc)
+CPPSRCS := xptcinvoke_x86_solaris.cpp xptcstubs_x86_solaris.cpp
+# 28817: if Solaris Intel OS, and native compiler, always build optimised.
+ifndef GNU_CC
+CXXFLAGS += -O
+endif
+endif
+endif
+
+######################################################################
+# Alpha
+######################################################################
+#
+# Tru64/Alpha
+#
+ifeq ($(OS_ARCH)$(OS_TEST),OSF1alpha)
+CPPSRCS := xptcinvoke_osf1_alpha.cpp xptcstubs_osf1_alpha.cpp
+ASFILES := xptcinvoke_asm_osf1_alpha.s xptcstubs_asm_osf1_alpha.s
+endif
+#
+# Linux/Alpha
+#
+ifneq (,$(filter Linuxalpha FreeBSDalpha NetBSDalpha,$(OS_ARCH)$(OS_TEST)))
+CPPSRCS := xptcinvoke_linux_alpha.cpp xptcstubs_linux_alpha.cpp
+endif
+#
+# OpenVMS/Alpha
+#
+ifeq ($(OS_ARCH)$(CPU_ARCH),OpenVMSAlpha)
+CPPSRCS := xptcinvoke_openvms_alpha.cpp xptcstubs_openvms_alpha.cpp
+ASFILES := xptcinvoke_asm_openvms_alpha.s xptcstubs_asm_openvms_alpha.s
+endif
+
+######################################################################
+# ARM
+######################################################################
+#
+# Linux/ARM
+#
+ifeq ($(OS_ARCH),Linux)
+ifneq (,$(filter arm% sa110,$(OS_TEST)))
+CPPSRCS := xptcinvoke_arm.cpp xptcstubs_arm.cpp
+CXXFLAGS += -O2
+endif
+endif
+#
+# NetBSD/ARM
+#
+ifeq ($(OS_ARCH),NetBSD)
+ifneq (,$(filter arm% sa110,$(OS_TEST)))
+CPPSRCS := xptcinvoke_arm_netbsd.cpp xptcstubs_arm_netbsd.cpp
+endif
+endif
+
+######################################################################
+# HPPA
+######################################################################
+#
+# HP-UX/PA32
+#
+# for gas and gcc, check comment in xptcinvoke_asm_pa32.s
+ifeq ($(OS_ARCH),HP-UX)
+ifneq ($(CC),gcc)
+ifneq ($(OS_TEST),ia64)
+CPPSRCS := xptcinvoke_pa32.cpp xptcstubs_pa32.cpp
+ASFILES := xptcstubs_asm_pa32.s xptcinvoke_asm_pa32.s
+else
+CPPSRCS := xptcinvoke_ipf32.cpp xptcstubs_ipf32.cpp
+ASFILES := xptcstubs_asm_ipf32.s xptcinvoke_asm_ipf32.s
+endif
+
+# #18875 Building the CPP's (CXX) optimized causes a crash
+CXXFLAGS := $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(CXXFLAGS))
+endif
+endif
+
+######################################################################
+# M68k
+######################################################################
+#
+# NetBSD/m68k
+#
+ifeq ($(OS_ARCH),NetBSD)
+ifneq (,$(filter amiga atari hp300 mac68k mvme68k next68k sun3 sun3x x68k,$(OS_TEST)))
+CPPSRCS := xptcinvoke_netbsd_m68k.cpp xptcstubs_netbsd_m68k.cpp
+endif
+endif
+
+#
+# Linux/m68k
+#
+ifeq ($(OS_ARCH),Linux)
+ifeq ($(OS_TEST),m68k)
+CPPSRCS := xptcinvoke_linux_m68k.cpp xptcstubs_linux_m68k.cpp
+endif
+endif
+
+######################################################################
+# MIPS
+######################################################################
+#
+# IRIX/MIPS
+#
+ifeq ($(OS_ARCH),IRIX)
+ifneq ($(basename $(OS_RELEASE)),5)
+CPPSRCS := xptcinvoke_irix.cpp xptcstubs_irix.cpp
+ASFILES := xptcinvoke_asm_irix.s xptcstubs_asm_irix.s
+ifdef GNU_CC
+ASFLAGS += -Wa,-D__GNUC__
+else
+CXXFLAGS := $(shell echo $(CXXFLAGS) | sed 's/-O\(3\|fast\)/-O2/g')
+endif
+endif
+endif
+
+ifeq ($(OS_ARCH),Linux)
+ifneq (,$(findstring mips, $(OS_TEST)))
+CPPSRCS := xptcinvoke_mips.cpp xptcstubs_mips.cpp
+ASFILES := xptcinvoke_asm_mips.s xptcstubs_asm_mips.s
+#xptcstubs_mips.cpp
+# xptcstubs_asm_mips.s
+ifdef GNU_CC
+ASFLAGS += $(INCLUDES) -x assembler-with-cpp -D__GNUC__
+endif
+endif
+endif
+
+######################################################################
+# PowerPC
+######################################################################
+#
+# AIX/PPC
+#
+ifeq ($(OS_ARCH),AIX)
+ifdef HAVE_64BIT_OS
+CPPSRCS := xptcinvoke_ppc_aix64.cpp xptcstubs_ppc_aix64.cpp
+ASFILES := xptcinvoke_asm_ppc_aix64.s xptcstubs_asm_ppc_aix64.s
+else
+ifeq ($(AIX_OBJMODEL),ibm)
+CPPSRCS := xptcinvoke_ppc_aix.cpp xptcstubs_ppc_aix.cpp
+ASFILES := xptcinvoke_asm_ppc_ibmobj_aix.s xptcstubs_asm_ppc_aix.s
+else
+CPPSRCS := xptcinvoke_ppc_aix.cpp xptcstubs_ppc_aix.cpp
+ASFILES := xptcinvoke_asm_ppc_aix.s xptcstubs_asm_ppc_aix.s
+endif
+endif
+
+# #24617 Building the CPP's (CXX) optimized causes a crash
+CXXFLAGS := $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(CXXFLAGS))
+endif
+
+#
+# Linux/PPC
+#
+ifeq ($(OS_ARCH)$(OS_TEST),Linuxppc)
+CPPSRCS := xptcinvoke_ppc_linux.cpp xptcstubs_ppc_linux.cpp
+ASFILES := xptcinvoke_asm_ppc_linux.s xptcstubs_asm_ppc_linux.s
+AS := $(CC) -c -x assembler-with-cpp
+endif
+
+#
+# NetBSD/PPC
+#
+ifneq (,$(filter NetBSDmacppc NetBSDbebox NetBSDofppc NetBSDprep NetBSDamigappc,$(OS_ARCH)$(OS_TEST)))
+CPPSRCS := xptcinvoke_ppc_netbsd.cpp xptcstubs_ppc_netbsd.cpp
+ASFILES := xptcinvoke_asm_ppc_netbsd.s xptcstubs_asm_ppc_netbsd.s
+endif
+
+#
+# Darwin/PPC
+#
+ifeq ($(OS_ARCH),Darwin)
+ifeq ($(TARGET_CPU), powerpc)
+ASFLAGS += -x assembler-with-cpp # assumes $(AS) == $(CC)
+ifdef HAVE_GCC3_ABI
+ASFLAGS += -DHAVE_GCC3_ABI
+endif
+CPPSRCS := xptcinvoke_ppc_rhapsody.cpp xptcstubs_ppc_rhapsody.cpp
+ASFILES := xptcinvoke_asm_ppc_rhapsody.s xptcstubs_asm_ppc_darwin.s
+endif
+endif
+
+######################################################################
+# SPARC
+######################################################################
+#
+# BSD_OS/SPARC
+#
+ifeq ($(OS_ARCH),BSD_OS)
+ifneq (,$(findstring sparc,$(OS_TEST)))
+CPPSRCS := xptcinvoke_sparc_solaris.cpp xptcstubs_sparc_solaris.cpp
+ASFILES := xptcinvoke_asm_sparc_bsdos.s xptcstubs_asm_sparc_solaris.s
+endif
+endif
+#
+# Linux/SPARC
+#
+ifeq ($(OS_ARCH),Linux)
+ifneq (,$(findstring sparc,$(OS_TEST)))
+CPPSRCS := xptcinvoke_sparc_solaris.cpp xptcstubs_sparc_solaris.cpp
+ifdef HAVE_GCC3_ABI
+ASFILES := xptcinvoke_asm_sparc_linux_GCC3.s xptcstubs_asm_sparc_solaris.s
+else
+ASFILES := xptcinvoke_asm_sparc_linux.s xptcstubs_asm_sparc_solaris.s
+endif
+endif
+endif
+#
+# NetBSD/SPARC
+#
+ifeq ($(OS_ARCH)$(OS_TEST),NetBSDsparc)
+CPPSRCS := xptcinvoke_sparc_netbsd.cpp xptcstubs_sparc_netbsd.cpp
+ASFILES := xptcinvoke_asm_sparc_netbsd.s xptcstubs_asm_sparc_netbsd.s
+endif
+#
+# Solaris/SPARC
+#
+ifeq ($(OS_ARCH),SunOS)
+ifneq (86,$(findstring 86,$(OS_TEST)))
+ifdef HAVE_64BIT_OS
+CPPSRCS := xptcinvoke_sparcv9_solaris.cpp xptcstubs_sparcv9_solaris.cpp
+else
+CPPSRCS := xptcinvoke_sparc_solaris.cpp xptcstubs_sparc_solaris.cpp
+endif
+
+ifeq ($(GNU_CC),1)
+ifdef HAVE_GCC3_ABI
+ASFILES := xptcinvoke_asm_sparc_solaris_GCC3.s xptcstubs_asm_sparc_solaris.s
+else
+ASFILES := xptcinvoke_asm_sparc_solaris_GCC.s xptcstubs_asm_sparc_solaris.s
+endif
+else
+ifdef HAVE_64BIT_OS
+ASFILES := xptcinvoke_asm_sparcv9_solaris_SUNW.s xptcstubs_asm_sparcv9_solaris.s
+else
+ASFILES := xptcinvoke_asm_sparc_solaris_SUNW.s xptcstubs_asm_sparc_solaris.s
+endif
+endif
+
+endif
+endif
+
+######################################################################
+# S/390
+######################################################################
+#
+# Linux for S/390
+#
+ifeq ($(OS_ARCH)$(OS_TEST),Linuxs390)
+CPPSRCS := xptcinvoke_linux_s390.cpp xptcstubs_linux_s390.cpp
+endif
+
+ifeq ($(OS_ARCH)$(OS_TEST),Linuxs390x)
+CPPSRCS := xptcinvoke_linux_s390x.cpp xptcstubs_linux_s390x.cpp
+endif
+
+
+# we don't want the shared lib, but we want to force the creation of a static lib.
+FORCE_STATIC_LIB = 1
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -DEXPORT_XPTC_API
+
+INCLUDES += -I$(srcdir)/../..
+
+ifeq ($(OS_ARCH),Linux)
+ifneq (,$(findstring mips, $(OS_TEST)))
+xptcstubs_asm_mips.o: xptcstubs_asm_mips.s.m4 $(PUBLIC)/xptcstubsdef.inc
+ m4 $(INCLUDES) $< > ./xptcstubs_asm_mips.s && \
+ $(AS) -o $@ $(ASFLAGS) $(AS_DASH_C_FLAG) ./xptcstubs_asm_mips.s
+ $(RM) -f ./xptcstubs_asm_mips.s
+endif
+endif
+
+ifeq ($(OS_ARCH),Darwin)
+xptcstubs_asm_ppc_darwin.o: xptcstubs_asm_ppc_darwin.s.m4 $(PUBLIC)/xptcstubsdef.inc Makefile
+ gm4 $(INCLUDES) $< > ./xptcstubs_asm_ppc_darwin.s && \
+ $(AS) -o $@ $(ASFLAGS) $(AS_DASH_C_FLAG) ./xptcstubs_asm_ppc_darwin.s
+ $(RM) -f ./xptcstubs_asm_ppc_darwin.s
+endif
+
+ifeq ($(OS_ARCH),IRIX)
+# The assembler on IRIX (6.3 only?) seems to have trouble with the default command,
+# but works fine if we first copy the header and source file into the current dir.
+xptcstubs_asm_irix.o: $(PUBLIC)/xptcstubsdef.inc $(srcdir)/xptcstubs_asm_irix.s
+ @rm -f ./xptcstubsdef.inc
+ @cp $(PUBLIC)/xptcstubsdef.inc .
+ @if test ! -f ./Makefile.in; then rm -f ./xptcstubs_asm_irix.s; cp $(srcdir)/xptcstubs_asm_irix.s .; else true; fi
+ $(AS) -o $@ $(ASFLAGS) $(AS_DASH_C_FLAG) ./xptcstubs_asm_irix.s
+ @rm -f ./xptcstubsdef.inc
+ @if test ! -f ./Makefile.in; then rm -f ./xptcstubs_asm_irix.s; else true; fi
+endif
+
+ifeq ($(OS_ARCH),OpenVMS)
+# Our assembler wants the include file to be of assembler syntax, not C/C++
+# syntax, so we have to massage it slightly.
+
+xptcstubs_asm_openvms_alpha.o: $(PUBLIC)/xptcstubsdef.inc $(srcdir)/xptcstubs_asm_openvms_alpha.s
+ sed \
+ -e 's/^\(.*_ENTRY\)(\([0-9]*\))/ \1 \2/' \
+ -e 's/\/\*\(.*\)\*\//; \1/' \
+ $(PUBLIC)/xptcstubsdef.inc > ./xptcstubsdef_asm.vms
+ $(AS) -o $@ $(ASFLAGS) $(AS_DASH_C_FLAG) $(srcdir)/xptcstubs_asm_openvms_alpha.s
+ @rm -f ./xptcstubsdef_asm.vms
+endif
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/Makefile.kup b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/Makefile.kup
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/vtable_layout_x86.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/vtable_layout_x86.cpp
new file mode 100644
index 00000000..912f50e4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/vtable_layout_x86.cpp
@@ -0,0 +1,62 @@
+/* this code contributed by Bert Driehuis <bert_driehuis@nl.compuware.com> */
+
+#include <stdio.h>
+
+// Try to determine the vtable layout generated by G++
+// Produces the offset at which the first vtable entry can be
+// found, and the factor to apply for subsequent entries on stdout.
+// Example output:
+// #define GCC_VTABLE_START 0xc
+// #define GCC_VTABLE_FACTOR 0x8
+
+class test {
+public:
+ virtual int t1(void);
+ virtual int t2(void);
+ int x;
+};
+
+test::test() { this->x = 0x12121212; };
+
+int test::t1(void) { return 1; }
+int test::t2(void) { return 2; }
+
+void die(char *x) {
+ fprintf(stderr, "%s\n", x);
+ exit(1);
+}
+
+int
+main()
+{
+ int i;
+ test *t = new test();
+ int *tp = (int *) t;
+ int off1 = -1;
+ int off2 = -1;
+ int factor;
+ int factorshift;
+
+ if (*tp++ != 0x12121212)
+ die("Integer element test::x not found!");
+ tp = (int *) *tp;
+ for (i = 0; i < 10; i++) {
+ if (tp[i] == (int) t->t1)
+ off1 = i;
+ if (tp[i] == (int) t->t2)
+ off2 = i;
+ }
+ if (off1 == -1 || off2 == -1)
+ die("Could not determine offset into vtable!");
+ factor = (off2 - off1) * 4;
+ factorshift = -1;
+ while (factor) {
+ factorshift++;
+ factor >>= 1;
+ }
+ printf("/* Automatically generated by vtable_layout_x86.cpp */\n");
+ printf("#define GCC_VTABLE_START\t0x%x\n", off1 * 4);
+ printf("#define GCC_VTABLE_FACTOR\t0x%x\n", (off2 - off1) * 4);
+ printf("#define GCC_VTABLE_SHIFT\t0x%x\n", factorshift);
+ exit(0);
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptc_gcc_x86_unix.h b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptc_gcc_x86_unix.h
new file mode 100644
index 00000000..707352aa
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptc_gcc_x86_unix.h
@@ -0,0 +1,92 @@
+/* -*- 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) 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 ***** */
+
+/* Special include file for xptc*_gcc_x86_unix.cpp */
+
+//
+// this may improve the static function calls, but may not.
+//
+
+// #define MOZ_USE_STDCALL
+
+#ifdef MOZ_USE_STDCALL
+#define ATTRIBUTE_STDCALL __attribute__ ((__stdcall__))
+#else
+#define ATTRIBUTE_STDCALL
+#endif
+
+#ifdef MOZ_NEED_LEADING_UNDERSCORE
+#define SYMBOL_UNDERSCORE "_"
+#else
+#define SYMBOL_UNDERSCORE
+#endif
+
+/*
+ What are those keeper functions?
+
+ The problem: gcc doesn't know that the assembler routines call
+ static functions so gcc may not emit the definition (i.e., the
+ code) for these functions. In gcc 3.1 and up
+ "__attribute__ ((used))" exists and solves the problem.
+ For older gcc versions it's not so easy. One could use the
+ -fkeep-inline-functions but that keeps a surprising number of
+ functions which bloats the compiled library. It seems otherwise
+ harmless, though. Alternatively, one could use
+ -fno-inline-functions which works right now but might cause a
+ slowdown under some circumstances. The problem with these methods
+ is that they do not automatically adapt to the compiler used.
+
+ The best solution seems to be to create dummy functions that
+ reference the appropriate static functions. It's then necessary
+ to "use" these functions in a way that gcc will not optimize
+ away. The keeper functions use assembly code to confuse gcc.
+
+ One drawback is that the keeper functions are externally visible
+ so they shouldn't do anything harmful.
+
+ With the right linker, one could make the keeper functions local
+ so they wouldn't be visible.
+ */
+
+
+// gcc 3.1 and up
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+#define ATTRIBUTE_USED __attribute__ ((__used__))
+#else
+#define ATTRIBUTE_USED
+#endif
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptc_platforms_unixish_x86.h b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptc_platforms_unixish_x86.h
new file mode 100644
index 00000000..23eb23ee
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptc_platforms_unixish_x86.h
@@ -0,0 +1,161 @@
+/* -*- 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) 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 ***** */
+
+/* Platform specific #defines to be shared by the various platforms sharing
+* the unixish_86 code
+*/
+
+/*
+* The goal here is to clearly define the binary compatibility parameters for
+* the platforms that will use this code. Rather than switch at compile time
+* based on the compiler that happens to be in use we are forcing implementors
+* to make a conscious decision.
+*
+* For some of these platforms the community may choose to have more than one
+* binary model in effect. In that case I suggest that there be explicit sub
+* defines for that platform specifying 'TYPE1', 'TYPE2', etc. The decision on
+* which 'TYPE' to use would be triggered by a setting passed through from the
+* config system.
+*
+* For example we might end up with something like:
+*
+* #elif defined(NTO)
+* # if defined(TYPE1)
+* # define CFRONT_STYLE_THIS_ADJUST
+* # elif defined(TYPE1)
+* # define THUNK_BASED_THIS_ADJUST
+* # else
+* # error "need TYPE1 or TYPE2 for NTO"
+* # endif
+* #elif defined(__BEOS__)
+*
+* and so on....
+*
+*/
+
+#if defined(LINUX)
+
+#if (__GNUC__ == 2) && (__GNUC_MINOR__ <= 7)
+/* Old gcc 2.7.x.x. What does gcc 2.8.x do?? */
+#define CFRONT_STYLE_THIS_ADJUST
+#else
+/* egcs and later */
+#define THUNK_BASED_THIS_ADJUST
+#endif
+
+#elif defined(__FreeBSD__)
+/* System versions of gcc on FreeBSD don't use thunks. On 3.x, the system
+ * compiler is gcc 2.7.2.3, which doesn't use thunks by default. On 4.x and
+ * 5.x, /usr/src/contrib/gcc/config/freebsd.h explicitly undef's
+ * DEFAULT_VTABLE_THUNKS. (The one exception is a brief period (September
+ * 1999 - Jan 2000) during 4.0-CURRENT, after egcs was merged --
+ * this was changed before 4.0-RELEASE, but we can handle it anyway.)
+ *
+ * Versions of gcc from the ports collection (/usr/ports/lang/egcs),
+ * however, have DEFAULT_VTABLE_THUNKS #defined to 1, at least
+ * in all ports collections since the 2.95 merge. (Supporting optional
+ * compilers from FreeBSD 3.2 or earlier seems unnecessary).
+ *
+ * The easiest way to distinguish the ports collection gcc from the system
+ * gcc is that the system gcc defines __FreeBSD_cc_version. This variable
+ * can also identify versions that use thunks. This includes some 4.x versions
+ * and now newer 5.x versions.
+ */
+#if defined(__FreeBSD_cc_version) && \
+ (__FreeBSD_cc_version < 500003) && \
+ (__FreeBSD_cc_version < 400002 || __FreeBSD_cc_version > 400003)
+#define CFRONT_STYLE_THIS_ADJUST
+#else
+#define THUNK_BASED_THIS_ADJUST
+#endif
+
+#elif defined(__NetBSD__)
+#define THUNK_BASED_THIS_ADJUST
+
+#elif defined(__OpenBSD__)
+/* OpenBSD instroduces GCC 2.95.x in late May 1999 */
+#include <sys/param.h>
+#if OpenBSD <= 199905
+#define THUNK_BASED_THIS_ADJUST
+#else
+#define CFRONT_STYLE_THIS_ADJUST
+#endif
+
+#elif defined(__bsdi__)
+#include <sys/param.h>
+#if _BSDI_VERSION >= 199910
+/* BSDI/4.1 ships with egcs, ergo thunk-based */
+#define THUNK_BASED_THIS_ADJUST
+#else
+#define CFRONT_STYLE_THIS_ADJUST
+#endif
+
+#elif defined(NTO)
+#define CFRONT_STYLE_THIS_ADJUST
+
+#elif defined(__BEOS__)
+#define CFRONT_STYLE_THIS_ADJUST
+
+#elif defined(__sun__) || defined(__sun)
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+#define THUNK_BASED_THIS_ADJUST
+#else
+#define CFRONT_STYLE_THIS_ADJUST
+#endif
+
+#elif defined(_WIN32)
+#define THUNK_BASED_THIS_ADJUST
+
+#elif defined(__EMX__)
+#define THUNK_BASED_THIS_ADJUST
+
+#elif defined (__APPLE__) && (__MACH__)
+#define THUNK_BASED_THIS_ADJUST
+
+#else
+#error "need a platform define if using unixish x86 code"
+#endif
+
+/***************************************************************************/
+
+#if !defined(THUNK_BASED_THIS_ADJUST) && !defined(CFRONT_STYLE_THIS_ADJUST)
+#error "need to define 'this' adjust scheme"
+#endif
+
+#if defined(THUNK_BASED_THIS_ADJUST) && defined(CFRONT_STYLE_THIS_ADJUST)
+#error "need to define only ONE 'this' adjust scheme"
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_amd64_darwin.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_amd64_darwin.cpp
new file mode 100644
index 00000000..af2919d8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_amd64_darwin.cpp
@@ -0,0 +1,218 @@
+/* -*- 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) 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 ***** */
+
+// Platform specific code to invoke XPCOM methods on native objects
+
+#include "xptcprivate.h"
+
+// 6 integral parameters are passed in registers
+const PRUint32 GPR_COUNT = 6;
+
+// 8 floating point parameters are passed in SSE registers
+const PRUint32 FPR_COUNT = 8;
+
+// Remember that these 'words' are 64-bit long
+static inline void
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant * s,
+ PRUint32 & nr_gpr, PRUint32 & nr_fpr, PRUint32 & nr_stack)
+{
+ nr_gpr = 1; // skip one GP register for 'that'
+ nr_fpr = 0;
+ nr_stack = 0;
+
+ /* Compute number of eightbytes of class MEMORY. */
+ for (uint32 i = 0; i < paramCount; i++, s++) {
+ if (!s->IsPtrData()
+ && (s->type == nsXPTType::T_FLOAT || s->type == nsXPTType::T_DOUBLE)) {
+ if (nr_fpr < FPR_COUNT)
+ nr_fpr++;
+ else
+ nr_stack++;
+ }
+ else {
+ if (nr_gpr < GPR_COUNT)
+ nr_gpr++;
+ else
+ nr_stack++;
+ }
+ }
+}
+
+static void
+invoke_copy_to_stack(PRUint64 * d, PRUint32 paramCount, nsXPTCVariant * s,
+ PRUint64 * gpregs, double * fpregs)
+{
+ PRUint32 nr_gpr = 1; // skip one GP register for 'that'
+ PRUint32 nr_fpr = 0;
+ PRUint64 value;
+
+ for (uint32 i = 0; i < paramCount; i++, s++) {
+ if (s->IsPtrData())
+ value = (PRUint64) s->ptr;
+ else {
+ switch (s->type) {
+ case nsXPTType::T_FLOAT: break;
+ case nsXPTType::T_DOUBLE: break;
+ case nsXPTType::T_I8: value = s->val.i8; break;
+ case nsXPTType::T_I16: value = s->val.i16; break;
+ case nsXPTType::T_I32: value = s->val.i32; break;
+ case nsXPTType::T_I64: value = s->val.i64; break;
+ case nsXPTType::T_U8: value = s->val.u8; break;
+ case nsXPTType::T_U16: value = s->val.u16; break;
+ case nsXPTType::T_U32: value = s->val.u32; break;
+ case nsXPTType::T_U64: value = s->val.u64; break;
+ case nsXPTType::T_BOOL: value = s->val.b; break;
+ case nsXPTType::T_CHAR: value = s->val.c; break;
+ case nsXPTType::T_WCHAR: value = s->val.wc; break;
+ default: value = (PRUint64) s->val.p; break;
+ }
+ }
+
+ if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) {
+ if (nr_fpr < FPR_COUNT)
+ fpregs[nr_fpr++] = s->val.d;
+ else {
+ *((double *)d) = s->val.d;
+ d++;
+ }
+ }
+ else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) {
+ if (nr_fpr < FPR_COUNT)
+ // The value in %xmm register is already prepared to
+ // be retrieved as a float. Therefore, we pass the
+ // value verbatim, as a double without conversion.
+ fpregs[nr_fpr++] = s->val.d;
+ else {
+ *((float *)d) = s->val.f;
+ d++;
+ }
+ }
+ else {
+ if (nr_gpr < GPR_COUNT)
+ gpregs[nr_gpr++] = value;
+ else
+ *d++ = value;
+ }
+ }
+}
+
+extern "C"
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports * that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant * params)
+{
+ PRUint32 nr_gpr, nr_fpr, nr_stack;
+ invoke_count_words(paramCount, params, nr_gpr, nr_fpr, nr_stack);
+
+ // Stack, if used, must be 16-bytes aligned
+ if (nr_stack)
+ nr_stack = (nr_stack + 1) & ~1;
+
+ // Load parameters to stack, if necessary
+ PRUint64 *stack = (PRUint64 *) __builtin_alloca(nr_stack * 8);
+ PRUint64 gpregs[GPR_COUNT];
+ double fpregs[FPR_COUNT];
+ invoke_copy_to_stack(stack, paramCount, params, gpregs, fpregs);
+
+ // disable the warning about sometimes not initialized variables which is hit
+ // when we pass less than 8 XMM or less than 6 GPR registers.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wsometimes-uninitialized"
+
+ // Load FPR registers from fpregs[]
+ register double d0 asm("xmm0");
+ register double d1 asm("xmm1");
+ register double d2 asm("xmm2");
+ register double d3 asm("xmm3");
+ register double d4 asm("xmm4");
+ register double d5 asm("xmm5");
+ register double d6 asm("xmm6");
+ register double d7 asm("xmm7");
+
+ switch (nr_fpr) {
+#define ARG_FPR(N) \
+ case N+1: d##N = fpregs[N];
+ ARG_FPR(7);
+ ARG_FPR(6);
+ ARG_FPR(5);
+ ARG_FPR(4);
+ ARG_FPR(3);
+ ARG_FPR(2);
+ ARG_FPR(1);
+ ARG_FPR(0);
+ case 0:;
+#undef ARG_FPR
+ }
+
+ // Load GPR registers from gpregs[]
+ register PRUint64 a0 asm("rdi");
+ register PRUint64 a1 asm("rsi");
+ register PRUint64 a2 asm("rdx");
+ register PRUint64 a3 asm("rcx");
+ register PRUint64 a4 asm("r8");
+ register PRUint64 a5 asm("r9");
+
+ switch (nr_gpr) {
+#define ARG_GPR(N) \
+ case N+1: a##N = gpregs[N];
+ ARG_GPR(5);
+ ARG_GPR(4);
+ ARG_GPR(3);
+ ARG_GPR(2);
+ ARG_GPR(1);
+ case 1: a0 = (PRUint64) that;
+ case 0:;
+#undef ARG_GPR
+ }
+
+ // Ensure that assignments to SSE registers won't be optimized away
+ asm("" ::
+ "x" (d0), "x" (d1), "x" (d2), "x" (d3),
+ "x" (d4), "x" (d5), "x" (d6), "x" (d7));
+
+ // Get pointer to method
+ PRUint64 methodAddress = *((PRUint64 *)that);
+ methodAddress += 8 * methodIndex;
+ methodAddress = *((PRUint64 *)methodAddress);
+
+ typedef PRUint32 (*Method)(PRUint64, PRUint64, PRUint64, PRUint64, PRUint64, PRUint64);
+ PRUint32 result = ((Method)methodAddress)(a0, a1, a2, a3, a4, a5);
+ return result;
+
+#pragma clang diagnostic pop
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_amd64_vbox.asm b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_amd64_vbox.asm
new file mode 100644
index 00000000..aaeaf84a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_amd64_vbox.asm
@@ -0,0 +1,403 @@
+; $Id: xptcinvoke_amd64_vbox.asm $
+;; @file
+; XPCOM - Implementation XPTC_InvokeByIndex in assembly.
+;
+; This solves the problem of Clang and gcc (sometimes) not playing along with
+; the alloca() based trick to pass stack parameters. We first had trouble
+; when enabling asan with gcc 8.2, then Clang 11 on mac had similar issues
+; (at least for profile builds).
+;
+
+;
+; Copyright (C) 2020-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; SPDX-License-Identifier: GPL-3.0-only
+;
+
+
+;*********************************************************************************************************************************
+;* Internal Functions *
+;*********************************************************************************************************************************
+%include "iprt/asmdefs.mac"
+
+
+;*********************************************************************************************************************************
+;* Structures and Typedefs *
+;*********************************************************************************************************************************
+struc nsXPTCVariant
+ .val resq 1
+ .ptr resq 1
+ .type resb 1
+ .flags resb 1
+ alignb 8
+endstruc
+
+
+;*********************************************************************************************************************************
+;* Defined Constants And Macros *
+;*********************************************************************************************************************************
+;; @name Selected nsXPTCVariant::flags values.
+;; @{
+%define PTR_IS_DATA 1
+;; @}
+
+;; @name Selected nsXPTType (nsXPTCVariant::type) values.
+;; @{
+%define T_FLOAT 8
+%define T_DOUBLE 9
+;; @}
+
+;; Error code we use if there are too many parameters.
+%define DISP_E_BADPARAMCOUNT 0x8002000e
+
+;; Effect name mangling.
+%ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+ %define XPTC_InvokeByIndex VBoxNsxpXPTC_InvokeByIndex
+%endif
+
+
+BEGINCODE
+
+;;
+;
+; @cproto nsresult XPTC_InvokeByIndex(nsISupports *pThat, PRUint32 idxMethod, PRUint32 cParams, nsXPTCVariant *paParams)
+;
+; @param pThat Pointer to the object we're invoking a method on. register:rdi
+; @param idxMethod The VTable method index. register:esi
+; @param cParams Number of parameters in addition to pThat. register:edx
+; @param paParams Array of parameter values and info. register:rcx
+;
+BEGINPROC_EXPORTED XPTC_InvokeByIndex
+ push rbp
+ mov rbp, rsp
+ push rbx
+ push r12
+
+ ;
+ ; Move essential input parameters into non-parameter registers.
+ ;
+ mov rbx, rcx ; rbx = first / current parameter
+ mov r12d, edx ; r12 = parameter count / left
+
+ ; Look up the method address in the vtable and store it in r11 (freeing up rsi).
+ mov r11, [rdi] ; r11 = vtable
+ mov esi, esi ; zero extend vtable index.
+ mov r11, [r11 + rsi * 8] ; r11 = method to call.
+
+%define WITH_OPTIMIZATION
+%ifdef WITH_OPTIMIZATION
+ ;
+ ; If there are 5 or fewer parameters and they are all suitable for GREGs,
+ ; we can try optimize the processing here.
+ ;
+ ; Switch on count, using fall-thought-to-smaller-value logic, default
+ ; case goes to generic (slow) code path.
+ ;
+ dec edx ; we can still use edx for the parameter count here as a throwaway.
+ jz .fast_1
+ dec edx
+ jz .fast_2
+ dec edx
+ jz .fast_3
+ dec edx
+ jz .fast_4
+ dec edx
+ jnz .slow_or_zero
+%macro fast_case 4
+%1:
+ mov eax, [rbx + nsXPTCVariant_size * %3 + nsXPTCVariant.type] ; ASSUMES 'type' and 'flags' are adjacent byte fields.
+ test ah, PTR_IS_DATA
+ mov %4, [rbx + nsXPTCVariant_size * %3 + nsXPTCVariant.ptr]
+ jnz %2
+ sub al, T_FLOAT
+ sub al, 2
+ jl .fast_bailout
+ mov %4, [rbx + nsXPTCVariant_size * %3 + nsXPTCVariant.val]
+%endmacro
+ fast_case .fast_5, .fast_4, 4, r9
+ fast_case .fast_4, .fast_3, 3, r8
+ fast_case .fast_3, .fast_2, 2, rcx
+ fast_case .fast_2, .fast_1, 1, rdx
+ fast_case .fast_1, .fast_0, 0, rsi
+.fast_0:
+ xor eax, eax
+ call r11 ; note! stack is aligned here.
+
+.fast_return:
+ lea rsp, [rbp - 8*2]
+ pop r12
+ pop rbx
+ leave
+ ret
+
+.slow_or_zero:
+ cmp r12d, 0
+ je .fast_0
+ %if 0
+ jmp .slow
+.fast_bailout:
+ int3
+ %else
+.fast_bailout:
+ %endif
+.slow:
+%endif
+ ; One more push.
+ push r13
+
+ ;
+ ; Check that there aren't unreasonably many parameters
+ ; (we could do ~255, but 64 is more reasonable number).
+ ;
+ cmp r12d, 64
+ je .too_many_parameters
+
+ ;
+ ; For simplicity reserve stack space for all parameters and point r10 at it.
+ ;
+ lea edx, [r12d * 8]
+ sub rsp, rdx
+ and rsp, byte 0ffffffffffffffe0h ; 32 byte aligned stack.
+ mov r10, rsp ; r10 = next stack parameter.
+
+ ;
+ ; Set up parameter pointer and register distribution counts.
+ ;
+ mov eax, 1 ; al = greg count, ah = fpreg count.
+
+ ;
+ ; Anything to do here?
+ ;
+%ifndef WITH_OPTIMIZATION
+ test r12d,r12d
+ jz .make_call
+%endif
+ jmp .param_loop
+
+ ;
+ ; The loop.
+ ;
+ ALIGNCODE(64)
+.param_loop_advance:
+ add rbx, nsXPTCVariant_size
+.param_loop:
+ ; First test for pointers using 'flags' then work 'type' for the rest.
+ test byte [rbx + nsXPTCVariant.flags], PTR_IS_DATA
+ jnz .is_ptr
+ cmp byte [rbx + nsXPTCVariant.type], T_FLOAT
+ jge .maybe_in_fpreg
+
+ ;
+ ; nsXPTCVariant.val belongs in a GREG or on the stack.
+ ; Note! Hope we can get away with not zero extending the value here.
+ ;
+.in_greg:
+ inc al
+ cmp al, 1+1
+ je .in_greg_rsi
+ cmp al, 2+1
+ je .in_greg_rdx
+ cmp al, 3+1
+ je .in_greg_rcx
+ cmp al, 4+1
+ je .in_greg_r8
+ cmp al, 5+1
+ ja .on_stack
+.in_greg_r9:
+ mov r9, [rbx + nsXPTCVariant.val]
+ jmp .next
+.in_greg_r8:
+ mov r8, [rbx + nsXPTCVariant.val]
+ jmp .next
+.in_greg_rcx:
+ mov rcx, [rbx + nsXPTCVariant.val]
+ jmp .next
+.in_greg_rdx:
+ mov rdx, [rbx + nsXPTCVariant.val]
+ jmp .next
+.in_greg_rsi:
+ mov rsi, [rbx + nsXPTCVariant.val]
+ jmp .next
+
+ ;
+ ; Pointers are loaded from the 'ptr' rather than the 'val' member.
+ ;
+ ALIGNCODE(64)
+.is_ptr:
+ inc al
+ cmp al, 1+1
+ je .ptr_in_greg_rsi
+ cmp al, 2+1
+ je .ptr_in_greg_rdx
+ cmp al, 3+1
+ je .ptr_in_greg_rcx
+ cmp al, 4+1
+ je .ptr_in_greg_r8
+ cmp al, 5+1
+ je .ptr_in_greg_r9
+ mov r13, [rbx + nsXPTCVariant.ptr]
+ jmp .r13_on_stack
+
+.ptr_in_greg_r9:
+ mov r9, [rbx + nsXPTCVariant.ptr]
+ jmp .next
+.ptr_in_greg_r8:
+ mov r8, [rbx + nsXPTCVariant.ptr]
+ jmp .next
+.ptr_in_greg_rcx:
+ mov rcx, [rbx + nsXPTCVariant.ptr]
+ jmp .next
+.ptr_in_greg_rdx:
+ mov rdx, [rbx + nsXPTCVariant.ptr]
+ jmp .next
+.ptr_in_greg_rsi:
+ mov rsi, [rbx + nsXPTCVariant.ptr]
+ jmp .next
+
+ ;
+ ; Maybe we've got a float or double type here...
+ ;
+.maybe_in_fpreg:
+ je .float_in_fpreg
+ cmp byte [rbx + nsXPTCVariant.type], T_DOUBLE
+ jne .in_greg
+
+.double_in_fpreg:
+ cmp ah, 8 ; Ensure max AL value of 8 when making call.
+ jge .on_stack
+ inc ah
+ cmp ah, 0+1
+ je .double_in_xmm0
+ cmp ah, 1+1
+ je .double_in_xmm1
+ cmp ah, 2+1
+ je .double_in_xmm2
+ cmp ah, 3+1
+ je .double_in_xmm3
+ cmp ah, 4+1
+ je .double_in_xmm4
+ cmp ah, 5+1
+ je .double_in_xmm5
+ cmp ah, 6+1
+ je .double_in_xmm6
+.double_in_xmm7:
+ movsd xmm7, [rbx + nsXPTCVariant.val]
+ jmp .next
+.double_in_xmm6:
+ movsd xmm6, [rbx + nsXPTCVariant.val]
+ jmp .next
+.double_in_xmm5:
+ movsd xmm5, [rbx + nsXPTCVariant.val]
+ jmp .next
+.double_in_xmm4:
+ movsd xmm4, [rbx + nsXPTCVariant.val]
+ jmp .next
+.double_in_xmm3:
+ movsd xmm3, [rbx + nsXPTCVariant.val]
+ jmp .next
+.double_in_xmm2:
+ movsd xmm2, [rbx + nsXPTCVariant.val]
+ jmp .next
+.double_in_xmm1:
+ movsd xmm1, [rbx + nsXPTCVariant.val]
+ jmp .next
+.double_in_xmm0:
+ movsd xmm0, [rbx + nsXPTCVariant.val]
+ jmp .next
+
+.float_in_fpreg:
+ cmp ah, 8 ; Ensure max AL value of 8 when making call.
+ jge .on_stack
+ inc ah
+ cmp ah, 0+1
+ je .float_in_xmm0
+ cmp ah, 1+1
+ je .float_in_xmm1
+ cmp ah, 2+1
+ je .float_in_xmm2
+ cmp ah, 3+1
+ je .float_in_xmm3
+ cmp ah, 4+1
+ je .float_in_xmm4
+ cmp ah, 5+1
+ je .float_in_xmm5
+ cmp ah, 6+1
+ je .float_in_xmm6
+.float_in_xmm7:
+ movss xmm7, [rbx + nsXPTCVariant.val]
+ jmp .next
+.float_in_xmm6:
+ movss xmm6, [rbx + nsXPTCVariant.val]
+ jmp .next
+.float_in_xmm5:
+ movss xmm5, [rbx + nsXPTCVariant.val]
+ jmp .next
+.float_in_xmm4:
+ movss xmm4, [rbx + nsXPTCVariant.val]
+ jmp .next
+.float_in_xmm3:
+ movss xmm3, [rbx + nsXPTCVariant.val]
+ jmp .next
+.float_in_xmm2:
+ movss xmm2, [rbx + nsXPTCVariant.val]
+ jmp .next
+.float_in_xmm1:
+ movss xmm1, [rbx + nsXPTCVariant.val]
+ jmp .next
+.float_in_xmm0:
+ movss xmm0, [rbx + nsXPTCVariant.val]
+ jmp .next
+
+ ;
+ ; Put the value onto the stack via r13.
+ ;
+ ALIGNCODE(64)
+.on_stack:
+ mov r13, [rbx + nsXPTCVariant.val]
+.r13_on_stack:
+ mov [r10], r13
+ lea r10, [r10 + 8]
+
+ ;
+ ; Update parameter pointer and count and maybe loop again.
+ ;
+.next:
+ dec r12d
+ jnz .param_loop_advance
+
+ ;
+ ; Call the method and return.
+ ;
+.make_call:
+ movzx eax, ah ; AL = number of parameters in XMM registers (variadict only, but easy to do).
+.make_just_call:
+ call r11
+
+.return:
+ lea rsp, [rbp - 8*3]
+ pop r13
+ pop r12
+ pop rbx
+ leave
+ ret
+
+.too_many_parameters:
+ mov eax, DISP_E_BADPARAMCOUNT
+ jmp .return
+ENDPROC XPTC_InvokeByIndex
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm.cpp
new file mode 100644
index 00000000..1b2c5c67
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm.cpp
@@ -0,0 +1,220 @@
+/* -*- 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 ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#if !defined(LINUX) || !defined(__arm__)
+#error "This code is for Linux ARM only. Check that it works on your system, too.\nBeware that this code is highly compiler dependent."
+#endif
+
+// Remember that these 'words' are 32bit DWORDS
+
+static PRUint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ PRUint32 result = 0;
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ return result;
+}
+
+static void
+invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPTCVariant* s)
+{
+ for(PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((PRInt8*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((PRInt16*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((PRInt32*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((PRInt64*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((PRUint8*) d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((PRUint16*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((PRUint32*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((PRUint64*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ case nsXPTType::T_BOOL : *((PRBool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+}
+
+extern "C" {
+ struct my_params_struct {
+ nsISupports* that;
+ PRUint32 Index;
+ PRUint32 Count;
+ nsXPTCVariant* params;
+ PRUint32 fn_count;
+ PRUint32 fn_copy;
+ };
+};
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ PRUint32 result;
+ struct my_params_struct my_params;
+ my_params.that = that;
+ my_params.Index = methodIndex;
+ my_params.Count = paramCount;
+ my_params.params = params;
+ my_params.fn_copy = (PRUint32) &invoke_copy_to_stack;
+ my_params.fn_count = (PRUint32) &invoke_count_words;
+
+/* This is to call a given method of class that.
+ * The parameters are in params, the number is in paramCount.
+ * The routine will issue calls to count the number of words
+ * required for argument passing and to copy the arguments to
+ * the stack.
+ * Since APCS passes the first 3 params in r1-r3, we need to
+ * load the first three words from the stack and correct the stack
+ * pointer (sp) in the appropriate way. This means:
+ *
+ * 1.) more than 3 arguments: load r1-r3, correct sp and remember No.
+ * of bytes left on the stack in r4
+ *
+ * 2.) <= 2 args: load r1-r3 (we won't be causing a stack overflow I hope),
+ * restore sp as if nothing had happened and set the marker r4 to zero.
+ *
+ * Afterwards sp will be restored using the value in r4 (which is not a temporary register
+ * and will be preserved by the function/method called according to APCS [ARM Procedure
+ * Calling Standard]).
+ *
+ * !!! IMPORTANT !!!
+ * This routine makes assumptions about the vtable layout of the c++ compiler. It's implemented
+ * for arm-linux GNU g++ >= 2.8.1 (including egcs and gcc-2.95.[1-3])!
+ *
+ */
+
+ __asm__ __volatile__(
+ "ldr r1, [%1, #12] \n\t" /* prepare to call invoke_count_words */
+ "ldr ip, [%1, #16] \n\t" /* r0=paramCount, r1=params */
+ "ldr r0, [%1, #8] \n\t"
+ "mov lr, pc \n\t" /* call it... */
+ "mov pc, ip \n\t"
+ "mov r4, r0, lsl #2 \n\t" /* This is the amount of bytes needed. */
+ "sub sp, sp, r4 \n\t" /* use stack space for the args... */
+ "mov r0, sp \n\t" /* prepare a pointer an the stack */
+ "ldr r1, [%1, #8] \n\t" /* =paramCount */
+ "ldr r2, [%1, #12] \n\t" /* =params */
+ "ldr ip, [%1, #20] \n\t" /* =invoke_copy_to_stack */
+ "mov lr, pc \n\t" /* copy args to the stack like the */
+ "mov pc, ip \n\t" /* compiler would. */
+ "ldr r0, [%1] \n\t" /* =that */
+ "ldr r1, [r0, #0] \n\t" /* get that->vtable offset */
+ "ldr r2, [%1, #4] \n\t"
+ "mov r2, r2, lsl #2 \n\t" /* a vtable_entry(x)=8 + (4 bytes * x) */
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+ "ldr ip, [r1, r2] \n\t" /* get method adress from vtable */
+#else /* non G++ V3 ABI */
+ "add r2, r2, #8 \n\t" /* with this compilers */
+ "ldr ip, [r1, r2] \n\t" /* get method adress from vtable */
+#endif
+ "cmp r4, #12 \n\t" /* more than 3 arguments??? */
+ "ldmgtia sp!, {r1, r2, r3}\n\t" /* yes: load arguments for r1-r3 */
+ "subgt r4, r4, #12 \n\t" /* and correct the stack pointer */
+ "ldmleia sp, {r1, r2, r3}\n\t" /* no: load r1-r3 from stack */
+ "addle sp, sp, r4 \n\t" /* and restore stack pointer */
+ "movle r4, #0 \n\t" /* a mark for restoring sp */
+ "ldr r0, [%1, #0] \n\t" /* get (self) */
+ "mov lr, pc \n\t" /* call mathod */
+ "mov pc, ip \n\t"
+ "add sp, sp, r4 \n\t" /* restore stack pointer */
+ "mov %0, r0 \n\t" /* the result... */
+ : "=r" (result)
+ : "r" (&my_params)
+ : "r0", "r1", "r2", "r3", "r4", "ip", "lr", "sp"
+ );
+
+ return result;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm64_vbox.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm64_vbox.cpp
new file mode 100644
index 00000000..d8334583
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm64_vbox.cpp
@@ -0,0 +1,296 @@
+/* $Id: xptcinvoke_arm64_vbox.cpp $ */
+/** @file
+ * XPCOM - Implementation XPTC_InvokeByIndex for arm64.
+ */
+
+/*
+ * Copyright (C) 2021-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include "xptcprivate.h"
+#include <iprt/cdefs.h>
+#include <iprt/alloca.h>
+#include <iprt/assert.h>
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+#define NUM_ARGS_IN_GPRS 8 /**< Number of arguments passed in general purpose registers (starting with x0). */
+#define NUM_ARGS_IN_FPRS 8 /**< Number of arguments passed in floating point registers (starting with d0). */
+
+#define MY_MAX_ARGS 64 /**< Limit ourselves to 64 arguments. */
+
+
+
+AssertCompileMemberOffset(nsXPTCVariant, val, 0);
+
+extern "C" __attribute__((naked)) nsresult
+arm64AsmInvoker(uintptr_t pfnMethod /*x0*/, uint32_t cParams /*w1*/, nsXPTCVariant *paParams /*x2*/, uint64_t cbStack /*x3*/,
+ uint8_t *acbStackArgs /*x4*/, uint64_t *pauGprArgs /*x5*/, uint64_t *pauFprArgs /*x6*/, uint32_t cFprArgs /*x7*/)
+{
+ __asm__ __volatile__(
+ /* Prologue - create the frame. */ "\
+ sub sp, sp, 16 \n\
+ stp x29, x30, [sp] \n\
+ mov x29, sp \n\
+ .cfi_def_cfa x29, 16 \n\
+ .cfi_rel_offset x30, -8 \n\
+ .cfi_rel_offset x29, -16 \n\
+\n\
+" /* Move pfnMethod to x16 and pauGprArgs to x7 free up x0 and x5: */ "\
+ mov x16, x0 \n\
+ mov x17, x5 \n\
+\n\
+" /* Load FPU registers first so we free up x6 & x7 early: */ "\
+ cmp w7, #0 \n\
+ b.eq Lno_fprs\n\
+ ldp d0, d1, [x6] \n\
+ ldp d2, d3, [x6, #16] \n\
+ ldp d4, d5, [x6, #32] \n\
+ ldp d6, d7, [x6, #48] \n\
+Lno_fprs:\n\
+\n\
+" /* Do argument passing by stack (if any). We align the stack to 16 bytes. */ "\
+ cmp x3, #0 \n\
+ beq Lno_stack_args \n\
+ sub x3, sp, x3 \n\
+ bic x3, x3, #15 \n\
+ mov sp, x3 \n\
+Lnext_parameter: \n\
+ ldrb w7, [x4] \n\
+ cmp w7, #0 \n\
+ beq Ladvance\n\
+\n\
+ cmp w7, #4 \n\
+ bgt Lstore_64bits\n\
+ cmp w7, #1 \n\
+ beq Lstore_8bits\n\
+ cmp w7, #2 \n\
+ beq Lstore_16bits\n\
+\n\
+Lstore_32bits:\n\
+ ldr w0, [x2] \n\
+ add x3, x3, #3 \n\
+ bic x3, x3, #3 \n\
+ str w0, [x3] \n"
+#ifdef RT_OS_DARWIN /* macOS compacts stack usage. */
+" add x3, x3, #4 \n"
+#endif
+" b Ladvance \n\
+\n\
+Lstore_8bits:\n\
+ ldrb w0, [x2] \n\
+ strb w0, [x3] \n"
+#ifdef RT_OS_DARWIN /* macOS compacts stack usage. */
+" add x3, x3, #1 \n"
+#endif
+" b Ladvance \n\
+\n\
+Lstore_16bits:\n\
+ ldrh w0, [x2] \n\
+ add x3, x3, #1 \n\
+ bic x3, x3, #1 \n\
+ strh w0, [x3] \n"
+#ifdef RT_OS_DARWIN /* macOS compacts stack usage. */
+" add x3, x3, #2 \n"
+#endif
+" b Ladvance \n\
+\n\
+Lstore_64bits_ptr:\n\
+ ldr x0, [x2, %[offPtrInXPTCVariant]] \n\
+ b Lstore_64bits_common \n\
+Lstore_64bits:\n\
+ tst w7, #0x80 \n\
+ bne Lstore_64bits_ptr \n\
+ ldr x0, [x2] \n\
+Lstore_64bits_common:\n\
+ add x3, x3, #7 \n\
+ bic x3, x3, #7 \n\
+ str x0, [x3] \n"
+#ifdef RT_OS_DARWIN /* macOS compacts stack usage. */
+" add x3, x3, #8 \n"
+#endif
+"\n\
+Ladvance:\n"
+#ifndef RT_OS_DARWIN /* macOS compacts stack usage. */
+" add x3, x3, #8 \n"
+#endif
+" add x4, x4, #1 \n\
+ add x2, x2, %[cbXPTCVariant] \n\
+ sub w1, w1, #1 \n\
+ cmp w1, #0 \n\
+ bne Lnext_parameter \n\
+\n\
+" /* reserve stack space for the integer and floating point registers and save them: */ "\
+Lno_stack_args: \n\
+\n\
+" /* Load general purpose argument registers: */ "\
+ ldp x0, x1, [x17] \n\
+ ldp x2, x3, [x17, #16] \n\
+ ldp x4, x5, [x17, #32] \n\
+ ldp x6, x7, [x17, #48] \n\
+\n\
+" /* Make the call: */ "\
+ blr x16 \n\
+\n\
+" /* Epilogue (clang does not emit the .cfi's here, so drop them too?): */ "\
+ mov sp, x29 \n\
+ ldp x29, x30, [sp] \n\
+ add sp, sp, #16 \n\
+ .cfi_def_cfa sp, 0 \n\
+ .cfi_restore x29 \n\
+ .cfi_restore x30 \n\
+ ret \n\
+" :
+ : [cbXPTCVariant] "i" (sizeof(nsXPTCVariant))
+ , [offPtrInXPTCVariant] "i" (offsetof(nsXPTCVariant, ptr))
+ :);
+}
+
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports *pThis, PRUint32 idxMethod, PRUint32 cParams, nsXPTCVariant *paParams)
+{
+ AssertMsgReturn(cParams <= MY_MAX_ARGS, ("cParams=%#x idxMethod=%#x\n", cParams, idxMethod), NS_ERROR_UNEXPECTED);
+
+ /*
+ * Prepare
+ */
+ uint64_t auGprArgs[NUM_ARGS_IN_GPRS] = {0};
+ uint64_t auFprArgs[NUM_ARGS_IN_GPRS] = {0};
+ uint8_t acbStackArgs[MY_MAX_ARGS]; /* The number of value bytes to copy onto the stack. Zero if in register. */
+ uint32_t cbStackArgs = 0;
+ uint32_t cFprArgs = 0;
+ uint32_t cGprArgs = 0;
+
+ /* First argument is always 'pThis'. The 'pThis' argument is not accounted
+ for in cParams or acbStackArgs. */
+ auGprArgs[cGprArgs++] = (uintptr_t)pThis;
+
+ /* Do the other arguments. */
+ for (PRUint32 i = 0; i < cParams; i++)
+ {
+ if (paParams[i].IsPtrData())
+ {
+ if (cGprArgs < NUM_ARGS_IN_GPRS)
+ {
+ auGprArgs[cGprArgs++] = (uintptr_t)paParams[i].ptr;
+ acbStackArgs[i] = 0;
+ }
+ else
+ {
+ acbStackArgs[i] = sizeof(paParams[i].ptr) | UINT8_C(0x80);
+#ifdef RT_OS_DARWIN /* macOS compacts stack usage. */
+ cbStackArgs = RT_ALIGN_32(cbStackArgs, sizeof(paParams[i].ptr)) + sizeof(paParams[i].ptr);
+#else
+ cbStackArgs += sizeof(uint64_t);
+#endif
+ }
+ }
+ else
+ {
+ if ( paParams[i].type != nsXPTType::T_FLOAT
+ && paParams[i].type != nsXPTType::T_DOUBLE)
+ {
+ if (cGprArgs < NUM_ARGS_IN_GPRS)
+ {
+ switch (paParams[i].type)
+ {
+ case nsXPTType::T_I8: auGprArgs[cGprArgs++] = paParams[i].val.i8; break;
+ case nsXPTType::T_I16: auGprArgs[cGprArgs++] = paParams[i].val.i16; break;
+ case nsXPTType::T_I32: auGprArgs[cGprArgs++] = paParams[i].val.i32; break;
+ case nsXPTType::T_I64: auGprArgs[cGprArgs++] = paParams[i].val.i64; break;
+ case nsXPTType::T_U8: auGprArgs[cGprArgs++] = paParams[i].val.u8; break;
+ case nsXPTType::T_U16: auGprArgs[cGprArgs++] = paParams[i].val.u16; break;
+ case nsXPTType::T_U32: auGprArgs[cGprArgs++] = paParams[i].val.u32; break;
+ default:
+ case nsXPTType::T_U64: auGprArgs[cGprArgs++] = paParams[i].val.u64; break;
+ case nsXPTType::T_BOOL: auGprArgs[cGprArgs++] = paParams[i].val.b; break;
+ case nsXPTType::T_CHAR: auGprArgs[cGprArgs++] = paParams[i].val.c; break;
+ case nsXPTType::T_WCHAR: auGprArgs[cGprArgs++] = paParams[i].val.wc; break;
+ }
+ acbStackArgs[i] = 0;
+ }
+ else
+ {
+ uint8_t cbStack;
+ switch (paParams[i].type)
+ {
+ case nsXPTType::T_I8: cbStack = sizeof(paParams[i].val.i8); break;
+ case nsXPTType::T_I16: cbStack = sizeof(paParams[i].val.i16); break;
+ case nsXPTType::T_I32: cbStack = sizeof(paParams[i].val.i32); break;
+ case nsXPTType::T_I64: cbStack = sizeof(paParams[i].val.i64); break;
+ case nsXPTType::T_U8: cbStack = sizeof(paParams[i].val.u8); break;
+ case nsXPTType::T_U16: cbStack = sizeof(paParams[i].val.u16); break;
+ case nsXPTType::T_U32: cbStack = sizeof(paParams[i].val.u32); break;
+ default:
+ case nsXPTType::T_U64: cbStack = sizeof(paParams[i].val.u64); break;
+ case nsXPTType::T_BOOL: cbStack = sizeof(paParams[i].val.b); break;
+ case nsXPTType::T_CHAR: cbStack = sizeof(paParams[i].val.c); break;
+ case nsXPTType::T_WCHAR: cbStack = sizeof(paParams[i].val.wc); break;
+ }
+ acbStackArgs[i] = cbStack;
+#ifdef RT_OS_DARWIN /* macOS compacts stack usage. */
+ cbStackArgs = RT_ALIGN_32(cbStackArgs, cbStack) + cbStack;
+#else
+ cbStackArgs += sizeof(uint64_t);
+#endif
+ }
+ }
+ else if (cFprArgs < NUM_ARGS_IN_FPRS)
+ {
+ AssertCompile(sizeof(paParams[i].val.f) == 4);
+ AssertCompile(sizeof(paParams[i].val.d) == 8);
+ if (paParams[i].type == nsXPTType::T_FLOAT)
+ auFprArgs[cFprArgs++] = paParams[i].val.u32;
+ else
+ auFprArgs[cFprArgs++] = paParams[i].val.u64;
+ acbStackArgs[i] = 0;
+ }
+ else
+ {
+ uint8_t cbStack;
+ if (paParams[i].type == nsXPTType::T_FLOAT)
+ cbStack = sizeof(paParams[i].val.f);
+ else
+ cbStack = sizeof(paParams[i].val.d);
+ acbStackArgs[i] = cbStack;
+#ifdef RT_OS_DARWIN /* macOS compacts stack usage. */
+ cbStackArgs = RT_ALIGN_32(cbStackArgs, cbStack) + cbStack;
+#else
+ cbStackArgs += sizeof(uint64_t);
+#endif
+ }
+ }
+ }
+
+ /*
+ * Pass it on to a naked wrapper function that does the nitty gritty work.
+ */
+ uintptr_t *pauVtable = *(uintptr_t **)pThis;
+ return arm64AsmInvoker(pauVtable[idxMethod], cParams, paParams, cbStackArgs, acbStackArgs, auGprArgs, auFprArgs, cFprArgs);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm_netbsd.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm_netbsd.cpp
new file mode 100644
index 00000000..0213bd76
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm_netbsd.cpp
@@ -0,0 +1,213 @@
+/* -*- 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 ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+// Remember that these 'words' are 32bit DWORDS
+
+static PRUint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ PRUint32 result = 0;
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ return result;
+}
+
+static void
+invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPTCVariant* s)
+{
+ for(PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((PRInt8*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((PRInt16*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((PRInt32*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((PRInt64*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((PRUint8*) d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((PRUint16*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((PRUint32*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((PRUint64*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ case nsXPTType::T_BOOL : *((PRBool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+}
+
+extern "C"
+struct my_params_struct {
+ nsISupports* that;
+ PRUint32 Index;
+ PRUint32 Count;
+ nsXPTCVariant* params;
+ PRUint32 fn_count;
+ PRUint32 fn_copy;
+};
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ PRUint32 result;
+ struct my_params_struct my_params;
+ my_params.that = that;
+ my_params.Index = methodIndex;
+ my_params.Count = paramCount;
+ my_params.params = params;
+ my_params.fn_copy = (PRUint32) &invoke_copy_to_stack;
+ my_params.fn_count = (PRUint32) &invoke_count_words;
+
+/* This is to call a given method of class that.
+ * The parameters are in params, the number is in paramCount.
+ * The routine will issue calls to count the number of words
+ * required for argument passing and to copy the arguments to
+ * the stack.
+ * Since APCS passes the first 3 params in r1-r3, we need to
+ * load the first three words from the stack and correct the stack
+ * pointer (sp) in the appropriate way. This means:
+ *
+ * 1.) more than 3 arguments: load r1-r3, correct sp and remember No.
+ * of bytes left on the stack in r4
+ *
+ * 2.) <= 2 args: load r1-r3 (we won't be causing a stack overflow I hope),
+ * restore sp as if nothing had happened and set the marker r4 to zero.
+ *
+ * Afterwards sp will be restored using the value in r4 (which is not a temporary register
+ * and will be preserved by the function/method called according to APCS [ARM Procedure
+ * Calling Standard]).
+ *
+ * !!! IMPORTANT !!!
+ * This routine makes assumptions about the vtable layout of the c++ compiler. It's implemented
+ * for arm-linux GNU g++ >= 2.8.1 (including egcs and gcc-2.95.[1-3])!
+ *
+ */
+
+ __asm__ __volatile__(
+ "ldr r1, [%1, #12] \n\t" /* prepare to call invoke_count_words */
+ "ldr ip, [%1, #16] \n\t" /* r0=paramCount, r1=params */
+ "ldr r0, [%1, #8] \n\t"
+ "mov lr, pc \n\t" /* call it... */
+ "mov pc, ip \n\t"
+ "mov r4, r0, lsl #2 \n\t" /* This is the amount of bytes needed. */
+ "sub sp, sp, r4 \n\t" /* use stack space for the args... */
+ "mov r0, sp \n\t" /* prepare a pointer an the stack */
+ "ldr r1, [%1, #8] \n\t" /* =paramCount */
+ "ldr r2, [%1, #12] \n\t" /* =params */
+ "ldr ip, [%1, #20] \n\t" /* =invoke_copy_to_stack */
+ "mov lr, pc \n\t" /* copy args to the stack like the */
+ "mov pc, ip \n\t" /* compiler would. */
+ "ldr r0, [%1] \n\t" /* =that */
+ "ldr r1, [r0, #0] \n\t" /* get that->vtable offset */
+ "ldr r2, [%1, #4] \n\t"
+ "add r2, r1, r2, lsl #3\n\t" /* a vtable_entry(x)=8 + (8 bytes * x) */
+ "add r2, r2, #8 \n\t" /* with this compilers */
+ "ldr r3, [r2] \n\t" /* get virtual offset from vtable */
+ "mov r3, r3, lsl #16 \n\t"
+ "add r0, r0, r3, asr #16\n\t"
+ "ldr ip, [r2, #4] \n\t" /* get method address from vtable */
+ "cmp r4, #12 \n\t" /* more than 3 arguments??? */
+ "ldmgtia sp!, {r1, r2, r3}\n\t" /* yes: load arguments for r1-r3 */
+ "subgt r4, r4, #12 \n\t" /* and correct the stack pointer */
+ "ldmleia sp, {r1, r2, r3}\n\t" /* no: load r1-r3 from stack */
+ "addle sp, sp, r4 \n\t" /* and restore stack pointer */
+ "movle r4, #0 \n\t" /* a mark for restoring sp */
+ "mov lr, pc \n\t" /* call mathod */
+ "mov pc, ip \n\t"
+ "add sp, sp, r4 \n\t" /* restore stack pointer */
+ "mov %0, r0 \n\t" /* the result... */
+ : "=r" (result)
+ : "r" (&my_params)
+ : "r0", "r1", "r2", "r3", "r4", "ip", "lr"
+ );
+
+ return result;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ipf32.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ipf32.s
new file mode 100644
index 00000000..c846b1f4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ipf32.s
@@ -0,0 +1,145 @@
+
+// Select C numeric constant
+ .radix C
+// for 64 bit mode, use .psr abi64
+ .psr abi32
+// big endian
+ .psr msb
+// Section has executable code
+ .section .text, "ax","progbits"
+// procedure named 'XPTC_InvokeByIndex'
+ .proc XPTC_InvokeByIndex
+// manual bundling
+ .explicit
+
+// extern "C" PRUint32
+// invoke_copy_to_stack(uint64_t* d,
+// const PRUint32 paramCount, nsXPTCVariant* s)
+ .global invoke_copy_to_stack
+// .exclass invoke_copy_to_stack, @fullyvisible
+ .type invoke_copy_to_stack,@function
+
+// .exclass XPTC_InvokeByIndex, @fullyvisible
+ .type XPTC_InvokeByIndex,@function
+
+// XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+// PRUint32 paramCount, nsXPTCVariant* params);
+XPTC_InvokeByIndex::
+ .prologue
+ .save ar.pfs, r37
+// allocate 4 input args, 6 local args, and 8 output args
+ alloc r37 = ar.pfs, 4, 6, 8, 0 // M
+ nop.i 0 ;; // I
+
+// unwind table already knows gp, no need to specify anything
+ add r39 = 0, gp // A
+ .save rp, r36
+ mov r36 = rp // I
+ .vframe r38
+ add r38 = 0, sp ;; // A
+
+// We first calculate the amount of extra memory stack space required
+// for the arguments, and register storage.
+// We then call invoke_copy_to_stack() to write the argument contents
+// to the specified memory regions.
+// We then copy the integer arguments to integer registers, and floating
+// arguments to float registers.
+// Lastly we load the virtual table jump pointer, and call the target
+// subroutine.
+
+// in0 : that
+// in1 : methodIndex
+// in2 : paramCount
+// in3 : params
+
+// stack frame size is 16 + (8 * even(paramCount)) + 64 + 64
+// 16 byte frame header
+// 8 * even(paramCount) memory argument area
+// 64 bytes integer register area
+// 64 bytes float register area
+// This scheme makes sure stack fram size is a multiple of 16
+
+ .body
+ add r10 = 8, r0 // A
+// r41 points to float register area
+ add r41 = -64, sp // A
+// r40 points to int register area
+ add r40 = -128, sp ;; // A
+
+ add out1 = 0, r40 // A
+ add out2 = 0, r41 // A
+ tbit.z p14,p15 = in2,0 ;; // I
+
+// compute 8 * even(paramCount)
+(p14) shladd r11 = in2, 3, r0 ;; // A
+(p15) shladd r11 = in2, 3, r10 ;; // A
+ sub out0 = r40, r11 ;; // A
+
+// advance the stack frame
+ add sp = -16, out0 // A
+ add out3 = 0, in2 // A
+ add out4 = 0, in3 // A
+
+// branch to invoke_copy_to_stack
+ br.call.sptk.few rp = invoke_copy_to_stack ;; // B
+
+// restore gp
+ add gp = 0, r39 // A
+ add out0 = 0, in0 // A
+
+// load the integer and float registers
+ ld8 out1 = [r40], 8 // M
+ ldfd f8 = [r41], 8 ;; // M
+
+ ld8 out2 = [r40], 8 // M
+ ldfd f9 = [r41], 8 ;; // M
+
+ ld8 out3 = [r40], 8 // M
+ ldfd f10 = [r41], 8 ;; // M
+
+ ld8 out4 = [r40], 8 // M
+ ldfd f11 = [r41], 8 ;; // M
+
+ ld8 out5 = [r40], 8 // M
+ ldfd f12 = [r41], 8 ;; // M
+// 16 * methodIndex
+ shladd r11 = in1, 4, r0 // A
+
+ ld8 out6 = [r40], 8 // M
+ ldfd f13 = [r41], 8 ;; // M
+
+ ld8 out7 = [r40], 8 // M
+ ldfd f14 = [r41], 8 // M
+ addp4 r8 = 0, in0 ;; // A
+
+// look up virtual base table and dispatch to target subroutine
+// This section assumes 32 bit pointer mode, and virtual base table
+// layout from the ABI http://www.codesourcery.com/cxx-abi/abi.html
+
+// load base table
+ ld4 r8 = [r8] ;; // M
+ addp4 r8 = r11, r8 ;; // A
+
+ // first entry is jump pointer, second entry is gp
+ addp4 r9 = 8, r8 ;; // A
+// load jump pointer
+ ld8 r8 = [r8]
+
+// load gp
+ ld8 gp = [r9] ;; // M
+ mov b6 = r8 ;; // I
+
+// branch to target virtual function
+ br.call.sptk.few rp = b6 ;; // B
+
+// epilog
+ mov ar.pfs = r37 // I
+ mov rp = r36 ;; // I
+
+ add sp = 0, r38 // A
+ add gp = 0, r39 // A
+ br.ret.sptk.few rp ;; // B
+
+ .endp
+
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ipf64.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ipf64.s
new file mode 100644
index 00000000..5e1b1a23
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ipf64.s
@@ -0,0 +1,145 @@
+
+// Select C numeric constant
+ .radix C
+// for 64 bit mode, use .psr abi64
+ .psr abi64
+// little endian
+ .psr lsb
+// Section has executable code
+ .section .text, "ax","progbits"
+// procedure named 'XPTC_InvokeByIndex'
+ .proc XPTC_InvokeByIndex
+// manual bundling
+ .explicit
+
+// extern "C" PRUint32
+// invoke_copy_to_stack(uint64_t* d,
+// const PRUint32 paramCount, nsXPTCVariant* s)
+ .global invoke_copy_to_stack
+// .exclass invoke_copy_to_stack, @fullyvisible
+ .type invoke_copy_to_stack,@function
+
+// .exclass XPTC_InvokeByIndex, @fullyvisible
+ .type XPTC_InvokeByIndex,@function
+
+// XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+// PRUint32 paramCount, nsXPTCVariant* params);
+XPTC_InvokeByIndex::
+ .prologue
+ .save ar.pfs, r37
+// allocate 4 input args, 6 local args, and 8 output args
+ alloc r37 = ar.pfs, 4, 6, 8, 0 // M
+ nop.i 0 ;; // I
+
+// unwind table already knows gp, no need to specify anything
+ add r39 = 0, gp // A
+ .save rp, r36
+ mov r36 = rp // I
+ .vframe r38
+ add r38 = 0, sp ;; // A
+
+// We first calculate the amount of extra memory stack space required
+// for the arguments, and register storage.
+// We then call invoke_copy_to_stack() to write the argument contents
+// to the specified memory regions.
+// We then copy the integer arguments to integer registers, and floating
+// arguments to float registers.
+// Lastly we load the virtual table jump pointer, and call the target
+// subroutine.
+
+// in0 : that
+// in1 : methodIndex
+// in2 : paramCount
+// in3 : params
+
+// stack frame size is 16 + (8 * even(paramCount)) + 64 + 64
+// 16 byte frame header
+// 8 * even(paramCount) memory argument area
+// 64 bytes integer register area
+// 64 bytes float register area
+// This scheme makes sure stack fram size is a multiple of 16
+
+ .body
+ add r10 = 8, r0 // A
+// r41 points to float register area
+ add r41 = -64, sp // A
+// r40 points to int register area
+ add r40 = -128, sp ;; // A
+
+ add out1 = 0, r40 // A
+ add out2 = 0, r41 // A
+ tbit.z p14,p15 = in2,0 ;; // I
+
+// compute 8 * even(paramCount)
+(p14) shladd r11 = in2, 3, r0 ;; // A
+(p15) shladd r11 = in2, 3, r10 ;; // A
+ sub out0 = r40, r11 ;; // A
+
+// advance the stack frame
+ add sp = -16, out0 // A
+ add out3 = 0, in2 // A
+ add out4 = 0, in3 // A
+
+// branch to invoke_copy_to_stack
+ br.call.sptk.few rp = invoke_copy_to_stack ;; // B
+
+// restore gp
+ add gp = 0, r39 // A
+ add out0 = 0, in0 // A
+
+// load the integer and float registers
+ ld8 out1 = [r40], 8 // M
+ ldfd f8 = [r41], 8 ;; // M
+
+ ld8 out2 = [r40], 8 // M
+ ldfd f9 = [r41], 8 ;; // M
+
+ ld8 out3 = [r40], 8 // M
+ ldfd f10 = [r41], 8 ;; // M
+
+ ld8 out4 = [r40], 8 // M
+ ldfd f11 = [r41], 8 ;; // M
+
+ ld8 out5 = [r40], 8 // M
+ ldfd f12 = [r41], 8 ;; // M
+// 16 * methodIndex
+ shladd r11 = in1, 4, r0 // A
+
+ ld8 out6 = [r40], 8 // M
+ ldfd f13 = [r41], 8 ;; // M
+
+ ld8 out7 = [r40], 8 // M
+ ldfd f14 = [r41], 8 // M
+ add r8 = 0, in0 ;; // A
+
+// look up virtual base table and dispatch to target subroutine
+// This section assumes 64 bit pointer mode, and virtual base table
+// layout from the ABI http://www.codesourcery.com/cxx-abi/abi.html
+
+// load base table
+ ld8 r8 = [r8] ;; // M
+ add r8 = r11, r8 ;; // A
+
+ // first entry is jump pointer, second entry is gp
+ add r9 = 8, r8 ;; // A
+// load jump pointer
+ ld8 r8 = [r8]
+
+// load gp
+ ld8 gp = [r9] ;; // M
+ mov b6 = r8 ;; // I
+
+// branch to target virtual function
+ br.call.sptk.few rp = b6 ;; // B
+
+// epilog
+ mov ar.pfs = r37 // I
+ mov rp = r36 ;; // I
+
+ add sp = 0, r38 // A
+ add gp = 0, r39 // A
+ br.ret.sptk.few rp ;; // B
+
+ .endp
+
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_irix.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_irix.s
new file mode 100644
index 00000000..4e8e0895
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_irix.s
@@ -0,0 +1,149 @@
+
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+.text
+.globl invoke_count_words
+.globl invoke_copy_to_stack
+
+LOCALSZ=7 # a0, a1, a2, a3, s0, ra, gp
+FRAMESZ=(((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK
+
+RAOFF=FRAMESZ-(1*SZREG)
+A0OFF=FRAMESZ-(2*SZREG)
+A1OFF=FRAMESZ-(3*SZREG)
+A2OFF=FRAMESZ-(4*SZREG)
+A3OFF=FRAMESZ-(5*SZREG)
+S0OFF=FRAMESZ-(6*SZREG)
+GPOFF=FRAMESZ-(7*SZREG)
+
+ #
+ # _XPTC_InvokeByIndex(that, methodIndex, paramCount, params)
+ # a0 a1 a2 a3
+
+NESTED(_XPTC_InvokeByIndex, FRAMESZ, ra)
+ SETUP_GP
+ PTR_SUBU sp, FRAMESZ
+ SETUP_GP64(GPOFF, _XPTC_InvokeByIndex)
+ SAVE_GP(GPOFF)
+
+ REG_S ra, RAOFF(sp)
+ REG_S a0, A0OFF(sp)
+ REG_S a1, A1OFF(sp)
+ REG_S a2, A2OFF(sp)
+ REG_S a3, A3OFF(sp)
+ REG_S s0, S0OFF(sp)
+ REG_S gp, GPOFF(sp)
+
+ # invoke_count_words(paramCount, params)
+ move a0, a2
+ move a1, a3
+ jal invoke_count_words
+
+ # invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount,
+ # nsXPTCVariant* s, PRUint32 *reg)
+
+ REG_L a1, A2OFF(sp) # a1 - paramCount
+ REG_L a2, A3OFF(sp) # a2 - params
+
+ # save sp before we copy the params to the stack
+ move t0, sp
+
+ # assume full size of 8 bytes per param to be safe
+ sll v0, 4 # 8 bytes * num params
+ subu sp, sp, v0 # make room
+ move a0, sp # a0 - param stack address
+
+ # create temporary stack space to write int and fp regs
+ subu sp, 64 # 64 = 8 regs of 8 bytes
+
+ move a3, sp
+
+ # save the old sp and save the arg stack
+ subu sp, sp, 16
+ REG_S t0, 0(sp)
+ REG_S a0, 8(sp)
+
+ # copy the param into the stack areas
+ jal invoke_copy_to_stack
+
+ REG_L t3, 8(sp) # get previous a0
+ REG_L sp, 0(sp) # get orig sp back
+
+ REG_L a0, A0OFF(sp) # a0 - that
+ REG_L a1, A1OFF(sp) # a1 - methodIndex
+
+#ifdef __GNUC__
+ # t1 = methodIndex * 8
+ # (use shift instead of mult)
+ sll t1, a1, 3
+#else
+ # t1 = methodIndex * 12
+ # (use shift and subtract trick instead of mult)
+ sll t1, a1, 2
+ subu t1, t1, a1
+ sll t1, t1, 2
+#endif
+
+ # calculate the function we need to jump to,
+ # which must then be saved in t9
+ lw t9, 0(a0)
+ addu t9, t9, t1
+#ifdef __GNUC__
+ lw t9, 12(t9) # t9 = *(that+t1+12)
+#else
+ li t2, 20
+ addu t9, t9, t2
+ lw t9, 0(t9) # t9 = *(that+t1+20)
+#endif
+
+ # calculate the proper "this" pointer for the
+ # function that they asked for
+ lw t0, 0(a0)
+ addu t0, t1
+#ifdef __GNUC__
+ lh t0, 8(t0)
+#else
+ lw t0, 12(t0)
+#endif
+
+ addu a0, a0, t0
+
+ # get register save area from invoke_copy_to_stack
+ subu t1, t3, 64
+
+ # a1..a7 and f13..f19 should now be set to what
+ # invoke_copy_to_stack told us. skip a0 and f12
+ # because that's the "this" pointer
+
+ REG_L a1, 0(t1)
+ REG_L a2, 8(t1)
+ REG_L a3, 16(t1)
+ REG_L a4, 24(t1)
+ REG_L a5, 32(t1)
+ REG_L a6, 40(t1)
+ REG_L a7, 48(t1)
+
+ l.d $f13, 0(t1)
+ l.d $f14, 8(t1)
+ l.d $f15, 16(t1)
+ l.d $f16, 24(t1)
+ l.d $f17, 32(t1)
+ l.d $f18, 40(t1)
+ l.d $f19, 48(t1)
+
+ # save away our stack pointer and create
+ # the stack pointer for the function
+ move s0, sp
+ move sp, t3
+
+ jalr ra, t9
+
+ move sp, s0
+
+ RESTORE_GP64
+ REG_L ra, RAOFF(sp)
+ REG_L s0, S0OFF(sp)
+ PTR_ADDU sp, FRAMESZ
+ j ra
+.end _XPTC_InvokeByIndex
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_mips.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_mips.s
new file mode 100644
index 00000000..f011aaf5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_mips.s
@@ -0,0 +1,166 @@
+/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * Version: MPL 1.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 Corp, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org>
+ * Stuart Parmenter <pavlov@netscape.com>
+ */
+
+/* This code is for MIPS using the O32 ABI. */
+
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+.text
+.globl invoke_count_words
+.globl invoke_copy_to_stack
+
+# We need a variable number of words allocated from the stack for copies of
+# the params, and this space must come between the high frame (where ra, gp,
+# and s0 are saved) and the low frame (where a0-a3 are saved by the callee
+# functions we invoke).
+
+LOCALSZ=4 # s0, s1, ra, gp
+NARGSAVE=4 # a0, a1, a2, a3
+HIFRAMESZ=(LOCALSZ*SZREG)
+LOFRAMESZ=(NARGSAVE*SZREG)
+FRAMESZ=(HIFRAMESZ+LOFRAMESZ+ALSZ)&ALMASK
+
+# XXX these 2*SZREG, etc. are very magic -- we *know* that ALSZ&ALMASK cause
+# FRAMESZ to be 0 mod 8, in this case to be 16 and not 12.
+RAOFF=FRAMESZ - (2*SZREG)
+GPOFF=FRAMESZ - (3*SZREG)
+S0OFF=FRAMESZ - (4*SZREG)
+S1OFF=FRAMESZ - (5*SZREG)
+
+# These are not magic -- they are just our argsave slots in the caller frame.
+A0OFF=FRAMESZ
+A1OFF=FRAMESZ + (1*SZREG)
+A2OFF=FRAMESZ + (2*SZREG)
+A3OFF=FRAMESZ + (3*SZREG)
+
+ #
+ # _XPTC_InvokeByIndex(that, methodIndex, paramCount, params)
+ # a0 a1 a2 a3
+
+NESTED(_XPTC_InvokeByIndex, FRAMESZ, ra)
+
+ .set noreorder
+ .cpload t9
+ .set reorder
+
+ subu sp, FRAMESZ
+
+ # specify the save register mask -- XXX do we want the a0-a3 here, given
+ # our "split" frame where the args are saved below a dynamicly allocated
+ # region under the high frame?
+ #
+ # 10010000000000010000000011110000
+ .mask 0x900100F0, -((NARGSAVE+LOCALSZ)*SZREG)
+
+ # thou shalt not use .cprestore if yer frame has variable size...
+ # .cprestore GPOFF
+
+ REG_S ra, RAOFF(sp)
+
+ # this happens automatically with .cprestore, but we cannot use that op...
+ REG_S gp, GPOFF(sp)
+ REG_S s0, S0OFF(sp)
+ REG_S s1, S1OFF(sp)
+
+ REG_S a0, A0OFF(sp)
+ REG_S a1, A1OFF(sp)
+ REG_S a2, A2OFF(sp)
+ REG_S a3, A3OFF(sp)
+
+ # invoke_count_words(paramCount, params)
+ move a0, a2
+ move a1, a3
+
+ jal invoke_count_words
+ lw gp, GPOFF(sp)
+
+ # save the old sp so we can pop the param area and any "low frame"
+ # needed as an argsave area below the param block for callees that
+ # we invoke.
+ move s0, sp
+
+ REG_L a1, A2OFF(sp) # a1 = paramCount
+ REG_L a2, A3OFF(sp) # a2 = params
+
+ # we define a word as 4 bytes, period end of story!
+ sll v0, 2 # 4 bytes * result of invoke_copy_words
+ subu v0, LOFRAMESZ # but we take back the argsave area built into
+ # our stack frame -- SWEET!
+ subu sp, sp, v0 # make room
+ move a0, sp # a0 = param stack address
+ move s1, a0 # save it for later -- it should be safe here
+
+ # the old sp is still saved in s0, but we now need another argsave
+ # area ("low frame") for the invoke_copy_to_stack call.
+ subu sp, sp, LOFRAMESZ
+
+ # copy the param into the stack areas
+ # invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount,
+ # nsXPTCVariant* s)
+ jal invoke_copy_to_stack
+ lw gp, GPOFF(s0)
+
+ move sp, s0 # get orig sp back, popping params and argsave
+
+ REG_L a0, A0OFF(sp) # a0 = set "that" to be "this"
+ REG_L a1, A1OFF(sp) # a1 = methodIndex
+
+ # t1 = methodIndex * 4
+ # (use shift instead of mult)
+ sll t1, a1, 2
+
+ # calculate the function we need to jump to,
+ # which must then be saved in t9
+ lw t9, 0(a0)
+ addu t9, t9, t1
+ lw t9, 8(t9)
+
+ # a1..a3 and f13..f14 should now be set to what
+ # invoke_copy_to_stack told us. skip a0 and f12
+ # because that is the "this" pointer
+
+ REG_L a1, 1*SZREG(s1)
+ REG_L a2, 2*SZREG(s1)
+ REG_L a3, 3*SZREG(s1)
+
+ l.d $f13, 8(s1)
+ l.d $f14, 16(s1)
+
+ # Create the stack pointer for the function, which must have 4 words
+ # of space for callee-saved args. invoke_count_words allocated space
+ # for a0 starting at s1, so we just move s1 into sp.
+ move sp, s1
+
+ jalr ra, t9
+ lw gp, GPOFF(s0)
+
+ move sp, s0
+
+ REG_L ra, RAOFF(sp)
+ REG_L s0, S0OFF(sp)
+ addu sp, FRAMESZ
+ j ra
+.end _XPTC_InvokeByIndex
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_openvms_alpha.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_openvms_alpha.s
new file mode 100644
index 00000000..d37a91d2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_openvms_alpha.s
@@ -0,0 +1,99 @@
+;* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+;*
+;* The contents of this file are subject to the Netscape 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/NPL/
+;*
+;* 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 Netscape are
+;* Copyright (C) 1998 Netscape Communications Corporation. All
+;* Rights Reserved.
+;*
+;* Contributor(s):
+;*/
+
+;
+; XPTC_PUBLIC_API(nsresult)
+; XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+; PRUint32 paramCount, nsXPTCVariant* params)
+;
+
+ .title "INVOKE" "Invoke By Index"
+
+ $routine XPTC_InvokeByIndex, kind=stack, saved_regs=<R2,R3,R4>
+
+ mov r27,r2 ; Need to set up a base register...
+ .base r2,$LS ; ...for the LINKAGE_PAIR call
+
+ mov r17,r3 ; save methodIndex in r3
+ mov r18,r4 ; save paramCount in r4
+
+;
+; Allocate enough stack space to hold the greater of 6 or "paramCount"+1
+; parameters. (+1 for "this" pointer) Room for at least 6 parameters
+; is required for storage of those passed via registers.
+;
+
+ cmplt R18,5,R1 ; paramCount = MAX(5, "paramCount")
+ cmovne R1,5,R18
+ s8addq R18,16,R1 ; room for "paramCount"+1 params (8 bytes each)
+ bic R1,15,R1 ; stack space is rounded up to 0 % 16
+ subq SP,R1,SP
+
+ stq R16,0(SP) ; save "that" (as "this" pointer)
+ addq SP,8,R16 ; pass stack pointer
+ mov R4,R17 ; pass original "paramCount
+ mov R19,R18 ; pass "params"
+ mov 4,r25 ; argument count
+
+ $LINKAGE_PAIR invoke_copy_to_stack
+ ldq r26,$LP ; get entry point address from linkage pair
+ ldq r27,$LP+8 ; get procedure descriptor address from lp
+ jsr r26,r26 ; and call the routine
+
+;
+; Copy the first 6 parameters to registers and remove from stack frame.
+; Both the integer and floating point registers are set for each parameter
+; except the first which is the "this" pointer. (integer only)
+; The floating point registers are all set as doubles since the
+; invoke_copy_to_stack function should have converted the floats.
+;
+ ldq R16,0(SP) ; integer registers
+ ldq R17,8(SP)
+ ldq R18,16(SP)
+ ldq R19,24(SP)
+ ldq R20,32(SP)
+ ldq R21,40(SP)
+ ldt F17,8(SP) ; floating point registers
+ ldt F18,16(SP)
+ ldt F19,24(SP)
+ ldt F20,32(SP)
+ ldt F21,40(SP)
+
+ addq SP,48,SP ; remove params from stack
+
+;
+; Call the virtual function with the constructed stack frame.
+; First three methods are always QueryInterface, AddRef and Release.
+;
+ addq r4,1,r25 ; argument count now includes "this"
+ mov R16,R1 ; load "this"
+ ldl R1,0(R1) ; load vtable
+ s4addq r3,0,r28 ; vtable index = "methodIndex" * 4
+ addq r1,r28,r1
+ ldl r27,0(r1) ; load procedure value
+ ldq r26,8(r27) ; load entry point address
+ jsr r26,r26 ; call virtual function
+
+ $return
+
+ $end_routine XPTC_InvokeByIndex
+ .end
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_osf1_alpha.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_osf1_alpha.s
new file mode 100644
index 00000000..ad7b2f82
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_osf1_alpha.s
@@ -0,0 +1,83 @@
+/*
+ * XPTC_PUBLIC_API(nsresult)
+ * XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ * PRUint32 paramCount, nsXPTCVariant* params)
+ */
+.text
+.align 4
+.globl XPTC_InvokeByIndex
+.ent XPTC_InvokeByIndex
+XPTC_InvokeByIndex:
+.frame $15,32,$26,0
+.mask 0x4008000,-32
+ldgp $29,0($27)
+XPTC_InvokeByIndexXv:
+subq $30,32,$30
+stq $26,0($30)
+stq $15,8($30)
+bis $30,$30,$15
+.prologue 1
+
+/*
+ * Allocate enough stack space to hold the greater of 6 or "paramCount"+1
+ * parameters. (+1 for "this" pointer) Room for at least 6 parameters
+ * is required for storage of those passed via registers.
+ */
+
+bis $31,5,$2 /* count = MAX(5, "paramCount") */
+cmplt $2,$18,$1
+cmovne $1,$18,$2
+s8addq $2,16,$1 /* room for count+1 params (8 bytes each) */
+bic $1,15,$1 /* stack space is rounded up to 0 % 16 */
+subq $30,$1,$30
+
+stq $16,0($30) /* save "that" (as "this" pointer) */
+stq $17,16($15) /* save "methodIndex" */
+
+addq $30,8,$16 /* pass stack pointer */
+bis $18,$18,$17 /* pass "paramCount" */
+bis $19,$19,$18 /* pass "params" */
+jsr $26,invoke_copy_to_stack /* call invoke_copy_to_stack */
+ldgp $29,0($26)
+
+/*
+ * Copy the first 6 parameters to registers and remove from stack frame.
+ * Both the integer and floating point registers are set for each parameter
+ * except the first which is the "this" pointer. (integer only)
+ * The floating point registers are all set as doubles since the
+ * invoke_copy_to_stack function should have converted the floats.
+ */
+ldq $16,0($30) /* integer registers */
+ldq $17,8($30)
+ldq $18,16($30)
+ldq $19,24($30)
+ldq $20,32($30)
+ldq $21,40($30)
+ldt $f17,8($30) /* floating point registers */
+ldt $f18,16($30)
+ldt $f19,24($30)
+ldt $f20,32($30)
+ldt $f21,40($30)
+
+addq $30,48,$30 /* remove params from stack */
+
+/*
+ * Call the virtual function with the constructed stack frame.
+ */
+bis $16,$16,$1 /* load "this" */
+ldq $2,16($15) /* load "methodIndex" */
+ldq $1,0($1) /* load vtable */
+s8addq $2,0,$2 /* vtable index = "methodIndex" * 8 + 16 */
+addq $1,$2,$1
+ldq $27,0($1) /* load address of function */
+jsr $26,($27),0 /* call virtual function */
+ldgp $29,0($26)
+
+bis $15,$15,$30
+ldq $26,0($30)
+ldq $15,8($30)
+addq $30,32,$30
+ret $31,($26),1
+.end XPTC_InvokeByIndex
+
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_pa32.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_pa32.s
new file mode 100644
index 00000000..8ce8f17f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_pa32.s
@@ -0,0 +1,131 @@
+ .LEVEL 1.1
+framesz .EQU 128
+
+; XPTC_InvokeByIndex(nsISuppots* that, PRUint32 methodIndex,
+; PRUint32 paramCount, nsXPTCVariant* params);
+
+; g++ need to compile everything with -fvtable-thunks !
+
+ .SPACE $TEXT$,SORT=8
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=0x2c,CODE_ONLY,SORT=24
+XPTC_InvokeByIndex
+ .PROC
+ .CALLINFO CALLER,FRAME=72,ENTRY_GR=%r3,SAVE_RP,SAVE_SP,ARGS_SAVED,ALLOCA_FRAME
+
+ ; frame marker takes 48 bytes,
+ ; register spill area takes 8 bytes,
+ ; local stack area takes 72 bytes result in 128 bytes total
+
+ .ENTRY
+ STW %rp,-20(%sp)
+ STW,MA %r3,128(%sp)
+
+ LDO -framesz(%r30),%r28
+ STW %r28,-4(%r30) ; save previous sp
+ STW %r19,-32(%r30)
+
+ STW %r26,-36-framesz(%r30) ; save argument registers in
+ STW %r25,-40-framesz(%r30) ; in PREVIOUS frame
+ STW %r24,-44-framesz(%r30) ;
+ STW %r23,-48-framesz(%r30) ;
+
+ B,L .+8,%r2
+ ADDIL L'invoke_count_bytes-$PIC_pcrel$1+4,%r2,%r1
+ LDO R'invoke_count_bytes-$PIC_pcrel$2+8(%r1),%r1
+$PIC_pcrel$1
+ LDSID (%r1),%r31
+$PIC_pcrel$2
+ MTSP %r31,%sr0
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR ;in=24,25,26;out=28
+ BE,L 0(%sr0,%r1),%r31
+ COPY %r31,%r2
+
+ CMPIB,>= 0,%r28, .+76
+ COPY %r30,%r3 ; copy stack ptr to saved stack ptr
+ ADD %r30,%r28,%r30 ; extend stack frame
+ LDW -4(%r3),%r28 ; move frame
+ STW %r28,-4(%r30)
+ LDW -8(%r3),%r28
+ STW %r28,-8(%r30)
+ LDW -12(%r3),%r28
+ STW %r28,-12(%r30)
+ LDW -16(%r3),%r28
+ STW %r28,-16(%r30)
+ LDW -20(%r3),%r28
+ STW %r28,-20(%r30)
+ LDW -24(%r3),%r28
+ STW %r28,-24(%r30)
+ LDW -28(%r3),%r28
+ STW %r28,-28(%r30)
+ LDW -32(%r3),%r28
+ STW %r28,-32(%r30)
+
+ LDO -40(%r30),%r26 ; load copy address
+ LDW -44-framesz(%r3),%r25 ; load rest of 2 arguments
+ LDW -48-framesz(%r3),%r24 ;
+
+ LDW -32(%r30),%r19 ; shared lib call destroys r19; reload
+ B,L .+8,%r2
+ ADDIL L'invoke_copy_to_stack-$PIC_pcrel$3+4,%r2,%r1
+ LDO R'invoke_copy_to_stack-$PIC_pcrel$4+8(%r1),%r1
+$PIC_pcrel$3
+ LDSID (%r1),%r31
+$PIC_pcrel$4
+ MTSP %r31,%sr0
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR ;in=24,25,26
+ BE,L 0(%sr0,%r1),%r31
+ COPY %r31,%r2
+
+ LDO -48(%r30),%r20
+ EXTRW,U,= %r28,31,1,%r22
+ FLDD 0(%r20),%fr7 ; load double arg 1
+ EXTRW,U,= %r28,30,1,%r22
+ FLDW 8(%r20),%fr5L ; load float arg 1
+ EXTRW,U,= %r28,29,1,%r22
+ FLDW 4(%r20),%fr6L ; load float arg 2
+ EXTRW,U,= %r28,28,1,%r22
+ FLDW 0(%r20),%fr7L ; load float arg 3
+
+ LDW -36-framesz(%r3),%r26 ; load ptr to 'that'
+ LDW -40(%r30),%r25 ; load the rest of dispatch argument registers
+ LDW -44(%r30),%r24
+ LDW -48(%r30),%r23
+
+ LDW -36-framesz(%r3),%r20 ; load vtable addr
+ LDW -40-framesz(%r3),%r28 ; load index
+ LDW 0(%r20),%r20 ; follow vtable
+ LDO 16(%r20),%r20 ; offset vtable by 16 bytes (g++: 8, aCC: 16)
+ SH2ADDL %r28,%r20,%r28 ; add 4*index to vtable entry
+ LDW 0(%r28),%r22 ; load vtable entry
+
+ B,L .+8,%r2
+ ADDIL L'$$dyncall_external-$PIC_pcrel$5+4,%r2,%r1
+ LDO R'$$dyncall_external-$PIC_pcrel$6+8(%r1),%r1
+$PIC_pcrel$5
+ LDSID (%r1),%r31
+$PIC_pcrel$6
+ MTSP %r31,%sr0
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR
+;in=22-26;out=28;
+ BE,L 0(%sr0,%r1),%r31
+ COPY %r31,%r2
+
+ LDW -32(%r30),%r19
+ COPY %r3,%r30 ; restore saved stack ptr
+
+ LDW -148(%sp),%rp
+ BVE (%rp)
+ .EXIT
+ LDW,MB -128(%sp),%r3
+
+ .PROCEND ;in=23,24,25,26;
+
+ .ALIGN 8
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+ .IMPORT $$dyncall_external,MILLICODE
+ .IMPORT invoke_count_bytes,CODE
+ .IMPORT invoke_copy_to_stack,CODE
+ .EXPORT XPTC_InvokeByIndex,ENTRY,PRIV_LEV=3,ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR,LONG_RETURN
+ .END
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_aix.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_aix.s
new file mode 100644
index 00000000..3684d154
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_aix.s
@@ -0,0 +1,146 @@
+ #
+ # -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ #
+ # The contents of this file are subject to the Netscape 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/NPL/
+ #
+ # 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 Netscape are
+ # Copyright (C) 1999 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s):
+ # IBM Corporation
+ #
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+.set BO_IF,12
+.set CR0_EQ,2
+
+
+
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.XPTC_InvokeByIndex{TC},"XPTC_InvokeByIndex"
+
+
+# .text section
+
+ .csect H.10.NO_SYMBOL{PR}
+ .globl .XPTC_InvokeByIndex
+ .globl XPTC_InvokeByIndex{DS}
+ .extern .invoke_copy_to_stack
+ .extern ._ptrgl{PR}
+
+
+#
+# XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+# PRUint32 paramCount, nsXPTCVariant* params)
+#
+
+.XPTC_InvokeByIndex:
+ mflr r0
+ stw r31,-4(sp)
+#
+# save off the incoming values in the caller's parameter area
+#
+ stw r3,24(sp) # that
+ stw r4,28(sp) # methodIndex
+ stw r5,32(sp) # paramCount
+ stw r6,36(sp) # params
+ stw r0,8(sp)
+ stwu sp,-136(sp) # = 24 for linkage area, 8 * 13 for fprData area, 8 for saved registers
+
+# prepare args for 'invoke_copy_to_stack' call
+#
+ lwz r4,168(sp) # paramCount
+ lwz r5,172(sp) # params
+ mr r6,sp # fprData
+ slwi r3,r4,3 # number of bytes of stack required
+ # at most 8*paramCount
+ addi r3,r3,28 # linkage area
+ mr r31,sp # save original stack top
+ subfc sp,r3,sp # bump the stack
+ addi r3,sp,28 # parameter pointer excludes linkage area size + 'this'
+
+ bl .invoke_copy_to_stack
+ nop
+
+ lfd f1,0(r31) # Restore floating point registers
+ lfd f2,8(r31)
+ lfd f3,16(r31)
+ lfd f4,24(r31)
+ lfd f5,32(r31)
+ lfd f6,40(r31)
+ lfd f7,48(r31)
+ lfd f8,56(r31)
+ lfd f9,64(r31)
+ lfd f10,72(r31)
+ lfd f11,80(r31)
+ lfd f12,88(r31)
+ lfd f13,96(r31)
+
+ lwz r3,160(r31) # that
+ lwz r4,0(r3) # get vTable from 'that'
+ lwz r5,164(r31) # methodIndex
+ slwi r5,r5,3 # methodIndex * 8
+ addi r5,r5,8 # step over junk at start of vTable !
+ lwzx r11,r5,r4 # get function pointer
+
+ addi r5,r5,4 # We need to manually adjust the 'that' pointer, this is CFRONT based
+ lwzx r5,r4,r5 # offset = r4(vtable) + r5(methodIndex offset) - 4
+ add r3,r5,r3 # adjust 'that' r3 = r3 + r5
+
+ lwz r4,28(sp)
+ lwz r5,32(sp)
+ lwz r6,36(sp)
+ lwz r7,40(sp)
+ lwz r8,44(sp)
+ lwz r9,48(sp)
+ lwz r10,52(sp)
+
+ bl ._ptrgl{PR}
+ nop
+
+ mr sp,r31
+ lwz r0,144(sp)
+ addi sp,sp,136
+ mtlr r0
+ lwz r31,-4(sp)
+ blr
+
+
+# .data section
+
+ .toc # 0x00000038
+T.18.XPTC_InvokeByIndex:
+ .tc H.18.XPTC_InvokeByIndex{TC},XPTC_InvokeByIndex{DS}
+
+ .csect XPTC_InvokeByIndex{DS}
+ .long .XPTC_InvokeByIndex # "\0\0\0\0"
+ .long TOC{TC0} # "\0\0\0008"
+ .long 0x00000000 # "\0\0\0\0"
+# End csect XPTC_InvokeByIndex{DS}
+
+# .bss section
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_aix64.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_aix64.s
new file mode 100644
index 00000000..a174e424
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_aix64.s
@@ -0,0 +1,161 @@
+# ***** BEGIN LICENSE BLOCK *****
+#
+# Version: MPL 1.1/LGPL 2.1/GPL 2.0
+#
+# 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 IBM Corporation.
+# Portions created by IBM are
+# Copyright (C) 2002, International Business Machines Corporation.
+# 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 LGPL or the GPL. 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 *****
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+.set BO_IF,12
+.set CR0_EQ,2
+
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.XPTC_InvokeByIndex{TC},"XPTC_InvokeByIndex"
+
+
+# .text section
+
+ .csect H.10.NO_SYMBOL{PR}
+ .globl .XPTC_InvokeByIndex
+ .globl XPTC_InvokeByIndex{DS}
+ .extern .invoke_copy_to_stack
+ .extern ._ptrgl{PR}
+
+#
+# XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+# PRUint32 paramCount, nsXPTCVariant* params)
+#
+
+.XPTC_InvokeByIndex:
+ mflr r0
+ std r31,-8(sp)
+#
+# save off the incoming values in the caller's parameter area
+#
+ std r3,48(sp) # that
+ std r4,56(sp) # methodIndex
+ std r5,64(sp) # paramCount
+ std r6,72(sp) # params
+ std r0,16(sp)
+ stdu sp,-168(sp) # 2*24=48 for linkage area,
+ # 8*13=104 for fprData area
+ # 16 for saved registers
+
+# prepare args for 'invoke_copy_to_stack' call
+#
+ ld r4,232(sp) # paramCount (168+8+56)
+ ld r5,240(sp) # params
+ mr r6,sp # fprData
+ sldi r3,r4,3 # number of bytes of stack required
+ # is at most numParams*8
+ addi r3,r3,56 # linkage area (48) + this (8)
+ mr r31,sp # save original stack top
+ subfc sp,r3,sp # bump the stack
+ addi r3,sp,56 # parameter pointer excludes linkage area
+ # size + 'this'
+
+ bl .invoke_copy_to_stack
+ nop
+
+ lfd f1,0(r31) # Restore floating point registers
+ lfd f2,8(r31)
+ lfd f3,16(r31)
+ lfd f4,24(r31)
+ lfd f5,32(r31)
+ lfd f6,40(r31)
+ lfd f7,48(r31)
+ lfd f8,56(r31)
+ lfd f9,64(r31)
+ lfd f10,72(r31)
+ lfd f11,80(r31)
+ lfd f12,88(r31)
+ lfd f13,96(r31)
+
+ ld r3,216(r31) # that (168+48)
+ ld r4,0(r3) # get vTable from 'that'
+ ld r5,224(r31) # methodIndex (168+56)
+ sldi r5,r5,3 # methodIndex * 8
+ # No junk at the start of 64bit vtable !!!
+ ldx r11,r5,r4 # get function pointer (this jumps
+ # either to the function if no adjustment
+ # is needed (displacement = 0), or it
+ # jumps to the thunk code, which will jump
+ # to the function at the end)
+
+ # No adjustment of the that pointer in 64bit mode, this is done
+ # by the thunk code
+
+ ld r4,56(sp)
+ ld r5,64(sp)
+ ld r6,72(sp)
+ ld r7,80(sp)
+ ld r8,88(sp)
+ ld r9,96(sp)
+ ld r10,104(sp)
+
+ bl ._ptrgl{PR}
+ nop
+
+ mr sp,r31
+ ld r0,184(sp) # 168+16
+ addi sp,sp,168
+ mtlr r0
+ ld r31,-8(sp)
+ blr
+
+# .data section
+
+ .toc # 0x00000038
+T.18.XPTC_InvokeByIndex:
+ .tc H.18.XPTC_InvokeByIndex{TC},XPTC_InvokeByIndex{DS}
+
+ .csect XPTC_InvokeByIndex{DS}
+ .llong .XPTC_InvokeByIndex # "\0\0\0\0"
+ .llong TOC{TC0} # "\0\0\0008"
+ .llong 0x00000000 # "\0\0\0\0"
+# End csect XPTC_InvokeByIndex{DS}
+
+# .bss section
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s
new file mode 100644
index 00000000..064a73ab
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s
@@ -0,0 +1,140 @@
+ #
+ # -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ #
+ # The contents of this file are subject to the Netscape 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/NPL/
+ #
+ # 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 IBM Corporation.
+ # Portions created by IBM are
+ # Copyright (C) 2004, International Business Machines Corporation.
+ # All Rights Reserved.
+ #
+ # Contributor(s):
+ #
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+.set BO_IF,12
+.set CR0_EQ,2
+
+
+
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.XPTC_InvokeByIndex{TC},"XPTC_InvokeByIndex"
+
+
+# .text section
+
+ .csect H.10.NO_SYMBOL{PR}
+ .globl .XPTC_InvokeByIndex
+ .globl XPTC_InvokeByIndex{DS}
+ .extern .invoke_copy_to_stack
+ .extern ._ptrgl{PR}
+
+
+#
+# XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+# PRUint32 paramCount, nsXPTCVariant* params)
+#
+
+.XPTC_InvokeByIndex:
+ mflr r0
+ stw r31,-4(sp)
+#
+# save off the incoming values in the caller's parameter area
+#
+ stw r3,24(sp) # that
+ stw r4,28(sp) # methodIndex
+ stw r5,32(sp) # paramCount
+ stw r6,36(sp) # params
+ stw r0,8(sp)
+ stwu sp,-136(sp) # = 24 for linkage area, 8 * 13 for fprData area, 8 for saved registers
+
+# prepare args for 'invoke_copy_to_stack' call
+#
+ lwz r4,168(sp) # paramCount
+ lwz r5,172(sp) # params
+ mr r6,sp # fprData
+ slwi r3,r4,3 # number of bytes of stack required
+ # at most 8*paramCount
+ addi r3,r3,28 # linkage area
+ mr r31,sp # save original stack top
+ subfc sp,r3,sp # bump the stack
+ addi r3,sp,28 # parameter pointer excludes linkage area size + 'this'
+
+ bl .invoke_copy_to_stack
+ nop
+
+ lfd f1,0(r31) # Restore floating point registers
+ lfd f2,8(r31)
+ lfd f3,16(r31)
+ lfd f4,24(r31)
+ lfd f5,32(r31)
+ lfd f6,40(r31)
+ lfd f7,48(r31)
+ lfd f8,56(r31)
+ lfd f9,64(r31)
+ lfd f10,72(r31)
+ lfd f11,80(r31)
+ lfd f12,88(r31)
+ lfd f13,96(r31)
+
+ lwz r3,160(r31) # that
+ lwz r4,0(r3) # get vTable from 'that'
+ lwz r5,164(r31) # methodIndex
+ slwi r5,r5,2 # methodIndex * 4
+ lwzx r11,r5,r4 # get function pointer
+
+ lwz r4,28(sp)
+ lwz r5,32(sp)
+ lwz r6,36(sp)
+ lwz r7,40(sp)
+ lwz r8,44(sp)
+ lwz r9,48(sp)
+ lwz r10,52(sp)
+
+ bl ._ptrgl{PR}
+ nop
+
+ mr sp,r31
+ lwz r0,144(sp)
+ addi sp,sp,136
+ mtlr r0
+ lwz r31,-4(sp)
+ blr
+
+
+# .data section
+
+ .toc # 0x00000038
+T.18.XPTC_InvokeByIndex:
+ .tc H.18.XPTC_InvokeByIndex{TC},XPTC_InvokeByIndex{DS}
+
+ .csect XPTC_InvokeByIndex{DS}
+ .long .XPTC_InvokeByIndex # "\0\0\0\0"
+ .long TOC{TC0} # "\0\0\0008"
+ .long 0x00000000 # "\0\0\0\0"
+# End csect XPTC_InvokeByIndex{DS}
+
+# .bss section
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_linux.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_linux.s
new file mode 100644
index 00000000..b9aaa997
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_linux.s
@@ -0,0 +1,113 @@
+// -*- Mode: Asm -*-
+//
+// The contents of this file are subject to the Netscape 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/NPL/
+//
+// 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 Netscape are
+// Copyright (C) 1999 Netscape Communications Corporation. All
+// Rights Reserved.
+//
+// Contributor(s):
+// Franz.Sirl-kernel@lauterbach.com (Franz Sirl)
+// beard@netscape.com (Patrick Beard)
+// waterson@netscape.com (Chris Waterson)
+//
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+ .section ".text"
+ .align 2
+ .globl XPTC_InvokeByIndex
+ .type XPTC_InvokeByIndex,@function
+
+//
+// XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+// PRUint32 paramCount, nsXPTCVariant* params)
+//
+
+XPTC_InvokeByIndex:
+ stwu sp,-32(sp) // setup standard stack frame
+ mflr r0 // save LR
+ stw r3,8(sp) // r3 <= that
+ stw r4,12(sp) // r4 <= methodIndex
+ stw r30,16(sp)
+ stw r31,20(sp)
+
+ stw r0,36(sp) // store LR backchain
+ mr r31,sp
+
+ rlwinm r10,r5,3,0,27 // r10 = (ParamCount * 2 * 4) & ~0x0f
+ addi r0,r10,96 // reserve stack for GPR and FPR register save area r0 = r10 + 96
+ lwz r9,0(sp) // r9 = backchain
+ neg r0,r0
+ stwux r9,sp,r0 // reserve stack space and save SP backchain
+
+ addi r3,sp,8 // r3 <= args
+ mr r4,r5 // r4 <= paramCount
+ mr r5,r6 // r5 <= params
+ add r6,r3,r10 // r6 <= gpregs ( == args + r10 )
+ mr r30,r6 // store in r30 for use later...
+ addi r7,r6,32 // r7 <= fpregs ( == gpregs + 32 )
+
+ bl invoke_copy_to_stack@local // (args, paramCount, params, gpregs, fpregs)
+
+ lfd f1,32(r30) // load FP registers with method parameters
+ lfd f2,40(r30)
+ lfd f3,48(r30)
+ lfd f4,56(r30)
+ lfd f5,64(r30)
+ lfd f6,72(r30)
+ lfd f7,80(r30)
+ lfd f8,88(r30)
+
+ lwz r3,8(r31) // r3 <= that
+ lwz r4,12(r31) // r4 <= methodIndex
+ lwz r5,0(r3) // r5 <= vtable ( == *that )
+#if !((__GNUC__ == 3 && __GNUC_MINOR__ < 2) || __GXX_ABI_VERSION >= 100) // G++ pre-V3 ABI
+ addi r4,r4,2 // skip first two vtable entries
+#endif
+ slwi r4,r4,2 // convert to offset ( *= 4 )
+ lwzx r0,r5,r4 // r0 <= methodpointer ( == vtable + offset )
+
+ lwz r4,4(r30) // load GP regs with method parameters
+ lwz r5,8(r30)
+ lwz r6,12(r30)
+ lwz r7,16(r30)
+ lwz r8,20(r30)
+ lwz r9,24(r30)
+ lwz r10,28(r30)
+
+ mtlr r0 // copy methodpointer to LR
+ blrl // call method
+
+ lwz r30,16(r31) // restore r30 & r31
+ lwz r31,20(r31)
+
+ lwz r11,0(sp) // clean up the stack
+ lwz r0,4(r11)
+ mtlr r0
+ mr sp,r11
+ blr
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_netbsd.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_netbsd.s
new file mode 100644
index 00000000..18c775a9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_netbsd.s
@@ -0,0 +1,114 @@
+# -*- Mode: Asm -*-
+#
+# The contents of this file are subject to the Netscape 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/NPL/
+#
+# 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 Netscape are
+# Copyright (C) 1999 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+# Franz.Sirl-kernel@lauterbach.com (Franz Sirl)
+# beard@netscape.com (Patrick Beard)
+# waterson@netscape.com (Chris Waterson)
+#
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+ .section ".text"
+ .align 2
+ .globl XPTC_InvokeByIndex
+ .type XPTC_InvokeByIndex,@function
+
+#
+# XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+# PRUint32 paramCount, nsXPTCVariant* params)
+#
+
+XPTC_InvokeByIndex:
+ stwu sp,-32(sp) # setup standard stack frame
+ mflr r0 # save LR
+ stw r3,8(sp) # r3 <= that
+ stw r4,12(sp) # r4 <= methodIndex
+ stw r30,16(sp)
+ stw r31,20(sp)
+
+ stw r0,36(sp) # store LR backchain
+ mr r31,sp
+
+ rlwinm r10,r5,3,0,27 # r10 = (ParamCount * 2 * 4) & ~0x0f
+ addi r0,r10,96 # reserve stack for GPR and FPR register save area r0 = r10 + 96
+ lwz r9,0(sp) # r9 = backchain
+ neg r0,r0
+ stwux r9,sp,r0 # reserve stack sapce and save SP backchain
+
+ addi r3,sp,8 # r3 <= args
+ mr r4,r5 # r4 <= paramCount
+ mr r5,r6 # r5 <= params
+ add r6,r3,r10 # r6 <= gpregs ( == args + r10 )
+ mr r30,r6 # store in r30 for use later...
+ addi r7,r6,32 # r7 <= fpregs ( == gpregs + 32 )
+
+ bl invoke_copy_to_stack@local # (args, paramCount, params, gpregs, fpregs)
+
+ lfd f1,32(r30) # load FP registers with method parameters
+ lfd f2,40(r30)
+ lfd f3,48(r30)
+ lfd f4,56(r30)
+ lfd f5,64(r30)
+ lfd f6,72(r30)
+ lfd f7,80(r30)
+ lfd f8,88(r30)
+
+ lwz r3,8(r31) # r3 <= that
+ lwz r4,12(r31) # r4 <= methodIndex
+ lwz r5,0(r3) # r5 <= vtable ( == *that )
+ slwi r4,r4,3 # convert to offset ( *= 8 )
+ addi r4,r4,8 # skip first two vtable entries
+ add r4,r4,r5
+ lhz r0,0(r4) # virtual base offset
+ extsh r0,r0
+ add r3,r3,r0
+ lwz r0,4(r4) # r0 <= methodpointer ( == vtable + offset )
+
+ lwz r4,4(r30) # load GP regs with method parameters
+ lwz r5,8(r30)
+ lwz r6,12(r30)
+ lwz r7,16(r30)
+ lwz r8,20(r30)
+ lwz r9,24(r30)
+ lwz r10,28(r30)
+
+ mtlr r0 # copy methodpointer to LR
+ blrl # call method
+
+ lwz r30,16(r31) # restore r30 & r31
+ lwz r31,20(r31)
+
+ lwz r11,0(sp) # clean up the stack
+ lwz r0,4(r11)
+ mtlr r0
+ mr sp,r11
+ blr
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_rhapsody.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_rhapsody.s
new file mode 100644
index 00000000..8a5c9afb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_rhapsody.s
@@ -0,0 +1,162 @@
+#
+# -*- Mode: Asm -*-
+#
+# The contents of this file are subject to the Netscape 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/NPL/
+#
+# 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 Netscape are
+# Copyright (C) 1999 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+# Patrick C. Beard <beard@netscape.com>
+#
+
+#
+# ** Assumed vtable layout (obtained by disassembling with gdb):
+# ** 4 bytes per vtable entry, skip 0th and 1st entries, so the mapping
+# ** from index to entry is (4 * index) + 8.
+#
+
+.text
+ .align 2
+#
+# XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+# PRUint32 paramCount, nsXPTCVariant* params)
+#
+
+.globl __XPTC_InvokeByIndex
+__XPTC_InvokeByIndex:
+ mflr r0
+ stw r31,-4(r1)
+#
+# save off the incoming values in the callers parameter area
+#
+ stw r3,24(r1) ; that
+ stw r4,28(r1) ; methodIndex
+ stw r5,32(r1) ; paramCount
+ stw r6,36(r1) ; params
+ stw r0,8(r1)
+ stwu r1,-144(r1) ; 24 for linkage area,
+ ; 8*13 for fprData area,
+ ; 8 for saved registers,
+ ; 8 to keep stack 16-byte aligned
+
+# set up for and call 'invoke_count_words' to get new stack size
+#
+ mr r3,r5
+ mr r4,r6
+
+ stwu r1,-24(r1)
+ bl L_invoke_count_words$stub
+ lwz r1,0(r1)
+
+# prepare args for 'invoke_copy_to_stack' call
+#
+ lwz r4,176(r1) ; paramCount
+ lwz r5,180(r1) ; params
+ mr r6,r1 ; fprData
+ slwi r3,r3,2 ; number of stack bytes required
+ addi r3,r3,28 ; linkage area
+ mr r31,r1 ; save original stack top
+ sub r1,r1,r3 ; bump the stack
+ clrrwi r1,r1,4 ; keep the stack 16-byte aligned
+ addi r3,r31,144 ; act like real alloca, so 0(sp) always
+ stw r3,0(r1) ; points back to previous stack frame
+ addi r3,r1,28 ; parameter pointer excludes linkage area size + 'this'
+
+# create "temporary" stack frame for _invoke_copy_to_stack to operate in.
+ stwu r1,-40(r1)
+ bl L_invoke_copy_to_stack$stub
+# remove temporary stack frame.
+ lwz r1,0(r1)
+
+ lfd f1,0(r31)
+ lfd f2,8(r31)
+ lfd f3,16(r31)
+ lfd f4,24(r31)
+ lfd f5,32(r31)
+ lfd f6,40(r31)
+ lfd f7,48(r31)
+ lfd f8,56(r31)
+ lfd f9,64(r31)
+ lfd f10,72(r31)
+ lfd f11,80(r31)
+ lfd f12,88(r31)
+ lfd f13,96(r31)
+
+ lwz r3,168(r31) ; that
+ lwz r4,0(r3) ; get vTable from 'that'
+ lwz r5,172(r31) ; methodIndex
+ slwi r5,r5,2 ; methodIndex * 4
+#ifndef HAVE_GCC3_ABI
+ addi r5,r5,8 ; (methodIndex * 4) + 8
+#endif
+ lwzx r12,r5,r4 ; get function pointer
+
+ lwz r4,28(r1)
+ lwz r5,32(r1)
+ lwz r6,36(r1)
+ lwz r7,40(r1)
+ lwz r8,44(r1)
+ lwz r9,48(r1)
+ lwz r10,52(r1)
+
+ mtlr r12
+ blrl
+
+ mr r1,r31
+ lwz r0,152(r1)
+ addi r1,r1,144
+ mtlr r0
+ lwz r31,-4(r1)
+
+ blr
+
+.picsymbol_stub
+L_invoke_count_words$stub:
+ .indirect_symbol _invoke_count_words
+ mflr r0
+ bcl 20,31,L1$pb
+L1$pb:
+ mflr r11
+ addis r11,r11,ha16(L1$lz-L1$pb)
+ mtlr r0
+ lwz r12,lo16(L1$lz-L1$pb)(r11)
+ mtctr r12
+ addi r11,r11,lo16(L1$lz-L1$pb)
+ bctr
+.lazy_symbol_pointer
+L1$lz:
+ .indirect_symbol _invoke_count_words
+ .long dyld_stub_binding_helper
+
+
+.picsymbol_stub
+L_invoke_copy_to_stack$stub:
+ .indirect_symbol _invoke_copy_to_stack
+ mflr r0
+ bcl 20,31,L2$pb
+L2$pb:
+ mflr r11
+ addis r11,r11,ha16(L2$lz-L2$pb)
+ mtlr r0
+ lwz r12,lo16(L2$lz-L2$pb)(r11)
+ mtctr r12
+ addi r11,r11,lo16(L2$lz-L2$pb)
+ bctr
+.lazy_symbol_pointer
+L2$lz:
+ .indirect_symbol _invoke_copy_to_stack
+ .long dyld_stub_binding_helper
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_bsdos.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_bsdos.s
new file mode 100644
index 00000000..b744ee9b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_bsdos.s
@@ -0,0 +1,121 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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 Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s): Chris Torek (torek@bsdi.com), Kurt Lidl (lidl@pix.net)
+ */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+ .global XPTC_InvokeByIndex
+/*
+ XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+*/
+XPTC_InvokeByIndex:
+ /* regular C/C++ stack frame -- see <machine/frame.h> */
+ save %sp, -96, %sp
+
+ /*
+ * invoke_count_words(paramCount, params) apparently tells us
+ * how many "32-bit words" are involved in passing the given
+ * parameters to the target function.
+ */
+ mov %i2, %o0
+ call invoke_count_words ! invoke_count_words(paramCount, params)
+ mov %i3, %o1
+
+ /*
+ * ??? Torek wonders: does invoke_count_words always force its
+ * return value to be even? If not, we would have to adjust
+ * the return value ... should make it a multiple of 8 anyway,
+ * for efficiency (32 byte cache lines); will do that here thus:
+ *
+ * We already have room (in our callee's "argument dump" area,
+ * sp->fr_argd) for six parameters, and we are going to use
+ * five of those (fr_argd[1] through fr_argd[5]) in a moment.
+ * This space is followed by fr_argx[1], room for a seventh.
+ * Thus, if invoke_count_words returns a value between 0 and 6
+ * inclusive, we do not need any stack adjustment. For values
+ * from 7 through (7+8) we want to make room for another 8
+ * parameters, and so on. Thus, we want to calculate:
+ *
+ * n_extra_words = (wordcount + 1) & ~7
+ *
+ * and then make room for that many more 32-bit words. (Normally
+ * it would be ((w+7)&~7; we just subtract off the room-for-6 we
+ * already have.)
+ */
+ inc %o0
+ andn %o0, 7, %o0
+ sll %o0, 2, %o0 ! convert to bytes
+ sub %sp, %o0, %sp ! and make room for arguments
+
+ /*
+ * Copy all the arguments to the stack, starting at the argument
+ * dump area at [%sp + 68], even though the first six arguments
+ * go in the six %o registers. We will just load up those
+ * arguments after the copy is done. The first argument to
+ * any C++ member function is always the "this" parameter so
+ * we actually start with what will go in %o1, at [%sp + 72].
+ */
+ add %sp, 72, %o0 ! invoke_copy_to_stack(addr,
+ mov %i2, %o1 ! paramCount,
+ call invoke_copy_to_stack
+ mov %i3, %o2 ! params);
+
+ /*
+ * This is the only really tricky (compiler-dependent) part
+ * (everything else here relies only on the V8 SPARC calling
+ * conventions). "methodIndex" (%i1) is an index into a C++
+ * vtable. The word at "*that" points to the vtable, but for
+ * some reason, the first function (index=0) is at vtable[2*4],
+ * the second (index 1) at vtable[3*4], the third at vtable[4*4],
+ * and so on. Thus, we want, in effect:
+ *
+ * that->vTable[index + 2]
+ */
+ ld [%i0], %l0 ! vTable = *that
+ add %i1, 2, %l1
+ sll %l1, 2, %l1
+ ld [%l0 + %l1], %l0 ! fn = vTable[index + 2]
+
+ /*
+ * Now load up the various function parameters. We do not know,
+ * nor really care, how many there are -- we just load five words
+ * from the stack (there are always at least five such words to
+ * load, even if some of them are junk) into %o1 through %o5,
+ * and set %o0 = %i0, to pass "that" to the target member function
+ * as its C++ "this" parameter.
+ *
+ * If there are more than five parameters, any extras go on our
+ * stack starting at sp->fr_argx ([%sp + 92]), which is of course
+ * where we have just copied them.
+ */
+ ld [%sp + 72], %o1
+ ld [%sp + 76], %o2
+ ld [%sp + 80], %o3
+ ld [%sp + 84], %o4
+ ld [%sp + 88], %o5
+ call %l0 ! fn(that, %o1, %o2, %o3, %o4, %o5)
+ mov %i0, %o0
+
+ ! return whatever fn() returned
+ ret
+ restore %o0, 0, %o0
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_linux.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_linux.s
new file mode 100644
index 00000000..c23fd1e7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_linux.s
@@ -0,0 +1,67 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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 Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+ .global XPTC_InvokeByIndex
+/*
+ XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+*/
+XPTC_InvokeByIndex:
+ save %sp,-(64 + 16),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 16
+ mov %i2,%o0 ! paramCount
+ call invoke_count_words ! returns the required stack size in %o0
+ mov %i3,%o1 ! params
+
+ sll %o0,2,%l0 ! number of bytes
+ sub %sp,%l0,%sp ! create the additional stack space
+
+ mov %sp,%o0 ! pointer for copied args
+ add %o0,72,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+!
+! calculate the target address from the vtable
+!
+ add %i1,1,%i1 ! vTable is zero-based, index is 1 based (?)
+ ld [%i0],%l1 ! *that --> vTable
+ sll %i1,2,%i1 ! 32 bit pointer
+ add %i1,%l1,%l1 ! vTable[index * 4], l1 now points to vTable entry
+ ld [%l1 + 4],%l0 ! target address
+
+.L5: ld [%sp + 88],%o5
+.L4: ld [%sp + 84],%o4
+.L3: ld [%sp + 80],%o3
+.L2: ld [%sp + 76],%o2
+.L1: ld [%sp + 72],%o1
+.L0:
+ jmpl %l0,%o7 ! call the routine
+! always have a 'this', from the incoming 'that'
+ mov %i0,%o0
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s
new file mode 100644
index 00000000..9a6b02ae
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s
@@ -0,0 +1,84 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * 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):
+ * David S. Miller <davem@redhat.com> (ported to gcc3)
+ *
+ * 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.
+ */
+
+/*
+ * Platform specific code to invoke XPCOM methods on native objects for
+ * Linux/Sparc with gcc 3 ABI.
+ */
+ .global XPTC_InvokeByIndex
+/*
+ * XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ * PRUint32 paramCount, nsXPTCVariant* params);
+ *
+ */
+XPTC_InvokeByIndex:
+ save %sp,-(64 + 16),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 16
+ mov %i2,%o0 ! paramCount
+ call invoke_count_words ! returns the required stack size in %o0
+ mov %i3,%o1 ! params
+
+ sll %o0,2,%l0 ! number of bytes
+ sub %sp,%l0,%sp ! create the additional stack space
+
+ mov %sp,%o0 ! pointer for copied args
+ add %o0,72,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+!
+! calculate the target address from the vtable
+!
+ ld [%i0],%l1 ! *that --> vTable
+ sll %i1,2,%i1 ! multiply index by 4
+ add %i1,%l1,%l1 ! l1 now points to vTable entry
+ ld [%l1],%l0 ! target address
+
+.L5: ld [%sp + 88],%o5
+.L4: ld [%sp + 84],%o4
+.L3: ld [%sp + 80],%o3
+.L2: ld [%sp + 76],%o2
+.L1: ld [%sp + 72],%o1
+.L0:
+ jmpl %l0,%o7 ! call the routine
+! always have a 'this', from the incoming 'that'
+ mov %i0,%o0
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_netbsd.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_netbsd.s
new file mode 100644
index 00000000..be0e34a7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_netbsd.s
@@ -0,0 +1,71 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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 Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+ .global XPTC_InvokeByIndex
+/*
+ XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+*/
+XPTC_InvokeByIndex:
+ save %sp,-(64 + 16),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 16
+ mov %i2,%o0 ! paramCount
+ call invoke_count_words ! returns the required stack size in %o0
+ mov %i3,%o1 ! params
+
+ sll %o0,2,%l0 ! number of bytes
+ sub %sp,%l0,%sp ! create the additional stack space
+
+ mov %sp,%o0 ! pointer for copied args
+ add %o0,72,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+!
+! calculate the target address from the vtable
+!
+ add %i1,1,%i1 ! vTable is zero-based, index is 1 based (?)
+ ld [%i0],%l1 ! *that --> vTable
+ sll %i1,3,%i1
+ add %i1,%l1,%l1 ! vTable[index * 8], l1 now points to vTable entry
+ lduh [%l1],%l0 ! this adjustor
+ sll %l0,16,%l0 ! sign extend to 32 bits
+ sra %l0,16,%l0
+ add %l0,%i0,%i0 ! adjust this
+ ld [%l1 + 4],%l0 ! target address
+
+.L5: ld [%sp + 88],%o5
+.L4: ld [%sp + 84],%o4
+.L3: ld [%sp + 80],%o3
+.L2: ld [%sp + 76],%o2
+.L1: ld [%sp + 72],%o1
+.L0:
+ jmpl %l0,%o7 ! call the routine
+! always have a 'this', from the incoming 'that'
+ mov %i0,%o0
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris.s
new file mode 100644
index 00000000..be0e34a7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris.s
@@ -0,0 +1,71 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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 Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+ .global XPTC_InvokeByIndex
+/*
+ XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+*/
+XPTC_InvokeByIndex:
+ save %sp,-(64 + 16),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 16
+ mov %i2,%o0 ! paramCount
+ call invoke_count_words ! returns the required stack size in %o0
+ mov %i3,%o1 ! params
+
+ sll %o0,2,%l0 ! number of bytes
+ sub %sp,%l0,%sp ! create the additional stack space
+
+ mov %sp,%o0 ! pointer for copied args
+ add %o0,72,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+!
+! calculate the target address from the vtable
+!
+ add %i1,1,%i1 ! vTable is zero-based, index is 1 based (?)
+ ld [%i0],%l1 ! *that --> vTable
+ sll %i1,3,%i1
+ add %i1,%l1,%l1 ! vTable[index * 8], l1 now points to vTable entry
+ lduh [%l1],%l0 ! this adjustor
+ sll %l0,16,%l0 ! sign extend to 32 bits
+ sra %l0,16,%l0
+ add %l0,%i0,%i0 ! adjust this
+ ld [%l1 + 4],%l0 ! target address
+
+.L5: ld [%sp + 88],%o5
+.L4: ld [%sp + 84],%o4
+.L3: ld [%sp + 80],%o3
+.L2: ld [%sp + 76],%o2
+.L1: ld [%sp + 72],%o1
+.L0:
+ jmpl %l0,%o7 ! call the routine
+! always have a 'this', from the incoming 'that'
+ mov %i0,%o0
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_GCC.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_GCC.s
new file mode 100644
index 00000000..203e3f1c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_GCC.s
@@ -0,0 +1,71 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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 Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+ .global XPTC_InvokeByIndex
+/*
+ XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+*/
+XPTC_InvokeByIndex:
+ save %sp,-(64 + 32),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 32
+ mov %i2,%o0 ! paramCount
+ call invoke_count_words ! returns the required stack size in %o0
+ mov %i3,%o1 ! params
+
+ sll %o0,2,%l0 ! number of bytes
+ sub %sp,%l0,%sp ! create the additional stack space
+
+ mov %sp,%o0 ! pointer for copied args
+ add %o0,72,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+!
+! calculate the target address from the vtable
+!
+ add %i1,1,%i1 ! vTable is zero-based, index is 1 based (?)
+ ld [%i0],%l1 ! *that --> vTable
+ sll %i1,3,%i1
+ add %i1,%l1,%l1 ! vTable[index * 8], l1 now points to vTable entry
+ lduh [%l1],%l0 ! this adjustor
+ sll %l0,16,%l0 ! sign extend to 32 bits
+ sra %l0,16,%l0
+ add %l0,%i0,%i0 ! adjust this
+ ld [%l1 + 4],%l0 ! target address
+
+.L5: ld [%sp + 88],%o5
+.L4: ld [%sp + 84],%o4
+.L3: ld [%sp + 80],%o3
+.L2: ld [%sp + 76],%o2
+.L1: ld [%sp + 72],%o1
+.L0:
+ jmpl %l0,%o7 ! call the routine
+! always have a 'this', from the incoming 'that'
+ mov %i0,%o0
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_GCC3.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_GCC3.s
new file mode 100644
index 00000000..6a2e9606
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_GCC3.s
@@ -0,0 +1,70 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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 Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ * David Baron <dbaron@dbaron.org> (ported to
+ * gcc 3/sparc-sun-solaris from gcc 2.x/sparc-sun-solaris)
+ */
+
+/*
+ * Platform specific code to invoke XPCOM methods on native objects for
+ * solaris/sparc with gcc 3 ABI.
+ */
+ .global XPTC_InvokeByIndex
+/*
+ * XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ * PRUint32 paramCount, nsXPTCVariant* params);
+ */
+XPTC_InvokeByIndex:
+ save %sp,-(64 + 32),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 32
+ mov %i2,%o0 ! paramCount
+ call invoke_count_words ! returns the required stack size in %o0
+ mov %i3,%o1 ! params
+
+ sll %o0,2,%l0 ! number of bytes
+ sub %sp,%l0,%sp ! create the additional stack space
+
+ mov %sp,%o0 ! pointer for copied args
+ add %o0,72,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+!
+! calculate the target address from the vtable
+!
+ ld [%i0],%l1 ! *that --> vTable
+ sll %i1,2,%i1 ! multiply index by 4
+ add %i1,%l1,%l1 ! l1 now points to vTable entry
+ ld [%l1],%l0 ! target address
+
+.L5: ld [%sp + 88],%o5
+.L4: ld [%sp + 84],%o4
+.L3: ld [%sp + 80],%o3
+.L2: ld [%sp + 76],%o2
+.L1: ld [%sp + 72],%o1
+.L0:
+ jmpl %l0,%o7 ! call the routine
+! always have a 'this', from the incoming 'that'
+ mov %i0,%o0
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_SUNW.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_SUNW.s
new file mode 100644
index 00000000..b70f1b46
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_SUNW.s
@@ -0,0 +1,72 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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 Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+ .global XPTC_InvokeByIndex
+ .type XPTC_InvokeByIndex, #function
+/*
+ XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+*/
+XPTC_InvokeByIndex:
+ save %sp,-(64 + 32),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 32
+ sll %i2,3,%l0 ! assume the worst case
+ ! paramCount * 2 * 4 bytes
+ cmp %l0, 0 ! are there any args? If not,
+ be .invoke ! no need to copy args to stack
+
+ sub %sp,%l0,%sp ! create the additional stack space
+ add %sp,72,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+
+!
+! load arguments from stack into the outgoing registers
+!
+ ld [%sp + 72],%o1
+ ld [%sp + 76],%o2
+ ld [%sp + 80],%o3
+ ld [%sp + 84],%o4
+ ld [%sp + 88],%o5
+
+!
+! calculate the target address from the vtable
+!
+.invoke:
+ sll %i1,2,%l0 ! index *= 4
+ add %l0,8,%l0 ! there are 2 extra entries in the vTable
+ ld [%i0],%l1 ! *that --> address of vtable
+ ld [%l0 + %l1],%l0 ! that->vtable[index * 4 + 8] --> address
+
+ jmpl %l0,%o7 ! call the routine
+ mov %i0,%o0 ! move 'this' pointer to out register
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
+
+ .size XPTC_InvokeByIndex, .-XPTC_InvokeByIndex
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparcv9_solaris_SUNW.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparcv9_solaris_SUNW.s
new file mode 100644
index 00000000..232ed6bd
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparcv9_solaris_SUNW.s
@@ -0,0 +1,103 @@
+/* -*- Mode: asm; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * 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 Netscape are
+ * Copyright (C) 2001 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ * Stuart Parmenter <pavlov@netscape.com>
+ * Chris Seawood <cls@seawood.org>
+ */
+
+/*
+ Platform specific code to invoke XPCOM methods on native objects
+ for sparcv9 Solaris.
+
+ See the SPARC Compliance Definition (SCD) Chapter 3
+ for more information about what is going on here, including
+ the use of BIAS (0x7ff).
+ The SCD is available from http://www.sparc.com/.
+*/
+
+ .global XPTC_InvokeByIndex
+ .type XPTC_InvokeByIndex, #function
+
+/*
+ XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+*/
+XPTC_InvokeByIndex:
+ save %sp,-(128 + 64),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 64
+ sll %i2,4,%l0 ! assume the worst case
+ ! paramCount * 2 * 8 bytes
+ cmp %l0, 0 ! are there any args? If not,
+ be .invoke ! no need to copy args to stack
+
+ sub %sp,%l0,%sp ! create the additional stack space
+ add %sp,0x7ff+136,%o0 ! step past the register window, the
+ ! struct result pointer and the 'this' slot
+ mov %i2,%o1 ! paramCount
+ call invoke_copy_to_stack
+ mov %i3,%o2 ! params
+
+!
+! load arguments from stack into the outgoing registers
+! BIAS is 0x7ff (2047)
+!
+
+! load the %o1..5 64bit (extended word) output registers registers
+ ldx [%sp + 0x7ff + 136],%o1 ! %i1
+ ldx [%sp + 0x7ff + 144],%o2 ! %i2
+ ldx [%sp + 0x7ff + 152],%o3 ! %i3
+ ldx [%sp + 0x7ff + 160],%o4 ! %i4
+ ldx [%sp + 0x7ff + 168],%o5 ! %i5
+
+! load the even number double registers starting with %d2
+ ldd [%sp + 0x7ff + 136],%d2
+ ldd [%sp + 0x7ff + 144],%d4
+ ldd [%sp + 0x7ff + 152],%d6
+ ldd [%sp + 0x7ff + 160],%d8
+ ldd [%sp + 0x7ff + 168],%d10
+ ldd [%sp + 0x7ff + 176],%d12
+ ldd [%sp + 0x7ff + 184],%d14
+ ldd [%sp + 0x7ff + 192],%d16
+ ldd [%sp + 0x7ff + 200],%d18
+ ldd [%sp + 0x7ff + 208],%d20
+ ldd [%sp + 0x7ff + 216],%d22
+ ldd [%sp + 0x7ff + 224],%d24
+ ldd [%sp + 0x7ff + 232],%d26
+ ldd [%sp + 0x7ff + 240],%d28
+ ldd [%sp + 0x7ff + 248],%d30
+
+!
+! calculate the target address from the vtable
+!
+.invoke:
+ sll %i1,3,%l0 ! index *= 8
+ add %l0,16,%l0 ! there are 2 extra entries in the vTable (16bytes)
+ ldx [%i0],%l1 ! *that --> address of vtable
+ ldx [%l0 + %l1],%l0 ! that->vtable[index * 8 + 16] --> address
+
+ jmpl %l0,%o7 ! call the routine
+ mov %i0,%o0 ! move 'this' pointer to out register
+
+ mov %o0,%i0 ! propagate return value
+ ret
+ restore
+
+ .size XPTC_InvokeByIndex, .-XPTC_InvokeByIndex
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_gcc_x86_unix.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_gcc_x86_unix.cpp
new file mode 100644
index 00000000..79b17ae3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_gcc_x86_unix.cpp
@@ -0,0 +1,215 @@
+/* -*- 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 ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#ifdef __GNUC__ /* Gnu compiler. */
+
+#include "xptcprivate.h"
+#include "xptc_platforms_unixish_x86.h"
+#include "xptc_gcc_x86_unix.h"
+
+extern "C" {
+#ifndef XP_WIN32
+static
+#endif
+void ATTRIBUTE_USED __attribute__ ((regparm(3)))
+invoke_copy_to_stack(PRUint32 paramCount, nsXPTCVariant* s, PRUint32* d)
+{
+ for(PRUint32 i = paramCount; i >0; i--, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I64 : *((PRInt64*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U64 : *((PRUint64*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ default : *((void**)d) = s->val.p; break;
+ }
+ }
+}
+} // extern "C"
+
+// NOTE! See xptc_gcc_x86_unix.h for the reason why this function exists.
+#if (__GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ == 0))
+PRUint32
+xptc_invoke_copy_to_stack_keeper (void)
+{
+ PRUint32 dummy1;
+ void ATTRIBUTE_USED __attribute__ ((regparm(3))) (*dummy2)
+ (PRUint32, nsXPTCVariant*, PRUint32*) = invoke_copy_to_stack;
+
+// dummy2 references invoke_copy_to_stack, now we have to "use" it
+ __asm__ __volatile__ (
+ ""
+ : "=&a" (dummy1)
+ : "g" (dummy2)
+ );
+
+ return dummy1 & 0xF0F00000;
+}
+#endif
+
+
+/*
+ XPTC_PUBLIC_API(nsresult)
+ XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+ Each param takes at most two 4-byte words.
+ It doesn't matter if we push too many words, and calculating the exact
+ amount takes time.
+
+ that = ebp + 0x08
+ methodIndex = ebp + 0x0c
+ paramCount = ebp + 0x10
+ params = ebp + 0x14
+
+ NOTE NOTE NOTE:
+ As of 2002-04-29 this function references no global variables nor does
+ it call non-static functions so preserving and loading the PIC register
+ is unnecessary. Define MOZ_PRESERVE_PIC if this changes. See mozilla
+ bug 140412 for details. However, avoid this if you can. It's slower.
+*/
+/*
+ * Hack for gcc for win32. Functions used externally must be
+ * explicitly dllexported.
+ * Bug 226609
+ */
+#ifdef XP_WIN32
+extern "C" {
+ nsresult _XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+ XPTC_PUBLIC_API(nsresult)
+ XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params) {
+ return _XPTC_InvokeByIndex(that, methodIndex, paramCount, params);
+ }
+}
+#endif
+
+__asm__ (
+ ".text\n\t"
+/* alignment here seems unimportant here; this was 16, now it's 2 which
+ is what xptcstubs uses. */
+ ".align 2\n\t"
+#ifdef XP_WIN32
+ ".globl " SYMBOL_UNDERSCORE "_XPTC_InvokeByIndex\n\t"
+ ".type " SYMBOL_UNDERSCORE "_XPTC_InvokeByIndex,@function\n"
+ SYMBOL_UNDERSCORE "_XPTC_InvokeByIndex:\n\t"
+#else
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+ ".globl " SYMBOL_UNDERSCORE "VBoxNsxpXPTC_InvokeByIndex\n\t"
+ ".type " SYMBOL_UNDERSCORE "VBoxNsxpXPTC_InvokeByIndex,@function\n"
+ SYMBOL_UNDERSCORE "VBoxNsxpXPTC_InvokeByIndex:\n\t"
+#else
+ ".globl " SYMBOL_UNDERSCORE "XPTC_InvokeByIndex\n\t"
+ ".type " SYMBOL_UNDERSCORE "XPTC_InvokeByIndex,@function\n"
+ SYMBOL_UNDERSCORE "XPTC_InvokeByIndex:\n\t"
+#endif
+#endif
+ "pushl %ebp\n\t"
+ "movl %esp, %ebp\n\t"
+#ifdef MOZ_PRESERVE_PIC
+ "pushl %ebx\n\t"
+ "call 0f\n\t"
+ ".subsection 1\n"
+ "0:\n\t"
+ "movl (%esp), %ebx\n\t"
+ "ret\n\t"
+ ".previous\n\t"
+ "addl $_GLOBAL_OFFSET_TABLE_, %ebx\n\t"
+#endif
+ "movl 0x10(%ebp), %eax\n\t"
+ "leal 0(,%eax,8),%edx\n\t"
+ "movl %esp, %ecx\n\t"
+ "subl %edx, %ecx\n\t"
+/* Since there may be 64-bit data, it occurs to me that aligning this
+ space might be a performance gain. However, I don't think the rest
+ of mozilla worries about such things. In any event, do it here.
+ "andl $0xfffffff8, %ecx\n\t"
+ */
+ "movl %ecx, %esp\n\t" /* make stack space */
+ "movl 0x14(%ebp), %edx\n\t"
+ "call " SYMBOL_UNDERSCORE "invoke_copy_to_stack\n\t"
+ "movl 0x08(%ebp), %ecx\n\t" /* 'that' */
+#ifdef CFRONT_STYLE_THIS_ADJUST
+ "movl (%ecx), %edx\n\t"
+ "movl 0x0c(%ebp), %eax\n\t" /* function index */
+ "shll $3, %eax\n\t" /* *= 8 */
+ "addl $8, %eax\n\t" /* += 8 skip first entry */
+ "addl %eax, %edx\n\t"
+ "movswl (%edx), %eax\n\t" /* 'this' offset */
+ "addl %eax, %ecx\n\t"
+ "pushl %ecx\n\t"
+ "addl $4, %edx\n\t" /* += 4, method pointer */
+#else /* THUNK_BASED_THIS_ADJUST */
+ "pushl %ecx\n\t"
+ "movl (%ecx), %edx\n\t"
+ "movl 0x0c(%ebp), %eax\n\t" /* function index */
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+ "leal (%edx,%eax,4), %edx\n\t"
+#else /* not G++ V3 ABI */
+ "leal 8(%edx,%eax,4), %edx\n\t"
+#endif /* G++ V3 ABI */
+#endif
+ "call *(%edx)\n\t"
+#ifdef MOZ_PRESERVE_PIC
+ "movl -4(%ebp), %ebx\n\t"
+#endif
+ "movl %ebp, %esp\n\t"
+ "popl %ebp\n\t"
+ "ret\n"
+#ifdef XP_WIN32
+ ".size " SYMBOL_UNDERSCORE "_XPTC_InvokeByIndex, . -" SYMBOL_UNDERSCORE "_XPTC_InvokeByIndex\n\t"
+#else
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+ ".size " SYMBOL_UNDERSCORE "VBoxNsxpXPTC_InvokeByIndex, . -" SYMBOL_UNDERSCORE "VBoxNsxpXPTC_InvokeByIndex\n\t"
+#else
+ ".size " SYMBOL_UNDERSCORE "XPTC_InvokeByIndex, . -" SYMBOL_UNDERSCORE "XPTC_InvokeByIndex\n\t"
+#endif
+#endif
+);
+
+#else
+#error "can't find a compiler to use"
+#endif /* __GNUC__ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ipf32.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ipf32.cpp
new file mode 100644
index 00000000..5a959317
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ipf32.cpp
@@ -0,0 +1,164 @@
+
+/* -*- 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) 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 "xptcprivate.h"
+
+#include <iostream.h>
+
+// "This code is for IA64 only"
+
+
+/* invoke_copy_to_stack() will copy from variant array 's' to
+ * the stack argument area 'mloc', the integer register area 'iloc', and
+ * the float register area 'floc'.
+ *
+ */
+extern "C" void
+invoke_copy_to_stack(uint64_t* mloc, uint64_t* iloc, uint64_t* floc,
+ const PRUint32 paramCount, nsXPTCVariant* s)
+{
+ uint64_t* dest = mloc;
+ PRUint32 len = paramCount;
+ nsXPTCVariant* source = s;
+
+ PRUint32 indx;
+ PRUint32 endlen;
+ endlen = (len > 7) ? 7 : len;
+ /* handle the memory arguments */
+ for (indx = 7; indx < len; ++indx)
+ {
+ if (source[indx].IsPtrData())
+ {
+#ifdef __LP64__
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].ptr;
+#else
+ /* 32 bit pointer mode */
+ uint32_t* adr = (uint32_t*) dest;
+ *(adr) = 0;
+ *(adr+1) = (uint32_t) source[indx].ptr;
+#endif
+ }
+ else
+ switch (source[indx].type)
+ {
+ case nsXPTType::T_I8 : *(dest) = source[indx].val.i8; break;
+ case nsXPTType::T_I16 : *(dest) = source[indx].val.i16; break;
+ case nsXPTType::T_I32 : *(dest) = source[indx].val.i32; break;
+ case nsXPTType::T_I64 : *(dest) = source[indx].val.i64; break;
+ case nsXPTType::T_U8 : *(dest) = source[indx].val.u8; break;
+ case nsXPTType::T_U16 : *(dest) = source[indx].val.u16; break;
+ case nsXPTType::T_U32 : *(dest) = source[indx].val.u32; break;
+ case nsXPTType::T_U64 : *(dest) = source[indx].val.u64; break;
+ case nsXPTType::T_FLOAT : *(dest) = source[indx].val.u32; break;
+ case nsXPTType::T_DOUBLE: *(dest) = source[indx].val.u64; break;
+ case nsXPTType::T_BOOL : *(dest) = source[indx].val.b; break;
+ case nsXPTType::T_CHAR : *(dest) = source[indx].val.c; break;
+ case nsXPTType::T_WCHAR : *(dest) = source[indx].val.wc; break;
+ default:
+ // all the others are plain pointer types
+#ifdef __LP64__
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].val.p;
+#else
+ {
+ /* 32 bit pointer mode */
+ uint32_t* adr = (uint32_t*) dest;
+ *(adr) = 0;
+ *(adr+1) = (uint32_t) source[indx].val.p;
+ }
+#endif
+ }
+ ++dest;
+ }
+ /* process register arguments */
+ dest = iloc;
+ for (indx = 0; indx < endlen; ++indx)
+ {
+ if (source[indx].IsPtrData())
+ {
+#ifdef __LP64__
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].ptr;
+#else
+ /* 32 bit pointer mode */
+ uint32_t* adr = (uint32_t*) dest;
+ *(adr) = 0;
+ *(adr+1) = (uint32_t) source[indx].ptr;
+#endif
+ }
+ else
+ switch (source[indx].type)
+ {
+ case nsXPTType::T_I8 : *(dest) = source[indx].val.i8; break;
+ case nsXPTType::T_I16 : *(dest) = source[indx].val.i16; break;
+ case nsXPTType::T_I32 : *(dest) = source[indx].val.i32; break;
+ case nsXPTType::T_I64 : *(dest) = source[indx].val.i64; break;
+ case nsXPTType::T_U8 : *(dest) = source[indx].val.u8; break;
+ case nsXPTType::T_U16 : *(dest) = source[indx].val.u16; break;
+ case nsXPTType::T_U32 : *(dest) = source[indx].val.u32; break;
+ case nsXPTType::T_U64 : *(dest) = source[indx].val.u64; break;
+ case nsXPTType::T_FLOAT :
+ *((double*) (floc++)) = (double) source[indx].val.f;
+ break;
+ case nsXPTType::T_DOUBLE:
+ *((double*) (floc++)) = source[indx].val.d;
+ break;
+ case nsXPTType::T_BOOL : *(dest) = source[indx].val.b; break;
+ case nsXPTType::T_CHAR : *(dest) = source[indx].val.c; break;
+ case nsXPTType::T_WCHAR : *(dest) = source[indx].val.wc; break;
+ default:
+ // all the others are plain pointer types
+#ifdef __LP64__
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].val.p;
+#else
+ {
+ /* 32 bit pointer mode */
+ uint32_t* adr = (uint32_t*) dest;
+ *(adr) = 0;
+ *(adr+1) = (uint32_t) source[indx].val.p;
+ }
+#endif
+ }
+ ++dest;
+ }
+
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ipf64.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ipf64.cpp
new file mode 100644
index 00000000..356c2c7b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ipf64.cpp
@@ -0,0 +1,133 @@
+
+/* -*- 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) 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 "xptcprivate.h"
+
+#include <stdint.h>
+#include <iostream.h>
+
+// "This code is for IA64 only"
+
+
+/* invoke_copy_to_stack() will copy from variant array 's' to
+ * the stack argument area 'mloc', the integer register area 'iloc', and
+ * the float register area 'floc'.
+ *
+ */
+extern "C" void
+invoke_copy_to_stack(uint64_t* mloc, uint64_t* iloc, uint64_t* floc,
+ const PRUint32 paramCount, nsXPTCVariant* s)
+{
+ uint64_t* dest = mloc;
+ PRUint32 len = paramCount;
+ nsXPTCVariant* source = s;
+
+ PRUint32 indx;
+ PRUint32 endlen;
+ endlen = (len > 7) ? 7 : len;
+ /* handle the memory arguments */
+ for (indx = 7; indx < len; ++indx)
+ {
+ if (source[indx].IsPtrData())
+ {
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].ptr;
+ }
+ else
+ switch (source[indx].type)
+ {
+ case nsXPTType::T_I8 : *(dest) = source[indx].val.i8; break;
+ case nsXPTType::T_I16 : *(dest) = source[indx].val.i16; break;
+ case nsXPTType::T_I32 : *(dest) = source[indx].val.i32; break;
+ case nsXPTType::T_I64 : *(dest) = source[indx].val.i64; break;
+ case nsXPTType::T_U8 : *(dest) = source[indx].val.u8; break;
+ case nsXPTType::T_U16 : *(dest) = source[indx].val.u16; break;
+ case nsXPTType::T_U32 : *(dest) = source[indx].val.u32; break;
+ case nsXPTType::T_U64 : *(dest) = source[indx].val.u64; break;
+ case nsXPTType::T_FLOAT : *(dest) = source[indx].val.u32; break;
+ case nsXPTType::T_DOUBLE: *(dest) = source[indx].val.u64; break;
+ case nsXPTType::T_BOOL : *(dest) = source[indx].val.b; break;
+ case nsXPTType::T_CHAR : *(dest) = source[indx].val.c; break;
+ case nsXPTType::T_WCHAR : *(dest) = source[indx].val.wc; break;
+ default:
+ // all the others are plain pointer types
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].val.p;
+ }
+ ++dest;
+ }
+ /* process register arguments */
+ dest = iloc;
+ for (indx = 0; indx < endlen; ++indx)
+ {
+ if (source[indx].IsPtrData())
+ {
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].ptr;
+ }
+ else
+ switch (source[indx].type)
+ {
+ case nsXPTType::T_I8 : *(dest) = source[indx].val.i8; break;
+ case nsXPTType::T_I16 : *(dest) = source[indx].val.i16; break;
+ case nsXPTType::T_I32 : *(dest) = source[indx].val.i32; break;
+ case nsXPTType::T_I64 : *(dest) = source[indx].val.i64; break;
+ case nsXPTType::T_U8 : *(dest) = source[indx].val.u8; break;
+ case nsXPTType::T_U16 : *(dest) = source[indx].val.u16; break;
+ case nsXPTType::T_U32 : *(dest) = source[indx].val.u32; break;
+ case nsXPTType::T_U64 : *(dest) = source[indx].val.u64; break;
+ case nsXPTType::T_FLOAT :
+ *((double*) (floc++)) = (double) source[indx].val.f;
+ break;
+ case nsXPTType::T_DOUBLE:
+ *((double*) (floc++)) = source[indx].val.d;
+ break;
+ case nsXPTType::T_BOOL : *(dest) = source[indx].val.b; break;
+ case nsXPTType::T_CHAR : *(dest) = source[indx].val.c; break;
+ case nsXPTType::T_WCHAR : *(dest) = source[indx].val.wc; break;
+ default:
+ // all the others are plain pointer types
+ /* 64 bit pointer mode */
+ *((void**) dest) = source[indx].val.p;
+ }
+ ++dest;
+ }
+
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_irix.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_irix.cpp
new file mode 100644
index 00000000..67aa6144
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_irix.cpp
@@ -0,0 +1,173 @@
+/* -*- 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 ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#if (_MIPS_SIM != _ABIN32)
+#error "This code is for IRIX N32 only"
+#endif
+
+extern "C" uint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ return(paramCount*2);
+}
+
+extern "C" void
+invoke_copy_to_stack(PRUint64* d, PRUint32 paramCount,
+ nsXPTCVariant* s, PRUint64 *regs)
+{
+#define N_ARG_REGS 7 /* 8 regs minus 1 for "this" ptr */
+
+ for (PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if (s->IsPtrData()) {
+ if (i < N_ARG_REGS)
+ regs[i] = (PRUint64)s->ptr;
+ else
+ *d++ = (PRUint64)s->ptr;
+ continue;
+ }
+ switch (s->type) {
+ //
+ // signed types first
+ //
+ case nsXPTType::T_I8:
+ if (i < N_ARG_REGS)
+ ((PRInt64*)regs)[i] = s->val.i8;
+ else
+ *d++ = s->val.i8;
+ break;
+ case nsXPTType::T_I16:
+ if (i < N_ARG_REGS)
+ ((PRInt64*)regs)[i] = s->val.i16;
+ else
+ *d++ = s->val.i16;
+ break;
+ case nsXPTType::T_I32:
+ if (i < N_ARG_REGS)
+ ((PRInt64*)regs)[i] = s->val.i32;
+ else
+ *d++ = s->val.i32;
+ break;
+ case nsXPTType::T_I64:
+ if (i < N_ARG_REGS)
+ ((PRInt64*)regs)[i] = s->val.i64;
+ else
+ *d++ = s->val.i64;
+ break;
+ //
+ // unsigned types next
+ //
+ case nsXPTType::T_U8:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.u8;
+ else
+ *d++ = s->val.u8;
+ break;
+ case nsXPTType::T_U16:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.u16;
+ else
+ *d++ = s->val.u16;
+ break;
+ case nsXPTType::T_U32:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.u32;
+ else
+ *d++ = s->val.u32;
+ break;
+ case nsXPTType::T_U64:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.u64;
+ else
+ *d++ = s->val.u64;
+ break;
+ case nsXPTType::T_FLOAT:
+ if (i < N_ARG_REGS)
+ // Place a float in least significant bytes.
+ *(float*)(((char*)&regs[i+1]) - sizeof(float)) = s->val.f;
+ else
+ *(float*)d++ = s->val.f;
+ break;
+ case nsXPTType::T_DOUBLE:
+ if (i < N_ARG_REGS)
+ *(double*)&regs[i] = s->val.d;
+ else
+ *(double*)d++ = s->val.d;
+ break;
+ case nsXPTType::T_BOOL:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.b;
+ else
+ *d++ = s->val.b;
+ break;
+ case nsXPTType::T_CHAR:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.c;
+ else
+ *d++ = s->val.c;
+ break;
+ case nsXPTType::T_WCHAR:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.wc;
+ else
+ *d++ = s->val.wc;
+ break;
+ default:
+ // all the others are plain pointer types
+ if (i < N_ARG_REGS)
+ regs[i] = (PRUint64)s->val.p;
+ else
+ *d++ = (PRUint64)s->val.p;
+ break;
+ }
+ }
+}
+
+extern "C" nsresult _XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+extern "C"
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ return _XPTC_InvokeByIndex(that, methodIndex, paramCount, params);
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_alpha.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_alpha.cpp
new file mode 100644
index 00000000..7f7d84c3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_alpha.cpp
@@ -0,0 +1,181 @@
+/* -*- 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):
+ * Glen Nakamura <glen@imodulo.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 ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+/* Prototype specifies unmangled function name and disables unused warning */
+static void
+invoke_copy_to_stack(PRUint64* d, PRUint32 paramCount, nsXPTCVariant* s)
+__asm__("invoke_copy_to_stack") __attribute__((unused));
+
+static void
+invoke_copy_to_stack(PRUint64* d, PRUint32 paramCount, nsXPTCVariant* s)
+{
+ const PRUint8 NUM_ARG_REGS = 6-1; // -1 for "this" pointer
+
+ for(PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *d = (PRUint64)s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *d = (PRUint64)s->val.i8; break;
+ case nsXPTType::T_I16 : *d = (PRUint64)s->val.i16; break;
+ case nsXPTType::T_I32 : *d = (PRUint64)s->val.i32; break;
+ case nsXPTType::T_I64 : *d = (PRUint64)s->val.i64; break;
+ case nsXPTType::T_U8 : *d = (PRUint64)s->val.u8; break;
+ case nsXPTType::T_U16 : *d = (PRUint64)s->val.u16; break;
+ case nsXPTType::T_U32 : *d = (PRUint64)s->val.u32; break;
+ case nsXPTType::T_U64 : *d = (PRUint64)s->val.u64; break;
+ case nsXPTType::T_FLOAT :
+ if(i < NUM_ARG_REGS)
+ {
+ // convert floats to doubles if they are to be passed
+ // via registers so we can just deal with doubles later
+ union { PRUint64 u64; double d; } t;
+ t.d = (double)s->val.f;
+ *d = t.u64;
+ }
+ else
+ // otherwise copy to stack normally
+ *d = (PRUint64)s->val.u32;
+ break;
+ case nsXPTType::T_DOUBLE : *d = (PRUint64)s->val.u64; break;
+ case nsXPTType::T_BOOL : *d = (PRUint64)s->val.b; break;
+ case nsXPTType::T_CHAR : *d = (PRUint64)s->val.c; break;
+ case nsXPTType::T_WCHAR : *d = (PRUint64)s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *d = (PRUint64)s->val.p;
+ break;
+ }
+ }
+}
+
+/*
+ * XPTC_PUBLIC_API(nsresult)
+ * XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ * PRUint32 paramCount, nsXPTCVariant* params)
+ */
+__asm__(
+ "#### XPTC_InvokeByIndex ####\n"
+".text\n\t"
+ ".align 5\n\t"
+ ".globl XPTC_InvokeByIndex\n\t"
+ ".ent XPTC_InvokeByIndex\n"
+"XPTC_InvokeByIndex:\n\t"
+ ".frame $15,32,$26,0\n\t"
+ ".mask 0x4008000,-32\n\t"
+ "ldgp $29,0($27)\n"
+"$XPTC_InvokeByIndex..ng:\n\t"
+ "subq $30,32,$30\n\t"
+ "stq $26,0($30)\n\t"
+ "stq $15,8($30)\n\t"
+ "bis $30,$30,$15\n\t"
+ ".prologue 1\n\t"
+
+ /*
+ * Allocate enough stack space to hold the greater of 6 or "paramCount"+1
+ * parameters. (+1 for "this" pointer) Room for at least 6 parameters
+ * is required for storage of those passed via registers.
+ */
+
+ "bis $31,5,$2\n\t" /* count = MAX(5, "paramCount") */
+ "cmplt $2,$18,$1\n\t"
+ "cmovne $1,$18,$2\n\t"
+ "s8addq $2,16,$1\n\t" /* room for count+1 params (8 bytes each) */
+ "bic $1,15,$1\n\t" /* stack space is rounded up to 0 % 16 */
+ "subq $30,$1,$30\n\t"
+
+ "stq $16,0($30)\n\t" /* save "that" (as "this" pointer) */
+ "stq $17,16($15)\n\t" /* save "methodIndex" */
+
+ "addq $30,8,$16\n\t" /* pass stack pointer */
+ "bis $18,$18,$17\n\t" /* pass "paramCount" */
+ "bis $19,$19,$18\n\t" /* pass "params" */
+ "bsr $26,$invoke_copy_to_stack..ng\n\t" /* call invoke_copy_to_stack */
+
+ /*
+ * Copy the first 6 parameters to registers and remove from stack frame.
+ * Both the integer and floating point registers are set for each parameter
+ * except the first which is the "this" pointer. (integer only)
+ * The floating point registers are all set as doubles since the
+ * invoke_copy_to_stack function should have converted the floats.
+ */
+ "ldq $16,0($30)\n\t" /* integer registers */
+ "ldq $17,8($30)\n\t"
+ "ldq $18,16($30)\n\t"
+ "ldq $19,24($30)\n\t"
+ "ldq $20,32($30)\n\t"
+ "ldq $21,40($30)\n\t"
+ "ldt $f17,8($30)\n\t" /* floating point registers */
+ "ldt $f18,16($30)\n\t"
+ "ldt $f19,24($30)\n\t"
+ "ldt $f20,32($30)\n\t"
+ "ldt $f21,40($30)\n\t"
+
+ "addq $30,48,$30\n\t" /* remove params from stack */
+
+ /*
+ * Call the virtual function with the constructed stack frame.
+ */
+ "bis $16,$16,$1\n\t" /* load "this" */
+ "ldq $2,16($15)\n\t" /* load "methodIndex" */
+ "ldq $1,0($1)\n\t" /* load vtable */
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+ "s8addq $2,$31,$2\n\t" /* vtable index = "methodIndex" * 8 */
+#else /* not G++ V3 ABI */
+ "s8addq $2,16,$2\n\t" /* vtable index = "methodIndex" * 8 + 16 */
+#endif /* G++ V3 ABI */
+ "addq $1,$2,$1\n\t"
+ "ldq $27,0($1)\n\t" /* load address of function */
+ "jsr $26,($27),0\n\t" /* call virtual function */
+ "ldgp $29,0($26)\n\t"
+
+ "bis $15,$15,$30\n\t"
+ "ldq $26,0($30)\n\t"
+ "ldq $15,8($30)\n\t"
+ "addq $30,32,$30\n\t"
+ "ret $31,($26),1\n\t"
+ ".end XPTC_InvokeByIndex"
+ );
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_m68k.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_m68k.cpp
new file mode 100644
index 00000000..363e45e0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_m68k.cpp
@@ -0,0 +1,170 @@
+/* -*- 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 ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+// Remember that these 'words' are 32bit DWORDS
+
+extern "C" {
+ static PRUint32
+ invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+ {
+ PRUint32 result = 0;
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ return result;
+ }
+
+ void
+ invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPTCVariant* s)
+ {
+ for(PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ // 8 and 16 bit types should be promoted to 32 bits when copying
+ // onto the stack.
+ case nsXPTType::T_I8 : *((PRUint32*)d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((PRUint32*)d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((PRInt32*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((PRInt64*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((PRUint32*)d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((PRUint32*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((PRUint32*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((PRUint64*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ case nsXPTType::T_BOOL : *((PRBool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((PRUint32*)d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break;
+
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+ }
+}
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ PRUint32 result, n;
+
+ n = invoke_count_words(paramCount, params) * 4;
+
+ __asm__ __volatile__(
+ "subl %5, %/sp\n\t" /* make room for params */
+ "movl %/sp, %/a0\n\t"
+ "movl %4, %/sp@-\n\t"
+ "movl %3, %/sp@-\n\t"
+ "movl %/a0, %/sp@-\n\t"
+ "jbsr invoke_copy_to_stack\n\t" /* copy params */
+ "addl #12, %/sp\n\t"
+ "movl %1, %/a0\n\t"
+ "movl %/a0, %/sp@-\n\t"
+ "movl %/a0@, %/a0\n\t"
+ "movl %2, %/d0\n\t" /* function index */
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+ "movl %/a0@(%/d0:l:4), %/a0\n\t"
+#else /* not V3 */
+ "movl %/a0@(8,%/d0:l:4), %/a0\n\t"
+#endif
+ "jbsr %/a0@\n\t" /* safe to not cleanup sp */
+ "movl %/d0, %0\n\t"
+ "addql #4, %/sp\n\t"
+ "addl %5, %/sp"
+ : "=g" (result) /* %0 */
+ : "g" (that), /* %1 */
+ "g" (methodIndex), /* %2 */
+ "g" (paramCount), /* %3 */
+ "g" (params), /* %4 */
+ "g" (n) /* %5 */
+ : "a0", "a1", "d0", "d1", "memory"
+ );
+
+ return result;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_s390.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_s390.cpp
new file mode 100644
index 00000000..5da035ca
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_s390.cpp
@@ -0,0 +1,254 @@
+/* -*- 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 ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+
+static PRUint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ PRUint32 overflow = 0, gpr = 1 /*this*/, fpr = 0;
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ if (gpr < 5) gpr++; else overflow++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ case nsXPTType::T_I64 :
+ if (gpr < 4) gpr+=2; else gpr=5, overflow+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ case nsXPTType::T_U64 :
+ if (gpr < 4) gpr+=2; else gpr=5, overflow+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ if (fpr < 2) fpr++; else overflow++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ if (fpr < 2) fpr++; else overflow+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ default:
+ // all the others are plain pointer types
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ }
+ }
+ /* Round up number of overflow words to ensure stack
+ stays aligned to 8 bytes. */
+ return (overflow + 1) & ~1;
+}
+
+static void
+invoke_copy_to_stack(PRUint32 paramCount, nsXPTCVariant* s, PRUint32* d_ov, PRUint32 overflow)
+{
+ PRUint32 *d_gpr = d_ov + overflow;
+ PRUint64 *d_fpr = (PRUint64 *)(d_gpr + 4);
+ PRUint32 gpr = 1 /*this*/, fpr = 0;
+
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ if (gpr < 5)
+ *((void**)d_gpr) = s->ptr, d_gpr++, gpr++;
+ else
+ *((void**)d_ov ) = s->ptr, d_ov++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ if (gpr < 5)
+ *((PRInt32*) d_gpr) = s->val.i8, d_gpr++, gpr++;
+ else
+ *((PRInt32*) d_ov ) = s->val.i8, d_ov++;
+ break;
+ case nsXPTType::T_I16 :
+ if (gpr < 5)
+ *((PRInt32*) d_gpr) = s->val.i16, d_gpr++, gpr++;
+ else
+ *((PRInt32*) d_ov ) = s->val.i16, d_ov++;
+ break;
+ case nsXPTType::T_I32 :
+ if (gpr < 5)
+ *((PRInt32*) d_gpr) = s->val.i32, d_gpr++, gpr++;
+ else
+ *((PRInt32*) d_ov ) = s->val.i32, d_ov++;
+ break;
+ case nsXPTType::T_I64 :
+ if (gpr < 4)
+ *((PRInt64*) d_gpr) = s->val.i64, d_gpr+=2, gpr+=2;
+ else
+ *((PRInt64*) d_ov ) = s->val.i64, d_ov+=2, gpr=5;
+ break;
+ case nsXPTType::T_U8 :
+ if (gpr < 5)
+ *((PRUint32*) d_gpr) = s->val.u8, d_gpr++, gpr++;
+ else
+ *((PRUint32*) d_ov ) = s->val.u8, d_ov++;
+ break;
+ case nsXPTType::T_U16 :
+ if (gpr < 5)
+ *((PRUint32*)d_gpr) = s->val.u16, d_gpr++, gpr++;
+ else
+ *((PRUint32*)d_ov ) = s->val.u16, d_ov++;
+ break;
+ case nsXPTType::T_U32 :
+ if (gpr < 5)
+ *((PRUint32*)d_gpr) = s->val.u32, d_gpr++, gpr++;
+ else
+ *((PRUint32*)d_ov ) = s->val.u32, d_ov++;
+ break;
+ case nsXPTType::T_U64 :
+ if (gpr < 4)
+ *((PRUint64*)d_gpr) = s->val.u64, d_gpr+=2, gpr+=2;
+ else
+ *((PRUint64*)d_ov ) = s->val.u64, d_ov+=2, gpr=5;
+ break;
+ case nsXPTType::T_FLOAT :
+ if (fpr < 2)
+ *((float*) d_fpr) = s->val.f, d_fpr++, fpr++;
+ else
+ *((float*) d_ov ) = s->val.f, d_ov++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ if (fpr < 2)
+ *((double*) d_fpr) = s->val.d, d_fpr++, fpr++;
+ else
+ *((double*) d_ov ) = s->val.d, d_ov+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ if (gpr < 5)
+ *((PRUint32*)d_gpr) = s->val.b, d_gpr++, gpr++;
+ else
+ *((PRUint32*)d_ov ) = s->val.b, d_ov++;
+ break;
+ case nsXPTType::T_CHAR :
+ if (gpr < 5)
+ *((PRUint32*)d_gpr) = s->val.c, d_gpr++, gpr++;
+ else
+ *((PRUint32*)d_ov ) = s->val.c, d_ov++;
+ break;
+ case nsXPTType::T_WCHAR :
+ if (gpr < 5)
+ *((PRUint32*)d_gpr) = s->val.wc, d_gpr++, gpr++;
+ else
+ *((PRUint32*)d_ov ) = s->val.wc, d_ov++;
+ break;
+ default:
+ // all the others are plain pointer types
+ if (gpr < 5)
+ *((void**) d_gpr) = s->val.p, d_gpr++, gpr++;
+ else
+ *((void**) d_ov ) = s->val.p, d_ov++;
+ break;
+ }
+ }
+}
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ PRUint32 *vtable = *(PRUint32 **)that;
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+ PRUint32 method = vtable[methodIndex];
+#else /* not G++ V3 ABI */
+ PRUint32 method = vtable[methodIndex + 2];
+#endif /* G++ V3 ABI */
+ PRUint32 overflow = invoke_count_words (paramCount, params);
+ PRUint32 result;
+
+ __asm__ __volatile__
+ (
+ "lr 7,15\n\t"
+ "ahi 7,-32\n\t"
+
+ "lr 3,%3\n\t"
+ "sll 3,2\n\t"
+ "lcr 3,3\n\t"
+ "l 2,0(15)\n\t"
+ "la 15,0(3,7)\n\t"
+ "st 2,0(15)\n\t"
+
+ "lr 2,%1\n\t"
+ "lr 3,%2\n\t"
+ "la 4,96(15)\n\t"
+ "lr 5,%3\n\t"
+ "basr 14,%4\n\t"
+
+ "lr 2,%5\n\t"
+ "ld 0,112(7)\n\t"
+ "ld 2,120(7)\n\t"
+ "lm 3,6,96(7)\n\t"
+ "basr 14,%6\n\t"
+
+ "la 15,32(7)\n\t"
+
+ "lr %0,2\n\t"
+ : "=r" (result)
+ : "r" (paramCount),
+ "r" (params),
+ "r" (overflow),
+ "a" (invoke_copy_to_stack),
+ "a" (that),
+ "a" (method)
+ : "2", "3", "4", "5", "6", "7", "memory"
+ );
+
+ return result;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_s390x.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_s390x.cpp
new file mode 100644
index 00000000..5a4268b6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_s390x.cpp
@@ -0,0 +1,250 @@
+/* -*- 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 ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+
+static PRUint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ PRUint32 overflow = 0, gpr = 1 /*this*/, fpr = 0;
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ if (gpr < 5) gpr++; else overflow++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ case nsXPTType::T_I64 :
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ case nsXPTType::T_U64 :
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ case nsXPTType::T_FLOAT :
+ case nsXPTType::T_DOUBLE :
+ if (fpr < 4) fpr++; else overflow++;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ default:
+ // all the others are plain pointer types
+ if (gpr < 5) gpr++; else overflow++;
+ break;
+ }
+ }
+ /* Round up number of overflow words to ensure stack
+ stays aligned to 8 bytes. */
+ return (overflow + 1) & ~1;
+}
+
+static void
+invoke_copy_to_stack(PRUint32 paramCount, nsXPTCVariant* s, PRUint64* d_ov, PRUint32 overflow)
+{
+ PRUint64 *d_gpr = d_ov + overflow;
+ PRUint64 *d_fpr = (PRUint64 *)(d_gpr + 4);
+ PRUint32 gpr = 1 /*this*/, fpr = 0;
+
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ if (gpr < 5)
+ *((void**)d_gpr) = s->ptr, d_gpr++, gpr++;
+ else
+ *((void**)d_ov ) = s->ptr, d_ov++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ if (gpr < 5)
+ *((PRInt64*) d_gpr) = s->val.i8, d_gpr++, gpr++;
+ else
+ *((PRInt64*) d_ov ) = s->val.i8, d_ov++;
+ break;
+ case nsXPTType::T_I16 :
+ if (gpr < 5)
+ *((PRInt64*) d_gpr) = s->val.i16, d_gpr++, gpr++;
+ else
+ *((PRInt64*) d_ov ) = s->val.i16, d_ov++;
+ break;
+ case nsXPTType::T_I32 :
+ if (gpr < 5)
+ *((PRInt64*) d_gpr) = s->val.i32, d_gpr++, gpr++;
+ else
+ *((PRInt64*) d_ov ) = s->val.i32, d_ov++;
+ break;
+ case nsXPTType::T_I64 :
+ if (gpr < 5)
+ *((PRInt64*) d_gpr) = s->val.i64, d_gpr++, gpr++;
+ else
+ *((PRInt64*) d_ov ) = s->val.i64, d_ov++;
+ break;
+ case nsXPTType::T_U8 :
+ if (gpr < 5)
+ *((PRUint64*) d_gpr) = s->val.u8, d_gpr++, gpr++;
+ else
+ *((PRUint64*) d_ov ) = s->val.u8, d_ov++;
+ break;
+ case nsXPTType::T_U16 :
+ if (gpr < 5)
+ *((PRUint64*)d_gpr) = s->val.u16, d_gpr++, gpr++;
+ else
+ *((PRUint64*)d_ov ) = s->val.u16, d_ov++;
+ break;
+ case nsXPTType::T_U32 :
+ if (gpr < 5)
+ *((PRUint64*)d_gpr) = s->val.u32, d_gpr++, gpr++;
+ else
+ *((PRUint64*)d_ov ) = s->val.u32, d_ov++;
+ break;
+ case nsXPTType::T_U64 :
+ if (gpr < 5)
+ *((PRUint64*)d_gpr) = s->val.u64, d_gpr++, gpr++;
+ else
+ *((PRUint64*)d_ov ) = s->val.u64, d_ov++;
+ break;
+ case nsXPTType::T_FLOAT :
+ if (fpr < 4)
+ *((float*) d_fpr) = s->val.f, d_fpr++, fpr++;
+ else
+ *(((float*) d_ov )+1) = s->val.f, d_ov++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ if (fpr < 4)
+ *((double*) d_fpr) = s->val.d, d_fpr++, fpr++;
+ else
+ *((double*) d_ov ) = s->val.d, d_ov++;
+ break;
+ case nsXPTType::T_BOOL :
+ if (gpr < 5)
+ *((PRUint64*)d_gpr) = s->val.b, d_gpr++, gpr++;
+ else
+ *((PRUint64*)d_ov ) = s->val.b, d_ov++;
+ break;
+ case nsXPTType::T_CHAR :
+ if (gpr < 5)
+ *((PRUint64*)d_gpr) = s->val.c, d_gpr++, gpr++;
+ else
+ *((PRUint64*)d_ov ) = s->val.c, d_ov++;
+ break;
+ case nsXPTType::T_WCHAR :
+ if (gpr < 5)
+ *((PRUint64*)d_gpr) = s->val.wc, d_gpr++, gpr++;
+ else
+ *((PRUint64*)d_ov ) = s->val.wc, d_ov++;
+ break;
+ default:
+ // all the others are plain pointer types
+ if (gpr < 5)
+ *((void**) d_gpr) = s->val.p, d_gpr++, gpr++;
+ else
+ *((void**) d_ov ) = s->val.p, d_ov++;
+ break;
+ }
+ }
+}
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ PRUint64 *vtable = *(PRUint64 **)that;
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+ PRUint64 method = vtable[methodIndex];
+#else /* not G++ V3 ABI */
+ PRUint64 method = vtable[methodIndex + 2];
+#endif /* G++ V3 ABI */
+ PRUint64 overflow = invoke_count_words (paramCount, params);
+ PRUint64 result;
+
+ __asm__ __volatile__
+ (
+ "lgr 7,15\n\t"
+ "aghi 7,-64\n\t"
+
+ "lgr 3,%3\n\t"
+ "sllg 3,3,3\n\t"
+ "lcgr 3,3\n\t"
+ "lg 2,0(15)\n\t"
+ "la 15,0(3,7)\n\t"
+ "stg 2,0(15)\n\t"
+
+ "lgr 2,%1\n\t"
+ "lgr 3,%2\n\t"
+ "la 4,160(15)\n\t"
+ "lgr 5,%3\n\t"
+ "basr 14,%4\n\t"
+
+ "lgr 2,%5\n\t"
+ "ld 0,192(7)\n\t"
+ "ld 2,200(7)\n\t"
+ "ld 4,208(7)\n\t"
+ "ld 6,216(7)\n\t"
+ "lmg 3,6,160(7)\n\t"
+ "basr 14,%6\n\t"
+
+ "la 15,64(7)\n\t"
+
+ "lgr %0,2\n\t"
+ : "=r" (result)
+ : "r" ((PRUint64)paramCount),
+ "r" (params),
+ "r" (overflow),
+ "a" (invoke_copy_to_stack),
+ "a" (that),
+ "a" (method)
+ : "2", "3", "4", "5", "6", "7", "memory"
+ );
+
+ return result;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_mips.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_mips.cpp
new file mode 100644
index 00000000..a73e4327
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_mips.cpp
@@ -0,0 +1,122 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * Version: MPL 1.1
+ *
+ * ***** 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 Corp, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Stuart Parmenter <pavlov@netscape.com>
+ * Brendan Eich <brendan@mozilla.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 ***** */
+
+/* This code is for MIPS using the O32 ABI. */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+
+extern "C" uint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ // Count a word for a0 even though it's never stored or loaded
+ // We do this only for alignment of register pairs.
+ PRUint32 result = 1;
+ for (PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ result++;
+
+ if (s->IsPtrData())
+ continue;
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_DOUBLE :
+ if (result & 1)
+ result++;
+ result++;
+ break;
+ }
+ }
+ return (result + 1) & ~(PRUint32)1;
+}
+
+extern "C" void
+invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount,
+ nsXPTCVariant* s)
+{
+ // Skip the unused a0 slot, which we keep only for register pair alignment.
+ d++;
+
+ for (PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ if (s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+
+ *((void**)d) = s->val.p;
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I64 :
+ if ((PRWord)d & 4) d++;
+ *((PRInt64*) d) = s->val.i64; d++;
+ break;
+ case nsXPTType::T_U64 :
+ if ((PRWord)d & 4) d++;
+ *((PRUint64*) d) = s->val.u64; d++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ if ((PRWord)d & 4) d++;
+ *((double*) d) = s->val.d; d++;
+ break;
+ }
+ }
+}
+
+extern "C" nsresult _XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount,
+ nsXPTCVariant* params);
+
+extern "C"
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ return _XPTC_InvokeByIndex(that, methodIndex, paramCount, params);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_netbsd_m68k.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_netbsd_m68k.cpp
new file mode 100644
index 00000000..65bf8f0c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_netbsd_m68k.cpp
@@ -0,0 +1,175 @@
+/* -*- 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 ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+// Remember that these 'words' are 32bit DWORDS
+
+#if !defined(__NetBSD__) || !defined(__m68k__)
+#error This code is for NetBSD/m68k only
+#endif
+
+extern "C" {
+ static PRUint32
+ invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+ {
+ PRUint32 result = 0;
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ return result;
+ }
+
+ static void
+ invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPTCVariant* s)
+ {
+ for(PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ // 8 and 16 bit types should be promoted to 32 bits when copying
+ // onto the stack.
+ case nsXPTType::T_I8 : *((PRUint32*)d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((PRUint32*)d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((PRInt32*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((PRInt64*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((PRUint32*)d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((PRUint32*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((PRUint32*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((PRUint64*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ case nsXPTType::T_BOOL : *((PRBool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((PRUint32*)d) = s->val.c; break;
+ // wchar_t is an int (32 bits) on NetBSD
+ case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+ }
+}
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ PRUint32 result;
+
+ __asm__ __volatile__(
+ "movl %4, sp@-\n\t"
+ "movl %3, sp@-\n\t"
+ "jbsr _invoke_count_words\n\t" /* count words */
+ "addql #8, sp\n\t"
+ "lsll #2, d0\n\t" /* *= 4 */
+ "movl sp, a2\n\t" /* save original sp */
+ "subl d0, sp\n\t" /* make room for params */
+ "movl sp, a0\n\t"
+ "movl %4, sp@-\n\t"
+ "movl %3, sp@-\n\t"
+ "movl a0, sp@-\n\t"
+ "jbsr _invoke_copy_to_stack\n\t" /* copy params */
+ "addl #12, sp\n\t"
+ "movl %1, a0\n\t"
+ "movl a0@, a1\n\t"
+ "movl %2, d0\n\t" /* function index */
+ "movl a0, d1\n\t"
+ "movw a1@(8,d0:l:8), a0\n\t"
+ "addl a0, d1\n\t"
+ "movl a1@(12,d0:l:8), a1\n\t"
+ "movl d1, sp@-\n\t"
+ "jbsr a1@\n\t"
+ "movl a2, sp\n\t" /* restore original sp */
+ "movl d0, %0\n\t"
+ : "=g" (result) /* %0 */
+ : "g" (that), /* %1 */
+ "g" (methodIndex), /* %2 */
+ "g" (paramCount), /* %3 */
+ "g" (params) /* %4 */
+ : "a0", "a1", "a2", "d0", "d1", "memory"
+ );
+
+ return result;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_openvms_alpha.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_openvms_alpha.cpp
new file mode 100644
index 00000000..ae22a48c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_openvms_alpha.cpp
@@ -0,0 +1,107 @@
+/* -*- 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 ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+extern "C" {
+
+/* This is in the ASM file */
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+
+void
+invoke_copy_to_stack(PRUint64* d, PRUint32 paramCount, nsXPTCVariant* s)
+{
+ const PRUint8 NUM_ARG_REGS = 6-1; // -1 for "this" pointer
+
+ for(PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *d = (PRUint64)s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ /*
+ ** The line for T_U32 may look wrong (we use signed value for an
+ ** unsigned data type), but it is right. Why? The Alpha calling
+ ** standard is defined to sign extend all 32-bit values, regardless
+ ** of whether they are int, unsigned int, or 32-bit pointer. The
+ ** caller must "sign-extend" it by replicating bit 31 in bits 32
+ ** thru 63 (yes, even for unsigned). This is the format that results
+ ** naturally from the LDL instruction, the ADDL instruction, etc.
+ */
+ case nsXPTType::T_I8 : *d = (PRUint64)s->val.i8; break;
+ case nsXPTType::T_I16 : *d = (PRUint64)s->val.i16; break;
+ case nsXPTType::T_I32 : *d = (PRUint64)s->val.i32; break;
+ case nsXPTType::T_I64 : *d = (PRUint64)s->val.i64; break;
+ case nsXPTType::T_U8 : *d = (PRUint64)s->val.u8; break;
+ case nsXPTType::T_U16 : *d = (PRUint64)s->val.u16; break;
+ case nsXPTType::T_U32 : *d = (PRUint64)s->val.i32; break;
+ case nsXPTType::T_U64 : *d = (PRUint64)s->val.u64; break;
+ case nsXPTType::T_FLOAT :
+ if(i < NUM_ARG_REGS)
+ {
+ // convert floats to doubles if they are to be passed
+ // via registers so we can just deal with doubles later
+ union { PRUint64 u64; double d; } t;
+ t.d = (double)s->val.f;
+ *d = t.u64;
+ }
+ else
+ // otherwise copy to stack normally
+ *d = (PRUint64)s->val.u32;
+ break;
+ case nsXPTType::T_DOUBLE : *d = (PRUint64)s->val.u64; break;
+ case nsXPTType::T_BOOL : *d = (PRUint64)s->val.b; break;
+ case nsXPTType::T_CHAR : *d = (PRUint64)s->val.c; break;
+ case nsXPTType::T_WCHAR : *d = (PRUint64)s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *d = (PRUint64)s->val.p;
+ break;
+ }
+ }
+}
+
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_osf1_alpha.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_osf1_alpha.cpp
new file mode 100644
index 00000000..13c3b23d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_osf1_alpha.cpp
@@ -0,0 +1,93 @@
+/* -*- 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 ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+/* contributed by Steve Streeter <Stephen.Streeter@Compaq.com> */
+
+#include "xptcprivate.h"
+
+/* Prototype specifies unmangled function name */
+extern "C" void
+invoke_copy_to_stack(PRUint64* d, PRUint32 paramCount, nsXPTCVariant* s);
+
+extern "C" void
+invoke_copy_to_stack(PRUint64* d, PRUint32 paramCount, nsXPTCVariant* s)
+{
+ const PRUint8 NUM_ARG_REGS = 6-1; // -1 for "this" pointer
+
+ for(PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *d = (PRUint64)s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *d = (PRUint64)s->val.i8; break;
+ case nsXPTType::T_I16 : *d = (PRUint64)s->val.i16; break;
+ case nsXPTType::T_I32 : *d = (PRUint64)s->val.i32; break;
+ case nsXPTType::T_I64 : *d = (PRUint64)s->val.i64; break;
+ case nsXPTType::T_U8 : *d = (PRUint64)s->val.u8; break;
+ case nsXPTType::T_U16 : *d = (PRUint64)s->val.u16; break;
+ case nsXPTType::T_U32 : *d = (PRUint64)s->val.u32; break;
+ case nsXPTType::T_U64 : *d = (PRUint64)s->val.u64; break;
+ case nsXPTType::T_FLOAT :
+ if(i < NUM_ARG_REGS)
+ {
+ // convert floats to doubles if they are to be passed
+ // via registers so we can just deal with doubles later
+ union { PRUint64 u64; double d; } t;
+ t.d = (double)s->val.f;
+ *d = t.u64;
+ }
+ else
+ // otherwise copy to stack normally
+ *d = (PRUint64)s->val.u32;
+ break;
+ case nsXPTType::T_DOUBLE : *d = (PRUint64)s->val.u64; break;
+ case nsXPTType::T_BOOL : *d = (PRUint64)s->val.b; break;
+ case nsXPTType::T_CHAR : *d = (PRUint64)s->val.c; break;
+ case nsXPTType::T_WCHAR : *d = (PRUint64)s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *d = (PRUint64)s->val.p;
+ break;
+ }
+ }
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_pa32.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_pa32.cpp
new file mode 100644
index 00000000..c6208a50
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_pa32.cpp
@@ -0,0 +1,181 @@
+
+/* -*- 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) 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 "xptcprivate.h"
+
+#if _HPUX
+#error "This code is for HP-PA RISC 32 bit mode only"
+#endif
+
+#include <alloca.h>
+
+typedef unsigned nsXPCVariant;
+
+extern "C" PRInt32
+invoke_count_bytes(nsISupports* that, const PRUint32 methodIndex,
+ const PRUint32 paramCount, const nsXPTCVariant* s)
+{
+ PRInt32 result = 4; /* variant records do not include self pointer */
+
+ /* counts the number of bytes required by the argument stack,
+ 64 bit integer, and double requires 8 bytes. All else requires
+ 4 bytes.
+ */
+
+ {
+ PRUint32 indx;
+ for (indx = paramCount; indx > 0; --indx, ++s)
+ {
+ if (! s->IsPtrData())
+ {
+ if (s->type == nsXPTType::T_I64 || s->type == nsXPTType::T_U64 ||
+ s->type == nsXPTType::T_DOUBLE)
+ {
+ /* 64 bit integer and double aligned on 8 byte boundaries */
+ result += (result & 4) + 8;
+ continue;
+ }
+ }
+ result += 4; /* all other cases use 4 bytes */
+ }
+ }
+ result -= 72; /* existing stack buffer is 72 bytes */
+ if (result < 0)
+ return 0;
+ {
+ /* round up to 64 bytes boundary */
+ PRInt32 remainder = result & 63;
+ return (remainder == 0) ? result : (result + 64 - remainder);
+ }
+}
+
+extern "C" PRUint32
+invoke_copy_to_stack(PRUint32* d,
+ const PRUint32 paramCount, nsXPTCVariant* s)
+{
+
+ typedef struct
+ {
+ PRUint32 hi;
+ PRUint32 lo;
+ } DU;
+
+ PRUint32* dest = d;
+ nsXPTCVariant* source = s;
+ /* we clobber param vars by copying stuff on stack, have to use local var */
+
+ PRUint32 floatflags = 0;
+ /* flag indicating which floating point registers to load */
+
+ PRUint32 regwords = 1; /* register 26 is reserved for ptr to 'that' */
+ PRUint32 indx;
+
+ for (indx = paramCount; indx > 0; --indx, --dest, ++source)
+ {
+ if (source->IsPtrData())
+ {
+ *((void**) dest) = source->ptr;
+ ++regwords;
+ continue;
+ }
+ switch (source->type)
+ {
+ case nsXPTType::T_I8 : *((PRInt32*) dest) = source->val.i8; break;
+ case nsXPTType::T_I16 : *((PRInt32*) dest) = source->val.i16; break;
+ case nsXPTType::T_I32 : *((PRInt32*) dest) = source->val.i32; break;
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ if (regwords & 1)
+ {
+ /* align on double word boundary */
+ --dest;
+ ++regwords;
+ }
+ *((uint32*) dest) = ((DU *) source)->lo;
+ *((uint32*) --dest) = ((DU *) source)->hi;
+ /* big endian - hi word in low addr */
+ regwords += 2;
+ continue;
+ case nsXPTType::T_DOUBLE :
+ if (regwords & 1)
+ {
+ /* align on double word boundary */
+ --dest;
+ ++regwords;
+ }
+ switch (regwords) /* load double precision float register */
+ {
+ case 2:
+ floatflags |= 1;
+ }
+ *((uint32*) dest) = ((DU *) source)->lo;
+ *((uint32*) --dest) = ((DU *) source)->hi;
+ /* big endian - hi word in low addr */
+ regwords += 2;
+ continue;
+ case nsXPTType::T_FLOAT :
+ switch (regwords) /* load single precision float register */
+ {
+ case 1:
+ floatflags |= 2;
+ break;
+ case 2:
+ floatflags |= 4;
+ break;
+ case 3:
+ floatflags |= 8;
+ }
+ *((float*) dest) = source->val.f;
+ break;
+ case nsXPTType::T_U8 : *((PRUint32*) (dest)) = source->val.u8; break;
+ case nsXPTType::T_U16 : *((PRUint32*) (dest)) = source->val.u16; break;
+ case nsXPTType::T_U32 : *((PRUint32*) (dest)) = source->val.u32; break;
+ case nsXPTType::T_BOOL : *((PRBool*) (dest)) = source->val.b; break;
+ case nsXPTType::T_CHAR : *((PRUint32*) (dest)) = source->val.c; break;
+ case nsXPTType::T_WCHAR : *((PRInt32*) (dest)) = source->val.wc; break;
+
+ default:
+ // all the others are plain pointer types
+ *((void**) dest) = source->val.p;
+ }
+ ++regwords;
+ }
+ return floatflags;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_aix.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_aix.cpp
new file mode 100644
index 00000000..d353063c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_aix.cpp
@@ -0,0 +1,106 @@
+/* -*- 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 ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#ifndef AIX
+#error "This code is for PowerPC only"
+#endif
+
+extern "C" void
+invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPTCVariant* s, double *fprData)
+{
+/*
+ We need to copy the parameters for this function to locals and use them
+ from there since the parameters occupy the same stack space as the stack
+ we're trying to populate.
+*/
+ PRUint32 *l_d = d;
+ nsXPTCVariant *l_s = s;
+ PRUint32 l_paramCount = paramCount, fpCount = 0;
+ double *l_fprData = fprData;
+
+ typedef struct {
+ uint32 hi;
+ uint32 lo;
+ } DU; // have to move 64 bit entities as 32 bit halves since
+ // stack slots are not guaranteed 16 byte aligned
+
+ for(uint32 i = 0; i < l_paramCount; i++, l_d++, l_s++)
+ {
+ if(l_s->IsPtrData())
+ {
+ *((void**)l_d) = l_s->ptr;
+ continue;
+ }
+ switch(l_s->type)
+ {
+ case nsXPTType::T_I8 : *((int32*) l_d) = l_s->val.i8; break;
+ case nsXPTType::T_I16 : *((int32*) l_d) = l_s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32*) l_d) = l_s->val.i32; break;
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ *((uint32*) l_d++) = ((DU *)l_s)->hi;
+ *((uint32*) l_d) = ((DU *)l_s)->lo;
+ break;
+ case nsXPTType::T_DOUBLE :
+ *((uint32*) l_d++) = ((DU *)l_s)->hi;
+ *((uint32*) l_d) = ((DU *)l_s)->lo;
+ if(fpCount < 13)
+ l_fprData[fpCount++] = l_s->val.d;
+ break;
+ case nsXPTType::T_U8 : *((uint32*) l_d) = l_s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint32*) l_d) = l_s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32*) l_d) = l_s->val.u32; break;
+ case nsXPTType::T_FLOAT :
+ *((float*) l_d) = l_s->val.f;
+ if(fpCount < 13)
+ l_fprData[fpCount++] = l_s->val.f;
+ break;
+ case nsXPTType::T_BOOL : *((PRBool*) l_d) = l_s->val.b; break;
+ case nsXPTType::T_CHAR : *((uint32*) l_d) = l_s->val.c; break;
+ case nsXPTType::T_WCHAR : *((int32*) l_d) = l_s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)l_d) = l_s->val.p;
+ break;
+ }
+ }
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_aix64.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_aix64.cpp
new file mode 100644
index 00000000..a42611b8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_aix64.cpp
@@ -0,0 +1,95 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/LGPL 2.1/GPL 2.0
+ *
+ * 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 IBM Corporation.
+ * Portions created by IBM are
+ * Copyright (C) 2002, International Business Machines Corporation.
+ * 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 LGPL or the GPL. 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 ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#ifdef _AIX
+
+extern "C" void
+invoke_copy_to_stack(PRUint64* d, PRUint32 paramCount, nsXPTCVariant* s, double *fprData)
+{
+/*
+ We need to copy the parameters for this function to locals and use them
+ from there since the parameters occupy the same stack space as the stack
+ we're trying to populate.
+*/
+ PRUint64 *l_d = d;
+ nsXPTCVariant *l_s = s;
+ PRUint32 l_paramCount = paramCount, fpCount = 0;
+ double *l_fprData = fprData;
+
+ for(PRUint32 i = 0; i < l_paramCount; i++, l_d++, l_s++)
+ {
+ if(l_s->IsPtrData())
+ {
+ *l_d = (PRUint64)l_s->ptr;
+ continue;
+ }
+ switch(l_s->type)
+ {
+ case nsXPTType::T_I8: *l_d = (PRUint64)l_s->val.i8; break;
+ case nsXPTType::T_I16: *l_d = (PRUint64)l_s->val.i16; break;
+ case nsXPTType::T_I32: *l_d = (PRUint64)l_s->val.i32; break;
+ case nsXPTType::T_I64: *l_d = (PRUint64)l_s->val.i64; break;
+ case nsXPTType::T_U8: *l_d = (PRUint64)l_s->val.u8; break;
+ case nsXPTType::T_U16: *l_d = (PRUint64)l_s->val.u16; break;
+ case nsXPTType::T_U32: *l_d = (PRUint64)l_s->val.u32; break;
+ case nsXPTType::T_U64: *l_d = (PRUint64)l_s->val.u64; break;
+ case nsXPTType::T_BOOL: *l_d = (PRUint64)l_s->val.b; break;
+ case nsXPTType::T_CHAR: *l_d = (PRUint64)l_s->val.c; break;
+ case nsXPTType::T_WCHAR: *l_d = (PRUint64)l_s->val.wc; break;
+
+ case nsXPTType::T_DOUBLE:
+ *((double*)l_d) = l_s->val.d;
+ if(fpCount < 13)
+ l_fprData[fpCount++] = l_s->val.d;
+ break;
+ case nsXPTType::T_FLOAT:
+ *((float*)l_d) = l_s->val.f;
+ if(fpCount < 13)
+ l_fprData[fpCount++] = l_s->val.f;
+ break;
+ default:
+ // all the others are plain pointer types
+ *l_d = (PRUint64)l_s->val.p;
+ break;
+ }
+ }
+}
+#endif
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_linux.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_linux.cpp
new file mode 100644
index 00000000..7303045a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_linux.cpp
@@ -0,0 +1,141 @@
+/* -*- 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):
+ * Franz.Sirl-kernel@lauterbach.com (Franz Sirl)
+ * beard@netscape.com (Patrick Beard)
+ * waterson@netscape.com (Chris Waterson)
+ *
+ * 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 ***** */
+
+// Platform specific code to invoke XPCOM methods on native objects
+
+// The purpose of XPTC_InvokeByIndex() is to map a platform
+// indepenpent call to the platform ABI. To do that,
+// XPTC_InvokeByIndex() has to determine the method to call via vtable
+// access. The parameters for the method are read from the
+// nsXPTCVariant* and prepared for th native ABI. For the Linux/PPC
+// ABI this means that the first 8 integral and floating point
+// parameters are passed in registers.
+
+#include "xptcprivate.h"
+
+// 8 integral parameters are passed in registers
+#define GPR_COUNT 8
+
+// 8 floating point parameters are passed in registers, floats are
+// promoted to doubles when passed in registers
+#define FPR_COUNT 8
+
+extern "C" PRUint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ return PRUint32(((paramCount * 2) + 3) & ~3);
+}
+
+extern "C" void
+invoke_copy_to_stack(PRUint32* d,
+ PRUint32 paramCount,
+ nsXPTCVariant* s,
+ PRUint32* gpregs,
+ double* fpregs)
+{
+ PRUint32 gpr = 1; // skip one GP reg for 'that'
+ PRUint32 fpr = 0;
+ PRUint32 tempu32;
+ PRUint64 tempu64;
+
+ for(uint32 i = 0; i < paramCount; i++, s++) {
+ if(s->IsPtrData())
+ tempu32 = (PRUint32) s->ptr;
+ else {
+ switch(s->type) {
+ case nsXPTType::T_FLOAT: break;
+ case nsXPTType::T_DOUBLE: break;
+ case nsXPTType::T_I8: tempu32 = s->val.i8; break;
+ case nsXPTType::T_I16: tempu32 = s->val.i16; break;
+ case nsXPTType::T_I32: tempu32 = s->val.i32; break;
+ case nsXPTType::T_I64: tempu64 = s->val.i64; break;
+ case nsXPTType::T_U8: tempu32 = s->val.u8; break;
+ case nsXPTType::T_U16: tempu32 = s->val.u16; break;
+ case nsXPTType::T_U32: tempu32 = s->val.u32; break;
+ case nsXPTType::T_U64: tempu64 = s->val.u64; break;
+ case nsXPTType::T_BOOL: tempu32 = s->val.b; break;
+ case nsXPTType::T_CHAR: tempu32 = s->val.c; break;
+ case nsXPTType::T_WCHAR: tempu32 = s->val.wc; break;
+ default: tempu32 = (PRUint32) s->val.p; break;
+ }
+ }
+
+ if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) {
+ if (fpr < FPR_COUNT)
+ fpregs[fpr++] = s->val.d;
+ else {
+ if ((PRUint32) d & 4) d++; // doubles are 8-byte aligned on stack
+ *((double*) d) = s->val.d;
+ d += 2;
+ }
+ }
+ else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) {
+ if (fpr < FPR_COUNT)
+ fpregs[fpr++] = s->val.f; // if passed in registers, floats are promoted to doubles
+ else
+ *((float*) d++) = s->val.f;
+ }
+ else if (!s->IsPtrData() && (s->type == nsXPTType::T_I64
+ || s->type == nsXPTType::T_U64)) {
+ if ((gpr + 1) < GPR_COUNT) {
+ if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ *((PRUint64*) &gpregs[gpr]) = tempu64;
+ gpr += 2;
+ }
+ else {
+ if ((PRUint32) d & 4) d++; // longlongs are 8-byte aligned on stack
+ *((PRUint64*) d) = tempu64;
+ d += 2;
+ }
+ }
+ else {
+ if (gpr < GPR_COUNT)
+ gpregs[gpr++] = tempu32;
+ else
+ *d++ = tempu32;
+ }
+
+ }
+}
+
+extern "C"
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_netbsd.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_netbsd.cpp
new file mode 100644
index 00000000..0de8ea62
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_netbsd.cpp
@@ -0,0 +1,147 @@
+/* -*- 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):
+ * Franz.Sirl-kernel@lauterbach.com (Franz Sirl)
+ * beard@netscape.com (Patrick Beard)
+ * waterson@netscape.com (Chris Waterson)
+ *
+ * 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 ***** */
+
+// Platform specific code to invoke XPCOM methods on native objects
+
+// The purpose of XPTC_InvokeByIndex() is to map a platform
+// indepenpent call to the platform ABI. To do that,
+// XPTC_InvokeByIndex() has to determine the method to call via vtable
+// access. The parameters for the method are read from the
+// nsXPTCVariant* and prepared for th native ABI. For the Linux/PPC
+// ABI this means that the first 8 integral and floating point
+// parameters are passed in registers.
+
+#include "xptcprivate.h"
+
+// 8 integral parameters are passed in registers
+#define GPR_COUNT 8
+
+// 8 floating point parameters are passed in registers, floats are
+// promoted to doubles when passed in registers
+#define FPR_COUNT 8
+
+extern "C" PRUint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ return PRUint32(((paramCount * 2) + 3) & ~3);
+}
+
+extern "C" void
+invoke_copy_to_stack(PRUint32* d,
+ PRUint32 paramCount,
+ nsXPTCVariant* s,
+ PRUint32* gpregs,
+ double* fpregs)
+{
+ PRUint32 gpr = 1; // skip one GP reg for 'that'
+ PRUint32 fpr = 0;
+ PRUint32 tempu32;
+ PRUint64 tempu64;
+
+ for(uint32 i = 0; i < paramCount; i++, s++) {
+ if(s->IsPtrData())
+ tempu32 = (PRUint32) s->ptr;
+ else {
+ switch(s->type) {
+ case nsXPTType::T_FLOAT: break;
+ case nsXPTType::T_DOUBLE: break;
+ case nsXPTType::T_I8: tempu32 = s->val.i8; break;
+ case nsXPTType::T_I16: tempu32 = s->val.i16; break;
+ case nsXPTType::T_I32: tempu32 = s->val.i32; break;
+ case nsXPTType::T_I64: tempu64 = s->val.i64; break;
+ case nsXPTType::T_U8: tempu32 = s->val.u8; break;
+ case nsXPTType::T_U16: tempu32 = s->val.u16; break;
+ case nsXPTType::T_U32: tempu32 = s->val.u32; break;
+ case nsXPTType::T_U64: tempu64 = s->val.u64; break;
+ case nsXPTType::T_BOOL: tempu32 = s->val.b; break;
+ case nsXPTType::T_CHAR: tempu32 = s->val.c; break;
+ case nsXPTType::T_WCHAR: tempu32 = s->val.wc; break;
+ default: tempu32 = (PRUint32) s->val.p; break;
+ }
+ }
+
+ if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) {
+ if (fpr < FPR_COUNT)
+ fpregs[fpr++] = s->val.d;
+ else {
+ if ((PRUint32) d & 4) d++; // doubles are 8-byte aligned on stack
+ *((double*) d) = s->val.d;
+ d += 2;
+ if (gpr < GPR_COUNT)
+ gpr += 2;
+ }
+ }
+ else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) {
+ if (fpr < FPR_COUNT)
+ fpregs[fpr++] = s->val.f; // if passed in registers, floats are promoted to doubles
+ else {
+ *((float*) d) = s->val.f;
+ d += 1;
+ if (gpr < GPR_COUNT)
+ gpr += 1;
+ }
+ }
+ else if (!s->IsPtrData() && (s->type == nsXPTType::T_I64
+ || s->type == nsXPTType::T_U64)) {
+ if ((gpr + 1) < GPR_COUNT) {
+ if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ *((PRUint64*) &gpregs[gpr]) = tempu64;
+ gpr += 2;
+ }
+ else {
+ if ((PRUint32) d & 4) d++; // longlongs are 8-byte aligned on stack
+ *((PRUint64*) d) = tempu64;
+ d += 2;
+ }
+ }
+ else {
+ if (gpr < GPR_COUNT)
+ gpregs[gpr++] = tempu32;
+ else
+ *d++ = tempu32;
+ }
+
+ }
+}
+
+extern "C"
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_rhapsody.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_rhapsody.cpp
new file mode 100644
index 00000000..9a08acfd
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_rhapsody.cpp
@@ -0,0 +1,145 @@
+/* -*- 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 ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+extern "C" uint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ PRUint32 result = 0;
+ /* fprintf(stderr,"invoke_count_words(%d,%p)\n",paramCount, s);*/
+
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ return result;
+}
+
+extern "C" void
+invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPTCVariant* s, double *fprData)
+{
+ PRUint32 fpCount = 0;
+
+ /* fprintf(stderr,"invoke_copy_to_stack(%p, %d, %p, %p)\n", d, paramCount, s, fprData);*/
+
+ for(PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((PRInt32*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((PRInt32*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((PRInt32*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((PRInt64*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((PRUint32*) d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((PRUint32*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((PRUint32*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((PRUint64*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f;
+ if (fpCount < 13)
+ fprData[fpCount++] = s->val.f;
+ break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++;
+ if (fpCount < 13)
+ fprData[fpCount++] = s->val.d;
+ break;
+ case nsXPTType::T_BOOL : *((PRBool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((PRInt32*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((PRUint32*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+}
+
+extern "C" nsresult _XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+extern "C"
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ return _XPTC_InvokeByIndex(that, methodIndex, paramCount, params);
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_sparc_netbsd.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_sparc_netbsd.cpp
new file mode 100644
index 00000000..fb2af366
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_sparc_netbsd.cpp
@@ -0,0 +1,156 @@
+/* -*- 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 ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+/* solaris defines __sparc for workshop compilers and
+ linux defines __sparc__ */
+
+#if !defined(__sparc) && !defined(__sparc__)
+#error "This code is for Sparc only"
+#endif
+
+typedef unsigned nsXPCVariant;
+
+extern "C" PRUint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ PRUint32 result = 0;
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ // nuts, I know there's a cooler way of doing this, but it's late
+ // now and it'll probably come to me in the morning.
+ if (result & 0x3) result += 4 - (result & 0x3); // ensure q-word alignment
+ return result;
+}
+
+extern "C" PRUint32
+invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPTCVariant* s)
+{
+/*
+ We need to copy the parameters for this function to locals and use them
+ from there since the parameters occupy the same stack space as the stack
+ we're trying to populate.
+*/
+ uint32 *l_d = d;
+ nsXPTCVariant *l_s = s;
+ uint32 l_paramCount = paramCount;
+ uint32 regCount = 0; // return the number of registers to load from the stack
+
+ typedef struct {
+ uint32 hi;
+ uint32 lo;
+ } DU; // have to move 64 bit entities as 32 bit halves since
+ // stack slots are not guaranteed 16 byte aligned
+
+ for(uint32 i = 0; i < l_paramCount; i++, l_d++, l_s++)
+ {
+ if (regCount < 5) regCount++;
+ if(l_s->IsPtrData())
+ {
+ *((void**)l_d) = l_s->ptr;
+ continue;
+ }
+ switch(l_s->type)
+ {
+ case nsXPTType::T_I8 : *((int32*) l_d) = l_s->val.i8; break;
+ case nsXPTType::T_I16 : *((int32*) l_d) = l_s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32*) l_d) = l_s->val.i32; break;
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_DOUBLE : *((uint32*) l_d++) = ((DU *)l_s)->hi;
+ if (regCount < 5) regCount++;
+ *((uint32*) l_d) = ((DU *)l_s)->lo;
+ break;
+ case nsXPTType::T_U8 : *((uint32*) l_d) = l_s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint32*) l_d) = l_s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32*) l_d) = l_s->val.u32; break;
+ case nsXPTType::T_FLOAT : *((float*) l_d) = l_s->val.f; break;
+ case nsXPTType::T_BOOL : *((PRBool*) l_d) = l_s->val.b; break;
+ case nsXPTType::T_CHAR : *((uint32*) l_d) = l_s->val.c; break;
+ case nsXPTType::T_WCHAR : *((int32*)l_d) = l_s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)l_d) = l_s->val.p;
+ break;
+ }
+ }
+ return regCount;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_sparc_solaris.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_sparc_solaris.cpp
new file mode 100644
index 00000000..fb2af366
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_sparc_solaris.cpp
@@ -0,0 +1,156 @@
+/* -*- 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 ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+/* solaris defines __sparc for workshop compilers and
+ linux defines __sparc__ */
+
+#if !defined(__sparc) && !defined(__sparc__)
+#error "This code is for Sparc only"
+#endif
+
+typedef unsigned nsXPCVariant;
+
+extern "C" PRUint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ PRUint32 result = 0;
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 :
+ case nsXPTType::T_I16 :
+ case nsXPTType::T_I32 :
+ result++;
+ break;
+ case nsXPTType::T_I64 :
+ result+=2;
+ break;
+ case nsXPTType::T_U8 :
+ case nsXPTType::T_U16 :
+ case nsXPTType::T_U32 :
+ result++;
+ break;
+ case nsXPTType::T_U64 :
+ result+=2;
+ break;
+ case nsXPTType::T_FLOAT :
+ result++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ result+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ case nsXPTType::T_CHAR :
+ case nsXPTType::T_WCHAR :
+ result++;
+ break;
+ default:
+ // all the others are plain pointer types
+ result++;
+ break;
+ }
+ }
+ // nuts, I know there's a cooler way of doing this, but it's late
+ // now and it'll probably come to me in the morning.
+ if (result & 0x3) result += 4 - (result & 0x3); // ensure q-word alignment
+ return result;
+}
+
+extern "C" PRUint32
+invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPTCVariant* s)
+{
+/*
+ We need to copy the parameters for this function to locals and use them
+ from there since the parameters occupy the same stack space as the stack
+ we're trying to populate.
+*/
+ uint32 *l_d = d;
+ nsXPTCVariant *l_s = s;
+ uint32 l_paramCount = paramCount;
+ uint32 regCount = 0; // return the number of registers to load from the stack
+
+ typedef struct {
+ uint32 hi;
+ uint32 lo;
+ } DU; // have to move 64 bit entities as 32 bit halves since
+ // stack slots are not guaranteed 16 byte aligned
+
+ for(uint32 i = 0; i < l_paramCount; i++, l_d++, l_s++)
+ {
+ if (regCount < 5) regCount++;
+ if(l_s->IsPtrData())
+ {
+ *((void**)l_d) = l_s->ptr;
+ continue;
+ }
+ switch(l_s->type)
+ {
+ case nsXPTType::T_I8 : *((int32*) l_d) = l_s->val.i8; break;
+ case nsXPTType::T_I16 : *((int32*) l_d) = l_s->val.i16; break;
+ case nsXPTType::T_I32 : *((int32*) l_d) = l_s->val.i32; break;
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_DOUBLE : *((uint32*) l_d++) = ((DU *)l_s)->hi;
+ if (regCount < 5) regCount++;
+ *((uint32*) l_d) = ((DU *)l_s)->lo;
+ break;
+ case nsXPTType::T_U8 : *((uint32*) l_d) = l_s->val.u8; break;
+ case nsXPTType::T_U16 : *((uint32*) l_d) = l_s->val.u16; break;
+ case nsXPTType::T_U32 : *((uint32*) l_d) = l_s->val.u32; break;
+ case nsXPTType::T_FLOAT : *((float*) l_d) = l_s->val.f; break;
+ case nsXPTType::T_BOOL : *((PRBool*) l_d) = l_s->val.b; break;
+ case nsXPTType::T_CHAR : *((uint32*) l_d) = l_s->val.c; break;
+ case nsXPTType::T_WCHAR : *((int32*)l_d) = l_s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)l_d) = l_s->val.p;
+ break;
+ }
+ }
+ return regCount;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_sparcv9_solaris.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_sparcv9_solaris.cpp
new file mode 100644
index 00000000..83b28ebb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_sparcv9_solaris.cpp
@@ -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) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Stuart Parmenter <pavlov@netscape.com>
+ * Chris Seawood <cls@seawood.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 ***** */
+
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#if !defined(__sparc) && !defined(__sparc__)
+#error "This code is for Sparc only"
+#endif
+
+/* Prototype specifies unmangled function name */
+extern "C" PRUint64
+invoke_copy_to_stack(PRUint64* d, PRUint32 paramCount, nsXPTCVariant* s);
+
+extern "C" PRUint64
+invoke_copy_to_stack(PRUint64* d, PRUint32 paramCount, nsXPTCVariant* s)
+{
+ /*
+ We need to copy the parameters for this function to locals and use them
+ from there since the parameters occupy the same stack space as the stack
+ we're trying to populate.
+ */
+ PRUint64 *l_d = d;
+ nsXPTCVariant *l_s = s;
+ PRUint64 l_paramCount = paramCount;
+ PRUint64 regCount = 0; // return the number of registers to load from the stack
+
+ for(PRUint64 i = 0; i < l_paramCount; i++, l_d++, l_s++)
+ {
+ if (regCount < 5) regCount++;
+
+ if (l_s->IsPtrData())
+ {
+ *l_d = (PRUint64)l_s->ptr;
+ continue;
+ }
+ switch (l_s->type)
+ {
+ case nsXPTType::T_I8 : *((PRInt64*)l_d) = l_s->val.i8; break;
+ case nsXPTType::T_I16 : *((PRInt64*)l_d) = l_s->val.i16; break;
+ case nsXPTType::T_I32 : *((PRInt64*)l_d) = l_s->val.i32; break;
+ case nsXPTType::T_I64 : *((PRInt64*)l_d) = l_s->val.i64; break;
+
+ case nsXPTType::T_U8 : *((PRUint64*)l_d) = l_s->val.u8; break;
+ case nsXPTType::T_U16 : *((PRUint64*)l_d) = l_s->val.u16; break;
+ case nsXPTType::T_U32 : *((PRUint64*)l_d) = l_s->val.u32; break;
+ case nsXPTType::T_U64 : *((PRUint64*)l_d) = l_s->val.u64; break;
+
+ /* in the case of floats, we want to put the bits in to the
+ 64bit space right justified... floats in the paramter array on
+ sparcv9 use odd numbered registers.. %f1, %f3, so we have to skip
+ the space that would be occupied by %f0, %f2, etc.
+ */
+ case nsXPTType::T_FLOAT : *(((float*)l_d) + 1) = l_s->val.f; break;
+ case nsXPTType::T_DOUBLE: *((double*)l_d) = l_s->val.d; break;
+ case nsXPTType::T_BOOL : *((PRBool*)l_d) = l_s->val.b; break;
+ case nsXPTType::T_CHAR : *((PRUint64*)l_d) = l_s->val.c; break;
+ case nsXPTType::T_WCHAR : *((PRInt64*)l_d) = l_s->val.wc; break;
+
+ default:
+ // all the others are plain pointer types
+ *((void**)l_d) = l_s->val.p;
+ break;
+ }
+ }
+
+ return regCount;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_unixish_x86.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_unixish_x86.cpp
new file mode 100644
index 00000000..76445fa4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_unixish_x86.cpp
@@ -0,0 +1,187 @@
+/* -*- 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):
+ * Mark Mentovai <mark@moxienet.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 ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+#include "xptc_platforms_unixish_x86.h"
+
+extern "C" {
+
+static void
+invoke_copy_to_stack(PRUint32 paramCount, nsXPTCVariant* s, PRUint32* d)
+{
+ for(PRUint32 i = paramCount; i >0; i--, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+
+/* XXX: the following line is here (rather than as the default clause in
+ * the following switch statement) so that the Sun native compiler
+ * will generate the correct assembly code on the Solaris Intel
+ * platform. See the comments in bug #28817 for more details.
+ */
+
+ *((void**)d) = s->val.p;
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I64 : *((PRInt64*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U64 : *((PRUint64*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ }
+ }
+}
+
+}
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+#ifdef __GNUC__ /* Gnu compiler. */
+ PRUint32 result;
+ /* Each param takes at most 2, 4-byte words
+ It doesn't matter if we push too many words, and calculating the exact
+ amount takes time. */
+ PRUint32 n = paramCount << 3;
+ void (*fn_copy) (unsigned int, nsXPTCVariant *, PRUint32 *) = invoke_copy_to_stack;
+ int temp1, temp2;
+
+ /* These are only significant when KEEP_STACK_16_BYTE_ALIGNED is
+ defined. Otherwise, they're just placeholders to keep the parameter
+ indices the same for aligned and unaligned users in the inline asm
+ block. */
+ unsigned int saved_esp;
+
+ __asm__ __volatile__(
+#ifdef KEEP_STACK_16_BYTE_ALIGNED
+ "movl %%esp, %3\n\t"
+#endif
+ "subl %8, %%esp\n\t" /* make room for params */
+#ifdef KEEP_STACK_16_BYTE_ALIGNED
+ /* For the second CALL, there will be one parameter before the ones
+ copied by invoke_copy_to_stack. Make sure that the stack will be
+ aligned for that CALL. */
+ "subl $4, %%esp\n\t"
+ "andl $0xfffffff0, %%esp\n\t"
+ /* For the first CALL, there are three parameters. Leave padding to
+ ensure alignment. */
+ "subl $4, %%esp\n\t"
+ /* The third parameter to invoke_copy_to_stack is the destination pointer.
+ It needs to point into the parameter area prepared for the second CALL,
+ leaving room for the |that| parameter. This reuses |n|, which was
+ the stack space to reserve, but that's OK because it's no longer needed
+ if the stack is being kept aligned. */
+ "leal 8(%%esp), %8\n\t"
+ "pushl %8\n\t"
+#else
+ "pushl %%esp\n\t"
+#endif
+ "pushl %7\n\t"
+ "pushl %6\n\t"
+ "call *%9\n\t" /* copy params */
+#ifdef KEEP_STACK_16_BYTE_ALIGNED
+ /* The stack is still aligned from the first CALL. Keep it aligned for
+ the next one by popping past the parameters from the first CALL and
+ leaving space for the first (|that|) parameter for the second CALL. */
+ "addl $0x14, %%esp\n\t"
+#else
+ "addl $0xc, %%esp\n\t"
+#endif
+ "movl %4, %%ecx\n\t"
+#ifdef CFRONT_STYLE_THIS_ADJUST
+ "movl (%%ecx), %%edx\n\t"
+ "movl %5, %%eax\n\t" /* function index */
+ "shl $3, %%eax\n\t" /* *= 8 */
+ "addl $8, %%eax\n\t" /* += 8 skip first entry */
+ "addl %%eax, %%edx\n\t"
+ "movswl (%%edx), %%eax\n\t" /* 'this' offset */
+ "addl %%eax, %%ecx\n\t"
+ "pushl %%ecx\n\t"
+ "addl $4, %%edx\n\t" /* += 4, method pointer */
+#else /* THUNK_BASED_THIS_ADJUST */
+ "pushl %%ecx\n\t"
+ "movl (%%ecx), %%edx\n\t"
+ "movl %5, %%eax\n\t" /* function index */
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+ "leal (%%edx,%%eax,4), %%edx\n\t"
+#else /* not G++ V3 ABI */
+ "leal 8(%%edx,%%eax,4), %%edx\n\t"
+#endif /* G++ V3 ABI */
+#endif
+ "call *(%%edx)\n\t" /* safe to not cleanup esp */
+#ifdef KEEP_STACK_16_BYTE_ALIGNED
+ "movl %3, %%esp\n\t"
+#else
+ "addl $4, %%esp\n\t"
+ "addl %8, %%esp"
+#endif
+ : "=a" (result), /* %0 */
+ "=c" (temp1), /* %1 */
+ "=d" (temp2), /* %2 */
+#ifdef KEEP_STACK_16_BYTE_ALIGNED
+ "=&g" (saved_esp) /* %3 */
+#else
+ /* Don't waste a register, this isn't used if alignment is unimportant */
+ "=m" (saved_esp) /* %3 */
+#endif
+ : "g" (that), /* %4 */
+ "g" (methodIndex), /* %5 */
+ "1" (paramCount), /* %6 */
+ "2" (params), /* %7 */
+#ifdef KEEP_STACK_16_BYTE_ALIGNED
+ /* Must be in a register, it's the target of an LEA instruction */
+ "r" (n), /* %8 */
+#else
+ "g" (n), /* %8 */
+#endif
+ "0" (fn_copy) /* %9 */
+ : "memory"
+ );
+
+ return result;
+
+#else
+#error "can't find a compiler to use"
+#endif /* __GNUC__ */
+
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_unsupported.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_unsupported.cpp
new file mode 100644
index 00000000..88219d8d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_unsupported.cpp
@@ -0,0 +1,48 @@
+/* -*- 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 ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ NS_ASSERTION(0,"XPTC_InvokeByIndex called on unsupported platform");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_64_linux.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_64_linux.cpp
new file mode 100644
index 00000000..b017c741
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_64_linux.cpp
@@ -0,0 +1,227 @@
+/* -*- 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) 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 ***** */
+
+// Platform specific code to invoke XPCOM methods on native objects
+
+#include "xptcprivate.h"
+
+// 6 integral parameters are passed in registers
+const PRUint32 GPR_COUNT = 6;
+
+// 8 floating point parameters are passed in SSE registers
+const PRUint32 FPR_COUNT = 8;
+
+// Remember that these 'words' are 64-bit long
+static inline void
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant * s,
+ PRUint32 & nr_gpr, PRUint32 & nr_fpr, PRUint32 & nr_stack)
+{
+ nr_gpr = 1; // skip one GP register for 'that'
+ nr_fpr = 0;
+ nr_stack = 0;
+
+ /* Compute number of eightbytes of class MEMORY. */
+ for (uint32 i = 0; i < paramCount; i++, s++) {
+ if (!s->IsPtrData()
+ && (s->type == nsXPTType::T_FLOAT || s->type == nsXPTType::T_DOUBLE)) {
+ if (nr_fpr < FPR_COUNT)
+ nr_fpr++;
+ else
+ nr_stack++;
+ }
+ else {
+ if (nr_gpr < GPR_COUNT)
+ nr_gpr++;
+ else
+ nr_stack++;
+ }
+ }
+}
+
+static void
+invoke_copy_to_stack(PRUint64 * d, PRUint32 paramCount, nsXPTCVariant * s,
+ PRUint64 * gpregs, double * fpregs)
+{
+ PRUint32 nr_gpr = 1; // skip one GP register for 'that'
+ PRUint32 nr_fpr = 0;
+ PRUint64 value;
+
+ for (uint32 i = 0; i < paramCount; i++, s++) {
+ if (s->IsPtrData())
+ value = (PRUint64) s->ptr;
+ else {
+ switch (s->type) {
+ case nsXPTType::T_FLOAT: break;
+ case nsXPTType::T_DOUBLE: break;
+ case nsXPTType::T_I8: value = s->val.i8; break;
+ case nsXPTType::T_I16: value = s->val.i16; break;
+ case nsXPTType::T_I32: value = s->val.i32; break;
+ case nsXPTType::T_I64: value = s->val.i64; break;
+ case nsXPTType::T_U8: value = s->val.u8; break;
+ case nsXPTType::T_U16: value = s->val.u16; break;
+ case nsXPTType::T_U32: value = s->val.u32; break;
+ case nsXPTType::T_U64: value = s->val.u64; break;
+ case nsXPTType::T_BOOL: value = s->val.b; break;
+ case nsXPTType::T_CHAR: value = s->val.c; break;
+ case nsXPTType::T_WCHAR: value = s->val.wc; break;
+ default: value = (PRUint64) s->val.p; break;
+ }
+ }
+
+ if (!s->IsPtrData() && s->type == nsXPTType::T_DOUBLE) {
+ if (nr_fpr < FPR_COUNT)
+ fpregs[nr_fpr++] = s->val.d;
+ else {
+ *((double *)d) = s->val.d;
+ d++;
+ }
+ }
+ else if (!s->IsPtrData() && s->type == nsXPTType::T_FLOAT) {
+ if (nr_fpr < FPR_COUNT)
+ // The value in %xmm register is already prepared to
+ // be retrieved as a float. Therefore, we pass the
+ // value verbatim, as a double without conversion.
+ fpregs[nr_fpr++] = s->val.d;
+ else {
+ *((float *)d) = s->val.f;
+ d++;
+ }
+ }
+ else {
+ if (nr_gpr < GPR_COUNT)
+ gpregs[nr_gpr++] = value;
+ else
+ *d++ = value;
+ }
+ }
+}
+
+extern "C"
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports * that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant * params)
+{
+ PRUint32 nr_gpr, nr_fpr, nr_stack;
+ invoke_count_words(paramCount, params, nr_gpr, nr_fpr, nr_stack);
+
+ // Stack, if used, must be 16-bytes aligned
+ if (nr_stack)
+ nr_stack = (nr_stack + 1) & ~1;
+
+#ifndef VBOX_WITH_GCC_SANITIZER
+ // Load parameters to stack, if necessary
+ PRUint64 *stack = (PRUint64 *) __builtin_alloca(nr_stack * 8);
+#else
+ typedef struct { PRUint64 stack[20]; } methodStack;
+ if (nr_stack > 20)
+ return NS_ERROR_CALL_FAILED;
+ methodStack stack;
+#endif
+ PRUint64 gpregs[GPR_COUNT];
+ double fpregs[FPR_COUNT];
+#ifndef VBOX_WITH_GCC_SANITIZER
+ invoke_copy_to_stack(stack, paramCount, params, gpregs, fpregs);
+#else
+ invoke_copy_to_stack(stack.stack, paramCount, params, gpregs, fpregs);
+#endif
+
+ // Load FPR registers from fpregs[]
+ register double d0 asm("xmm0");
+ register double d1 asm("xmm1");
+ register double d2 asm("xmm2");
+ register double d3 asm("xmm3");
+ register double d4 asm("xmm4");
+ register double d5 asm("xmm5");
+ register double d6 asm("xmm6");
+ register double d7 asm("xmm7");
+
+ switch (nr_fpr) {
+#define ARG_FPR(N) \
+ case N+1: d##N = fpregs[N];
+ ARG_FPR(7);
+ ARG_FPR(6);
+ ARG_FPR(5);
+ ARG_FPR(4);
+ ARG_FPR(3);
+ ARG_FPR(2);
+ ARG_FPR(1);
+ ARG_FPR(0);
+ case 0:;
+#undef ARG_FPR
+ }
+
+ // Load GPR registers from gpregs[]
+ register PRUint64 a0 asm("rdi");
+ register PRUint64 a1 asm("rsi");
+ register PRUint64 a2 asm("rdx");
+ register PRUint64 a3 asm("rcx");
+ register PRUint64 a4 asm("r8");
+ register PRUint64 a5 asm("r9");
+
+ switch (nr_gpr) {
+#define ARG_GPR(N) \
+ case N+1: a##N = gpregs[N];
+ ARG_GPR(5);
+ ARG_GPR(4);
+ ARG_GPR(3);
+ ARG_GPR(2);
+ ARG_GPR(1);
+ case 1: a0 = (PRUint64) that;
+ case 0:;
+#undef ARG_GPR
+ }
+
+ // Ensure that assignments to SSE registers won't be optimized away
+ asm("" ::
+ "x" (d0), "x" (d1), "x" (d2), "x" (d3),
+ "x" (d4), "x" (d5), "x" (d6), "x" (d7));
+
+ // Get pointer to method
+ PRUint64 methodAddress = *((PRUint64 *)that);
+ methodAddress += 8 * methodIndex;
+ methodAddress = *((PRUint64 *)methodAddress);
+
+#ifndef VBOX_WITH_GCC_SANITIZER
+ typedef PRUint32 (*Method)(PRUint64, PRUint64, PRUint64, PRUint64, PRUint64, PRUint64);
+ PRUint32 result = ((Method)methodAddress)(a0, a1, a2, a3, a4, a5);
+#else
+ typedef PRUint32 (*Method)(PRUint64, PRUint64, PRUint64, PRUint64, PRUint64, PRUint64, methodStack);
+ PRUint32 result = ((Method)methodAddress)(a0, a1, a2, a3, a4, a5, stack);
+#endif
+ return result;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_solaris.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_solaris.cpp
new file mode 100644
index 00000000..14ecb2d8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_solaris.cpp
@@ -0,0 +1,285 @@
+/* -*- 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) 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 ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+#include "xptc_platforms_unixish_x86.h"
+#ifdef VBOX
+# include <iprt/alloca.h>
+#endif
+
+extern "C" {
+
+// Remember that these 'words' are 32bit DWORDS
+
+static PRUint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ PRUint32 result = 0;
+ for(PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ result++;
+ continue;
+ }
+ result++;
+ switch(s->type)
+ {
+ case nsXPTType::T_I64 :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_DOUBLE :
+ result++;
+ break;
+ }
+ }
+ return result;
+}
+
+static void
+invoke_copy_to_stack(PRUint32 paramCount, nsXPTCVariant* s, PRUint32* d)
+{
+ for(PRUint32 i = 0; i < paramCount; i++, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+
+/* XXX: the following line is here (rather than as the default clause in
+ * the following switch statement) so that the Sun native compiler
+ * will generate the correct assembly code on the Solaris Intel
+ * platform. See the comments in bug #28817 for more details.
+ */
+
+ *((void**)d) = s->val.p;
+
+ switch(s->type)
+ {
+ case nsXPTType::T_I64 : *((PRInt64*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U64 : *((PRUint64*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ }
+ }
+}
+
+}
+
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+#ifdef __GNUC__ /* Gnu compiler. */
+ PRUint32 result;
+ PRUint32 n = invoke_count_words (paramCount, params) * 4;
+ int temp1, temp2, temp3;
+
+# ifdef VBOX
+ /* This is for dealing with gcc 4.5.2 not using registers for 'g' parameters
+ and instead trying to get things like 'that' via %esp after we've changed it. */
+# if 1 /* safe version. */
+ void (*fn_copy) (unsigned int, nsXPTCVariant *, PRUint32 *) = invoke_copy_to_stack;
+ struct Combined
+ {
+ PRUint32 that; /* offset: 0 */
+ PRUint32 pfn; /* offset: 4 */
+ PRUint32 savedEsp; /* offset: 8 */
+ PRUint32 paramCount; /* offset: 12 */
+ PRUint32 params; /* offset: 16 */
+ } Combined;
+# ifdef CFRONT_STYLE_THIS_ADJUST
+ struct CFRONTVTE { uintptr_t off, pfn } *pVtab = *(struct CFRONTVTE **)that;
+ Combined.that = (uintptr_t)that + pVtab[methodIndex + 1].off;
+ Combined.pfn = pVtab[methodIndex + 1].pfn;
+# elif defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+ Combined.that = (uintptr_t)that;
+ Combined.pfn = (*(uintptr_t **)that)[methodIndex];
+# else /* not G++ V3 ABI */
+ Combined.that = (uintptr_t)that;
+ Combined.pfn = (*(uintptr_t **)that)[2 + methodIndex];
+# endif /* G++ V3 ABI */
+ Combined.paramCount = paramCount;
+ Combined.params = (uintptr_t)params;
+
+ __asm__ __volatile__(
+ "mov %%esp, 8(%%esi)\n\t" /* savedEsp = %esp */
+ "subl %1, %%esp\n\t" /* make room for params */
+
+ /* Call invoke_count_words to copy the parameters. */
+ "pushl %%esp\n\t" /* arg2: dest */
+ "pushl 16(%%esi)\n\t" /* arg1: params */
+ "pushl 12(%%esi)\n\t" /* arg0: paramCount */
+ "call *%0\n\t"
+ "addl $0xc, %%esp\n\t"
+
+ /* Push the this pointer. */
+ "pushl (%%esi)\n\t" /* that */
+ "call *4(%%esi)\n\t"
+ "mov 8(%%esi), %%esp\n\t"
+ : "=a" (result), /* %0 */
+ "=c" (temp1), /* %1 */
+ "=d" (temp2) /* %2 */
+ : "S" (&Combined), /* %3 */
+ "0" (fn_copy),
+ "1" (n)
+ : "memory"
+ );
+
+# else /* Small version; ASSUMES nothing important gets put on the stack after the the alloca. */
+ uintptr_t *pauStack = (uintptr_t *)alloca(n + sizeof(uintptr_t));
+ invoke_copy_to_stack(paramCount, params, &pauStack[1]);
+# ifdef CFRONT_STYLE_THIS_ADJUST
+ struct CFRONTVTE { uintptr_t off, pfn } *pVtab = *(struct CFRONTVTE **)that;
+ pauStack[0] = (uintptr_t)that + pVtab[methodIndex + 1].off;
+ uintptr_t pfn = pVtab[methodIndex + 1].pfn;
+# elif defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+ pauStack[0] = (uintptr_t)that;
+ uintptr_t pfn = (*(uintptr_t **)that)[methodIndex];
+# else /* not G++ V3 ABI */
+ pauStack[0] = (uintptr_t)that;
+ uintptr_t pfn = (*(uintptr_t **)that)[2 + methodIndex];
+# endif /* G++ V3 ABI */
+
+ __asm__ __volatile__(
+ "xchg %%esp, %3\n\t" /* save+load %esp */
+ "call *%0\n\t"
+ "xchg %%esp, %3\n\t" /* restore %esp */
+ : "=a" (result), /* %0 */
+ "=c" (temp1), /* %1 */
+ "=d" (temp2) /* %2 */
+ : "S" (pauStack), /* %3 */
+ "0" (pfn)
+ : "memory"
+ );
+# endif
+
+# else /* !VBOX */
+ void (*fn_copy) (unsigned int, nsXPTCVariant *, PRUint32 *) = invoke_copy_to_stack;
+ __asm__ __volatile__(
+ "subl %8, %%esp\n\t" /* make room for params */
+ "pushl %%esp\n\t"
+ "pushl %7\n\t"
+ "pushl %6\n\t"
+ "call *%0\n\t" /* copy params */
+ "addl $0xc, %%esp\n\t"
+ "movl %4, %%ecx\n\t"
+#ifdef CFRONT_STYLE_THIS_ADJUST
+ "movl (%%ecx), %%edx\n\t"
+ "movl %5, %%eax\n\t" /* function index */
+ "shl $3, %%eax\n\t" /* *= 8 */
+ "addl $8, %%eax\n\t" /* += 8 skip first entry */
+ "addl %%eax, %%edx\n\t"
+ "movswl (%%edx), %%eax\n\t" /* 'this' offset */
+ "addl %%eax, %%ecx\n\t"
+ "pushl %%ecx\n\t"
+ "addl $4, %%edx\n\t" /* += 4, method pointer */
+#else /* THUNK_BASED_THIS_ADJUST */
+ "pushl %%ecx\n\t"
+ "movl (%%ecx), %%edx\n\t"
+ "movl %5, %%eax\n\t" /* function index */
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+ "leal (%%edx,%%eax,4), %%edx\n\t"
+#else /* not G++ V3 ABI */
+ "leal 8(%%edx,%%eax,4), %%edx\n\t"
+#endif /* G++ V3 ABI */
+#endif
+ "call *(%%edx)\n\t" /* safe to not cleanup esp */
+ "addl $4, %%esp\n\t"
+ "addl %8, %%esp"
+ : "=a" (result), /* %0 */
+ "=c" (temp1), /* %1 */
+ "=d" (temp2), /* %2 */
+ "=g" (temp3) /* %3 */
+ : "g" (that), /* %4 */
+ "g" (methodIndex), /* %5 */
+ "1" (paramCount), /* %6 */
+ "2" (params), /* %7 */
+ "g" (n), /* %8 */
+ "0" (fn_copy) /* %3 */
+ : "memory"
+ );
+# endif /* !VBOX */
+
+ return result;
+#elif defined(__SUNPRO_CC) /* Sun Workshop Compiler. */
+
+asm(
+ "\n\t /: PRUint32 n = invoke_count_words (paramCount, params) * 4;"
+
+ "\n\t pushl %ebx / preserve ebx"
+ "\n\t pushl %esi / preserve esi"
+ "\n\t movl %esp, %ebx / save address of pushed esi and ebx"
+
+ "\n\t pushl 20(%ebp) / \"params\""
+ "\n\t pushl 16(%ebp) / \"paramCount\""
+ "\n\t call invoke_count_words"
+ "\n\t mov %ebx, %esp / restore esp"
+
+ "\n\t sall $2,%eax"
+ "\n\t subl %eax, %esp / make room for arguments"
+ "\n\t movl %esp, %esi / save new esp"
+
+ "\n\t pushl %esp"
+ "\n\t pushl 20(%ebp) / \"params\""
+ "\n\t pushl 16(%ebp) / \"paramCount\""
+ "\n\t call invoke_copy_to_stack / copy params"
+ "\n\t movl %esi, %esp / restore new esp"
+
+ "\n\t movl 8(%ebp),%ecx / \"that\""
+ "\n\t pushl %ecx / \"that\""
+ "\n\t movl (%ecx), %edx"
+ "\n\t movl 12(%ebp), %eax / function index: \"methodIndex\""
+ "\n\t movl 8(%edx,%eax,4), %edx"
+
+ "\n\t call *%edx"
+ "\n\t mov %ebx, %esp"
+ "\n\t popl %esi"
+ "\n\t popl %ebx"
+);
+
+/* result == %eax */
+ if(0) /* supress "*** is expected to return a value." error */
+ return 0;
+
+#else
+#error "can't find a compiler to use"
+#endif /* __GNUC__ */
+
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_amd64_darwin.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_amd64_darwin.cpp
new file mode 100644
index 00000000..5b55c930
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_amd64_darwin.cpp
@@ -0,0 +1,243 @@
+/* -*- 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) 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 ***** */
+
+// Implement shared vtbl methods.
+
+#include "xptcprivate.h"
+
+// The Linux/x86-64 ABI passes the first 6 integer parameters and the
+// first 8 floating point parameters in registers (rdi, rsi, rdx, rcx,
+// r8, r9 and xmm0-xmm7), no stack space is allocated for these by the
+// caller. The rest of the parameters are passed in the callers stack
+// area.
+
+const PRUint32 PARAM_BUFFER_COUNT = 16;
+const PRUint32 GPR_COUNT = 6;
+const PRUint32 FPR_COUNT = 8;
+
+// PrepareAndDispatch() is called by SharedStub() and calls the actual method.
+//
+// - 'args[]' contains the arguments passed on stack
+// - 'gpregs[]' contains the arguments passed in integer registers
+// - 'fpregs[]' contains the arguments passed in floating point registers
+//
+// The parameters are mapped into an array of type 'nsXPTCMiniVariant'
+// and then the method gets called.
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase * self, PRUint32 methodIndex,
+ PRUint64 * args, PRUint64 * gpregs, double *fpregs)
+{
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info = NULL;
+ PRUint32 paramCount;
+ PRUint32 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+ if (!iface_info)
+ return NS_ERROR_UNEXPECTED;
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (!info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if (paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PRUint64* ap = args;
+ PRUint32 nr_gpr = 1; // skip one GPR register for 'that'
+ PRUint32 nr_fpr = 0;
+ PRUint64 value;
+
+ for (i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+ if (nr_fpr < FPR_COUNT)
+ dp->val.d = fpregs[nr_fpr++];
+ else
+ dp->val.d = *(double*) ap++;
+ continue;
+ }
+ else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+ if (nr_fpr < FPR_COUNT)
+ // The value in %xmm register is already prepared to
+ // be retrieved as a float. Therefore, we pass the
+ // value verbatim, as a double without conversion.
+ dp->val.d = *(double*) ap++;
+ else
+ dp->val.f = *(float*) ap++;
+ continue;
+ }
+ else {
+ if (nr_gpr < GPR_COUNT)
+ value = gpregs[nr_gpr++];
+ else
+ value = *ap++;
+ }
+
+ if (param.IsOut() || !type.IsArithmetic()) {
+ dp->val.p = (void*) value;
+ continue;
+ }
+
+ switch (type) {
+ case nsXPTType::T_I8: dp->val.i8 = (PRInt8) value; break;
+ case nsXPTType::T_I16: dp->val.i16 = (PRInt16) value; break;
+ case nsXPTType::T_I32: dp->val.i32 = (PRInt32) value; break;
+ case nsXPTType::T_I64: dp->val.i64 = (PRInt64) value; break;
+ case nsXPTType::T_U8: dp->val.u8 = (PRUint8) value; break;
+ case nsXPTType::T_U16: dp->val.u16 = (PRUint16) value; break;
+ case nsXPTType::T_U32: dp->val.u32 = (PRUint32) value; break;
+ case nsXPTType::T_U64: dp->val.u64 = (PRUint64) value; break;
+ case nsXPTType::T_BOOL: dp->val.b = (PRBool) value; break;
+ case nsXPTType::T_CHAR: dp->val.c = (char) value; break;
+ case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) value; break;
+
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16) methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if (dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+// Darwin/AMD64 uses gcc >= 3.1
+#define STUB_ENTRY(n) \
+asm(".text\n\t" \
+ ".align 2\n\t" \
+ ".if " #n " < 10\n\t" \
+ ".globl __ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \
+ /*".type __ZN14nsXPTCStubBase5Stub" #n "Ev,@function\n"*/ \
+ "__ZN14nsXPTCStubBase5Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 100\n\t" \
+ ".globl __ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \
+ /*".type __ZN14nsXPTCStubBase6Stub" #n "Ev,@function\n"*/ \
+ "__ZN14nsXPTCStubBase6Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 1000\n\t" \
+ ".globl __ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \
+ /*".type __ZN14nsXPTCStubBase7Stub" #n "Ev,@function\n"*/ \
+ "__ZN14nsXPTCStubBase7Stub" #n "Ev:\n\t" \
+ ".else\n\t" \
+ ".err \"stub number " #n " >= 1000 not yet supported\"\n\t" \
+ ".endif\n\t" \
+ "movl $" #n ", %eax\n\t" \
+ "jmp SharedStub\n\t" \
+ ".if " #n " < 10\n\t" \
+ /*".size __ZN14nsXPTCStubBase5Stub" #n "Ev,.-__ZN14nsXPTCStubBase5Stub" #n "Ev\n\t"*/ \
+ ".elseif " #n " < 100\n\t" \
+ /*".size __ZN14nsXPTCStubBase6Stub" #n "Ev,.-__ZN14nsXPTCStubBase6Stub" #n "Ev\n\t"*/ \
+ ".else\n\t" \
+ /*".size __ZN14nsXPTCStubBase7Stub" #n "Ev,.-__ZN14nsXPTCStubBase7Stub" #n "Ev\n\t"*/ \
+ ".endif");
+
+// static nsresult SharedStub(PRUint32 methodIndex) [methodIndex is in eax].
+asm(".text\n\t"
+ ".align 2\n\t"
+/* ".type SharedStub,@function\n\t" */
+ "SharedStub:\n\t"
+ // make room for gpregs (48), fpregs (64)
+ "pushq %rbp\n\t"
+ "movq %rsp,%rbp\n\t"
+ "subq $112,%rsp\n\t"
+ // save GP registers
+ "movq %rdi,-112(%rbp)\n\t"
+ "movq %rsi,-104(%rbp)\n\t"
+ "movq %rdx, -96(%rbp)\n\t"
+ "movq %rcx, -88(%rbp)\n\t"
+ "movq %r8 , -80(%rbp)\n\t"
+ "movq %r9 , -72(%rbp)\n\t"
+ "leaq -112(%rbp),%rcx\n\t"
+ // save FP registers
+ "movsd %xmm0,-64(%rbp)\n\t"
+ "movsd %xmm1,-56(%rbp)\n\t"
+ "movsd %xmm2,-48(%rbp)\n\t"
+ "movsd %xmm3,-40(%rbp)\n\t"
+ "movsd %xmm4,-32(%rbp)\n\t"
+ "movsd %xmm5,-24(%rbp)\n\t"
+ "movsd %xmm6,-16(%rbp)\n\t"
+ "movsd %xmm7, -8(%rbp)\n\t"
+ "leaq -64(%rbp),%r8\n\t"
+ // rdi has the 'self' pointer already
+ "movl %eax,%esi\n\t"
+ "leaq 16(%rbp),%rdx\n\t"
+ "call _PrepareAndDispatch\n\t"
+ "leave\n\t"
+ "ret\n\t"
+/* ".size SharedStub,.-SharedStub" */
+ );
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#else
+#error "Unsupported compiler. Use gcc >= 3.1 for Darwin/AMD64."
+#endif /* __GNUC__ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm.cpp
new file mode 100644
index 00000000..fc90ecea
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm.cpp
@@ -0,0 +1,244 @@
+/* -*- 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) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Russell King <rmk@arm.linux.org.uk>
+ *
+ * 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 ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if !defined(LINUX) || !defined(__arm__)
+#error "This code is for Linux ARM only. Please check if it works for you, too.\nDepends strongly on gcc behaviour."
+#endif
+
+/* Specify explicitly a symbol for this function, don't try to guess the c++ mangled symbol. */
+static nsresult PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, PRUint32* args) asm("_PrepareAndDispatch");
+
+static nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, PRUint32* args)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((PRInt8*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((PRInt16*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((PRInt64*) ap); ap++; break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((PRUint8*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((PRUint16*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((PRUint32*)ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((PRUint64*)ap); ap++; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((PRBool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+/*
+ * This is our shared stub.
+ *
+ * r0 = Self.
+ *
+ * The Rules:
+ * We pass an (undefined) number of arguments into this function.
+ * The first 3 C++ arguments are in r1 - r3, the rest are built
+ * by the calling function on the stack.
+ *
+ * We are allowed to corrupt r0 - r3, ip, and lr.
+ *
+ * Other Info:
+ * We pass the stub number in using `ip'.
+ *
+ * Implementation:
+ * - We save r1 to r3 inclusive onto the stack, which will be
+ * immediately below the caller saved arguments.
+ * - setup r2 (PrepareAndDispatch's args pointer) to point at
+ * the base of all these arguments
+ * - Save LR (for the return address)
+ * - Set r1 (PrepareAndDispatch's methodindex argument) from ip
+ * - r0 is passed through (self)
+ * - Call PrepareAndDispatch
+ * - When the call returns, we return by loading the PC off the
+ * stack, and undoing the stack (one instruction)!
+ *
+ */
+__asm__ ("\n\
+SharedStub: \n\
+ stmfd sp!, {r1, r2, r3} \n\
+ mov r2, sp \n\
+ str lr, [sp, #-4]! \n\
+ mov r1, ip \n\
+ bl _PrepareAndDispatch \n\
+ ldr pc, [sp], #16");
+
+/*
+ * Create sets of stubs to call the SharedStub.
+ * We don't touch the stack here, nor any registers, other than IP.
+ * IP is defined to be corruptable by a called function, so we are
+ * safe to use it.
+ *
+ * This will work with or without optimisation.
+ */
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+/*
+ * Note : As G++3 ABI contains the length of the functionname in the
+ * mangled name, it is difficult to get a generic assembler mechanism like
+ * in the G++ 2.95 case.
+ * Create names would be like :
+ * _ZN14nsXPTCStubBase5Stub9Ev
+ * _ZN14nsXPTCStubBase6Stub13Ev
+ * _ZN14nsXPTCStubBase7Stub144Ev
+ * Use the assembler directives to get the names right...
+ */
+
+#define STUB_ENTRY(n) \
+ __asm__( \
+ ".section \".text\"\n" \
+" .align 2\n" \
+" .iflt ("#n" - 10)\n" \
+" .globl _ZN14nsXPTCStubBase5Stub"#n"Ev\n" \
+" .type _ZN14nsXPTCStubBase5Stub"#n"Ev,#function\n" \
+"_ZN14nsXPTCStubBase5Stub"#n"Ev:\n" \
+" .else\n" \
+" .iflt ("#n" - 100)\n" \
+" .globl _ZN14nsXPTCStubBase6Stub"#n"Ev\n" \
+" .type _ZN14nsXPTCStubBase6Stub"#n"Ev,#function\n" \
+"_ZN14nsXPTCStubBase6Stub"#n"Ev:\n" \
+" .else\n" \
+" .iflt ("#n" - 1000)\n" \
+" .globl _ZN14nsXPTCStubBase7Stub"#n"Ev\n" \
+" .type _ZN14nsXPTCStubBase7Stub"#n"Ev,#function\n" \
+"_ZN14nsXPTCStubBase7Stub"#n"Ev:\n" \
+" .else\n" \
+" .err \"stub number "#n"> 1000 not yet supported\"\n" \
+" .endif\n" \
+" .endif\n" \
+" .endif\n" \
+" mov ip, #"#n"\n" \
+" b SharedStub\n\t");
+
+#if 0
+/*
+ * This part is left in as comment : this is how the method definition
+ * should look like.
+ */
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n () \
+{ \
+ __asm__ ( \
+" mov ip, #"#n"\n" \
+" b SharedStub\n\t"); \
+ return 0; /* avoid warnings */ \
+}
+#endif
+
+#else /* G++2.95 ABI */
+
+#define STUB_ENTRY(n) \
+ __asm__( \
+ ".section \".text\"\n" \
+" .align\n" \
+" .globl Stub"#n"__14nsXPTCStubBase\n" \
+" .type Stub"#n"__14nsXPTCStubBase,#function\n\n" \
+"Stub"#n"__14nsXPTCStubBase:\n" \
+" mov ip, #"#n"\n" \
+" b SharedStub\n\t");
+
+#endif
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm64_vbox.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm64_vbox.cpp
new file mode 100644
index 00000000..b6e1a9e8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm64_vbox.cpp
@@ -0,0 +1,272 @@
+/* $Id: xptcstubs_arm64_vbox.cpp $ */
+/** @file
+ * XPCOM - XPTC stubs for arm64.
+ */
+
+/*
+ * Copyright (C) 2021-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include "xptcprivate.h"
+#include <iprt/cdefs.h>
+#include <iprt/alloca.h>
+#include <iprt/assert.h>
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+#if defined(RT_OS_DARWIN)
+# define NAME_PREFIX _
+# define NAME_PREFIX_STR "_"
+#else
+# define NAME_PREFIX
+# define NAME_PREFIX_STR ""
+#endif
+#define ASMNAME(a_Name) NAME_PREFIX ## a_Name
+#define NUM_ARGS_IN_GPRS 8 /**< Number of arguments passed in general purpose registers (starting with x0). */
+#define NUM_ARGS_IN_FPRS 8 /**< Number of arguments passed in floating point registers (starting with d0). */
+
+
+/*********************************************************************************************************************************
+* Internal Functions *
+*********************************************************************************************************************************/
+extern "C" __attribute__((naked)) nsresult CommonXPTCStub(void);
+DECL_NO_INLINE(extern "C", nsresult)
+CommonXPTCStubCWorker(nsXPTCStubBase *pThis, uint32_t idxMethod, uint64_t *pauGprArgs, uint64_t *pauFprArgs, uint64_t *puStackArgs);
+
+
+/**
+ * All the stubs call this shared code w/ method index in w17.
+ *
+ * The naked attribute means pure inline assembly function. clang complains
+ * if we put C statements in it. So, this exacty what we need here and for the
+ * stubs.
+ *
+ * @note This could be static if we weren't afraid the compile would optimize it
+ * out.
+ */
+extern "C" __attribute__((naked)) nsresult CommonXPTCStub(void)
+{
+ __asm__ __volatile__(
+ /* Prologue - reserve space for frame+link reg spill and the GPR and FPR arrays. */ "\
+ sub sp, sp, %[cbGPRandFPRs] + 16 \n\
+ stp x29, x30, [sp, %[cbGPRandFPRs]] \n\
+ add x29, sp, %[cbGPRandFPRs] \n\
+ .cfi_def_cfa x29, 16 \n\
+ .cfi_rel_offset x30, -8 \n\
+ .cfi_rel_offset x29, -16 \n\
+"
+ /* reserve stack space for the integer and floating point registers and save them: */ "\
+ \n\
+ stp x0, x1, [sp, #0] \n\
+ stp x2, x3, [sp, #16] \n\
+ stp x4, x5, [sp, #32] \n\
+ stp x6, x7, [sp, #48] \n\
+ \n\
+ stp d0, d1, [sp, %[cbGPRs]] \n\
+ stp d2, d3, [sp, %[cbGPRs] + 16] \n\
+ stp d4, d5, [sp, %[cbGPRs] + 32] \n\
+ stp d6, d7, [sp, %[cbGPRs] + 48] \n\
+\n"
+ /* Call the C worker. We keep x0 as is.
+ Set w1 to the w17 method index from the stubs. */ "\
+ mov w1, w17 \n\
+ mov x2, sp \n\
+ add x3, sp, %[cbGPRs] \n\
+ add x4, sp, %[cbGPRandFPRs] + 16 \n\
+ bl " NAME_PREFIX_STR "CommonXPTCStubCWorker \n\
+"
+ /* Epilogue (clang does not emit the .cfi's here, so drop them too?): */ "\
+ ldp x29, x30, [sp, %[cbGPRandFPRs]] \n\
+ add sp, sp, %[cbGPRandFPRs] + 16 \n\
+ .cfi_def_cfa sp, 0 \n\
+ .cfi_restore x29 \n\
+ .cfi_restore x30 \n\
+ ret \n\
+" :
+ : [cbGPRandFPRs] "i" (NUM_ARGS_IN_GPRS * 8 + NUM_ARGS_IN_FPRS * 8)
+ , [cbGPRs] "i" (NUM_ARGS_IN_GPRS * 8)
+ :);
+}
+
+#define STUB_ENTRY(n) \
+ __attribute__((naked)) nsresult nsXPTCStubBase::Stub##n() \
+ { \
+ __asm__ __volatile__ ("mov w17, #" #n "\n\t" \
+ "b " NAME_PREFIX_STR "CommonXPTCStub\n\t"); \
+ }
+
+#define SENTINEL_ENTRY(n) \
+ nsresult nsXPTCStubBase::Sentinel##n() \
+ { \
+ AssertMsgFailed(("nsXPTCStubBase::Sentinel" #n " called!\n")); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+ }
+
+/* Instantiate the stubs and sentinels */
+#include "xptcstubsdef.inc"
+
+
+
+/*
+ * Function templates for fetching arguments
+ */
+
+template<typename Type> static inline void fetchStack(Type *pRet, uint64_t *&rpuStackArgs)
+{
+#ifdef RT_OS_DARWIN /* macOS compacts stack usage. */
+ Type *pStackTmp = RT_ALIGN_PT(rpuStackArgs, sizeof(Type), Type *);
+ *pRet = *pStackTmp;
+ rpuStackArgs = (uint64_t *)(pStackTmp + 1);
+#else
+ *pRet = (Type)*rpuStackArgs++;
+#endif
+}
+
+template<typename Type> static inline void fetchFpr(Type *pRet, uint64_t *pauFprArgs, unsigned &ridxFpr, uint64_t *&rpuStackArgs)
+{
+ if (ridxFpr < NUM_ARGS_IN_FPRS)
+ *pRet = (Type)pauFprArgs[ridxFpr++];
+ else
+ fetchStack(pRet, rpuStackArgs);
+}
+
+
+template<typename Type> static inline void fetchGpr(Type *pRet, uint64_t *pauGprArgs, unsigned &ridxGpr, uint64_t *&rpuStackArgs)
+{
+ if (ridxGpr < NUM_ARGS_IN_GPRS)
+ *pRet = (Type)pauGprArgs[ridxGpr++];
+ else
+ fetchStack(pRet, rpuStackArgs);
+}
+
+
+/**
+ * Called by CommonXPTCStub below after it dumps registers and locates
+ * arguments on the stack (if any).
+ */
+DECL_NO_INLINE(extern "C", nsresult)
+CommonXPTCStubCWorker(nsXPTCStubBase *pThis, uint32_t idxMethod, uint64_t *pauGprArgs, uint64_t *pauFprArgs, uint64_t *puStackArgs)
+{
+ AssertReturn(pThis, NS_ERROR_UNEXPECTED);
+
+ /* Get method information: */
+ nsIInterfaceInfo *pInterfaceInfo = NULL;
+ nsresult hrc = pThis->GetInterfaceInfo(&pInterfaceInfo);
+ AssertReturn(NS_SUCCEEDED(hrc), hrc);
+ AssertReturn(pInterfaceInfo, NS_ERROR_UNEXPECTED);
+
+ const nsXPTMethodInfo *pMethodInfo;
+ hrc = pInterfaceInfo->GetMethodInfo((PRUint16)idxMethod, &pMethodInfo);
+ AssertReturn(NS_SUCCEEDED(hrc), hrc);
+ AssertReturn(pMethodInfo, NS_ERROR_UNEXPECTED);
+
+ /* Allocate dispatcher parameter array. */
+ PRUint8 const cParams = pMethodInfo->GetParamCount();
+ nsXPTCMiniVariant aParamsStatic[8];
+ nsXPTCMiniVariant *paParams;
+ if (cParams <= RT_ELEMENTS(aParamsStatic))
+ paParams = aParamsStatic;
+ else
+ {
+ paParams = (nsXPTCMiniVariant *)alloca(sizeof(paParams[0]) * cParams);
+ AssertReturn(paParams, NS_ERROR_UNEXPECTED);
+ }
+
+ /*
+ * Populate the dispatcher parameter array.
+ */
+ unsigned idxGprArgs = 1; /* The 'pThis' pointer (x0) is not included in cParams. */
+ unsigned idxFprArgs = 0;
+ for (PRUint8 i = 0; i < cParams; i++)
+ {
+ const nsXPTParamInfo &rParam = pMethodInfo->GetParam(i);
+ if (rParam.IsOut())
+ fetchGpr(&paParams[i].val.p, pauGprArgs, idxGprArgs, puStackArgs);
+ else
+ {
+ const nsXPTType Type = rParam.GetType();
+ switch (Type)
+ {
+ case nsXPTType::T_I8: fetchGpr(&paParams[i].val.i8, pauGprArgs, idxGprArgs, puStackArgs); break;
+ case nsXPTType::T_I16: fetchGpr(&paParams[i].val.i16, pauGprArgs, idxGprArgs, puStackArgs); break;
+ case nsXPTType::T_I32: fetchGpr(&paParams[i].val.i32, pauGprArgs, idxGprArgs, puStackArgs); break;
+ case nsXPTType::T_I64: fetchGpr(&paParams[i].val.i64, pauGprArgs, idxGprArgs, puStackArgs); break;
+ case nsXPTType::T_U8: fetchGpr(&paParams[i].val.u8, pauGprArgs, idxGprArgs, puStackArgs); break;
+ case nsXPTType::T_U16: fetchGpr(&paParams[i].val.u16, pauGprArgs, idxGprArgs, puStackArgs); break;
+ case nsXPTType::T_U32: fetchGpr(&paParams[i].val.u32, pauGprArgs, idxGprArgs, puStackArgs); break;
+ case nsXPTType::T_U64: fetchGpr(&paParams[i].val.u64, pauGprArgs, idxGprArgs, puStackArgs); break;
+ case nsXPTType::T_BOOL: fetchGpr(&paParams[i].val.b, pauGprArgs, idxGprArgs, puStackArgs); break;
+ case nsXPTType::T_CHAR: fetchGpr(&paParams[i].val.c, pauGprArgs, idxGprArgs, puStackArgs); break;
+ case nsXPTType::T_WCHAR: fetchGpr(&paParams[i].val.wc, pauGprArgs, idxGprArgs, puStackArgs); break;
+
+ case nsXPTType::T_FLOAT: fetchFpr(&paParams[i].val.f, pauFprArgs, idxFprArgs, puStackArgs); break;
+ case nsXPTType::T_DOUBLE: fetchFpr(&paParams[i].val.d, pauFprArgs, idxFprArgs, puStackArgs); break;
+
+ default:
+ if (!Type.IsArithmetic())
+ fetchGpr(&paParams[i].val.p, pauGprArgs, idxGprArgs, puStackArgs);
+ else
+ AssertMsgFailedReturn(("%#x idxMethod=%#x\n",(unsigned)Type, idxMethod), NS_ERROR_UNEXPECTED);
+ break;
+ }
+ }
+ }
+
+ /*
+ * Dispatch the method call.
+ */
+ hrc = pThis->CallMethod((PRUint16)idxMethod, pMethodInfo, paParams);
+
+ NS_RELEASE(pInterfaceInfo);
+ return hrc;
+
+}
+
+#if 0
+extern "C" nsresult CommonXPTCStubTest(uint64_t x0,
+ uint64_t x1,
+ uint64_t x2,
+ uint64_t x3,
+ uint64_t x4,
+ uint64_t x5,
+ uint64_t x6,
+ uint64_t x7)
+{
+ uint64_t aGprs[8];
+ aGprs[0] = x0;
+ aGprs[1] = x1;
+ aGprs[2] = x2;
+ aGprs[3] = x3;
+ aGprs[4] = x4;
+ aGprs[5] = x5;
+ aGprs[6] = x6;
+ aGprs[7] = x7;
+
+ return CommonXPTCStubCWorker((nsXPTCStubBase *)x0, x1, aGprs, aGprs, aGprs);
+}
+#endif
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm_netbsd.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm_netbsd.cpp
new file mode 100644
index 00000000..47c09a42
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_arm_netbsd.cpp
@@ -0,0 +1,145 @@
+/* -*- 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) 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 ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, PRUint32* args)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((PRInt8*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((PRInt16*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((PRInt64*) ap); ap++; break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((PRUint8*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((PRUint16*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((PRUint32*)ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((PRUint64*)ap); ap++; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((PRBool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+/*
+ * These stubs move just move the values passed in registers onto the stack,
+ * so they are contiguous with values passed on the stack, and then calls
+ * PrepareAndDispatch() to do the dirty work.
+ */
+
+#define STUB_ENTRY(n) \
+__asm__( \
+ ".global _Stub"#n"__14nsXPTCStubBase\n\t" \
+"_Stub"#n"__14nsXPTCStubBase:\n\t" \
+ "stmfd sp!, {r1, r2, r3} \n\t" \
+ "mov ip, sp \n\t" \
+ "stmfd sp!, {fp, ip, lr, pc} \n\t" \
+ "sub fp, ip, #4 \n\t" \
+ "mov r1, #"#n" \n\t" /* = methodIndex */ \
+ "add r2, sp, #16 \n\t" \
+ "bl _PrepareAndDispatch__FP14nsXPTCStubBaseUiPUi \n\t" \
+ "ldmea fp, {fp, sp, lr} \n\t" \
+ "add sp, sp, #12 \n\t" \
+ "mov pc, lr \n\t" \
+);
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ipf32.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ipf32.s
new file mode 100644
index 00000000..591e88e5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ipf32.s
@@ -0,0 +1,124 @@
+
+// Select C numeric constant
+ .radix C
+ .psr abi32
+ .psr msb
+// Section has executable code
+ .section .text, "ax","progbits"
+// procedure named 'SharedStub'
+ .proc SharedStub
+// manual bundling
+ .explicit
+
+ .global PrepareAndDispatch
+// .exclass PrepareAndDispatch, @fullyvisible
+ .type PrepareAndDispatch,@function
+
+SharedStub::
+// 9 arguments, first 8 are the input arguments of previous
+// function call. The last one is methodIndex, and is passed in memory
+ .prologue
+ .save ar.pfs , r41
+// allocate 8 input args, 4 local args, and 5 output args
+ alloc r41 = ar.pfs, 8, 4, 5, 0 // M
+ .save rp, r40
+ mov r40 = rp // I
+ nop.i 0 ;; // I
+
+ .save ar.unat, r42
+ mov r42 = ar.unat // M
+ .fframe 144
+ add sp = -144, sp // A
+// unwind table already knows gp, don't need to specify anything
+ add r43 = 0, gp ;; // A
+
+// We have possible 8 integer registers and 8 float registers that could
+// be arguments. We also have a stack region from the previous
+// stack frame that may hold some stack arguments.
+// We need to write the integer registers to a memory region, write
+// the float registers to a memory region (making sure we don't step
+// on NAT while touching the registers). We also mark the memory
+// address of the stack arguments.
+// We then call PrepareAndDispatch() specifying the three memory
+// region pointers.
+
+
+ .body
+ add out0 = 0, in0 // A move self ptr
+// 144 bytes = 16 byte stack header + 64 byte int space + 64 byte float space
+// current frame is 144 bytes, previous frame is 112 bytes
+// restarg is at 144 + 112 + 16 bytes away from current sp
+// (current frame + previous frame + previous previous frame header)
+// methodIndex is at 144 + 16 bytes away from current sp
+// (current frame + previous frame header)
+ add out4 = 192, sp // A restarg address
+ add r11 = 160, sp ;; // A address of methodIndex
+
+ ld8 out1 = [r11] // M load methodIndex
+// sp + 16 is the start of intargs
+ add out2 = 16, sp // A address of intargs
+// the intargs take up 64 bytes, so sp + 16 + 64 is the start of floatargs
+ add out3 = 80, sp ;; // A address of floatargs
+
+ add r11 = 0, out2 ;; // A
+ st8.spill [r11] = in1, 8 // M
+ add r10 = 0, out3 ;; // A
+
+ st8.spill [r11] = in2, 8 ;; // M
+ st8.spill [r11] = in3, 8 // M
+ nop.i 0 ;; // I
+
+ st8.spill [r11] = in4, 8 ;; // M
+ st8.spill [r11] = in5, 8 // M
+ nop.i 0 ;; // I
+
+ st8.spill [r11] = in6, 8 ;; // M
+ st8.spill [r11] = in7 // M
+ fclass.nm p14,p15 = f8,@nat ;; // F
+
+(p14) stfd [r10] = f8, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 = f9,@nat ;; // F
+
+(p12) stfd [r10] = f9, 8 // M
+(p13) add r10 = 8, r10 // A
+ fclass.nm p14,p15 =f10,@nat ;; // F
+
+(p14) stfd [r10] = f10, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 =f11,@nat ;; // F
+
+(p12) stfd [r10] = f11, 8 // M
+(p13) add r10 = 8, r10 // A
+ fclass.nm p14,p15 =f12,@nat ;; // F
+
+(p14) stfd [r10] = f12, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 =f13,@nat ;; // F
+
+(p12) stfd [r10] = f13, 8 // M
+(p13) add r10 = 8, r10 // A
+ fclass.nm p14,p15 =f14,@nat ;; // F
+
+(p14) stfd [r10] = f14, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 =f15,@nat ;; // F
+
+(p12) stfd [r10] = f15, 8 // M
+(p13) add r10 = 8, r10 // A
+
+// branch to PrepareAndDispatch
+ br.call.dptk.few rp = PrepareAndDispatch ;; // B
+
+// epilog
+ mov ar.unat = r42 // M
+ mov ar.pfs = r41 // I
+ mov rp = r40 ;; // I
+
+ add gp = 0, r43 // A
+ add sp = 144, sp // A
+ br.ret.dptk.few rp ;; // B
+
+ .endp
+
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ipf64.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ipf64.s
new file mode 100644
index 00000000..177b2646
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ipf64.s
@@ -0,0 +1,124 @@
+
+// Select C numeric constant
+ .radix C
+ .psr abi64
+ .psr lsb
+// Section has executable code
+ .section .text, "ax","progbits"
+// procedure named 'SharedStub'
+ .proc SharedStub
+// manual bundling
+ .explicit
+
+ .global PrepareAndDispatch
+// .exclass PrepareAndDispatch, @fullyvisible
+ .type PrepareAndDispatch,@function
+
+SharedStub::
+// 9 arguments, first 8 are the input arguments of previous
+// function call. The last one is methodIndex, and is passed in memory
+ .prologue
+ .save ar.pfs , r41
+// allocate 8 input args, 4 local args, and 5 output args
+ alloc r41 = ar.pfs, 8, 4, 5, 0 // M
+ .save rp, r40
+ mov r40 = rp // I
+ nop.i 0 ;; // I
+
+ .save ar.unat, r42
+ mov r42 = ar.unat // M
+ .fframe 144
+ add sp = -144, sp // A
+// unwind table already knows gp, don't need to specify anything
+ add r43 = 0, gp ;; // A
+
+// We have possible 8 integer registers and 8 float registers that could
+// be arguments. We also have a stack region from the previous
+// stack frame that may hold some stack arguments.
+// We need to write the integer registers to a memory region, write
+// the float registers to a memory region (making sure we don't step
+// on NAT while touching the registers). We also mark the memory
+// address of the stack arguments.
+// We then call PrepareAndDispatch() specifying the three memory
+// region pointers.
+
+
+ .body
+ add out0 = 0, in0 // A move self ptr
+// 144 bytes = 16 byte stack header + 64 byte int space + 64 byte float space
+// current frame is 144 bytes, previous frame is 112 bytes
+// restarg is at 144 + 112 + 16 bytes away from current sp
+// (current frame + previous frame + previous previous frame header)
+// methodIndex is at 144 + 16 bytes away from current sp
+// (current frame + previous frame header)
+ add out4 = 192, sp // A restarg address
+ add r11 = 160, sp ;; // A address of methodIndex
+
+ ld8 out1 = [r11] // M load methodIndex
+// sp + 16 is the start of intargs
+ add out2 = 16, sp // A address of intargs
+// the intargs take up 64 bytes, so sp + 16 + 64 is the start of floatargs
+ add out3 = 80, sp ;; // A address of floatargs
+
+ add r11 = 0, out2 ;; // A
+ st8.spill [r11] = in1, 8 // M
+ add r10 = 0, out3 ;; // A
+
+ st8.spill [r11] = in2, 8 ;; // M
+ st8.spill [r11] = in3, 8 // M
+ nop.i 0 ;; // I
+
+ st8.spill [r11] = in4, 8 ;; // M
+ st8.spill [r11] = in5, 8 // M
+ nop.i 0 ;; // I
+
+ st8.spill [r11] = in6, 8 ;; // M
+ st8.spill [r11] = in7 // M
+ fclass.nm p14,p15 = f8,@nat ;; // F
+
+(p14) stfd [r10] = f8, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 = f9,@nat ;; // F
+
+(p12) stfd [r10] = f9, 8 // M
+(p13) add r10 = 8, r10 // A
+ fclass.nm p14,p15 =f10,@nat ;; // F
+
+(p14) stfd [r10] = f10, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 =f11,@nat ;; // F
+
+(p12) stfd [r10] = f11, 8 // M
+(p13) add r10 = 8, r10 // A
+ fclass.nm p14,p15 =f12,@nat ;; // F
+
+(p14) stfd [r10] = f12, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 =f13,@nat ;; // F
+
+(p12) stfd [r10] = f13, 8 // M
+(p13) add r10 = 8, r10 // A
+ fclass.nm p14,p15 =f14,@nat ;; // F
+
+(p14) stfd [r10] = f14, 8 // M
+(p15) add r10 = 8, r10 // A
+ fclass.nm p12,p13 =f15,@nat ;; // F
+
+(p12) stfd [r10] = f15, 8 // M
+(p13) add r10 = 8, r10 // A
+
+// branch to PrepareAndDispatch
+ br.call.dptk.few rp = PrepareAndDispatch ;; // B
+
+// epilog
+ mov ar.unat = r42 // M
+ mov ar.pfs = r41 // I
+ mov rp = r40 ;; // I
+
+ add gp = 0, r43 // A
+ add sp = 144, sp // A
+ br.ret.dptk.few rp ;; // B
+
+ .endp
+
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_irix.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_irix.s
new file mode 100644
index 00000000..4ca1e542
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_irix.s
@@ -0,0 +1,97 @@
+
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+ .text
+ .globl PrepareAndDispatch
+
+LOCALSZ=16
+FRAMESZ=(((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK
+
+A1OFF=FRAMESZ-(9*SZREG)
+A2OFF=FRAMESZ-(8*SZREG)
+A3OFF=FRAMESZ-(7*SZREG)
+A4OFF=FRAMESZ-(6*SZREG)
+A5OFF=FRAMESZ-(5*SZREG)
+A6OFF=FRAMESZ-(4*SZREG)
+A7OFF=FRAMESZ-(3*SZREG)
+GPOFF=FRAMESZ-(2*SZREG)
+RAOFF=FRAMESZ-(1*SZREG)
+
+F13OFF=FRAMESZ-(16*SZREG)
+F14OFF=FRAMESZ-(15*SZREG)
+F15OFF=FRAMESZ-(14*SZREG)
+F16OFF=FRAMESZ-(13*SZREG)
+F17OFF=FRAMESZ-(12*SZREG)
+F18OFF=FRAMESZ-(11*SZREG)
+F19OFF=FRAMESZ-(10*SZREG)
+
+#define SENTINEL_ENTRY(nn) /* defined in cpp file, not here */
+
+#ifdef __GNUC__
+#define STUB_ENTRY(nn) MAKE_STUB(nn, Stub/**/nn/**/__14nsXPTCStubBase)
+#else
+#define STUB_ENTRY(nn) MAKE_STUB(nn, Stub/**/nn/**/__14nsXPTCStubBaseGv)
+#endif
+
+#define MAKE_STUB(nn, name) \
+NESTED(name, FRAMESZ, ra); \
+ SETUP_GP; \
+ PTR_SUBU sp, FRAMESZ; \
+ SETUP_GP64(GPOFF, name); \
+ SAVE_GP(GPOFF); \
+ li t0, nn; \
+ b sharedstub; \
+.end name; \
+
+#include "xptcstubsdef.inc"
+
+ .globl sharedstub
+ .ent sharedstub
+sharedstub:
+
+ REG_S a1, A1OFF(sp)
+ REG_S a2, A2OFF(sp)
+ REG_S a3, A3OFF(sp)
+ REG_S a4, A4OFF(sp)
+ REG_S a5, A5OFF(sp)
+ REG_S a6, A6OFF(sp)
+ REG_S a7, A7OFF(sp)
+ REG_S ra, RAOFF(sp)
+
+ s.d $f13, F13OFF(sp)
+ s.d $f14, F14OFF(sp)
+ s.d $f15, F15OFF(sp)
+ s.d $f16, F16OFF(sp)
+ s.d $f17, F17OFF(sp)
+ s.d $f18, F18OFF(sp)
+ s.d $f19, F19OFF(sp)
+
+ # t0 is methodIndex
+ move a1, t0
+
+ # a2 is stack address where extra function params
+ # are stored that do not fit in registers
+ move a2, sp
+ addi a2, FRAMESZ
+
+ # a3 is stack address of a1..a7
+ move a3, sp
+ addi a3, A1OFF
+
+ # a4 is stack address of f13..f19
+ move a4, sp
+ addi a4, F13OFF
+
+ # PrepareAndDispatch(that, methodIndex, args, gprArgs, fpArgs)
+ # a0 a1 a2 a3 a4
+ #
+ jal PrepareAndDispatch
+
+ REG_L ra, RAOFF(sp)
+ REG_L gp, GPOFF(sp)
+
+ PTR_ADDU sp, FRAMESZ
+ j ra
+
+.end sharedstub
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_mips.s.m4 b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_mips.s.m4
new file mode 100644
index 00000000..f327adfb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_mips.s.m4
@@ -0,0 +1,109 @@
+/* -*- Mode: asm; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * Version: MPL 1.1
+ *
+ * ***** 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 Corp, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Stuart Parmenter <pavlov@netscape.com>
+ * 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 ***** */
+
+/* This code is for MIPS using the O32 ABI. */
+
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+ .text
+ .globl PrepareAndDispatch
+
+NARGSAVE=4 # extra space for the callee to use. gccism
+ # we can put our a0-a3 in our callers space.
+LOCALSZ=2 # gp, ra
+FRAMESZ=(((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK
+
+define(STUB_NAME, `Stub'$1`__14nsXPTCStubBase')
+
+define(STUB_ENTRY,
+` .globl 'STUB_NAME($1)`
+ .align 2
+ .type 'STUB_NAME($1)`,@function
+ .ent 'STUB_NAME($1)`, 0
+'STUB_NAME($1)`:
+ .frame sp, FRAMESZ, ra
+ .set noreorder
+ .cpload t9
+ .set reorder
+ subu sp, FRAMESZ
+ .cprestore 16
+ li t0, '$1`
+ b sharedstub
+.end 'STUB_NAME($1)`
+
+')
+
+define(SENTINEL_ENTRY, `')
+
+include(xptcstubsdef.inc)
+
+ .globl sharedstub
+ .ent sharedstub
+sharedstub:
+
+ REG_S ra, 20(sp)
+
+ REG_S a0, 24(sp)
+ REG_S a1, 28(sp)
+ REG_S a2, 32(sp)
+ REG_S a3, 36(sp)
+
+ # t0 is methodIndex
+ move a1, t0
+
+ # put the start of a1, a2, a3, and stack
+ move a2, sp
+ addi a2, 24 # have a2 point to sp + 24 (where a0 is)
+
+ # PrepareAndDispatch(that, methodIndex, args)
+ # a0 a1 a2
+ #
+ jal PrepareAndDispatch
+
+ REG_L ra, 20(sp)
+ REG_L a1, 28(sp)
+ REG_L a2, 32(sp)
+
+ addu sp, FRAMESZ
+ j ra
+
+.end sharedstub
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_openvms_alpha.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_openvms_alpha.s
new file mode 100644
index 00000000..9f04d4c4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_openvms_alpha.s
@@ -0,0 +1,115 @@
+;* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+;*
+;* The contents of this file are subject to the Netscape 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/NPL/
+;*
+;* 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 Netscape are
+;* Copyright (C) 1999 Netscape Communications Corporation. All
+;* Rights Reserved.
+;*
+;* Contributor(s):
+;*/
+
+; Implement shared vtbl methods.
+
+ .title "STUBS" "Stub Code"
+
+ MBIT = "__14nsXPTCStubBasexv" ; this is the mangled part of the name
+
+; The layout of the linkage section is important. First comes
+; PrepareAndDispatch, and then the Procedure Descriptors for the stubs. Each
+; is known to be 16 bytes long, and we use this fact to be able to locate the
+; PrepareAndDispatch linkage pair from any of the stubs.
+
+ .PSECT $LINK$, OCTA, NOPIC, CON, REL, LCL, NOSHR, NOEXE, RD, NOWRT
+ .LINKAGE_PAIR PrepareAndDispatch
+ LINKOFF = 16 ; first stub lp will be 16 bytes away
+
+; STUB_ENTRY createa a routine nsXPTCStubBase::Stub<n>() where n is the
+; argument passed in to STUB_ENTRY. It puts its stub number into R1 and then
+; jumps into SharedStub. It does it this way because we don't want to mess
+; up the arguments that may be on the stack. In order that we can find
+; our way around the linkage section, we subtract our offset from the
+; start of the linkage section (LINKOFF) from our own PV, thus giving
+; us the PV os the first entry in the linkage section (this should be
+; PrepareAndDispatch);
+
+ .macro STUB_ENTRY n
+ $routine Stub'n%MBIT%, kind=null
+ mov LINKOFF, r1 ; distance from lp for PrepareAndDispatch
+ subq r27,r1,r27 ; subtract it from address of our proc desc
+ mov n,r1 ; stub number is passed in r1
+ br SharedStub ; off to common code
+ $end_routine
+ LINKOFF = LINKOFF + 16 ; we just put 16 bytes into linkage section
+ .endm STUB_ENTRY
+
+; SENTINEL_ENTRY is in the C++ module. We need to define a empty macro
+; here to keep the assembler happy.
+ .macro SENTINEL_ENTRY n
+ .endm SENTINEL_ENTRY
+
+ .PSECT $CODE$, OCTA, PIC, CON, REL, LCL, SHR, EXE, NORD, NOWRT
+
+;
+; SharedStub()
+; Collects arguments and calls PrepareAndDispatch.
+;
+; r1 - The "methodIndex"
+; r27 - points to the first entry in the linkage section, which by design
+; is the linkage pair for PrepareAndDispatch.
+;
+; Arguments are passed in a non-standard way so that we don't disturb the
+; original arguments that were passed in to the stub. Since some args (if
+; there were more than 6) will already be on the stack, the stub had to not
+; only preserve R16-R21, but also preserve the stack too.
+;
+
+SharedStub::
+ subq sp,96,sp ; get some stack space for the args and saves
+ stq r26,0(sp) ; save r26 (the return address)
+
+ ;
+ ; Store arguments passed via registers to the stack.
+ ; Floating point registers are stored as doubles and converted
+ ; to floats in PrepareAndDispatch if necessary.
+ ;
+ stt f17,16(sp) ; floating point registers
+ stt f18,24(sp)
+ stt f19,32(sp)
+ stt f20,40(sp)
+ stt f21,48(sp)
+ stq r17,56(sp) ; integer registers
+ stq r18,64(sp)
+ stq r19,72(sp)
+ stq r20,80(sp)
+ stq r21,88(sp)
+
+ ;
+ ; Call PrepareAndDispatch function.
+ ;
+ mov r1,r17 ; pass "methodIndex"
+ addq sp,16,r18 ; pass "args"
+ mov 3,r25 ; number of args into AI
+
+ LDQ R26, 0(R27) ; get entry point address from linkage pair
+ LDQ R27, 8(R27) ; get procedure descriptor address from lp
+ JSR R26, R26
+
+ ldq r26, 0(sp) ; restore return address
+ addq sp,96,sp ; return stack space
+ ret r26 ; and we're outta here
+
+ .include "xptcstubsdef_asm.vms"
+
+ .end
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_osf1_alpha.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_osf1_alpha.s
new file mode 100644
index 00000000..3bef9b1b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_osf1_alpha.s
@@ -0,0 +1,75 @@
+ .text
+ .align 5
+ .globl SharedStub
+ .ent SharedStub
+SharedStub:
+ .frame $30, 96, $26, 0
+ .mask 0x4000000,-96
+ ldgp $29,0($27)
+SharedStubXv:
+ subq $30,96,$30
+ stq $26,0($30)
+ .prologue 1
+ stt $f17,16($30)
+ stt $f18,24($30)
+ stt $f19,32($30)
+ stt $f20,40($30)
+ stt $f21,48($30)
+ stq $17,56($30)
+ stq $18,64($30)
+ stq $19,72($30)
+ stq $20,80($30)
+ stq $21,88($30)
+ bis $1,$1,$17
+ addq $30,16,$18
+ bsr $26,PrepareAndDispatch
+ ldq $26,0($30)
+ addq $30,96,$30
+ ret $31,($26),1
+ .end SharedStub
+
+/*
+ The C preprocessor doesn't handle # and ## if run with -std or -std0.
+
+ If -std then __STDC__ is 0 [default] (K&R behavior)
+ If -std0 then __STDC__ is undefined (K&R behavior)
+ If -std1 then __STDC__ is 1 (ANSI preprocessor)
+*/
+
+#if __STDC__
+#define STUB_ENTRY(n) ;\
+ .text ;\
+ .align 5 ;\
+ .globl Stub##n##__14nsXPTCStubBase ;\
+ .globl Stub##n##__14nsXPTCStubBaseXv ;\
+ .ent Stub##n##__14nsXPTCStubBase ;\
+Stub##n##__14nsXPTCStubBase: ;\
+ .frame $30,0,$26,0 ;\
+ ldgp $29,0($27) ;\
+ .prologue 1 ;\
+Stub##n##__14nsXPTCStubBaseXv: ;\
+ lda $1,n ;\
+ br $31,SharedStubXv ;\
+ .end Stub##n##__14nsXPTCStubBase \
+
+#else
+#define STUB_ENTRY(n) ;\
+ .text ;\
+ .align 5 ;\
+ .globl Stub/**/n/**/__14nsXPTCStubBase ;\
+ .globl Stub/**/n/**/__14nsXPTCStubBaseXv ;\
+ .ent Stub/**/n/**/__14nsXPTCStubBase ;\
+Stub/**/n/**/__14nsXPTCStubBase: ;\
+ .frame $30,0,$26,0 ;\
+ ldgp $29,0($27) ;\
+ .prologue 1 ;\
+Stub/**/n/**/__14nsXPTCStubBaseXv: ;\
+ lda $1,n ;\
+ br $31,SharedStubXv ;\
+ .end Stub/**/n/**/__14nsXPTCStubBase \
+
+#endif
+
+#define SENTINEL_ENTRY(n) \
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_pa32.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_pa32.s
new file mode 100644
index 00000000..9e86848f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_pa32.s
@@ -0,0 +1,68 @@
+ .LEVEL 1.1
+
+curframesz .EQU 128
+; SharedStub has stack size of 128 bytes
+
+lastframesz .EQU 64
+; the StubN C++ function has a small stack size of 64 bytes
+
+ .SPACE $TEXT$,SORT=8
+ .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=0x2c,CODE_ONLY,SORT=24
+SharedStub
+ .PROC
+ .CALLINFO CALLER,FRAME=80,SAVE_RP,ARGS_SAVED
+
+ .ENTRY
+ STW %rp,-20(%sp)
+ LDO 128(%sp),%sp
+
+ STW %r19,-32(%r30)
+ STW %r26,-36-curframesz(%r30) ; save arg0 in previous frame
+
+ LDO -80(%r30),%r28
+ FSTD,MA %fr5,8(%r28) ; save darg0
+ FSTD,MA %fr7,8(%r28) ; save darg1
+ FSTW,MA %fr4L,4(%r28) ; save farg0
+ FSTW,MA %fr5L,4(%r28) ; save farg1
+ FSTW,MA %fr6L,4(%r28) ; save farg2
+ FSTW,MA %fr7L,4(%r28) ; save farg3
+
+ ; Former value of register 26 is already properly saved by StubN,
+ ; but register 25-23 are not because of the arguments mismatch
+ STW %r25,-40-curframesz-lastframesz(%r30) ; save r25
+ STW %r24,-44-curframesz-lastframesz(%r30) ; save r24
+ STW %r23,-48-curframesz-lastframesz(%r30) ; save r23
+ COPY %r26,%r25 ; method index is arg1
+ LDW -36-curframesz-lastframesz(%r30),%r26 ; self is arg0
+ LDO -40-curframesz-lastframesz(%r30),%r24 ; normal args is arg2
+ LDO -80(%r30),%r23 ; floating args is arg3
+
+ BL .+8,%r2
+ ADDIL L'PrepareAndDispatch-$PIC_pcrel$0+4,%r2
+ LDO R'PrepareAndDispatch-$PIC_pcrel$1+8(%r1),%r1
+$PIC_pcrel$0
+ LDSID (%r1),%r31
+$PIC_pcrel$1
+ MTSP %r31,%sr0
+ .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR
+;in=23-26;out=28;
+ BLE 0(%sr0,%r1)
+ COPY %r31,%r2
+
+ LDW -32(%r30),%r19
+
+ LDW -148(%sp),%rp
+ BVE (%rp)
+ .EXIT
+ LDO -128(%sp),%sp
+
+
+ .PROCEND ;in=26;out=28;
+
+ .ALIGN 8
+ .SPACE $TEXT$
+ .SUBSPA $CODE$
+ .IMPORT PrepareAndDispatch,CODE
+ .EXPORT SharedStub,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR,LONG_RETURN
+ .END
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_aix.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_aix.s
new file mode 100644
index 00000000..667da705
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_aix.s
@@ -0,0 +1,117 @@
+ #
+ # -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ #
+ # The contents of this file are subject to the Netscape 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/NPL/
+ #
+ # 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 Netscape are
+ # Copyright (C) 1999 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s):
+ #
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+
+
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.SharedStub{TC},"SharedStub"
+
+
+# .text section
+
+ .csect H.10.NO_SYMBOL{PR}
+ .globl .SharedStub
+ .globl SharedStub{DS}
+ .extern .PrepareAndDispatch
+
+
+#jimbo csect CODE{PR}
+#
+# on entry SharedStub has the method selector in r12, the rest of the original
+# parameters are in r3 thru r10 and f1 thru f13
+#
+#jimbo import .PrepareAndDispatch
+
+.SharedStub:
+ mflr r0
+ stw r0,8(sp)
+
+ mr r12,r3 # Move methodIndex into r12 for LATER
+ lwz r3,104(sp) # Get the 'original' r3
+
+ stwu sp,-176(sp) # room for linkage (24), fprData (104), gprData(28)
+ # outgoing params to PrepareAndDispatch (20)
+
+ stw r4,44(sp)
+ stw r5,48(sp)
+ stw r6,52(sp)
+ stw r7,56(sp)
+ stw r8,60(sp)
+ stw r9,64(sp)
+ stw r10,68(sp)
+ stfd f1,72(sp)
+ stfd f2,80(sp)
+ stfd f3,88(sp)
+ stfd f4,96(sp)
+ stfd f5,104(sp)
+ stfd f6,112(sp)
+ stfd f7,120(sp)
+ stfd f8,128(sp)
+ stfd f9,136(sp)
+ stfd f10,144(sp)
+ stfd f11,152(sp)
+ stfd f12,156(sp)
+ stfd f13,164(sp)
+
+ addi r6,sp,44 # gprData
+ addi r7,sp,72 # fprData
+ # r3 has the 'self' pointer already
+ mr r4,r12 # methodIndex selector (it is now LATER)
+ addi r5,sp,312 # pointer to callers args area, beyond r3-r10 mapped range
+
+ bl .PrepareAndDispatch
+ nop
+
+ lwz r0,184(sp)
+ addi sp,sp,176
+ mtlr r0
+ blr
+
+# .data section
+
+ .toc # 0x00000038
+T.18.SharedStub:
+ .tc H.18.SharedStub{TC},SharedStub{DS}
+
+ .csect SharedStub{DS}
+ .long .SharedStub # "\0\0\0\0"
+ .long TOC{TC0} # "\0\0\0008"
+ .long 0x00000000 # "\0\0\0\0"
+# End csect SharedStub{DS}
+
+# .bss section
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_aix64.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_aix64.s
new file mode 100644
index 00000000..94245d5e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_aix64.s
@@ -0,0 +1,137 @@
+# ***** BEGIN LICENSE BLOCK *****
+#
+# Version: MPL 1.1/LGPL 2.1/GPL 2.0
+#
+# 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 IBM Corporation.
+# Portions created by IBM are
+# Copyright (C) 2002, International Business Machines Corporation.
+# 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 LGPL or the GPL. 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 *****
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+
+ .rename H.10.NO_SYMBOL{PR},""
+ .rename H.18.SharedStub{TC},"SharedStub"
+
+
+# .text section
+
+ .csect H.10.NO_SYMBOL{PR}
+ .globl .SharedStub
+ .globl SharedStub{DS}
+ .extern .PrepareAndDispatch
+
+
+#jimbo csect CODE{PR}
+#
+# on entry SharedStub has the method selector in r12, the rest of the original
+# parameters are in r3 thru r10 and f1 thru f13
+#
+#jimbo import .PrepareAndDispatch
+
+.SharedStub:
+ mflr r0
+ std r0,16(sp)
+
+ mr r12,r3 # Move methodIndex into r12 for LATER
+ ld r3,176(sp) # Get the 'original' r3 (load 'this' into r3)
+
+ stdu sp,-248(sp) # room for linkage (24*2), fprData (104),
+ # gprData(28*2), outgoing params to
+ # PrepareAndDispatch (40)
+
+ std r4,88(sp) # link area (48) + PrepareAndDispatch parms (40)
+ std r5,96(sp)
+ std r6,104(sp)
+ std r7,112(sp)
+ std r8,120(sp)
+ std r9,128(sp)
+ std r10,136(sp)
+ stfd f1,144(sp)
+ stfd f2,152(sp)
+ stfd f3,160(sp)
+ stfd f4,168(sp)
+ stfd f5,176(sp)
+ stfd f6,184(sp)
+ stfd f7,192(sp)
+ stfd f8,200(sp)
+ stfd f9,208(sp)
+ stfd f10,216(sp)
+ stfd f11,224(sp)
+ stfd f12,232(sp)
+ stfd f13,240(sp)
+
+ addi r6,sp,88 # gprData
+ addi r7,sp,144 # fprData
+ # r3 has the 'self' pointer already
+ mr r4,r12 # methodIndex selector (it is now LATER)
+ addi r5,sp,488 # pointer to callers args area, beyond r3-r10
+ # mapped range
+ # 32bit: 176 (stack-distance) 64bit: 248 (stack-distance)
+ # 104 (this ptr offset) 176
+ # 32 (8*4 for r3-r10) 64 (8*8)
+ # --- ---
+ # 312 488
+
+ bl .PrepareAndDispatch
+ nop
+
+ ld r0,264(sp) # 248+16
+ addi sp,sp,248
+ mtlr r0
+ blr
+
+# .data section
+
+ .toc # 0x00000038
+T.18.SharedStub:
+ .tc H.18.SharedStub{TC},SharedStub{DS}
+
+ .csect SharedStub{DS}
+ .llong .SharedStub # "\0\0\0\0"
+ .llong TOC{TC0} # "\0\0\0008"
+ .llong 0x00000000 # "\0\0\0\0"
+# End csect SharedStub{DS}
+
+# .bss section
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_darwin.s.m4 b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_darwin.s.m4
new file mode 100644
index 00000000..60dbd7c3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_darwin.s.m4
@@ -0,0 +1,126 @@
+/* -*- Mode: asm; 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) 1999-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 ***** */
+
+ .text
+ .globl _SharedStub
+
+define(STUB_MANGLED_ENTRY,
+` .globl '$2`
+ .align 2
+'$2`:
+ addi r12, 0, '$1`
+ b _SharedStub
+')
+
+define(STUB_ENTRY,
+`#ifdef HAVE_GCC3_ABI
+ .if '$1` < 10
+STUB_MANGLED_ENTRY('$1`, `__ZN14nsXPTCStubBase5Stub'$1`Ev')
+ .elseif '$1` < 100
+STUB_MANGLED_ENTRY('$1`, `__ZN14nsXPTCStubBase6Stub'$1`Ev')
+ .elseif '$1` < 1000
+STUB_MANGLED_ENTRY('$1`, `__ZN14nsXPTCStubBase7Stub'$1`Ev')
+ .else
+ .err "Stub'$1` >= 1000 not yet supported."
+ .endif
+#else /* !defined(HAVE_GCC3_ABI) */
+STUB_MANGLED_ENTRY('$1`, `_Stub'$1`__14nsXPTCStubBase')
+#endif /* !defined(HAVE_GCC3_ABI) */
+')
+
+define(SENTINEL_ENTRY, `')
+
+include(xptcstubsdef.inc)
+
+_SharedStub:
+ mflr r0
+ stw r0,8(r1)
+
+ stwu r1,-176(r1)
+
+ stw r4,44(r1)
+ stw r5,48(r1)
+ stw r6,52(r1)
+ stw r7,56(r1)
+ stw r8,60(r1)
+ stw r9,64(r1)
+ stw r10,68(r1)
+ stfd f1,72(r1)
+ stfd f2,80(r1)
+ stfd f3,88(r1)
+ stfd f4,96(r1)
+ stfd f5,104(r1)
+ stfd f6,112(r1)
+ stfd f7,120(r1)
+ stfd f8,128(r1)
+ stfd f9,136(r1)
+ stfd f10,144(r1)
+ stfd f11,152(r1)
+ stfd f12,156(r1)
+ stfd f13,164(r1)
+
+ addi r6,r1,44
+ addi r7,r1,72
+
+ mr r4,r12
+ addi r5,r1,232
+
+ bl L_PrepareAndDispatch$stub
+ nop
+
+ lwz r0,184(r1)
+ addi r1,r1,176
+ mtlr r0
+ blr
+
+.picsymbol_stub
+L_PrepareAndDispatch$stub:
+ .indirect_symbol _PrepareAndDispatch
+ mflr r0
+ bcl 20,31,L1$pb
+L1$pb:
+ mflr r11
+ addis r11,r11,ha16(L1$lz-L1$pb)
+ mtlr r0
+ lwz r12,lo16(L1$lz-L1$pb)(r11)
+ mtctr r12
+ addi r11,r11,lo16(L1$lz-L1$pb)
+ bctr
+.lazy_symbol_pointer
+L1$lz:
+ .indirect_symbol _PrepareAndDispatch
+ .long dyld_stub_binding_helper
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_linux.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_linux.s
new file mode 100644
index 00000000..fc85bdb9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_linux.s
@@ -0,0 +1,89 @@
+// -*- Mode: Asm -*-
+//
+// The contents of this file are subject to the Netscape 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/NPL/
+//
+// 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 Netscape are
+// Copyright (C) 1999 Netscape Communications Corporation. All
+// Rights Reserved.
+//
+// Contributor(s):
+// Franz.Sirl-kernel@lauterbach.com (Franz Sirl)
+// beard@netscape.com (Patrick Beard)
+// waterson@netscape.com (Chris Waterson)
+//
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+ .section ".text"
+ .align 2
+ .globl SharedStub
+ .type SharedStub,@function
+
+SharedStub:
+ stwu sp,-112(sp) // room for
+ // linkage (8),
+ // gprData (32),
+ // fprData (64),
+ // stack alignment(8)
+ mflr r0
+ stw r0,116(sp) // save LR backchain
+
+ stw r4,12(sp) // save GP registers
+ stw r5,16(sp) // (n.b. that we don't save r3
+ stw r6,20(sp) // because PrepareAndDispatch() is savvy)
+ stw r7,24(sp)
+ stw r8,28(sp)
+ stw r9,32(sp)
+ stw r10,36(sp)
+
+ stfd f1,40(sp) // save FP registers
+ stfd f2,48(sp)
+ stfd f3,56(sp)
+ stfd f4,64(sp)
+ stfd f5,72(sp)
+ stfd f6,80(sp)
+ stfd f7,88(sp)
+ stfd f8,96(sp)
+
+ // r3 has the 'self' pointer already
+
+ mr r4,r11 // r4 <= methodIndex selector, passed
+ // via r11 in the nsXPTCStubBase::StubXX() call
+
+ addi r5,sp,120 // r5 <= pointer to callers args area,
+ // beyond r3-r10/f1-f8 mapped range
+
+ addi r6,sp,8 // r6 <= gprData
+ addi r7,sp,40 // r7 <= fprData
+
+ bl PrepareAndDispatch@local // Go!
+
+ lwz r0,116(sp) // restore LR
+ mtlr r0
+ la sp,112(sp) // clean up the stack
+ blr
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_netbsd.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_netbsd.s
new file mode 100644
index 00000000..f94aac4f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_ppc_netbsd.s
@@ -0,0 +1,89 @@
+# -*- Mode: Asm -*-
+#
+# The contents of this file are subject to the Netscape 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/NPL/
+#
+# 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 Netscape are
+# Copyright (C) 1999 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+# Franz.Sirl-kernel@lauterbach.com (Franz Sirl)
+# beard@netscape.com (Patrick Beard)
+# waterson@netscape.com (Chris Waterson)
+#
+
+.set r0,0; .set sp,1; .set RTOC,2; .set r3,3; .set r4,4
+.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9
+.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14
+.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19
+.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24
+.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29
+.set r30,30; .set r31,31
+.set f0,0; .set f1,1; .set f2,2; .set f3,3; .set f4,4
+.set f5,5; .set f6,6; .set f7,7; .set f8,8; .set f9,9
+.set f10,10; .set f11,11; .set f12,12; .set f13,13; .set f14,14
+.set f15,15; .set f16,16; .set f17,17; .set f18,18; .set f19,19
+.set f20,20; .set f21,21; .set f22,22; .set f23,23; .set f24,24
+.set f25,25; .set f26,26; .set f27,27; .set f28,28; .set f29,29
+.set f30,30; .set f31,31
+
+ .section ".text"
+ .align 2
+ .globl SharedStub
+ .type SharedStub,@function
+
+SharedStub:
+ stwu sp,-112(sp) # room for
+ # linkage (8),
+ # gprData (32),
+ # fprData (64),
+ # stack alignment(8)
+ mflr r0
+ stw r0,116(sp) # save LR backchain
+
+ stw r4,12(sp) # save GP registers
+ stw r5,16(sp) # (n.b. that we don't save r3
+ stw r6,20(sp) # because PrepareAndDispatch() is savvy)
+ stw r7,24(sp)
+ stw r8,28(sp)
+ stw r9,32(sp)
+ stw r10,36(sp)
+
+ stfd f1,40(sp) # save FP registers
+ stfd f2,48(sp)
+ stfd f3,56(sp)
+ stfd f4,64(sp)
+ stfd f5,72(sp)
+ stfd f6,80(sp)
+ stfd f7,88(sp)
+ stfd f8,96(sp)
+
+ # r3 has the 'self' pointer already
+
+ mr r4,r11 # r4 <= methodIndex selector, passed
+ # via r11 in the nsXPTCStubBase::StubXX() call
+
+ addi r5,sp,120 # r5 <= pointer to callers args area,
+ # beyond r3-r10/f1-f8 mapped range
+
+ addi r6,sp,8 # r6 <= gprData
+ addi r7,sp,40 # r7 <= fprData
+
+ bl PrepareAndDispatch@local # Go!
+
+ lwz r0,116(sp) # restore LR
+ mtlr r0
+ la sp,112(sp) # clean up the stack
+ blr
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_sparc_netbsd.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_sparc_netbsd.s
new file mode 100644
index 00000000..4a8a4698
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_sparc_netbsd.s
@@ -0,0 +1,65 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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 Netscape are
+ * Copyright (C) 1999 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ */
+
+ .global SharedStub
+
+/*
+ in the frame for the function that called SharedStub are the
+ rest of the parameters we need
+
+*/
+
+SharedStub:
+! we don't create a new frame yet, but work within the frame of the calling
+! function to give ourselves the other parameters we want
+
+ mov %o0, %o1 ! shuffle the index up to 2nd place
+ mov %i0, %o0 ! the original 'this'
+ add %fp, 72, %o2 ! previous stack top adjusted to the first argument slot (beyond 'this')
+! save off the original incoming parameters that arrived in
+! registers, the ABI guarantees the space for us to do this
+ st %i1, [%fp + 72]
+ st %i2, [%fp + 76]
+ st %i3, [%fp + 80]
+ st %i4, [%fp + 84]
+ st %i5, [%fp + 88]
+! now we can build our own stack frame
+ save %sp,-(64 + 32),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 32
+! our function now appears to have been called
+! as SharedStub(nsISupports* that, PRUint32 index, PRUint32* args)
+! so we can just copy these through
+
+ mov %i0, %o0
+ mov %i1, %o1
+ mov %i2, %o2
+ call PrepareAndDispatch
+ nop
+ mov %o0,%i0 ! propagate return value
+ b .LL1
+ nop
+.LL1:
+ ret
+ restore
+
+ .size SharedStub, .-SharedStub
+ .type SharedStub, #function
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_sparc_solaris.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_sparc_solaris.s
new file mode 100644
index 00000000..4a8a4698
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_sparc_solaris.s
@@ -0,0 +1,65 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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 Netscape are
+ * Copyright (C) 1999 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ */
+
+ .global SharedStub
+
+/*
+ in the frame for the function that called SharedStub are the
+ rest of the parameters we need
+
+*/
+
+SharedStub:
+! we don't create a new frame yet, but work within the frame of the calling
+! function to give ourselves the other parameters we want
+
+ mov %o0, %o1 ! shuffle the index up to 2nd place
+ mov %i0, %o0 ! the original 'this'
+ add %fp, 72, %o2 ! previous stack top adjusted to the first argument slot (beyond 'this')
+! save off the original incoming parameters that arrived in
+! registers, the ABI guarantees the space for us to do this
+ st %i1, [%fp + 72]
+ st %i2, [%fp + 76]
+ st %i3, [%fp + 80]
+ st %i4, [%fp + 84]
+ st %i5, [%fp + 88]
+! now we can build our own stack frame
+ save %sp,-(64 + 32),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 32
+! our function now appears to have been called
+! as SharedStub(nsISupports* that, PRUint32 index, PRUint32* args)
+! so we can just copy these through
+
+ mov %i0, %o0
+ mov %i1, %o1
+ mov %i2, %o2
+ call PrepareAndDispatch
+ nop
+ mov %o0,%i0 ! propagate return value
+ b .LL1
+ nop
+.LL1:
+ ret
+ restore
+
+ .size SharedStub, .-SharedStub
+ .type SharedStub, #function
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_sparcv9_solaris.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_sparcv9_solaris.s
new file mode 100644
index 00000000..e3bbcf8b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_asm_sparcv9_solaris.s
@@ -0,0 +1,67 @@
+/* -*- Mode: asm; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * 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 Netscape are
+ * Copyright (C) 2001 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ * Stuart Parmenter <pavlov@netscape.com>
+ */
+
+ .global SharedStub
+
+/*
+ in the frame for the function that called SharedStub are the
+ rest of the parameters we need
+
+*/
+
+SharedStub:
+! we don't create a new frame yet, but work within the frame of the calling
+! function to give ourselves the other parameters we want
+
+ mov %o0, %o1 ! shuffle the index up to 2nd place
+ mov %i0, %o0 ! the original 'this'
+ add %fp, 0x7ff + 136, %o2 ! previous stack top adjusted to the first argument slot (beyond 'this')
+
+! save off the original incoming parameters that arrived in
+! registers, the ABI guarantees the space for us to do this
+ stx %i1, [%fp + 0x7ff + 136]
+ stx %i2, [%fp + 0x7ff + 144]
+ stx %i3, [%fp + 0x7ff + 152]
+ stx %i4, [%fp + 0x7ff + 160]
+ stx %i5, [%fp + 0x7ff + 168]
+! now we can build our own stack frame
+ save %sp,-(128 + 64),%sp ! room for the register window and
+ ! struct pointer, rounded up to 0 % 64
+! our function now appears to have been called
+! as SharedStub(nsISupports* that, PRUint32 index, PRUint32* args)
+! so we can just copy these through
+
+ mov %i0, %o0
+ mov %i1, %o1
+ mov %i2, %o2
+ call PrepareAndDispatch
+ nop
+ mov %o0,%i0 ! propagate return value
+ b .LL1
+ nop
+.LL1:
+ ret
+ restore
+
+ .size SharedStub, .-SharedStub
+ .type SharedStub, #function
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_gcc_x86_unix.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_gcc_x86_unix.cpp
new file mode 100644
index 00000000..351ee512
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_gcc_x86_unix.cpp
@@ -0,0 +1,202 @@
+/* -*- 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) 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 ***** */
+
+/* Implement shared vtbl methods. */
+
+#ifdef __GNUC__ /* Gnu Compiler. */
+
+#include "xptcprivate.h"
+#include "xptc_platforms_unixish_x86.h"
+#include "xptc_gcc_x86_unix.h"
+
+extern "C" {
+static nsresult ATTRIBUTE_USED
+__attribute__ ((regparm (3)))
+PrepareAndDispatch(uint32 methodIndex, nsXPTCStubBase* self, PRUint32* args)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info = NULL;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+ if (!iface_info)
+ return NS_ERROR_UNEXPECTED;
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (!info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ dp->val.p = (void*) *ap;
+ switch(type)
+ {
+ case nsXPTType::T_I64 : dp->val.i64 = *((PRInt64*) ap); ap++; break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((PRUint64*)ap); ap++; break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+} // extern "C"
+
+// NOTE! See xptc_gcc_x86_unix.h for the reason this function exists.
+#if (__GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ == 0))
+PRUint32
+xptc_PrepareAndDispatch_keeper (void)
+{
+ PRUint32 dummy1;
+ nsresult ATTRIBUTE_USED __attribute__ ((regparm (3))) (*dummy2)
+ (uint32, nsXPTCStubBase *, PRUint32*) = PrepareAndDispatch;
+// dummy2 references PrepareAndDispatch, now "use" it
+ __asm__ __volatile__ (
+ ""
+ : "=&a" (dummy1)
+ : "g" (dummy2)
+ );
+ return dummy1 & 0xF0F00000;
+}
+#endif
+
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+// gcc3 mangling tends to insert the length of the method name
+#define STUB_ENTRY(n) \
+asm(".text\n\t" \
+ ".align 2\n\t" \
+ ".if " #n " < 10\n\t" \
+ ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \
+ ".type " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev,@function\n" \
+ SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 100\n\t" \
+ ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \
+ ".type " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev,@function\n" \
+ SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 1000\n\t" \
+ ".globl " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \
+ ".type " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev,@function\n" \
+ SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev:\n\t" \
+ ".else\n\t" \
+ ".err \"stub number " #n " >= 1000 not yet supported\"\n\t" \
+ ".endif\n\t" \
+ "movl $" #n ", %eax\n\t" \
+ "jmp " SYMBOL_UNDERSCORE "SharedStub\n\t" \
+ ".if " #n " < 10\n\t" \
+ ".size " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev,.-" SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \
+ ".elseif " #n " < 100\n\t" \
+ ".size " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev,.-" SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \
+ ".else\n\t" \
+ ".size " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev,.-" SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \
+ ".endif");
+#else
+#define STUB_ENTRY(n) \
+asm(".text\n\t" \
+ ".align 2\n\t" \
+ ".globl " SYMBOL_UNDERSCORE "Stub" #n "__14nsXPTCStubBase\n\t" \
+ ".type " SYMBOL_UNDERSCORE "Stub" #n "__14nsXPTCStubBase,@function\n" \
+ SYMBOL_UNDERSCORE "Stub" #n "__14nsXPTCStubBase:\n\t" \
+ "movl $" #n ", %eax\n\t" \
+ "jmp " SYMBOL_UNDERSCORE "SharedStub\n\t" \
+ ".size " SYMBOL_UNDERSCORE "Stub" #n "__14nsXPTCStubBase,.-" SYMBOL_UNDERSCORE "Stub" #n "__14nsXPTCStubBase");
+#endif
+
+// static nsresult SharedStub(PRUint32 methodIndex) __attribute__((regparm(1)))
+asm(".text\n\t"
+ ".align 2\n\t"
+ ".type " SYMBOL_UNDERSCORE "SharedStub,@function\n\t"
+ SYMBOL_UNDERSCORE "SharedStub:\n\t"
+ "leal 0x08(%esp), %ecx\n\t"
+ "movl 0x04(%esp), %edx\n\t"
+ "jmp " SYMBOL_UNDERSCORE "PrepareAndDispatch\n\t"
+ ".size " SYMBOL_UNDERSCORE "SharedStub,.-" SYMBOL_UNDERSCORE "SharedStub");
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+void
+xptc_dummy()
+{
+}
+
+#else
+#error "can't find a compiler to use"
+#endif /* __GNUC__ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ipf32.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ipf32.cpp
new file mode 100644
index 00000000..844f55dd
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ipf32.cpp
@@ -0,0 +1,185 @@
+
+/* -*- 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) 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 "xptcprivate.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+
+// "This code is for IA64 only"
+
+/* Implement shared vtbl methods. */
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, PRUint32 methodIndex,
+ uint64_t* intargs, uint64_t* floatargs, uint64_t* restargs)
+{
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ nsresult result = NS_ERROR_FAILURE;
+ uint64_t* iargs = intargs;
+ uint64_t* fargs = floatargs;
+ PRUint8 paramCount;
+ PRUint8 i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ for(i = 0; i < paramCount; ++i)
+ {
+ int isfloat = 0;
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+#ifdef __LP64__
+ /* 64 bit pointer mode */
+ dp->val.p = (void*) *iargs;
+#else
+ /* 32 bit pointer mode */
+ uint32_t* adr = (uint32_t*) iargs;
+ dp->val.p = (void*) (*(adr+1));
+#endif
+ }
+ else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *(iargs); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *(iargs); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *(iargs); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *(iargs); break;
+ case nsXPTType::T_U8 : dp->val.u8 = *(iargs); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *(iargs); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *(iargs); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *(iargs); break;
+ case nsXPTType::T_FLOAT :
+ isfloat = 1;
+ if (i < 7)
+ dp->val.f = (float) *((double*) fargs); /* register */
+ else
+ dp->val.u32 = *(fargs); /* memory */
+ break;
+ case nsXPTType::T_DOUBLE :
+ isfloat = 1;
+ dp->val.u64 = *(fargs);
+ break;
+ case nsXPTType::T_BOOL : dp->val.b = *(iargs); break;
+ case nsXPTType::T_CHAR : dp->val.c = *(iargs); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *(iargs); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ if (i < 7)
+ {
+ /* we are parsing register arguments */
+ if (i == 6)
+ {
+ // run out of register arguments, move on to memory arguments
+ iargs = restargs;
+ fargs = restargs;
+ }
+ else
+ {
+ ++iargs; // advance one integer register slot
+ if (isfloat) ++fargs; // advance float register slot if isfloat
+ }
+ }
+ else
+ {
+ /* we are parsing memory arguments */
+ ++iargs;
+ ++fargs;
+ }
+ }
+
+ result = self->CallMethod((PRUint16) methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" int SharedStub(PRUint64,PRUint64,PRUint64,PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+
+/* Variable a0-a7 were put there so we can have access to the 8 input
+ registers on Stubxyz entry */
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n(PRUint64 a1, \
+PRUint64 a2,PRUint64 a3,PRUint64 a4,PRUint64 a5,PRUint64 a6,PRUint64 a7) \
+{ uint64_t a0 = (uint64_t) this; \
+ return SharedStub(a0,a1,a2,a3,a4,a5,a6,a7,(PRUint64) n); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ipf64.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ipf64.cpp
new file mode 100644
index 00000000..6a11f692
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ipf64.cpp
@@ -0,0 +1,186 @@
+
+/* -*- 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) 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 "xptcprivate.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+// "This code is for IA64 only"
+
+/* Implement shared vtbl methods. */
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, PRUint32 methodIndex,
+ uint64_t* intargs, uint64_t* floatargs, uint64_t* restargs)
+{
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ nsresult result = NS_ERROR_FAILURE;
+ uint64_t* iargs = intargs;
+ uint64_t* fargs = floatargs;
+ PRUint8 paramCount;
+ PRUint8 i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ for(i = 0; i < paramCount; ++i)
+ {
+ int isfloat = 0;
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+#ifdef __LP64__
+ /* 64 bit pointer mode */
+ dp->val.p = (void*) *iargs;
+#else
+ /* 32 bit pointer mode */
+ uint32_t* adr = (uint32_t*) iargs;
+ dp->val.p = (void*) (*(adr+1));
+#endif
+ }
+ else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *(iargs); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *(iargs); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *(iargs); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *(iargs); break;
+ case nsXPTType::T_U8 : dp->val.u8 = *(iargs); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *(iargs); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *(iargs); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *(iargs); break;
+ case nsXPTType::T_FLOAT :
+ isfloat = 1;
+ if (i < 7)
+ dp->val.f = (float) *((double*) fargs); /* register */
+ else
+ dp->val.u32 = *(fargs); /* memory */
+ break;
+ case nsXPTType::T_DOUBLE :
+ isfloat = 1;
+ dp->val.u64 = *(fargs);
+ break;
+ case nsXPTType::T_BOOL : dp->val.b = *(iargs); break;
+ case nsXPTType::T_CHAR : dp->val.c = *(iargs); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *(iargs); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ if (i < 7)
+ {
+ /* we are parsing register arguments */
+ if (i == 6)
+ {
+ // run out of register arguments, move on to memory arguments
+ iargs = restargs;
+ fargs = restargs;
+ }
+ else
+ {
+ ++iargs; // advance one integer register slot
+ if (isfloat) ++fargs; // advance float register slot if isfloat
+ }
+ }
+ else
+ {
+ /* we are parsing memory arguments */
+ ++iargs;
+ ++fargs;
+ }
+ }
+
+ result = self->CallMethod((PRUint16) methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" int SharedStub(PRUint64,PRUint64,PRUint64,PRUint64,
+ PRUint64,PRUint64,PRUint64,PRUint64,PRUint64);
+
+/* Variable a0-a7 were put there so we can have access to the 8 input
+ registers on Stubxyz entry */
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n(PRUint64 a1, \
+PRUint64 a2,PRUint64 a3,PRUint64 a4,PRUint64 a5,PRUint64 a6,PRUint64 a7) \
+{ uint64_t a0 = (uint64_t) this; \
+ return SharedStub(a0,a1,a2,a3,a4,a5,a6,a7,(PRUint64) n); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_irix.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_irix.cpp
new file mode 100644
index 00000000..556b5bbe
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_irix.cpp
@@ -0,0 +1,226 @@
+/* -*- 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) 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 "xptcprivate.h"
+
+#if defined(IRIX)
+
+#if (_MIPS_SIM != _ABIN32)
+#error "This code is for IRIX N32 only"
+#endif
+
+/*
+ * This is for IRIX N32 ABI
+ *
+ * When we're called, the "gp" registers are stored in gprData and
+ * the "fp" registers are stored in fprData. There are 8 regs
+ * available which coorespond to the first 7 parameters of the
+ * function and the "this" pointer. If there are additional parms,
+ * they are stored on the stack at address "args".
+ *
+ */
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, PRUint32 methodIndex, PRUint64* args,
+ PRUint64 *gprData, double *fprData)
+{
+#define PARAM_BUFFER_COUNT 16
+#define PARAM_GPR_COUNT 7
+#define PARAM_FPR_COUNT 7
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint64* ap = args;
+ PRUint32 iCount = 0;
+ for(i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.p = (void*)gprData[iCount++];
+ else
+ dp->val.p = (void*)*ap++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (PRInt8)gprData[iCount++];
+ else
+ dp->val.i8 = (PRInt8)*ap++;
+ break;
+
+ case nsXPTType::T_I16:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (PRInt16)gprData[iCount++];
+ else
+ dp->val.i16 = (PRInt16)*ap++;
+ break;
+
+ case nsXPTType::T_I32:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (PRInt32)gprData[iCount++];
+ else
+ dp->val.i32 = (PRInt32)*ap++;
+ break;
+
+ case nsXPTType::T_I64:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64 = (PRInt64)gprData[iCount++];
+ else
+ dp->val.i64 = (PRInt64)*ap++;
+ break;
+
+ case nsXPTType::T_U8:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u8 = (PRUint8)gprData[iCount++];
+ else
+ dp->val.u8 = (PRUint8)*ap++;
+ break;
+
+ case nsXPTType::T_U16:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u16 = (PRUint16)gprData[iCount++];
+ else
+ dp->val.u16 = (PRUint16)*ap++;
+ break;
+
+ case nsXPTType::T_U32:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u32 = (PRUint32)gprData[iCount++];
+ else
+ dp->val.u32 = (PRUint32)*ap++;
+ break;
+
+ case nsXPTType::T_U64:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u64 = (PRUint64)gprData[iCount++];
+ else
+ dp->val.u64 = (PRUint64)*ap++;
+ break;
+
+ case nsXPTType::T_FLOAT:
+ if (iCount < PARAM_FPR_COUNT)
+ dp->val.f = (double)fprData[iCount++];
+ else
+ dp->val.f = *((double*)ap++);
+ break;
+
+ case nsXPTType::T_DOUBLE:
+ if (iCount < PARAM_FPR_COUNT)
+ dp->val.d = (double)fprData[iCount++];
+ else
+ dp->val.d = *((double*)ap++);
+ break;
+
+ case nsXPTType::T_BOOL:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.b = (PRBool)gprData[iCount++];
+ else
+ dp->val.b = (PRBool)*ap++;
+ break;
+
+ case nsXPTType::T_CHAR:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.c = (char)gprData[iCount++];
+ else
+ dp->val.c = (char)*ap++;
+ break;
+
+ case nsXPTType::T_WCHAR:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.wc = (wchar_t)gprData[iCount++];
+ else
+ dp->val.wc = (wchar_t)*ap++;
+ break;
+
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#define STUB_ENTRY(n) /* defined in the assembly file */
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_alpha.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_alpha.cpp
new file mode 100644
index 00000000..e5b1c642
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_alpha.cpp
@@ -0,0 +1,236 @@
+/* -*- 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) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Glen Nakamura <glen@imodulo.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 ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+/* Prototype specifies unmangled function name and disables unused warning */
+static nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, PRUint64* args)
+__asm__("PrepareAndDispatch") __attribute__((unused));
+
+static nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, PRUint64* args)
+{
+ const PRUint8 PARAM_BUFFER_COUNT = 16;
+ const PRUint8 NUM_ARG_REGS = 6-1; // -1 for "this" pointer
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ // args[0] to args[NUM_ARG_REGS] hold floating point register values
+ PRUint64* ap = args + NUM_ARG_REGS;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = (PRInt8) *ap; break;
+ case nsXPTType::T_I16 : dp->val.i16 = (PRInt16) *ap; break;
+ case nsXPTType::T_I32 : dp->val.i32 = (PRInt32) *ap; break;
+ case nsXPTType::T_I64 : dp->val.i64 = (PRInt64) *ap; break;
+ case nsXPTType::T_U8 : dp->val.u8 = (PRUint8) *ap; break;
+ case nsXPTType::T_U16 : dp->val.u16 = (PRUint16) *ap; break;
+ case nsXPTType::T_U32 : dp->val.u32 = (PRUint32) *ap; break;
+ case nsXPTType::T_U64 : dp->val.u64 = (PRUint64) *ap; break;
+ case nsXPTType::T_FLOAT :
+ if(i < NUM_ARG_REGS)
+ {
+ // floats passed via registers are stored as doubles
+ // in the first NUM_ARG_REGS entries in args
+ dp->val.u64 = (PRUint64) args[i];
+ dp->val.f = (float) dp->val.d; // convert double to float
+ }
+ else
+ dp->val.u32 = (PRUint32) *ap;
+ break;
+ case nsXPTType::T_DOUBLE :
+ // doubles passed via registers are also stored
+ // in the first NUM_ARG_REGS entries in args
+ dp->val.u64 = (i < NUM_ARG_REGS) ? args[i] : *ap;
+ break;
+ case nsXPTType::T_BOOL : dp->val.b = (PRBool) *ap; break;
+ case nsXPTType::T_CHAR : dp->val.c = (char) *ap; break;
+ case nsXPTType::T_WCHAR : dp->val.wc = (PRUnichar) *ap; break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+/*
+ * SharedStub()
+ * Collects arguments and calls PrepareAndDispatch. The "methodIndex" is
+ * passed to this function via $1 to preserve the argument registers.
+ */
+__asm__(
+ "#### SharedStub ####\n"
+".text\n\t"
+ ".align 5\n\t"
+ ".ent SharedStub\n"
+"SharedStub:\n\t"
+ ".frame $30,96,$26,0\n\t"
+ ".mask 0x4000000,-96\n\t"
+ "ldgp $29,0($27)\n"
+"$SharedStub..ng:\n\t"
+ "subq $30,96,$30\n\t"
+ "stq $26,0($30)\n\t"
+ ".prologue 1\n\t"
+
+ /*
+ * Store arguments passed via registers to the stack.
+ * Floating point registers are stored as doubles and converted
+ * to floats in PrepareAndDispatch if necessary.
+ */
+ "stt $f17,16($30)\n\t" /* floating point registers */
+ "stt $f18,24($30)\n\t"
+ "stt $f19,32($30)\n\t"
+ "stt $f20,40($30)\n\t"
+ "stt $f21,48($30)\n\t"
+ "stq $17,56($30)\n\t" /* integer registers */
+ "stq $18,64($30)\n\t"
+ "stq $19,72($30)\n\t"
+ "stq $20,80($30)\n\t"
+ "stq $21,88($30)\n\t"
+
+ /*
+ * Call PrepareAndDispatch function.
+ */
+ "bis $1,$1,$17\n\t" /* pass "methodIndex" */
+ "addq $30,16,$18\n\t" /* pass "args" */
+ "bsr $26,$PrepareAndDispatch..ng\n\t"
+
+ "ldq $26,0($30)\n\t"
+ "addq $30,96,$30\n\t"
+ "ret $31,($26),1\n\t"
+ ".end SharedStub"
+ );
+
+/*
+ * nsresult nsXPTCStubBase::Stub##n()
+ * Sets register $1 to "methodIndex" and jumps to SharedStub.
+ */
+#define STUB_MANGLED_ENTRY(n, symbol) \
+ "#### Stub"#n" ####" "\n\t" \
+ ".text" "\n\t" \
+ ".align 5" "\n\t" \
+ ".globl " symbol "\n\t" \
+ ".ent " symbol "\n" \
+symbol ":" "\n\t" \
+ ".frame $30,0,$26,0" "\n\t" \
+ "ldgp $29,0($27)" "\n" \
+"$" symbol "..ng:" "\n\t" \
+ ".prologue 1" "\n\t" \
+ "lda $1,"#n "\n\t" \
+ "br $31,$SharedStub..ng" "\n\t" \
+ ".end " symbol
+
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+
+#define STUB_ENTRY(n) \
+__asm__( \
+ ".if "#n" < 10" "\n\t" \
+ STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase5Stub"#n"Ev") "\n\t" \
+ ".elseif "#n" < 100" "\n\t" \
+ STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase6Stub"#n"Ev") "\n\t" \
+ ".elseif "#n" < 1000" "\n\t" \
+ STUB_MANGLED_ENTRY(n, "_ZN14nsXPTCStubBase7Stub"#n"Ev") "\n\t" \
+ ".else" "\n\t" \
+ ".err \"Stub"#n" >= 1000 not yet supported.\"" "\n\t" \
+ ".endif" \
+ );
+
+#else /* not G++ V3 ABI */
+
+#define STUB_ENTRY(n) \
+__asm__( \
+ STUB_MANGLED_ENTRY(n, "Stub"#n"__14nsXPTCStubBase") \
+ );
+
+#endif /* G++ V3 ABI */
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_m68k.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_m68k.cpp
new file mode 100644
index 00000000..eb094762
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_m68k.cpp
@@ -0,0 +1,146 @@
+/* -*- 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) 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 ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+extern "C" {
+ nsresult
+ PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, uint32* args)
+ {
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+
+ switch(type)
+ {
+ // the 8 and 16 bit types will have been promoted to 32 bits before
+ // being pushed onto the stack. Since the 68k is big endian, we
+ // need to skip over the leading high order bytes.
+ case nsXPTType::T_I8 : dp->val.i8 = *(((PRInt8*) ap) + 3); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *(((PRInt16*) ap) + 1); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((PRInt64*) ap); ap++; break;
+ case nsXPTType::T_U8 : dp->val.u8 = *(((PRUint8*) ap) + 3); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *(((PRUint16*)ap) + 1); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((PRUint32*)ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((PRUint64*)ap); ap++; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((PRBool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *(((char*) ap) + 3); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+ }
+}
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ register nsresult result; \
+ __asm__ __volatile__( \
+ "lea %/a6@(12), %/a0\n\t" /* args */ \
+ "movl %/a0, %/sp@-\n\t" \
+ "movl #"#n", %/sp@-\n\t" /* method index */ \
+ "movl %/a6@(8), %/sp@-\n\t" /* this */ \
+ "jbsr PrepareAndDispatch\n\t" \
+ "movl %/d0, %0\n\t" \
+ "addl #12, %/sp" \
+ : "=d" (result) /* %0 */ \
+ : \
+ : "a0", "a1", "d0", "d1", "memory" ); \
+ return result; \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_s390.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_s390.cpp
new file mode 100644
index 00000000..0f8502cd
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_s390.cpp
@@ -0,0 +1,220 @@
+/* -*- 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) 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 ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+static nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex,
+ PRUint32* a_gpr, PRUint64 *a_fpr, PRUint32 *a_ov)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32 gpr = 1, fpr = 0;
+
+ for(i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (gpr < 5)
+ dp->val.p = (void*) *a_gpr++, gpr++;
+ else
+ dp->val.p = (void*) *a_ov++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 :
+ if (gpr < 5)
+ dp->val.i8 = *((PRInt32*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i8 = *((PRInt32*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_I16 :
+ if (gpr < 5)
+ dp->val.i16 = *((PRInt32*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i16 = *((PRInt32*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_I32 :
+ if (gpr < 5)
+ dp->val.i32 = *((PRInt32*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i32 = *((PRInt32*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_I64 :
+ if (gpr < 4)
+ dp->val.i64 = *((PRInt64*) a_gpr), a_gpr+=2, gpr+=2;
+ else
+ dp->val.i64 = *((PRInt64*) a_ov ), a_ov+=2, gpr=5;
+ break;
+ case nsXPTType::T_U8 :
+ if (gpr < 5)
+ dp->val.u8 = *((PRUint32*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u8 = *((PRUint32*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U16 :
+ if (gpr < 5)
+ dp->val.u16 = *((PRUint32*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u16 = *((PRUint32*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U32 :
+ if (gpr < 5)
+ dp->val.u32 = *((PRUint32*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u32 = *((PRUint32*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U64 :
+ if (gpr < 4)
+ dp->val.u64 = *((PRUint64*)a_gpr), a_gpr+=2, gpr+=2;
+ else
+ dp->val.u64 = *((PRUint64*)a_ov ), a_ov+=2, gpr=5;
+ break;
+ case nsXPTType::T_FLOAT :
+ if (fpr < 2)
+ dp->val.f = *((float*) a_fpr), a_fpr++, fpr++;
+ else
+ dp->val.f = *((float*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ if (fpr < 2)
+ dp->val.d = *((double*) a_fpr), a_fpr++, fpr++;
+ else
+ dp->val.d = *((double*) a_ov ), a_ov+=2;
+ break;
+ case nsXPTType::T_BOOL :
+ if (gpr < 5)
+ dp->val.b = *((PRUint32*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.b = *((PRUint32*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_CHAR :
+ if (gpr < 5)
+ dp->val.c = *((PRUint32*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.c = *((PRUint32*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_WCHAR :
+ if (gpr < 5)
+ dp->val.wc = *((PRUint32*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.wc = *((PRUint32*)a_ov ), a_ov++;
+ break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ PRUint32 a_gpr[4]; \
+ PRUint64 a_fpr[2]; \
+ PRUint32 *a_ov; \
+ \
+ __asm__ __volatile__ \
+ ( \
+ "l %0,0(15)\n\t" \
+ "ahi %0,96\n\t" \
+ "stm 3,6,0(%3)\n\t" \
+ "std 0,%1\n\t" \
+ "std 2,%2\n\t" \
+ : "=&a" (a_ov), \
+ "=m" (a_fpr[0]), \
+ "=m" (a_fpr[1]) \
+ : "a" (a_gpr) \
+ : "memory", "cc", \
+ "3", "4", "5", "6" \
+ ); \
+ \
+ return PrepareAndDispatch(this, n, a_gpr, a_fpr, a_ov); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_s390x.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_s390x.cpp
new file mode 100644
index 00000000..9a645dd1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_linux_s390x.cpp
@@ -0,0 +1,224 @@
+/* -*- 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) 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 ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+static nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex,
+ PRUint64* a_gpr, PRUint64 *a_fpr, PRUint64 *a_ov)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32 gpr = 1, fpr = 0;
+
+ for(i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (gpr < 5)
+ dp->val.p = (void*) *a_gpr++, gpr++;
+ else
+ dp->val.p = (void*) *a_ov++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 :
+ if (gpr < 5)
+ dp->val.i8 = *((PRInt64*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i8 = *((PRInt64*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_I16 :
+ if (gpr < 5)
+ dp->val.i16 = *((PRInt64*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i16 = *((PRInt64*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_I32 :
+ if (gpr < 5)
+ dp->val.i32 = *((PRInt64*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i32 = *((PRInt64*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_I64 :
+ if (gpr < 5)
+ dp->val.i64 = *((PRInt64*) a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.i64 = *((PRInt64*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U8 :
+ if (gpr < 5)
+ dp->val.u8 = *((PRUint64*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u8 = *((PRUint64*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U16 :
+ if (gpr < 5)
+ dp->val.u16 = *((PRUint64*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u16 = *((PRUint64*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U32 :
+ if (gpr < 5)
+ dp->val.u32 = *((PRUint64*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u32 = *((PRUint64*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_U64 :
+ if (gpr < 5)
+ dp->val.u64 = *((PRUint64*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.u64 = *((PRUint64*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_FLOAT :
+ if (fpr < 4)
+ dp->val.f = *((float*) a_fpr), a_fpr++, fpr++;
+ else
+ dp->val.f = *(((float*) a_ov )+1), a_ov++;
+ break;
+ case nsXPTType::T_DOUBLE :
+ if (fpr < 4)
+ dp->val.d = *((double*) a_fpr), a_fpr++, fpr++;
+ else
+ dp->val.d = *((double*) a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_BOOL :
+ if (gpr < 5)
+ dp->val.b = *((PRUint64*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.b = *((PRUint64*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_CHAR :
+ if (gpr < 5)
+ dp->val.c = *((PRUint64*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.c = *((PRUint64*)a_ov ), a_ov++;
+ break;
+ case nsXPTType::T_WCHAR :
+ if (gpr < 5)
+ dp->val.wc = *((PRUint64*)a_gpr), a_gpr++, gpr++;
+ else
+ dp->val.wc = *((PRUint64*)a_ov ), a_ov++;
+ break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ PRUint64 a_gpr[4]; \
+ PRUint64 a_fpr[4]; \
+ PRUint64 *a_ov; \
+ \
+ __asm__ __volatile__ \
+ ( \
+ "lg %0,0(15)\n\t" \
+ "aghi %0,160\n\t" \
+ "stmg 3,6,0(%5)\n\t"\
+ "std 0,%1\n\t" \
+ "std 2,%2\n\t" \
+ "std 4,%3\n\t" \
+ "std 6,%4\n\t" \
+ : "=&a" (a_ov), \
+ "=m" (a_fpr[0]), \
+ "=m" (a_fpr[1]), \
+ "=m" (a_fpr[2]), \
+ "=m" (a_fpr[3]) \
+ : "a" (a_gpr) \
+ : "memory", "cc", \
+ "3", "4", "5", "6" \
+ ); \
+ \
+ return PrepareAndDispatch(this, n, a_gpr, a_fpr, a_ov); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_mips.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_mips.cpp
new file mode 100644
index 00000000..4d60f7be
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_mips.cpp
@@ -0,0 +1,131 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * Version: MPL 1.1
+ *
+ * ***** 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 Corp, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Stuart Parmenter <pavlov@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 "xptcprivate.h"
+
+/*
+ * This is for MIPS O32 ABI
+ * Args contains a0-3 and then the stack.
+ * Because a0 is 'this', we want to skip it
+ */
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, PRUint32 methodIndex, PRUint32* args)
+{
+ args++; // always skip over a0
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+
+ dp->val.p = (void*) *ap;
+
+ switch(type)
+ {
+ case nsXPTType::T_I64 :
+ if ((PRWord)ap & 4) ap++;
+ dp->val.i64 = *((PRInt64*) ap); ap++;
+ break;
+ case nsXPTType::T_U64 :
+ if ((PRWord)ap & 4) ap++;
+ dp->val.u64 = *((PRInt64*) ap); ap++;
+ break;
+ case nsXPTType::T_DOUBLE:
+ if ((PRWord)ap & 4) ap++;
+ dp->val.d = *((double*) ap); ap++;
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#define STUB_ENTRY(n) // done in the .s file
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_netbsd_m68k.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_netbsd_m68k.cpp
new file mode 100644
index 00000000..4069a6bc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_netbsd_m68k.cpp
@@ -0,0 +1,147 @@
+/* -*- 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) 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 ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if !defined(__NetBSD__) || !defined(__m68k__)
+#error This code is for NetBSD/m68k only
+#endif
+
+extern "C" {
+ static nsresult
+ PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, uint32* args)
+ {
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+
+ switch(type)
+ {
+ // the 8 and 16 bit types will have been promoted to 32 bits before
+ // being pushed onto the stack. Since the 68k is big endian, we
+ // need to skip over the leading high order bytes.
+ case nsXPTType::T_I8 : dp->val.i8 = *(((PRInt8*) ap) + 3); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *(((PRInt16*) ap) + 1); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((PRInt64*) ap); ap++; break;
+ case nsXPTType::T_U8 : dp->val.u8 = *(((PRUint8*) ap) + 3); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *(((PRUint16*)ap) + 1); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((PRUint32*)ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((PRUint64*)ap); ap++; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((PRBool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *(((char*) ap) + 3); break;
+ // wchar_t is an int (32 bits) on NetBSD
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+ }
+}
+
+#define STUB_ENTRY(n) \
+__asm__( \
+ ".global _Stub"#n"__14nsXPTCStubBase\n\t" \
+"_Stub"#n"__14nsXPTCStubBase:\n\t" \
+ "link a6,#0 \n\t" \
+ "lea a6@(12), a0 \n\t" /* pointer to args */ \
+ "movl a0, sp@- \n\t" \
+ "movl #"#n", sp@- \n\t" /* method index */ \
+ "movl a6@(8), sp@- \n\t" /* this */ \
+ "jbsr _PrepareAndDispatch \n\t" \
+ "unlk a6 \n\t" \
+ "rts \n\t" \
+);
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_openvms_alpha.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_openvms_alpha.cpp
new file mode 100644
index 00000000..c4d1b364
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_openvms_alpha.cpp
@@ -0,0 +1,147 @@
+/* -*- 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) 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 ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+extern "C" {
+
+nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, PRUint64* args)
+{
+ const PRUint8 PARAM_BUFFER_COUNT = 16;
+ const PRUint8 NUM_ARG_REGS = 6-1; // -1 for "this" pointer
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ // args[0] to args[NUM_ARG_REGS] hold floating point register values
+ PRUint64* ap = args + NUM_ARG_REGS;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = (PRInt8) *ap; break;
+ case nsXPTType::T_I16 : dp->val.i16 = (PRInt16) *ap; break;
+ case nsXPTType::T_I32 : dp->val.i32 = (PRInt32) *ap; break;
+ case nsXPTType::T_I64 : dp->val.i64 = (PRInt64) *ap; break;
+ case nsXPTType::T_U8 : dp->val.u8 = (PRUint8) *ap; break;
+ case nsXPTType::T_U16 : dp->val.u16 = (PRUint16) *ap; break;
+ case nsXPTType::T_U32 : dp->val.u32 = (PRUint32) *ap; break;
+ case nsXPTType::T_U64 : dp->val.u64 = (PRUint64) *ap; break;
+ case nsXPTType::T_FLOAT :
+ if(i < NUM_ARG_REGS)
+ {
+ // floats passed via registers are stored as doubles
+ // in the first NUM_ARG_REGS entries in args
+ dp->val.u64 = (PRUint64) args[i];
+ dp->val.f = (float) dp->val.d; // convert double to float
+ }
+ else
+ dp->val.u32 = (PRUint32) *ap;
+ break;
+ case nsXPTType::T_DOUBLE :
+ // doubles passed via registers are also stored
+ // in the first NUM_ARG_REGS entries in args
+ dp->val.u64 = (i < NUM_ARG_REGS) ? args[i] : *ap;
+ break;
+ case nsXPTType::T_BOOL : dp->val.b = (PRBool) *ap; break;
+ case nsXPTType::T_CHAR : dp->val.c = (char) *ap; break;
+ case nsXPTType::T_WCHAR : dp->val.wc = (PRUnichar) *ap; break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+}
+
+#define STUB_ENTRY(n) /* This is in the ASM file */
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_osf1_alpha.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_osf1_alpha.cpp
new file mode 100644
index 00000000..cd8fe40b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_osf1_alpha.cpp
@@ -0,0 +1,149 @@
+/* -*- 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) 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 ***** */
+
+/* Implement shared vtbl methods. */
+
+/* contributed by Glen Nakamura <glen.nakamura@usa.net> */
+
+#include "xptcprivate.h"
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, PRUint64* args)
+{
+ const PRUint8 PARAM_BUFFER_COUNT = 16;
+ const PRUint8 NUM_ARG_REGS = 6-1; // -1 for "this" pointer
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ // args[0] to args[NUM_ARG_REGS] hold floating point register values
+ PRUint64* ap = args + NUM_ARG_REGS;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = (PRInt8) *ap; break;
+ case nsXPTType::T_I16 : dp->val.i16 = (PRInt16) *ap; break;
+ case nsXPTType::T_I32 : dp->val.i32 = (PRInt32) *ap; break;
+ case nsXPTType::T_I64 : dp->val.i64 = (PRInt64) *ap; break;
+ case nsXPTType::T_U8 : dp->val.u8 = (PRUint8) *ap; break;
+ case nsXPTType::T_U16 : dp->val.u16 = (PRUint16) *ap; break;
+ case nsXPTType::T_U32 : dp->val.u32 = (PRUint32) *ap; break;
+ case nsXPTType::T_U64 : dp->val.u64 = (PRUint64) *ap; break;
+ case nsXPTType::T_FLOAT :
+ if(i < NUM_ARG_REGS)
+ {
+ // floats passed via registers are stored as doubles
+ // in the first NUM_ARG_REGS entries in args
+ dp->val.u64 = (PRUint64) args[i];
+ dp->val.f = (float) dp->val.d; // convert double to float
+ }
+ else
+ dp->val.u32 = (PRUint32) *ap;
+ break;
+ case nsXPTType::T_DOUBLE :
+ // doubles passed via registers are also stored
+ // in the first NUM_ARG_REGS entries in args
+ dp->val.u64 = (i < NUM_ARG_REGS) ? args[i] : *ap;
+ break;
+ case nsXPTType::T_BOOL : dp->val.b = (PRBool) *ap; break;
+ case nsXPTType::T_CHAR : dp->val.c = (char) *ap; break;
+ case nsXPTType::T_WCHAR : dp->val.wc = (PRUnichar) *ap; break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+/*
+ * nsresult nsXPTCStubBase::Stub##n() ;\
+ * Sets arguments to registers and calls PrepareAndDispatch.
+ * This is defined in the ASM file.
+ */
+#define STUB_ENTRY(n) \
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_pa32.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_pa32.cpp
new file mode 100644
index 00000000..b3a42442
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_pa32.cpp
@@ -0,0 +1,176 @@
+
+/* -*- 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) 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 ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if _HPUX
+#error "This code is for HP-PA RISC 32 bit mode only"
+#endif
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, PRUint32 methodIndex,
+ PRUint32* args, PRUint32* floatargs)
+{
+
+ typedef struct {
+ uint32 hi;
+ uint32 lo;
+ } DU;
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRInt32 regwords = 1; /* self pointer is not in the variant records */
+ nsresult result = NS_ERROR_FAILURE;
+ PRUint8 paramCount;
+ PRUint8 i;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ for(i = 0; i < paramCount; ++i, --args)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *args;
+ ++regwords;
+ continue;
+ }
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((PRInt32*) args); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((PRInt32*) args); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((PRInt32*) args); break;
+ case nsXPTType::T_DOUBLE :
+ if (regwords & 1)
+ {
+ ++regwords; /* align on double word */
+ --args;
+ }
+ if (regwords == 0 || regwords == 2)
+ {
+ dp->val.d=*((double*) (floatargs + regwords));
+ --args;
+ }
+ else
+ {
+ dp->val.d = *((double*) --args);
+ }
+ regwords += 2;
+ continue;
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_I64 :
+ if (regwords & 1)
+ {
+ ++regwords; /* align on double word */
+ --args;
+ }
+ ((DU *)dp)->lo = *((PRUint32*) args);
+ ((DU *)dp)->hi = *((PRUint32*) --args);
+ regwords += 2;
+ continue;
+ case nsXPTType::T_FLOAT :
+ if (regwords >= 4)
+ dp->val.f = *((float*) args);
+ else
+ dp->val.f = *((float*) floatargs+4+regwords);
+ break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((PRUint32*) args); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((PRUint32*) args); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((PRUint32*) args); break;
+ case nsXPTType::T_BOOL : dp->val.b = *((PRBool*) args); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((PRUint32*) args); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((PRInt32*) args); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ ++regwords;
+ }
+
+ result = self->CallMethod((PRUint16) methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" int SharedStub(int);
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ return SharedStub(n); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_aix.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_aix.cpp
new file mode 100644
index 00000000..870669d7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_aix.cpp
@@ -0,0 +1,228 @@
+/* -*- 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) 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 ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if defined(AIX)
+
+/*
+ For PPC (AIX & MAC), the first 8 integral and the first 13 f.p. parameters
+ arrive in a separate chunk of data that has been loaded from the registers.
+ The args pointer has been set to the start of the parameters BEYOND the ones
+ arriving in registers
+*/
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, PRUint32 methodIndex, PRUint32* args, PRUint32 *gprData, double *fprData)
+{
+ typedef struct {
+ uint32 hi;
+ uint32 lo; // have to move 64 bit entities as 32 bit halves since
+ } DU; // stack slots are not guaranteed 16 byte aligned
+
+#define PARAM_BUFFER_COUNT 16
+#define PARAM_GPR_COUNT 7
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ PRUint32 iCount = 0;
+ PRUint32 fpCount = 0;
+ for(i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.p = (void*) gprData[iCount++];
+ else
+ dp->val.p = (void*) *ap++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (PRInt8) gprData[iCount++];
+ else
+ dp->val.i8 = (PRInt8) *ap++;
+ break;
+ case nsXPTType::T_I16 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (PRInt16) gprData[iCount++];
+ else
+ dp->val.i16 = (PRInt16) *ap++;
+ break;
+ case nsXPTType::T_I32 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (PRInt32) gprData[iCount++];
+ else
+ dp->val.i32 = (PRInt32) *ap++;
+ break;
+ case nsXPTType::T_I64 : if (iCount < PARAM_GPR_COUNT)
+ ((DU *)dp)->hi = (PRInt32) gprData[iCount++];
+ else
+ ((DU *)dp)->hi = (PRInt32) *ap++;
+ if (iCount < PARAM_GPR_COUNT)
+ ((DU *)dp)->lo = (PRUint32) gprData[iCount++];
+ else
+ ((DU *)dp)->lo = (PRUint32) *ap++;
+ break;
+ case nsXPTType::T_U8 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u8 = (PRUint8) gprData[iCount++];
+ else
+ dp->val.u8 = (PRUint8) *ap++;
+ break;
+ case nsXPTType::T_U16 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u16 = (PRUint16) gprData[iCount++];
+ else
+ dp->val.u16 = (PRUint16) *ap++;
+ break;
+ case nsXPTType::T_U32 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u32 = (PRUint32) gprData[iCount++];
+ else
+ dp->val.u32 = (PRUint32) *ap++;
+ break;
+ case nsXPTType::T_U64 : if (iCount < PARAM_GPR_COUNT)
+ ((DU *)dp)->hi = (PRUint32) gprData[iCount++];
+ else
+ ((DU *)dp)->hi = (PRUint32) *ap++;
+ if (iCount < PARAM_GPR_COUNT)
+ ((DU *)dp)->lo = (PRUint32) gprData[iCount++];
+ else
+ ((DU *)dp)->lo = (PRUint32) *ap++;
+ break;
+ case nsXPTType::T_FLOAT : if (fpCount < 13) {
+ dp->val.f = (float) fprData[fpCount++];
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ }
+ else
+ dp->val.f = *((float*) ap++);
+ break;
+ case nsXPTType::T_DOUBLE : if (fpCount < 13) {
+ dp->val.d = (double) fprData[fpCount++];
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ }
+ else {
+ dp->val.f = *((double*) ap);
+ ap += 2;
+ }
+ break;
+ case nsXPTType::T_BOOL : if (iCount < PARAM_GPR_COUNT)
+ dp->val.b = (PRBool) gprData[iCount++];
+ else
+ dp->val.b = (PRBool) *ap++;
+ break;
+ case nsXPTType::T_CHAR : if (iCount < PARAM_GPR_COUNT)
+ dp->val.c = (char) gprData[iCount++];
+ else
+ dp->val.c = (char) *ap++;
+ break;
+ case nsXPTType::T_WCHAR : if (iCount < PARAM_GPR_COUNT)
+ dp->val.wc = (wchar_t) gprData[iCount++];
+ else
+ dp->val.wc = (wchar_t) *ap++;
+ break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" int SharedStub(int);
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ return SharedStub(n); \
+} \
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif /* AIX */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_aix64.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_aix64.cpp
new file mode 100644
index 00000000..cf2ddba9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_aix64.cpp
@@ -0,0 +1,215 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/LGPL 2.1/GPL 2.0
+ *
+ * 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 IBM Corporation.
+ * Portions created by IBM are
+ * Copyright (C) 2002, International Business Machines Corporation.
+ * 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 LGPL or the GPL. 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 ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if defined(AIX)
+
+/*
+ For PPC (AIX & MAC), the first 8 integral and the first 13 f.p. parameters
+ arrive in a separate chunk of data that has been loaded from the registers.
+ The args pointer has been set to the start of the parameters BEYOND the ones
+ arriving in registers
+*/
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, PRUint64 methodIndex, PRUint64* args, PRUint64 *gprData, double *fprData)
+{
+
+#define PARAM_BUFFER_COUNT 16
+#define PARAM_GPR_COUNT 7
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint64* ap = args;
+ PRUint32 iCount = 0;
+ PRUint32 fpCount = 0;
+ for(i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.p = (void*) gprData[iCount++];
+ else
+ dp->val.p = (void*) *ap++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (PRInt8) gprData[iCount++];
+ else
+ dp->val.i8 = (PRInt8) *ap++;
+ break;
+ case nsXPTType::T_I16 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (PRInt16) gprData[iCount++];
+ else
+ dp->val.i16 = (PRInt16) *ap++;
+ break;
+ case nsXPTType::T_I32 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (PRInt32) gprData[iCount++];
+ else
+ dp->val.i32 = (PRInt32) *ap++;
+ break;
+ case nsXPTType::T_I64 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64 = (PRInt64) gprData[iCount++];
+ else
+ dp->val.i64 = (PRInt64) *ap++;
+ break;
+ case nsXPTType::T_U8 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u8 = (PRUint8) gprData[iCount++];
+ else
+ dp->val.u8 = (PRUint8) *ap++;
+ break;
+ case nsXPTType::T_U16 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u16 = (PRUint16) gprData[iCount++];
+ else
+ dp->val.u16 = (PRUint16) *ap++;
+ break;
+ case nsXPTType::T_U32 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u32 = (PRUint32) gprData[iCount++];
+ else
+ dp->val.u32 = (PRUint32) *ap++;
+ break;
+ case nsXPTType::T_U64 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.u64 = (PRUint64) gprData[iCount++];
+ else
+ dp->val.u64 = (PRUint64) *ap++;
+ break;
+ case nsXPTType::T_FLOAT : if (fpCount < 13) {
+ dp->val.f = (float) fprData[fpCount++];
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ }
+ else
+ dp->val.f = *((float*) ap++);
+ break;
+ case nsXPTType::T_DOUBLE : if (fpCount < 13) {
+ dp->val.d = (double) fprData[fpCount++];
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ }
+ else {
+ dp->val.f = *((double*) ap);
+ ap += 2;
+ }
+ break;
+ case nsXPTType::T_BOOL : if (iCount < PARAM_GPR_COUNT)
+ dp->val.b = (PRBool) gprData[iCount++];
+ else
+ dp->val.b = (PRBool) *ap++;
+ break;
+ case nsXPTType::T_CHAR : if (iCount < PARAM_GPR_COUNT)
+ dp->val.c = (char) gprData[iCount++];
+ else
+ dp->val.c = (char) *ap++;
+ break;
+ case nsXPTType::T_WCHAR : if (iCount < PARAM_GPR_COUNT)
+ dp->val.wc = (wchar_t) gprData[iCount++];
+ else
+ dp->val.wc = (wchar_t) *ap++;
+ break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" int SharedStub(int);
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ return SharedStub(n); \
+} \
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif /* AIX */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_linux.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_linux.cpp
new file mode 100644
index 00000000..b1c98571
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_linux.cpp
@@ -0,0 +1,253 @@
+/* -*- 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) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Franz.Sirl-kernel@lauterbach.com (Franz Sirl)
+ * beard@netscape.com (Patrick Beard)
+ * waterson@netscape.com (Chris Waterson)
+ *
+ * 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 ***** */
+
+// Implement shared vtbl methods.
+
+#include "xptcprivate.h"
+
+// The Linux/PPC ABI (aka PPC/SYSV ABI) passes the first 8 integral
+// parameters and the first 8 floating point parameters in registers
+// (r3-r10 and f1-f8), no stack space is allocated for these by the
+// caller. The rest of the parameters are passed in the callers stack
+// area. The stack pointer has to retain 16-byte alignment, longlongs
+// and doubles are aligned on 8-byte boundaries.
+
+#define PARAM_BUFFER_COUNT 16
+#define GPR_COUNT 8
+#define FPR_COUNT 8
+
+// PrepareAndDispatch() is called by SharedStub() and calls the actual method.
+//
+// - 'args[]' contains the arguments passed on stack
+// - 'gprData[]' contains the arguments passed in integer registers
+// - 'fprData[]' contains the arguments passed in floating point registers
+//
+// The parameters are mapped into an array of type 'nsXPTCMiniVariant'
+// and then the method gets called.
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self,
+ PRUint32 methodIndex,
+ PRUint32* args,
+ PRUint32 *gprData,
+ double *fprData)
+{
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint32 paramCount;
+ PRUint32 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+ if (! iface_info)
+ return NS_ERROR_UNEXPECTED;
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (! info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (! dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PRUint32* ap = args;
+ PRUint32 gpr = 1; // skip one GPR register
+ PRUint32 fpr = 0;
+ PRUint32 tempu32;
+ PRUint64 tempu64;
+
+ for(i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+ if (fpr < FPR_COUNT)
+ dp->val.d = fprData[fpr++];
+ else {
+ if ((PRUint32) ap & 4) ap++; // doubles are 8-byte aligned on stack
+ dp->val.d = *(double*) ap;
+ ap += 2;
+ }
+ continue;
+ }
+ else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+ if (fpr < FPR_COUNT)
+ dp->val.f = (float) fprData[fpr++]; // in registers floats are passed as doubles
+ else
+ dp->val.f = *(float*) ap++;
+ continue;
+ }
+ else if (!param.IsOut() && (type == nsXPTType::T_I64
+ || type == nsXPTType::T_U64)) {
+ if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ if ((gpr + 1) < GPR_COUNT) {
+ tempu64 = *(PRUint64*) &gprData[gpr];
+ gpr += 2;
+ }
+ else {
+ if ((PRUint32) ap & 4) ap++; // longlongs are 8-byte aligned on stack
+ tempu64 = *(PRUint64*) ap;
+ ap += 2;
+ }
+ }
+ else {
+ if (gpr < GPR_COUNT)
+ tempu32 = gprData[gpr++];
+ else
+ tempu32 = *ap++;
+ }
+
+ if(param.IsOut() || !type.IsArithmetic()) {
+ dp->val.p = (void*) tempu32;
+ continue;
+ }
+
+ switch(type) {
+ case nsXPTType::T_I8: dp->val.i8 = (PRInt8) tempu32; break;
+ case nsXPTType::T_I16: dp->val.i16 = (PRInt16) tempu32; break;
+ case nsXPTType::T_I32: dp->val.i32 = (PRInt32) tempu32; break;
+ case nsXPTType::T_I64: dp->val.i64 = (PRInt64) tempu64; break;
+ case nsXPTType::T_U8: dp->val.u8 = (PRUint8) tempu32; break;
+ case nsXPTType::T_U16: dp->val.u16 = (PRUint16) tempu32; break;
+ case nsXPTType::T_U32: dp->val.u32 = (PRUint32) tempu32; break;
+ case nsXPTType::T_U64: dp->val.u64 = (PRUint64) tempu64; break;
+ case nsXPTType::T_BOOL: dp->val.b = (PRBool) tempu32; break;
+ case nsXPTType::T_CHAR: dp->val.c = (char) tempu32; break;
+ case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) tempu32; break;
+
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16) methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if (dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+// Load r11 with the constant 'n' and branch to SharedStub().
+//
+// XXX Yes, it's ugly that we're relying on gcc's name-mangling here;
+// however, it's quick, dirty, and'll break when the ABI changes on
+// us, which is what we want ;-).
+
+#if __GXX_ABI_VERSION < 100
+// gcc-2 version
+# define STUB_ENTRY(n) \
+__asm__ ( \
+ ".section \".text\" \n\t" \
+ ".align 2 \n\t" \
+ ".globl Stub"#n"__14nsXPTCStubBase \n\t" \
+ ".type Stub"#n"__14nsXPTCStubBase,@function \n\n" \
+ \
+"Stub"#n"__14nsXPTCStubBase: \n\t" \
+ "li 11,"#n" \n\t" \
+ "b SharedStub@local \n" \
+);
+#else
+// gcc-3 version
+//
+// As G++3 ABI contains the length of the functionname in the mangled
+// name, it is difficult to get a generic assembler mechanism like
+// in the G++ 2.95 case.
+// Create names would be like:
+// _ZN14nsXPTCStubBase5Stub1Ev
+// _ZN14nsXPTCStubBase6Stub12Ev
+// _ZN14nsXPTCStubBase7Stub123Ev
+// _ZN14nsXPTCStubBase8Stub1234Ev
+// etc.
+// Use assembler directives to get the names right...
+
+# define STUB_ENTRY(n) \
+__asm__ ( \
+ ".align 2 \n\t" \
+ ".if "#n" < 10 \n\t" \
+ ".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \
+ ".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \
+"_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \
+ \
+ ".elseif "#n" < 100 \n\t" \
+ ".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \
+ ".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \
+"_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \
+ \
+ ".elseif "#n" < 1000 \n\t" \
+ ".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \
+ ".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \
+"_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \
+ \
+ ".else \n\t" \
+ ".err \"stub number "#n" >= 1000 not yet supported\"\n" \
+ ".endif \n\t" \
+ \
+ "li 11,"#n" \n\t" \
+ "b SharedStub@local \n" \
+);
+#endif
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_netbsd.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_netbsd.cpp
new file mode 100644
index 00000000..68d572ca
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_netbsd.cpp
@@ -0,0 +1,217 @@
+/* -*- 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) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Franz.Sirl-kernel@lauterbach.com (Franz Sirl)
+ * beard@netscape.com (Patrick Beard)
+ * waterson@netscape.com (Chris Waterson)
+ *
+ * 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 ***** */
+
+// Implement shared vtbl methods.
+
+#include "xptcprivate.h"
+
+// The Linux/PPC ABI (aka PPC/SYSV ABI) passes the first 8 integral
+// parameters and the first 8 floating point parameters in registers
+// (r3-r10 and f1-f8), no stack space is allocated for these by the
+// caller. The rest of the parameters are passed in the callers stack
+// area. The stack pointer has to retain 16-byte alignment, longlongs
+// and doubles are aligned on 8-byte boundaries.
+
+#define PARAM_BUFFER_COUNT 16
+#define GPR_COUNT 8
+#define FPR_COUNT 8
+
+// PrepareAndDispatch() is called by SharedStub() and calls the actual method.
+//
+// - 'args[]' contains the arguments passed on stack
+// - 'gprData[]' contains the arguments passed in integer registers
+// - 'fprData[]' contains the arguments passed in floating point registers
+//
+// The parameters are mapped into an array of type 'nsXPTCMiniVariant'
+// and then the method gets called.
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self,
+ PRUint32 methodIndex,
+ PRUint32* args,
+ PRUint32 *gprData,
+ double *fprData)
+{
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint32 paramCount;
+ PRUint32 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+ if (! iface_info)
+ return NS_ERROR_UNEXPECTED;
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (! info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (! dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PRUint32* ap = args;
+ PRUint32 gpr = 1; // skip one GPR register
+ PRUint32 fpr = 0;
+ PRUint32 tempu32;
+ PRUint64 tempu64;
+
+ for(i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+ if (fpr < FPR_COUNT)
+ dp->val.d = fprData[fpr++];
+ else {
+ if ((PRUint32) ap & 4) ap++; // doubles are 8-byte aligned on stack
+ dp->val.d = *(double*) ap;
+ ap += 2;
+ if (gpr < GPR_COUNT)
+ gpr += 2;
+ }
+ continue;
+ }
+ else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+ if (fpr < FPR_COUNT)
+ dp->val.f = (float) fprData[fpr++]; // in registers floats are passed as doubles
+ else {
+ dp->val.f = *(float*) ap;
+ ap += 1;
+ if (gpr < GPR_COUNT)
+ gpr += 1;
+ }
+ continue;
+ }
+ else if (!param.IsOut() && (type == nsXPTType::T_I64
+ || type == nsXPTType::T_U64)) {
+ if (gpr & 1) gpr++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ if ((gpr + 1) < GPR_COUNT) {
+ tempu64 = *(PRUint64*) &gprData[gpr];
+ gpr += 2;
+ }
+ else {
+ if ((PRUint32) ap & 4) ap++; // longlongs are 8-byte aligned on stack
+ tempu64 = *(PRUint64*) ap;
+ ap += 2;
+ }
+ }
+ else {
+ if (gpr < GPR_COUNT)
+ tempu32 = gprData[gpr++];
+ else
+ tempu32 = *ap++;
+ }
+
+ if(param.IsOut() || !type.IsArithmetic()) {
+ dp->val.p = (void*) tempu32;
+ continue;
+ }
+
+ switch(type) {
+ case nsXPTType::T_I8: dp->val.i8 = (PRInt8) tempu32; break;
+ case nsXPTType::T_I16: dp->val.i16 = (PRInt16) tempu32; break;
+ case nsXPTType::T_I32: dp->val.i32 = (PRInt32) tempu32; break;
+ case nsXPTType::T_I64: dp->val.i64 = (PRInt64) tempu64; break;
+ case nsXPTType::T_U8: dp->val.u8 = (PRUint8) tempu32; break;
+ case nsXPTType::T_U16: dp->val.u16 = (PRUint16) tempu32; break;
+ case nsXPTType::T_U32: dp->val.u32 = (PRUint32) tempu32; break;
+ case nsXPTType::T_U64: dp->val.u64 = (PRUint64) tempu64; break;
+ case nsXPTType::T_BOOL: dp->val.b = (PRBool) tempu32; break;
+ case nsXPTType::T_CHAR: dp->val.c = (char) tempu32; break;
+ case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) tempu32; break;
+
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16) methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if (dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+// Load r11 with the constant 'n' and branch to SharedStub().
+//
+// XXX Yes, it's ugly that we're relying on gcc's name-mangling here;
+// however, it's quick, dirty, and'll break when the ABI changes on
+// us, which is what we want ;-).
+
+#define STUB_ENTRY(n) \
+__asm__ ( \
+ ".section \".text\" \n\t" \
+ ".align 2 \n\t" \
+ ".globl Stub"#n"__14nsXPTCStubBase \n\t" \
+ ".type Stub"#n"__14nsXPTCStubBase,@function \n\n" \
+ \
+"Stub"#n"__14nsXPTCStubBase: \n\t" \
+ "li 11,"#n" \n\t" \
+ "b SharedStub@local \n" \
+);
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_rhapsody.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_rhapsody.cpp
new file mode 100644
index 00000000..fcf96d4f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_ppc_rhapsody.cpp
@@ -0,0 +1,254 @@
+/* -*- 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) 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 ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+/*
+ For mac, the first 8 integral and the first 13 f.p. parameters arrive
+ in a separate chunk of data that has been loaded from the registers. The
+ args pointer has been set to the start of the parameters BEYOND the ones
+ arriving in registers
+*/
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, PRUint32 methodIndex, PRUint32* args, PRUint32 *gprData, double *fprData)
+{
+#define PARAM_BUFFER_COUNT 16
+#define PARAM_GPR_COUNT 7
+
+ // fprintf(stderr, "PrepareAndDispatch %p, %d, %p, %p, %p\n", self, methodIndex, args, gprData, fprData);
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ PRUint32 iCount = 0;
+ PRUint32 fpCount = 0;
+ for(i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.p = (void*) gprData[iCount++];
+ else
+ dp->val.p = (void*) *ap++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (PRInt8) gprData[iCount++];
+ else
+ dp->val.i8 = (PRInt8) *ap++;
+ break;
+ case nsXPTType::T_I16 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (PRInt16) gprData[iCount++];
+ else
+ dp->val.i16 = (PRInt16) *ap++;
+ break;
+ case nsXPTType::T_I32 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (PRInt32) gprData[iCount++];
+ else
+ dp->val.i32 = (PRInt32) *ap++;
+ break;
+
+ case nsXPTType::T_I64 :
+ {
+ PRUint64 tempu64;
+ if (iCount & 1) iCount++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ if ((iCount + 1) < PARAM_GPR_COUNT) {
+ tempu64 = *(PRUint64*) &gprData[iCount];
+ iCount += 2;
+ }
+ else {
+ if ((PRUint32) ap & 4) ap++; // longlongs are 8-byte aligned on stack
+ tempu64 = *(PRUint64*) ap;
+ ap += 2;
+ }
+ dp->val.i64 = (PRUint64)tempu64;
+ }
+ break;
+
+#if 0
+ case nsXPTType::T_I64 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64.hi = (PRInt32) gprData[iCount++];
+ else
+ dp->val.i64.hi = (PRInt32) *ap++;
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64.lo = (PRUint32) gprData[iCount++];
+ else
+ dp->val.i64.lo = (PRUint32) *ap++;
+ break;
+#endif
+ case nsXPTType::T_U8 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (PRUint8) gprData[iCount++];
+ else
+ dp->val.i8 = (PRUint8) *ap++;
+ break;
+ case nsXPTType::T_U16 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (PRUint16) gprData[iCount++];
+ else
+ dp->val.i16 = (PRUint16) *ap++;
+ break;
+ case nsXPTType::T_U32 : if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (PRUint32) gprData[iCount++];
+ else
+ dp->val.i32 = (PRUint32) *ap++;
+ break;
+
+ case nsXPTType::T_U64 :
+#if 0
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64.hi = (PRUint32) gprData[iCount++];
+ else
+ dp->val.i64.hi = (PRUint32) *ap++;
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64.lo = (PRUint32) gprData[iCount++];
+ else
+ dp->val.i64.lo = (PRUint32) *ap++;
+#endif
+ {
+ PRUint64 tempu64;
+ if (iCount & 1) iCount++; // longlongs are aligned in odd/even register pairs, eg. r5/r6
+ if ((iCount + 1) < PARAM_GPR_COUNT) {
+ tempu64 = *(PRUint64*) &gprData[iCount];
+ iCount += 2;
+ }
+ else {
+ if ((PRUint32) ap & 4) ap++; // longlongs are 8-byte aligned on stack
+ tempu64 = *(PRUint64*) ap;
+ ap += 2;
+ }
+ dp->val.i64 = (PRUint64)tempu64;
+ }
+ break;
+ case nsXPTType::T_FLOAT : if (fpCount < 13) {
+ dp->val.f = (float) fprData[fpCount++];
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ }
+ else
+ dp->val.f = *((float*) ap++);
+ break;
+ case nsXPTType::T_DOUBLE : if (fpCount < 13) {
+ dp->val.d = (double) fprData[fpCount++];
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ if (iCount < PARAM_GPR_COUNT)
+ ++iCount;
+ else
+ ++ap;
+ }
+ else {
+ dp->val.f = *((double*) ap);
+ ap += 2;
+ }
+ break;
+ case nsXPTType::T_BOOL : if (iCount < PARAM_GPR_COUNT)
+ dp->val.b = (PRBool) gprData[iCount++];
+ else
+ dp->val.b = (PRBool) *ap++;
+ break;
+ case nsXPTType::T_CHAR : if (iCount < PARAM_GPR_COUNT)
+ dp->val.c = (char) gprData[iCount++];
+ else
+ dp->val.c = (char) *ap++;
+ break;
+ case nsXPTType::T_WCHAR : if (iCount < PARAM_GPR_COUNT)
+ dp->val.wc = (wchar_t) gprData[iCount++];
+ else
+ dp->val.wc = (wchar_t) *ap++;
+ break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+
+#define STUB_ENTRY(n)
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_sparc_netbsd.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_sparc_netbsd.cpp
new file mode 100644
index 00000000..cbed6041
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_sparc_netbsd.cpp
@@ -0,0 +1,146 @@
+/* -*- 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) 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 ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if defined(sparc) || defined(__sparc__)
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, uint32* args)
+{
+
+ typedef struct {
+ uint32 hi;
+ uint32 lo;
+ } DU; // have to move 64 bit entities as 32 bit halves since
+ // stack slots are not guaranteed 16 byte aligned
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((PRInt32*) ap); break;
+ case nsXPTType::T_DOUBLE :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_I64 : ((DU *)dp)->hi = ((DU *)ap)->hi;
+ ((DU *)dp)->lo = ((DU *)ap)->lo;
+ ap++;
+ break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((PRUint32*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((PRUint32*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((PRUint32*)ap); break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_BOOL : dp->val.b = *((PRBool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((PRUint32*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((PRInt32*) ap); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" int SharedStub(int, int*);
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ int dummy; /* defeat tail-call optimization */ \
+ return SharedStub(n, &dummy); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif /* sparc || __sparc__ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_sparc_solaris.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_sparc_solaris.cpp
new file mode 100644
index 00000000..cbed6041
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_sparc_solaris.cpp
@@ -0,0 +1,146 @@
+/* -*- 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) 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 ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if defined(sparc) || defined(__sparc__)
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, uint32* args)
+{
+
+ typedef struct {
+ uint32 hi;
+ uint32 lo;
+ } DU; // have to move 64 bit entities as 32 bit halves since
+ // stack slots are not guaranteed 16 byte aligned
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((PRInt32*) ap); break;
+ case nsXPTType::T_DOUBLE :
+ case nsXPTType::T_U64 :
+ case nsXPTType::T_I64 : ((DU *)dp)->hi = ((DU *)ap)->hi;
+ ((DU *)dp)->lo = ((DU *)ap)->lo;
+ ap++;
+ break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((PRUint32*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((PRUint32*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((PRUint32*)ap); break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_BOOL : dp->val.b = *((PRBool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((PRUint32*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((PRInt32*) ap); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" int SharedStub(int, int*);
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ int dummy; /* defeat tail-call optimization */ \
+ return SharedStub(n, &dummy); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif /* sparc || __sparc__ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_sparcv9_solaris.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_sparcv9_solaris.cpp
new file mode 100644
index 00000000..f64b309e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_sparcv9_solaris.cpp
@@ -0,0 +1,139 @@
+/* -*- 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) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Stuart Parmenter <pavlov@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 ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#if defined(sparc) || defined(__sparc__)
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, PRUint64 methodIndex, PRUint64* args)
+{
+
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint64* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((PRInt32*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((PRUint64*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((PRInt64*) ap); break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((PRUint32*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((PRUint32*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((PRUint32*)ap); break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_BOOL : dp->val.b = *((PRBool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((PRUint32*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((PRInt32*) ap); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+extern "C" int SharedStub(int, int*);
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ int dummy; /* defeat tail-call optimization */ \
+ return SharedStub(n, &dummy); \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#endif /* sparc || __sparc__ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_unixish_x86.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_unixish_x86.cpp
new file mode 100644
index 00000000..91c5c5db
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_unixish_x86.cpp
@@ -0,0 +1,188 @@
+/* -*- 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) 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 ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptc_platforms_unixish_x86.h"
+/*#include "xptiprivate.h"*/
+
+static nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, PRUint32* args)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info = NULL;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+ if (!iface_info)
+ return NS_ERROR_UNEXPECTED;
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (!info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ dp->val.p = (void*) *ap;
+ switch(type)
+ {
+ case nsXPTType::T_I64 : dp->val.i64 = *((PRInt64*) ap); ap++; break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((PRUint64*)ap); ap++; break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#ifdef __GNUC__ /* Gnu Compiler. */
+
+#ifdef KEEP_STACK_16_BYTE_ALIGNED
+/* Make sure the stack is 16-byte aligned. Do that by aligning to 16 bytes and
+ * then subtracting 4 so the three subsequent pushes result in a 16-byte aligned
+ * stack. */
+#define ALIGN_STACK_DECL \
+ unsigned int saved_esp = 0; /* VBOX: Initialize it to shut up half a million gcc warnings on darwin.
+ * ALIGN_STACK_REGS_OUT/IN are a bit bogus, so the warning is probably correct. */
+
+#define ALIGN_STACK_SAVE \
+ "movl %%esp, %3\n\t"
+
+#define ALIGN_STACK_ALIGN \
+ "addl $0x4, %%esp\n\t" \
+ "andl $0xfffffff0, %%esp\n\t" \
+ "subl $0x4, %%esp\n\t"
+
+#define STACK_RESTORE \
+ "movl %3, %%esp\n"
+
+#define ALIGN_STACK_REGS_IN \
+ , "=r"(saved_esp) /* 3 */
+
+#define ALIGN_STACK_REGS_OUT \
+ , "3"(saved_esp)
+
+#else
+#define ALIGN_STACK_DECL
+#define ALIGN_STACK_SAVE
+#define ALIGN_STACK_ALIGN
+#define STACK_RESTORE \
+ "addl $12, %%esp\n"
+#define ALIGN_STACK_REGS_IN
+#define ALIGN_STACK_REGS_OUT
+#endif
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ register nsresult (*method) (nsXPTCStubBase *, uint32, PRUint32 *) = PrepareAndDispatch; \
+ int temp0, temp1; \
+ register nsresult result; \
+ ALIGN_STACK_DECL \
+ __asm__ __volatile__( \
+ ALIGN_STACK_SAVE \
+ ALIGN_STACK_ALIGN \
+ "leal 0x0c(%%ebp), %%ecx\n\t" /* args */ \
+ "pushl %%ecx\n\t" \
+ "pushl $"#n"\n\t" /* method index */ \
+ "movl 0x08(%%ebp), %%ecx\n\t" /* this */ \
+ "pushl %%ecx\n\t" \
+ "call *%%edx\n\t" /* PrepareAndDispatch */ \
+ STACK_RESTORE /* "addl $12, %%esp" or restore saved */ \
+ : "=a" (result), /* %0 */ \
+ "=&c" (temp0), /* %1 */ \
+ "=d" (temp1) /* %2 */ \
+ ALIGN_STACK_REGS_IN \
+ : "2" (method) /* %2 */ \
+ ALIGN_STACK_REGS_OUT \
+ : "memory" \
+ ); \
+ return result; \
+}
+
+#else
+#error "can't find a compiler to use"
+#endif /* __GNUC__ */
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_unsupported.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_unsupported.cpp
new file mode 100644
index 00000000..0eea6567
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_unsupported.cpp
@@ -0,0 +1,56 @@
+/* -*- 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) 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 ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Stub called on unsupported platform"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_linux.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_linux.cpp
new file mode 100644
index 00000000..3381c48e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_linux.cpp
@@ -0,0 +1,242 @@
+/* -*- 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) 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 ***** */
+
+// Implement shared vtbl methods.
+
+#include "xptcprivate.h"
+
+// The Linux/x86-64 ABI passes the first 6 integer parameters and the
+// first 8 floating point parameters in registers (rdi, rsi, rdx, rcx,
+// r8, r9 and xmm0-xmm7), no stack space is allocated for these by the
+// caller. The rest of the parameters are passed in the callers stack
+// area.
+
+const PRUint32 PARAM_BUFFER_COUNT = 16;
+const PRUint32 GPR_COUNT = 6;
+const PRUint32 FPR_COUNT = 8;
+
+// PrepareAndDispatch() is called by SharedStub() and calls the actual method.
+//
+// - 'args[]' contains the arguments passed on stack
+// - 'gpregs[]' contains the arguments passed in integer registers
+// - 'fpregs[]' contains the arguments passed in floating point registers
+//
+// The parameters are mapped into an array of type 'nsXPTCMiniVariant'
+// and then the method gets called.
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase * self, PRUint32 methodIndex,
+ PRUint64 * args, PRUint64 * gpregs, double *fpregs)
+{
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info = NULL;
+ PRUint32 paramCount;
+ PRUint32 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+ if (!iface_info)
+ return NS_ERROR_UNEXPECTED;
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (!info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if (paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PRUint64* ap = args;
+ PRUint32 nr_gpr = 1; // skip one GPR register for 'that'
+ PRUint32 nr_fpr = 0;
+ PRUint64 value;
+
+ for (i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+ if (nr_fpr < FPR_COUNT)
+ dp->val.d = fpregs[nr_fpr++];
+ else
+ dp->val.d = *(double*) ap++;
+ continue;
+ }
+ else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+ if (nr_fpr < FPR_COUNT)
+ // The value in %xmm register is already prepared to
+ // be retrieved as a float. Therefore, we pass the
+ // value verbatim, as a double without conversion.
+ dp->val.d = *(double*) ap++;
+ else
+ dp->val.f = *(float*) ap++;
+ continue;
+ }
+ else {
+ if (nr_gpr < GPR_COUNT)
+ value = gpregs[nr_gpr++];
+ else
+ value = *ap++;
+ }
+
+ if (param.IsOut() || !type.IsArithmetic()) {
+ dp->val.p = (void*) value;
+ continue;
+ }
+
+ switch (type) {
+ case nsXPTType::T_I8: dp->val.i8 = (PRInt8) value; break;
+ case nsXPTType::T_I16: dp->val.i16 = (PRInt16) value; break;
+ case nsXPTType::T_I32: dp->val.i32 = (PRInt32) value; break;
+ case nsXPTType::T_I64: dp->val.i64 = (PRInt64) value; break;
+ case nsXPTType::T_U8: dp->val.u8 = (PRUint8) value; break;
+ case nsXPTType::T_U16: dp->val.u16 = (PRUint16) value; break;
+ case nsXPTType::T_U32: dp->val.u32 = (PRUint32) value; break;
+ case nsXPTType::T_U64: dp->val.u64 = (PRUint64) value; break;
+ case nsXPTType::T_BOOL: dp->val.b = (PRBool) value; break;
+ case nsXPTType::T_CHAR: dp->val.c = (char) value; break;
+ case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) value; break;
+
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16) methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if (dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+// Linux/x86-64 uses gcc >= 3.1
+#define STUB_ENTRY(n) \
+asm(".section \".text\"\n\t" \
+ ".align 2\n\t" \
+ ".if " #n " < 10\n\t" \
+ ".globl _ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \
+ ".type _ZN14nsXPTCStubBase5Stub" #n "Ev,@function\n" \
+ "_ZN14nsXPTCStubBase5Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 100\n\t" \
+ ".globl _ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \
+ ".type _ZN14nsXPTCStubBase6Stub" #n "Ev,@function\n" \
+ "_ZN14nsXPTCStubBase6Stub" #n "Ev:\n\t" \
+ ".elseif " #n " < 1000\n\t" \
+ ".globl _ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \
+ ".type _ZN14nsXPTCStubBase7Stub" #n "Ev,@function\n" \
+ "_ZN14nsXPTCStubBase7Stub" #n "Ev:\n\t" \
+ ".else\n\t" \
+ ".err \"stub number " #n " >= 1000 not yet supported\"\n\t" \
+ ".endif\n\t" \
+ "movl $" #n ", %eax\n\t" \
+ "jmp SharedStub\n\t" \
+ ".if " #n " < 10\n\t" \
+ ".size _ZN14nsXPTCStubBase5Stub" #n "Ev,.-_ZN14nsXPTCStubBase5Stub" #n "Ev\n\t" \
+ ".elseif " #n " < 100\n\t" \
+ ".size _ZN14nsXPTCStubBase6Stub" #n "Ev,.-_ZN14nsXPTCStubBase6Stub" #n "Ev\n\t" \
+ ".else\n\t" \
+ ".size _ZN14nsXPTCStubBase7Stub" #n "Ev,.-_ZN14nsXPTCStubBase7Stub" #n "Ev\n\t" \
+ ".endif");
+
+// static nsresult SharedStub(PRUint32 methodIndex)
+asm(".section \".text\"\n\t"
+ ".align 2\n\t"
+ ".type SharedStub,@function\n\t"
+ "SharedStub:\n\t"
+ // make room for gpregs (48), fpregs (64)
+ "pushq %rbp\n\t"
+ "movq %rsp,%rbp\n\t"
+ "subq $112,%rsp\n\t"
+ // save GP registers
+ "movq %rdi,-112(%rbp)\n\t"
+ "movq %rsi,-104(%rbp)\n\t"
+ "movq %rdx, -96(%rbp)\n\t"
+ "movq %rcx, -88(%rbp)\n\t"
+ "movq %r8 , -80(%rbp)\n\t"
+ "movq %r9 , -72(%rbp)\n\t"
+ "leaq -112(%rbp),%rcx\n\t"
+ // save FP registers
+ "movsd %xmm0,-64(%rbp)\n\t"
+ "movsd %xmm1,-56(%rbp)\n\t"
+ "movsd %xmm2,-48(%rbp)\n\t"
+ "movsd %xmm3,-40(%rbp)\n\t"
+ "movsd %xmm4,-32(%rbp)\n\t"
+ "movsd %xmm5,-24(%rbp)\n\t"
+ "movsd %xmm6,-16(%rbp)\n\t"
+ "movsd %xmm7, -8(%rbp)\n\t"
+ "leaq -64(%rbp),%r8\n\t"
+ // rdi has the 'self' pointer already
+ "movl %eax,%esi\n\t"
+ "leaq 16(%rbp),%rdx\n\t"
+ "call PrepareAndDispatch@plt\n\t"
+ "leave\n\t"
+ "ret\n\t"
+ ".size SharedStub,.-SharedStub");
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+#else
+#error "Unsupported compiler. Use gcc >= 3.1 for Linux/x86-64."
+#endif /* __GNUC__ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_solaris.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_solaris.cpp
new file mode 100644
index 00000000..59e0202f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_64_solaris.cpp
@@ -0,0 +1,271 @@
+/* -*- 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) 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 ***** */
+
+// Implement shared vtbl methods.
+
+#include "xptcprivate.h"
+
+// The Linux/x86-64 ABI passes the first 6 integer parameters and the
+// first 8 floating point parameters in registers (rdi, rsi, rdx, rcx,
+// r8, r9 and xmm0-xmm7), no stack space is allocated for these by the
+// caller. The rest of the parameters are passed in the callers stack
+// area.
+// Solaris does the same, just the assembler may differ.
+
+const PRUint32 PARAM_BUFFER_COUNT = 16;
+const PRUint32 GPR_COUNT = 6;
+const PRUint32 FPR_COUNT = 8;
+
+// PrepareAndDispatch() is called by SharedStub() and calls the actual method.
+//
+// - 'args[]' contains the arguments passed on stack
+// - 'gpregs[]' contains the arguments passed in integer registers
+// - 'fpregs[]' contains the arguments passed in floating point registers
+//
+// The parameters are mapped into an array of type 'nsXPTCMiniVariant'
+// and then the method gets called.
+
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase * self, PRUint32 methodIndex,
+ PRUint64 * args, PRUint64 * gpregs, double *fpregs)
+{
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint32 paramCount;
+ PRUint32 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+ if (!iface_info)
+ return NS_ERROR_UNEXPECTED;
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (!info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if (paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PRUint64* ap = args;
+ PRUint32 nr_gpr = 1; // skip one GPR register for 'that'
+ PRUint32 nr_fpr = 0;
+ PRUint64 value;
+
+ for (i = 0; i < paramCount; i++) {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if (!param.IsOut() && type == nsXPTType::T_DOUBLE) {
+ if (nr_fpr < FPR_COUNT)
+ dp->val.d = fpregs[nr_fpr++];
+ else
+ dp->val.d = *(double*) ap++;
+ continue;
+ }
+ else if (!param.IsOut() && type == nsXPTType::T_FLOAT) {
+ if (nr_fpr < FPR_COUNT)
+ // The value in %xmm register is already prepared to
+ // be retrieved as a float. Therefore, we pass the
+ // value verbatim, as a double without conversion.
+ dp->val.d = *(double*) ap++;
+ else
+ dp->val.f = *(float*) ap++;
+ continue;
+ }
+ else {
+ if (nr_gpr < GPR_COUNT)
+ value = gpregs[nr_gpr++];
+ else
+ value = *ap++;
+ }
+
+ if (param.IsOut() || !type.IsArithmetic()) {
+ dp->val.p = (void*) value;
+ continue;
+ }
+
+ switch (type) {
+ case nsXPTType::T_I8: dp->val.i8 = (PRInt8) value; break;
+ case nsXPTType::T_I16: dp->val.i16 = (PRInt16) value; break;
+ case nsXPTType::T_I32: dp->val.i32 = (PRInt32) value; break;
+ case nsXPTType::T_I64: dp->val.i64 = (PRInt64) value; break;
+ case nsXPTType::T_U8: dp->val.u8 = (PRUint8) value; break;
+ case nsXPTType::T_U16: dp->val.u16 = (PRUint16) value; break;
+ case nsXPTType::T_U32: dp->val.u32 = (PRUint32) value; break;
+ case nsXPTType::T_U64: dp->val.u64 = (PRUint64) value; break;
+ case nsXPTType::T_BOOL: dp->val.b = (PRBool) value; break;
+ case nsXPTType::T_CHAR: dp->val.c = (char) value; break;
+ case nsXPTType::T_WCHAR: dp->val.wc = (wchar_t) value; break;
+
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16) methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if (dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#include <iprt/cdefs.h>
+
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */
+// Solaris/x86-64 uses gcc >= 3.1
+#define STUB_ENTRY(n,m) \
+asm(".section .text\n\t" \
+ ".align 2\n\t" \
+ ".globl _ZN14nsXPTCStubBase" #m "Stub" #n "Ev\n\t" \
+ ".type _ZN14nsXPTCStubBase" #m "Stub" #n "Ev,@function\n" \
+ "_ZN14nsXPTCStubBase" #m "Stub" #n "Ev:\n\t" \
+ "movl $" #n ", %eax\n\t" \
+ "jmp SharedStub\n\t" \
+ ".size _ZN14nsXPTCStubBase" #m "Stub" #n "Ev,.-_ZN14nsXPTCStubBase" #m "Stub" #n "Ev\n\t" \
+ )
+
+#define STUB_ENTRY_10(n10,m) \
+ STUB_ENTRY(n10##0,m); \
+ STUB_ENTRY(n10##1,m); \
+ STUB_ENTRY(n10##2,m); \
+ STUB_ENTRY(n10##3,m); \
+ STUB_ENTRY(n10##4,m); \
+ STUB_ENTRY(n10##5,m); \
+ STUB_ENTRY(n10##6,m); \
+ STUB_ENTRY(n10##7,m); \
+ STUB_ENTRY(n10##8,m); \
+ STUB_ENTRY(n10##9,m)
+STUB_ENTRY_10(,5);
+STUB_ENTRY_10(1,6);
+STUB_ENTRY_10(2,6);
+STUB_ENTRY_10(3,6);
+STUB_ENTRY_10(4,6);
+STUB_ENTRY_10(5,6);
+STUB_ENTRY_10(6,6);
+STUB_ENTRY_10(7,6);
+STUB_ENTRY_10(8,6);
+STUB_ENTRY_10(9,6);
+STUB_ENTRY_10(10,7);
+STUB_ENTRY_10(11,7);
+STUB_ENTRY_10(12,7);
+STUB_ENTRY_10(13,7);
+STUB_ENTRY_10(14,7);
+STUB_ENTRY_10(15,7);
+STUB_ENTRY_10(16,7);
+STUB_ENTRY_10(17,7);
+STUB_ENTRY_10(18,7);
+STUB_ENTRY_10(19,7);
+STUB_ENTRY_10(20,7);
+STUB_ENTRY_10(21,7);
+STUB_ENTRY_10(22,7);
+STUB_ENTRY_10(23,7);
+STUB_ENTRY_10(24,7);
+
+
+// static nsresult SharedStub(PRUint32 methodIndex)
+asm(".section .text\n\t"
+ ".align 2\n\t"
+ ".type SharedStub,@function\n\t"
+ "SharedStub:\n\t"
+ // make room for gpregs (48), fpregs (64)
+ "pushq %rbp\n\t"
+ "movq %rsp,%rbp\n\t"
+ "subq $112,%rsp\n\t"
+ // save GP registers
+ "movq %rdi,-112(%rbp)\n\t"
+ "movq %rsi,-104(%rbp)\n\t"
+ "movq %rdx, -96(%rbp)\n\t"
+ "movq %rcx, -88(%rbp)\n\t"
+ "movq %r8 , -80(%rbp)\n\t"
+ "movq %r9 , -72(%rbp)\n\t"
+ "leaq -112(%rbp),%rcx\n\t"
+ // save FP registers
+ "movsd %xmm0,-64(%rbp)\n\t"
+ "movsd %xmm1,-56(%rbp)\n\t"
+ "movsd %xmm2,-48(%rbp)\n\t"
+ "movsd %xmm3,-40(%rbp)\n\t"
+ "movsd %xmm4,-32(%rbp)\n\t"
+ "movsd %xmm5,-24(%rbp)\n\t"
+ "movsd %xmm6,-16(%rbp)\n\t"
+ "movsd %xmm7, -8(%rbp)\n\t"
+ "leaq -64(%rbp),%r8\n\t"
+ // rdi has the 'self' pointer already
+ "movl %eax,%esi\n\t"
+ "leaq 16(%rbp),%rdx\n\t"
+ "call PrepareAndDispatch@plt\n\t"
+ "leave\n\t"
+ "ret\n\t"
+ ".size SharedStub,.-SharedStub");
+
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+SENTINEL_ENTRY(0)
+SENTINEL_ENTRY(1)
+SENTINEL_ENTRY(2)
+SENTINEL_ENTRY(3)
+SENTINEL_ENTRY(4)
+
+#else
+#error "Unsupported compiler. Use gcc >= 3.1 for Linux/x86-64."
+#endif /* __GNUC__ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_solaris.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_solaris.cpp
new file mode 100644
index 00000000..d4ae7667
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/unix/xptcstubs_x86_solaris.cpp
@@ -0,0 +1,165 @@
+/* -*- 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) 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 ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+#include "xptc_platforms_unixish_x86.h"
+
+static nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, uint32 methodIndex, PRUint32* args)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info = NULL;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+ if (!iface_info)
+ return NS_ERROR_UNEXPECTED;
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no method info");
+ if (!info)
+ return NS_ERROR_UNEXPECTED;
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+ if (!dispatchParams)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ dp->val.p = (void*) *ap;
+ switch(type)
+ {
+ case nsXPTType::T_I64 : dp->val.i64 = *((PRInt64*) ap); ap++; break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((PRUint64*)ap); ap++; break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#ifdef __GNUC__ /* Gnu Compiler. */
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ register nsresult (*method) (nsXPTCStubBase *, uint32, PRUint32 *) = PrepareAndDispatch; \
+ int temp0, temp1; \
+ register nsresult result; \
+ __asm__ __volatile__( \
+ "leal 0x0c(%%ebp), %%ecx\n\t" /* args */ \
+ "pushl %%ecx\n\t" \
+ "pushl $"#n"\n\t" /* method index */ \
+ "movl 0x08(%%ebp), %%ecx\n\t" /* this */ \
+ "pushl %%ecx\n\t" \
+ "call *%%edx\n\t" /* PrepareAndDispatch */ \
+ "addl $12, %%esp" \
+ : "=a" (result), /* %0 */ \
+ "=&c" (temp0), /* %1 */ \
+ "=d" (temp1) /* %2 */ \
+ : "2" (method) /* %2 */ \
+ : "memory" ); \
+ return result; \
+}
+
+#elif defined(__SUNPRO_CC) /* Sun Workshop Compiler. */
+
+#define STUB_ENTRY(n) \
+nsresult nsXPTCStubBase::Stub##n() \
+{ \
+ asm ( \
+ "\n\t leal 0x0c(%ebp), %ecx\t / args" \
+ "\n\t pushl %ecx" \
+ "\n\t pushl $"#n"\t / method index" \
+ "\n\t movl 0x08(%ebp), %ecx\t / this" \
+ "\n\t pushl %ecx" \
+ "\n\t call __1cSPrepareAndDispatch6FpnOnsXPTCStubBase_IpI_I_\t / PrepareAndDispatch" \
+ "\n\t addl $12, %esp" \
+ ); \
+/* result == %eax */ \
+ if(0) /* supress "*** is expected to return a value." error */ \
+ return 0; \
+}
+
+#else
+#error "can't find a compiler to use"
+#endif /* __GNUC__ */
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/Makefile.in
new file mode 100644
index 00000000..0de74ee2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/Makefile.in
@@ -0,0 +1,82 @@
+#
+# ***** 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
+LIBRARY_NAME = xptcmd
+
+#
+# The default is this buildable, but non-functioning code.
+#
+ifdef GNU_CXX
+CPPSRCS = \
+ ../unix/xptcinvoke_gcc_x86_unix.cpp \
+ xptcstubs.cpp \
+ $(NULL)
+LOCAL_INCLUDES = -I$(srcdir)/../unix
+DEFINES += -DMOZ_USE_STDCALL -DMOZ_NEED_LEADING_UNDERSCORE
+else
+CPPSRCS = xptcinvoke.cpp xptcstubs.cpp
+endif
+
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+include $(topsrcdir)/config/config.mk
+
+ifeq ($(CPU),ALPHA)
+CPPSRCS := xptcinvoke_alpha.cpp xptcstubs_alpha.cpp
+ASFILES := xptcinvoke_asm_alpha.s xptcstubs_asm_alpha.s
+AS := asaxp
+ASFLAGS += /I../../..public
+endif
+
+# we don't want the shared lib, but we want to force the creation of a static lib.
+FORCE_STATIC_LIB = 1
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -DEXPORT_XPTC_API -D_IMPL_NS_COM -D_IMPL_NS_BASE
+
+LOCAL_INCLUDES += -I$(srcdir)/../..
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcinvoke.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcinvoke.cpp
new file mode 100644
index 00000000..9fbf2f94
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcinvoke.cpp
@@ -0,0 +1,107 @@
+/* -*- 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 ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+#include "xptcprivate.h"
+
+#ifndef WIN32
+#error "This code is for Win32 only"
+#endif
+
+static void __fastcall
+invoke_copy_to_stack(PRUint32* d, PRUint32 paramCount, nsXPTCVariant* s)
+{
+ for(; paramCount > 0; paramCount--, d++, s++)
+ {
+ if(s->IsPtrData())
+ {
+ *((void**)d) = s->ptr;
+ continue;
+ }
+ switch(s->type)
+ {
+ case nsXPTType::T_I8 : *((PRInt8*) d) = s->val.i8; break;
+ case nsXPTType::T_I16 : *((PRInt16*) d) = s->val.i16; break;
+ case nsXPTType::T_I32 : *((PRInt32*) d) = s->val.i32; break;
+ case nsXPTType::T_I64 : *((PRInt64*) d) = s->val.i64; d++; break;
+ case nsXPTType::T_U8 : *((PRUint8*) d) = s->val.u8; break;
+ case nsXPTType::T_U16 : *((PRUint16*)d) = s->val.u16; break;
+ case nsXPTType::T_U32 : *((PRUint32*)d) = s->val.u32; break;
+ case nsXPTType::T_U64 : *((PRUint64*)d) = s->val.u64; d++; break;
+ case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break;
+ case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break;
+ case nsXPTType::T_BOOL : *((PRBool*) d) = s->val.b; break;
+ case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break;
+ case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break;
+ default:
+ // all the others are plain pointer types
+ *((void**)d) = s->val.p;
+ break;
+ }
+ }
+}
+
+#pragma warning(disable : 4035) // OK to have no return value
+__declspec(naked) XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ __asm {
+ push ebp
+ mov ebp,esp
+ mov edx,paramCount // Save paramCount for later
+ test edx,edx // maybe we don't have any params to copy
+ jz noparams
+ mov eax,edx
+ shl eax,3 // *= 8 (max possible param size)
+ sub esp,eax // make space for params
+ mov ecx,esp
+ push params
+ call invoke_copy_to_stack // fastcall, ecx = d, edx = paramCount, params is on the stack
+noparams:
+ mov ecx,that // instance in ecx
+ push ecx // push this
+ mov edx,[ecx] // vtable in edx
+ mov eax,methodIndex
+ call [edx][eax*4] // stdcall, i.e. callee cleans up stack.
+ mov esp,ebp
+ pop ebp
+ ret
+ }
+}
+#pragma warning(default : 4035) // restore default
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_alpha.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_alpha.cpp
new file mode 100644
index 00000000..06334ac0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_alpha.cpp
@@ -0,0 +1,171 @@
+/* -*- 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 ***** */
+
+/* Platform specific code to invoke XPCOM methods on native objects */
+
+/* contributed by bob meader <bob@guiduck.com> */
+
+#include "xptcprivate.h"
+
+extern "C" uint32
+invoke_count_words(PRUint32 paramCount, nsXPTCVariant* s)
+{
+ return(paramCount*2);
+}
+
+extern "C" void
+invoke_copy_to_stack(PRUint64* d, PRUint32 paramCount,
+ nsXPTCVariant* s, PRUint64 *regs)
+{
+#define N_ARG_REGS 5 /* 6 regs minus 1 for "this" ptr */
+
+ for (PRUint32 i = 0; i < paramCount; i++, s++)
+ {
+ if (s->IsPtrData()) {
+ if (i < N_ARG_REGS)
+ regs[i] = (PRUint32)s->ptr;
+ else
+ *((PRUint32*)d++) = (PRUint32)s->ptr;
+ continue;
+ }
+ switch (s->type) {
+ //
+ // signed types first
+ //
+ case nsXPTType::T_I8:
+ if (i < N_ARG_REGS)
+ ((PRInt64*)regs)[i] = s->val.i8;
+ else
+ *((PRInt8 *)d++) = s->val.i8;
+ break;
+ case nsXPTType::T_I16:
+ if (i < N_ARG_REGS)
+ ((PRInt64*)regs)[i] = s->val.i16;
+ else
+ *((PRInt16 *)d++) = s->val.i16;
+ break;
+ case nsXPTType::T_I32:
+ if (i < N_ARG_REGS)
+ ((PRInt64*)regs)[i] = s->val.i32;
+ else
+ *((PRUint32*)d++) = s->val.i32;
+ break;
+ case nsXPTType::T_I64:
+ if (i < N_ARG_REGS)
+ ((PRInt64*)regs)[i] = s->val.i64;
+ else
+ *((PRInt64*)d++) = s->val.i64;
+ break;
+ //
+ // unsigned types next
+ //
+ case nsXPTType::T_U8:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.u8;
+ else
+ *((PRUint8 *)d++) = s->val.u8;
+ break;
+ case nsXPTType::T_U16:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.u16;
+ else
+ *((PRUint16 *)d++) = s->val.u16;
+ break;
+ case nsXPTType::T_U32:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.u32;
+ else
+ *((PRUint32*)d++) = s->val.u32;
+ break;
+ case nsXPTType::T_U64:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.u64;
+ else
+ *((PRUint64*)d++) = s->val.u64;
+ break;
+ case nsXPTType::T_FLOAT:
+ if (i < N_ARG_REGS)
+ ((double*)regs)[i] = s->val.f;
+ else
+ *((float*)d++) = s->val.f;
+ break;
+ case nsXPTType::T_DOUBLE:
+ if (i < N_ARG_REGS)
+ ((double*)regs)[i] = s->val.d;
+ else
+ *((double*)d++) = s->val.d;
+ break;
+ case nsXPTType::T_BOOL:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.b;
+ else
+ *((PRBool*)d++) = s->val.b;
+ break;
+ case nsXPTType::T_CHAR:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.c;
+ else
+ *((char*)d++) = s->val.c;
+ break;
+ case nsXPTType::T_WCHAR:
+ if (i < N_ARG_REGS)
+ regs[i] = s->val.wc;
+ else
+ *((wchar_t*)d++) = s->val.wc;
+ break;
+ default:
+ // all the others are plain pointer types
+ if (i < N_ARG_REGS)
+ regs[i] = (PRUint32)s->val.p;
+ else
+ *((PRUint32*)d++) = (PRUint32)s->val.p;
+ break;
+ }
+ }
+}
+
+extern "C" nsresult XPTC__InvokebyIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params);
+
+extern "C"
+XPTC_PUBLIC_API(nsresult)
+XPTC_InvokeByIndex(nsISupports* that, PRUint32 methodIndex,
+ PRUint32 paramCount, nsXPTCVariant* params)
+{
+ return XPTC__InvokebyIndex(that, methodIndex, paramCount, params);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_asm_alpha.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_asm_alpha.s
new file mode 100644
index 00000000..7f8b343b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_asm_alpha.s
@@ -0,0 +1,128 @@
+.text
+.globl invoke_count_words
+.globl invoke_copy_to_stack
+
+#define v0 $0
+#define t0 $1
+#define t1 $2
+#define t2 $3
+#define t3 $4
+#define s0 $9
+#define fp $15
+#define a0 $16
+#define a1 $17
+#define a2 $18
+#define a3 $19
+#define a4 $20
+#define a5 $21
+#define t9 $23
+#define ra $26
+#define gp $29
+#define sp $30
+#define zero $31
+#define f0 $f0
+
+#define LOCALSZ 7
+#define NARG 2
+#define SZREG 8
+#define FRAMESZ ((NARG+LOCALSZ)*SZREG)
+RAOFF=FRAMESZ-(1*SZREG)
+A0OFF=FRAMESZ-(2*SZREG)
+A1OFF=FRAMESZ-(3*SZREG)
+A2OFF=FRAMESZ-(4*SZREG)
+A3OFF=FRAMESZ-(5*SZREG)
+S0OFF=FRAMESZ-(6*SZREG)
+GPOFF=FRAMESZ-(7*SZREG)
+
+//
+// Nested
+// XPTC__InvokebyIndex( that, methodIndex, paramCount, params)
+// a0 a1 a2 a3
+//
+ .text
+ .align 4
+ .globl XPTC__InvokebyIndex
+ .ent XPTC__InvokebyIndex,0
+XPTC__InvokebyIndex:
+ .frame sp, FRAMESZ, ra
+ subl sp,FRAMESZ,sp // allocate stack space for structure
+ stq ra, RAOFF(sp)
+ stq a0, A0OFF(sp)
+ stq a1, A1OFF(sp)
+ stq a2, A2OFF(sp)
+ stq a3, A3OFF(sp)
+ stq s0, S0OFF(sp)
+// stq gp, GPOFF(sp) Don't think I am to save gp
+
+ // invoke_count_words(paramCount, params)
+ bis a2,zero,a0 // move a2 into a0
+ bis a3,zero,a1 // move a3 into a1
+ bsr ra,invoke_count_words
+
+ // invoke_copy_to_stack
+ ldq a1, A2OFF(sp) // a1 = paramCount
+ ldq a2, A3OFF(sp) // a2 = params
+
+ // save sp before we copy the params to the stack
+ bis sp,zero,t0 // t0 = sp
+
+ // assume full size of 8 bytes per param to be safe
+ sll v0,4,v0 //v0 = 8 bytes * num params
+ subl sp,v0,sp //sp = sp - v0
+ bis sp,zero,a0 //a0 = param stack address
+
+ // create temporary stack space to write int and fp regs
+ subl sp,64,sp //sp = sp -64 // (64 = 8 regs of eight bytes)
+ bis sp,zero,a3 // a3 = sp
+
+ // save the old sp and save the arg stack
+ subl sp,16,sp //sp = sp -16
+ stq t0,0(sp)
+ stq a0,8(sp)
+ // copy the param into the stack areas
+ bsr ra,invoke_copy_to_stack
+
+ ldq t3,8(sp) // get previous a0
+ ldq sp,0(sp) // get orig sp back
+
+ ldq a0,A0OFF(sp) // a0 = that
+ ldq a1,A1OFF(sp) // a1 = methodIndex
+
+ // calculate jmp address from method index
+ ldl t1,0(a0) // t1 = *that
+ sll a1,2,a1 // a1 = 4*index
+ addl t1,a1,t9
+ ldl t9,0(t9) // t9=*(that + 4*index)
+
+ // get register save area from invoke_copy_to_stack
+ subl t3,64,t1
+
+ // a1..a5 and f17..f21 should now be set to what
+ // invoke_copy_to_stack told us. skip a0 and f16
+ // because that's the "this" pointer
+
+ ldq a1,0(t1)
+ ldq a2,8(t1)
+ ldq a3,16(t1)
+ ldq a4,24(t1)
+ ldq a5,32(t1)
+
+ ldt $f17,0(t1)
+ ldt $f18,8(t1)
+ ldt $f19,16(t1)
+ ldt $f20,24(t1)
+ ldt $f21,32(t1)
+
+ // save away our stack point and create
+ // the stack pointer for the function
+ bis sp,zero,s0
+ bis t3,zero,sp
+ jsr ra,(t9)
+ bis s0,zero,sp
+ ldq ra,RAOFF(sp)
+ ldq s0,S0OFF(sp)
+ addl sp,FRAMESZ,sp
+ ret
+
+.end XPTC__InvokebyIndex
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcstubs.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcstubs.cpp
new file mode 100644
index 00000000..bd5ab975
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcstubs.cpp
@@ -0,0 +1,202 @@
+/* -*- 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) 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 ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+#ifndef WIN32
+#error "This code is for Win32 only"
+#endif
+
+extern "C" {
+
+static nsresult __stdcall
+PrepareAndDispatch(nsXPTCStubBase* self, PRUint32 methodIndex,
+ PRUint32* args, PRUint32* stackBytesToPop)
+{
+#define PARAM_BUFFER_COUNT 16
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info = NULL;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ // If anything fails before stackBytesToPop can be set then
+ // the failure is completely catastrophic!
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint32* ap = args;
+ for(i = 0; i < paramCount; i++, ap++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ dp->val.p = (void*) *ap;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8 : dp->val.i8 = *((PRInt8*) ap); break;
+ case nsXPTType::T_I16 : dp->val.i16 = *((PRInt16*) ap); break;
+ case nsXPTType::T_I32 : dp->val.i32 = *((PRInt32*) ap); break;
+ case nsXPTType::T_I64 : dp->val.i64 = *((PRInt64*) ap); ap++; break;
+ case nsXPTType::T_U8 : dp->val.u8 = *((PRUint8*) ap); break;
+ case nsXPTType::T_U16 : dp->val.u16 = *((PRUint16*)ap); break;
+ case nsXPTType::T_U32 : dp->val.u32 = *((PRUint32*)ap); break;
+ case nsXPTType::T_U64 : dp->val.u64 = *((PRUint64*)ap); ap++; break;
+ case nsXPTType::T_FLOAT : dp->val.f = *((float*) ap); break;
+ case nsXPTType::T_DOUBLE : dp->val.d = *((double*) ap); ap++; break;
+ case nsXPTType::T_BOOL : dp->val.b = *((PRBool*) ap); break;
+ case nsXPTType::T_CHAR : dp->val.c = *((char*) ap); break;
+ case nsXPTType::T_WCHAR : dp->val.wc = *((wchar_t*) ap); break;
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+ *stackBytesToPop = ((PRUint32)ap) - ((PRUint32)args);
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+} // extern "C"
+
+// declspec(naked) is broken in gcc
+#ifndef __GNUC__
+static
+__declspec(naked)
+void SharedStub(void)
+{
+ __asm {
+ push ebp // set up simple stack frame
+ mov ebp, esp // stack has: ebp/vtbl_index/retaddr/this/args
+ push ecx // make room for a ptr
+ lea eax, [ebp-4] // pointer to stackBytesToPop
+ push eax
+ lea eax, [ebp+12] // pointer to args
+ push eax
+ push ecx // vtbl_index
+ mov eax, [ebp+8] // this
+ push eax
+ call PrepareAndDispatch
+ mov edx, [ebp+4] // return address
+ mov ecx, [ebp-4] // stackBytesToPop
+ add ecx, 8 // for 'this' and return address
+ mov esp, ebp
+ pop ebp
+ add esp, ecx // fix up stack pointer
+ jmp edx // simulate __stdcall return
+ }
+}
+
+// these macros get expanded (many times) in the file #included below
+#define STUB_ENTRY(n) \
+__declspec(naked) nsresult __stdcall nsXPTCStubBase::Stub##n() \
+{ __asm mov ecx, n __asm jmp SharedStub }
+
+#else
+
+#define STUB_ENTRY(n) \
+nsresult __stdcall nsXPTCStubBase::Stub##n() \
+{ \
+ PRUint32 *args, stackBytesToPop = 0; \
+ nsresult result = 0; \
+ nsXPTCStubBase *obj; \
+ __asm__ __volatile__ ( \
+ "leal 0x0c(%%ebp), %%ecx\n\t" /* args */ \
+ "movl 0x08(%%ebp), %%edx\n\t" /* this */ \
+ : "=c" (args), \
+ "=d" (obj)); \
+ result = PrepareAndDispatch(obj, n, args, &stackBytesToPop); \
+ return result; \
+}
+
+#endif /* __GNUC__ */
+
+#define SENTINEL_ENTRY(n) \
+nsresult __stdcall nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#ifdef _MSC_VER
+#pragma warning(disable : 4035) // OK to have no return value
+#endif
+#include "xptcstubsdef.inc"
+#ifdef _MSC_VER
+#pragma warning(default : 4035) // restore default
+#endif
+
+void
+#ifdef __GNUC__
+__cdecl
+#endif
+xptc_dummy()
+{
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcstubs_alpha.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcstubs_alpha.cpp
new file mode 100644
index 00000000..69a10e70
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcstubs_alpha.cpp
@@ -0,0 +1,228 @@
+/* -*- 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) 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 ***** */
+
+/* Implement shared vtbl methods. */
+
+#include "xptcprivate.h"
+
+/* contributed by bob meader <bob@guiduck.com> */
+
+/*
+ * This is for Alpha /NT 32 bits
+ *
+ * When we're called, the "gp" registers are stored in gprData and
+ * the "fp" registers are stored in fprData. There are 6 regs
+ * available which coorespond to the first 5 parameters of the
+ * function and the "this" pointer. If there are additional parms,
+ * they are stored on the stack at address "args".
+ *
+ */
+extern "C" nsresult
+PrepareAndDispatch(nsXPTCStubBase* self, PRUint32 methodIndex, PRUint64* args,
+ PRUint64 *gprData, double *fprData)
+{
+#define PARAM_BUFFER_COUNT 16
+#define PARAM_GPR_COUNT 5
+#define PARAM_FPR_COUNT 5
+
+ nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
+ nsXPTCMiniVariant* dispatchParams = NULL;
+ nsIInterfaceInfo* iface_info = NULL;
+ const nsXPTMethodInfo* info;
+ PRUint8 paramCount;
+ PRUint8 i;
+ nsresult result = NS_ERROR_FAILURE;
+
+ NS_ASSERTION(self,"no self");
+
+ self->GetInterfaceInfo(&iface_info);
+ NS_ASSERTION(iface_info,"no interface info");
+
+ iface_info->GetMethodInfo(PRUint16(methodIndex), &info);
+ NS_ASSERTION(info,"no interface info");
+
+ paramCount = info->GetParamCount();
+
+ // setup variant array pointer
+ if(paramCount > PARAM_BUFFER_COUNT)
+ dispatchParams = new nsXPTCMiniVariant[paramCount];
+ else
+ dispatchParams = paramBuffer;
+ NS_ASSERTION(dispatchParams,"no place for params");
+
+ PRUint64* ap = args;
+ PRUint32 iCount = 0;
+ for(i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& param = info->GetParam(i);
+ const nsXPTType& type = param.GetType();
+ nsXPTCMiniVariant* dp = &dispatchParams[i];
+
+ if(param.IsOut() || !type.IsArithmetic())
+ {
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.p = (void*)gprData[iCount++];
+ else
+ dp->val.p = (void*)ap++;
+ continue;
+ }
+ // else
+ switch(type)
+ {
+ case nsXPTType::T_I8:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i8 = (PRInt8)gprData[iCount++];
+ else
+ dp->val.i8 = *((PRInt8*)ap++);
+ break;
+
+ case nsXPTType::T_I16:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i16 = (PRInt16)gprData[iCount++];
+ else
+ dp->val.i16 = *((PRInt16*)ap++);
+ break;
+
+ case nsXPTType::T_I32:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i32 = (PRInt32)gprData[iCount++];
+ else
+ dp->val.i32 = *((PRInt32*)ap++);
+ break;
+
+ case nsXPTType::T_I64:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.i64 = (PRInt64)gprData[iCount++];
+ else
+ dp->val.i64 = *((PRInt64*)ap++);
+ break;
+
+ case nsXPTType::T_U8:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u8 = (PRUint8)gprData[iCount++];
+ else
+ dp->val.u8 = *((PRUint8*)ap++);
+ break;
+
+ case nsXPTType::T_U16:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u16 = (PRUint16)gprData[iCount++];
+ else
+ dp->val.u16 = *((PRUint16*)ap++);
+ break;
+
+ case nsXPTType::T_U32:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u32 = (PRUint32)gprData[iCount++];
+ else
+ dp->val.u32 = *((PRUint32*)ap++);
+ break;
+
+ case nsXPTType::T_U64:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.u64 = (PRUint64)gprData[iCount++];
+ else
+ dp->val.u64 = (PRUint64)*ap++;
+ break;
+
+ case nsXPTType::T_FLOAT:
+ if (iCount < PARAM_FPR_COUNT)
+ dp->val.f = (float)fprData[iCount++];
+ else
+ dp->val.f = *((float*)ap++);
+ break;
+
+ case nsXPTType::T_DOUBLE:
+ if (iCount < PARAM_FPR_COUNT)
+ dp->val.d = (double)fprData[iCount++];
+ else
+ dp->val.d = *((double*)ap++);
+ break;
+
+ case nsXPTType::T_BOOL:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.b = (PRBool)gprData[iCount++];
+ else
+ dp->val.b = *((PRBool*)ap++);
+ break;
+
+ case nsXPTType::T_CHAR:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.c = (char)gprData[iCount++];
+ else
+ dp->val.c = *((char*)ap++);
+ break;
+
+ case nsXPTType::T_WCHAR:
+ if (iCount < PARAM_GPR_COUNT)
+ dp->val.wc = (wchar_t)gprData[iCount++];
+ else
+ dp->val.wc = *((wchar_t*)ap++);
+ break;
+
+ default:
+ NS_ASSERTION(0, "bad type");
+ break;
+ }
+ }
+
+ result = self->CallMethod((PRUint16)methodIndex, info, dispatchParams);
+
+ NS_RELEASE(iface_info);
+
+ if(dispatchParams != paramBuffer)
+ delete [] dispatchParams;
+
+ return result;
+}
+
+#define STUB_ENTRY(n) /* defined in the assembly file */
+
+#define SENTINEL_ENTRY(n) \
+nsresult nsXPTCStubBase::Sentinel##n() \
+{ \
+ NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
+ return NS_ERROR_NOT_IMPLEMENTED; \
+}
+
+#include "xptcstubsdef.inc"
+
+void
+xptc_dummy()
+{
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcstubs_asm_alpha.s b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcstubs_asm_alpha.s
new file mode 100644
index 00000000..5f8f861d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/md/win32/xptcstubs_asm_alpha.s
@@ -0,0 +1,120 @@
+
+#define v0 $0 // return value register
+#define t0 $1 // caller saved (temporary) registers
+#define t1 $2 //
+#define t2 $3 //
+#define t3 $4 //
+#define t4 $5 //
+#define t5 $6 //
+#define t6 $7 //
+#define t7 $8 //
+#define s0 $9 // callee saved (nonvolatile) registers
+#define a0 $16 // argument registers
+#define a1 $17 //
+#define a2 $18 //
+#define a3 $19 //
+#define a4 $20 //
+#define a5 $21 //
+#define t8 $22 // caller saved (temporary) registers
+#define t9 $23 //
+#define t10 $24 //
+#define t11 $25 //
+#define ra $26 // return address register
+#define sp $30 // stack pointer register
+#define zero $31 // zero register
+#define f16 $f16 // argument registers
+#define f17 $f17 //
+#define f18 $f18 //
+#define f19 $f19 //
+#define f20 $f20 //
+#define f21 $f21 //
+
+#define NARGSAVE 2
+#define LOCALSZ 16
+#define SZREG 8
+#define FRAMESZ (NARGSAVE+LOCALSZ)*SZREG
+
+ .text
+ .globl PrepareAndDispatch
+
+A1OFF=FRAMESZ-(9*SZREG)
+A2OFF=FRAMESZ-(8*SZREG)
+A3OFF=FRAMESZ-(7*SZREG)
+A4OFF=FRAMESZ-(6*SZREG)
+A5OFF=FRAMESZ-(5*SZREG)
+A6OFF=FRAMESZ-(4*SZREG) //not used
+A7OFF=FRAMESZ-(3*SZREG) //not used
+GPOFF=FRAMESZ-(2*SZREG) //not used
+RAOFF=FRAMESZ-(1*SZREG)
+
+F16OFF=FRAMESZ-(16*SZREG) //not used
+F17OFF=FRAMESZ-(15*SZREG)
+F18OFF=FRAMESZ-(14*SZREG)
+F19OFF=FRAMESZ-(13*SZREG)
+F20OFF=FRAMESZ-(12*SZREG)
+F21OFF=FRAMESZ-(11*SZREG)
+F22OFF=FRAMESZ-(10*SZREG) // not used
+
+#define NESTED_ENTRY(Name, fsize, retrg) \
+ .text; \
+ .align 4; \
+ .globl Name; \
+ .ent Name, 0; \
+Name:; \
+ .frame sp, fsize, retrg;
+
+#define SENTINEL_ENTRY(nn)
+#define STUB_ENTRY(nn) MAKE_PART(nn,@nsXPTCStubBase@@UAAIXZ )
+
+#define MAKE_PART(aa, bb) MAKE_STUB(aa, ?Stub##aa##bb )
+
+#define MAKE_STUB(nn, name) \
+NESTED_ENTRY(name, FRAMESZ,ra); \
+ subl sp,FRAMESZ,sp; \
+ mov nn,t0; \
+ jmp sharedstub; \
+.end name;
+
+#include "xptcstubsdef.inc"
+
+ .globl sharedstub
+ .ent sharedstub
+sharedstub:
+ stq a1,A1OFF(sp)
+ stq a2,A2OFF(sp)
+ stq a3,A3OFF(sp)
+ stq a4,A4OFF(sp)
+ stq a5,A5OFF(sp)
+ stq ra,RAOFF(sp)
+
+ stt f17,F17OFF(sp)
+ stt f18,F18OFF(sp)
+ stt f19,F19OFF(sp)
+ stt f20,F20OFF(sp)
+ stt f21,F21OFF(sp)
+
+ // t0 is methodIndex
+ bis t0,zero,a1 // a1 = methodIndex
+
+ // a2 is stack address where extra function params
+ // are stored that do not fit in registers
+ bis sp,zero,a2 //a2 = sp
+ addl a2,FRAMESZ,a2 //a2+=FRAMESZ
+
+ // a3 is stack addrss of a1..a5
+ bis sp,zero,a3 //a3 = sp
+ addl a3,A1OFF,a3 //a3+=A1OFF
+
+ // a4 is stack address of f17..f21
+ bis sp,zero,a4 //a4 = sp
+ addl a4,F17OFF,a4 //a4+=F17OFF
+
+ // PrepareAndDispatch(that, methodIndex, args, gprArgs, fpArgs)
+ // a0 a1 a2 a3 a4
+ bsr PrepareAndDispatch
+ ldq ra,RAOFF(sp)
+ addl sp,FRAMESZ,sp
+ ret
+
+.end sharedstub
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/xptcall.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/xptcall.cpp
new file mode 100644
index 00000000..f25a94e5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/xptcall.cpp
@@ -0,0 +1,62 @@
+/* -*- 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 ***** */
+
+/* entry point wrappers. */
+
+#if defined(XP_MAC)
+#pragma export on
+#endif
+
+#include "xptcprivate.h"
+
+// This method is never called and is only here so the compiler
+// will generate a vtbl for this class.
+// *Needed by the Irix implementation.*
+NS_IMETHODIMP nsXPTCStubBase::QueryInterface(REFNSIID aIID,
+ void** aInstancePtr)
+{
+ NS_ASSERTION(0,"wowa! nsXPTCStubBase::QueryInterface called");
+ return NS_ERROR_FAILURE;
+}
+#if defined(XP_MAC)
+#pragma export off
+#endif
+
+void
+xptc_dummy2()
+{
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/xptcprivate.h b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/xptcprivate.h
new file mode 100644
index 00000000..3691fa0a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/src/xptcprivate.h
@@ -0,0 +1,45 @@
+/* -*- 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 ***** */
+
+/* All the xptcall private declarations - only include locally. */
+
+#ifndef xptcprivate_h___
+#define xptcprivate_h___
+
+#include "xptcall.h"
+
+#endif /* xptcprivate_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/status.html b/src/libs/xpcom18a4/xpcom/reflect/xptcall/status.html
new file mode 100644
index 00000000..e3686999
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/status.html
@@ -0,0 +1,404 @@
+<html>
+<head>
+<title>xptcall Porting Status</title>
+</head>
+<body bgcolor = "white">
+<h2><center>xptcall Porting Status</center></h2>
+
+<h3>What is this?</h3>
+
+This is a status page for the multiplatform porting of xptcall.
+xptcall has a
+<a href="http://www.mozilla.org/scriptable/xptcall-faq.html">FAQ</a>
+and a
+<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/porting.html">Porting Guide</a>.
+
+<p>
+
+This is being maintained by <a href="mailto:jband@netscape.com">John Bandhauer &lt;jband@netscape.com&gt;</a>.
+Feel free to email me with questions or to volunteer to contribute xptcall code for any platform.
+
+<p>
+
+<a href="mailto:shaver@mozilla.org">Mike Shaver &lt;shaver@mozilla.org&gt;</a>
+is the best contact regarding 'nix (Unix, Linux, Finux, etc.) ports of xptcall.
+
+<h3>Status</h3>
+
+<table BORDER="1">
+<TR align="left" BGCOLOR="yellow">
+<TH>Status</TH>
+<TH>Platform</TH>
+<TH><img src="http://tinderbox.mozilla.org/star.gif">Contributors and <font color="red"><b>?</b></font> Possible Contributors</TH>
+<TH>Notes</TH>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Win32 x86</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:jband@netscape.com">John Bandhauer &lt;jband@netscape.com&gt;</a>
+</TD>
+<TD>
+<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/win32">win32</a></TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Linux x86</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:jband@netscape.com">John Bandhauer &lt;jband@netscape.com&gt;</a><br>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:drepper@cygnus.com">Ulrich Drepper &lt;drepper@cygnus.com&gt;</a>
+</TD>
+<TD><a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/unix">unix</a>
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>FreeBSD and NetBSD x86</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:toshok@hungry.com">Christoph Toshok &lt;toshok@hungry.com&gt;</a>,<BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:jband@netscape.com">John Bandhauer &lt;jband@netscape.com&gt;</a></TD>
+<TD><a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/unix">unix</a> (same as Linux 86 code)</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>BSD/OS x86</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:bert_driehuis@nl.compuware.com">Bert Driehuis &lt;bert_driehuis@nl.compuware.com&gt;</a></TD>
+<TD><a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/unix">unix</a> (same as Linux 86 code)
+Bert contributed patches that *should* do the right thing for all the unixish-x86
+versions of this code for GCC 2.7 or 2.8 vs. EGCS 1.1. He notes that the vtbl
+scheme is different. He is hoping that others will help test the changes using
+these two compilers on the various platforms where this same code is used.
+<a href="news://news.mozilla.org/372DD257.4248C821%40nl.compuware.com">Bert's details</a>
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Mac PPC</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+ <a href="mailto:rogerl@netscape.com">Roger Lawrence &lt;rogerl@netscape.com&gt;</a>,<BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:beard@netscape.com">Patrick Beard &lt;beard@netscape.com&gt;</a>
+</TD>
+<TD><a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/mac">mac</a> (passing tests and checked in)</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Solaris Sparc</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:rogerl@netscape.com">Roger Lawrence &lt;rogerl@netscape.com&gt;</a>,<BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:mcafee@netscape.com">Chris McAfee &lt;mcafee@netscape.com&gt;</a>
+</TD>
+<TD><a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/unix">unix</a> This is checked in and working.</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Solaris Sparc v9 (64bit)</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:pavlov@netscape.com">Stuart Parmenter &lt;pavlov@netscape.com&gt;</a>,<BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:cls@seawood.org">Chris Seawood &lt;cls@seawood.org&gt;</a>
+</TD>
+<TD><a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/unix">unix</a> This is checked in and (pavlov claims!) working.</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>OS/2</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:mjf35@cam.ac.uk">John Fairhurst &lt;mjf35@cam.ac.uk&gt;</a></TD>
+<TD>I never heard exactly who did what. But mozilla has been working on OS/2
+for a long time now.
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>OpenVMS Alpha</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:colin@theblakes.com">Colin R. Blake &lt;colin@theblakes.com&gt;</a></TD>
+<TD>
+Colin says this is passing all the tests on OpenVMS Alpha!
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>NT Alpha</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:bob@guiduck.com">bob meader &lt;bob@guiduck.com&gt;</a></TD>
+<TD>
+bob writes:<br>
+Enclosed is xptcall for alpha/nt target..
+<p>
+It is a variation of the IRIS port (only targeted for win32).
+<p>
+Notice the last 2 files (the change to mozilla\xpcom\build\makefile.win and
+mozilla\xpcom\build) are needed because I was unable to figure how to do a
+"declspecexport" from the assembler ASAXP ... if some knows how to do that then
+those last 2 files won't be needed.
+<p>
+I have had someone look over this code at bridge.com (the entry point to
+compaq/gem compiler team) and this code was given the OK. I consider it "done".
+<p>
+This code lives in the files where the name includes 'alpha' in the <a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/win32">win32</a> directory.<BR>
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Linux ARM</TD>
+<TD><img alt="Started" title="Started" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:sh990154@mail.uni-greifswald.de">Stefan Hanske&lt;sh990154@mail.uni-greifswald.de&gt;</a><BR>
+<font color="red"><b>?</b></font>
+<a href="mailto:willy@bofh.ai">Matthew Wilcox &lt;willy@bofh.ai&gt;</a></TD>
+<TD>
+Stefan's code is checked in and he says it is working.
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Linux Sparc</TD>
+<TD>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:anton@progsoc.uts.edu.au">Anton Blanchard &lt;anton@progsoc.uts.edu.au&gt;</a>,
+<BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:rogerl@netscape.com">Roger Lawrence &lt;rogerl@netscape.com&gt;</a>,
+<BR>
+<img alt="Maybe" title="Maybe" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:ehle.3@osu.eduehle.3@osu.edu">Brandon Ehle &lt;ehle.3@osu.edu&gt;</a>
+</TD>
+<TD>
+Anton contributed patches to Roger's Sparc code. Anton says it works and passes the tests!<b>
+(24-Aug-1999) Brandon writes: I've finished testing XPTCALL Sparc Linux on 12 different Sparc machines and it checks out good.
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Linux PPC</TD>
+<TD>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:beard@netscape.com">Patrick Beard &lt;beard@netscape.com&gt;</a><BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:waterson@netscape.com">Chris Waterson &lt;waterson@netscape.com&gt;</a><BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:Franz.Sirl-kernel@lauterbach.com">Franz Sirl &lt;Franz.Sirl-kernel@lauterbach.com&gt;</a><BR>
+<font color="red"><b>?</b></font>
+<a href="mailto:jsproul@condor.fddi.wesleyan.edu">Jason Y. Sproul &lt;jsproul@condor.fddi.wesleyan.edu&gt;</a><BR>
+ <font color="red"><b>?</b></font>
+ <a href="mailto:darkmane@w-link.net">Sean Chitwood &lt;darkmane@w-link.net&gt;</a></TD>
+<TD>
+waterson said: <b>Mozilla runs on Linux/PPC</b>
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Linux Alpha</TD>
+<TD>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:glen.nakamura@usa.net">Glen Nakamura &lt;glen.nakamura@usa.net&gt;</a><BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:morrildl@nycap.rr.com">Dan Morril &lt;morrildl@nycap.rr.com&gt;</a><BR>
+</TD>
+<TD>
+Glen writes:
+<p>
+I am attaching a patch which contains my Linux Alpha xptcall code.
+It passes TestXPTCInvoke and TestXPC on my machine which runs
+kernel 2.2.7, glibc 2.1.1, and egcs 1.1.2. I have not tested it
+with older GNU compilers such as gcc 2.8.x. From looking at the
+Linux x86 code, I gather that the vtable layout is a little different
+for those compilers and the code will need minor modifications
+in order to work properly.
+<p>
+I am not sure how much of the code can be used for OpenVMS Alpha
+and/or Digital UNIX. Currently the code is dependent on the g++
+name mangling convention and a few GNU extensions so I'm not sure
+how useful it will be for the other systems. Hopefully the
+comments in the code are detailed enough to help people attempting
+a port.
+<p>
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>SunOS x86</TD>
+<TD>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:aljones@lbl.gov">Arthur Jones &lt;aljones@lbl.gov&gt;</a><BR>
+<font color="red"><b>?</b></font>
+<a href="mailto:ppokorny@mindspring.com">Philip Pokorny &lt;ppokorny@mindspring.com&gt;</a><BR>
+</TD>
+<TD>
+The word I hear is that this is working and done
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>HP-UX</TD>
+<TD>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:wang@cup.hp.com">Thomas Wang &lt;wang@cup.hp.com&gt;</a><BR>
+<img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:mgleeson1@netscape.com">Mike Gleeson &lt;mgleeson1@netscape.com&gt;</a>
+</TD>
+<TD>I hear that this code is checked in and working. Though, there is some
+doubt - see bug
+#<a href="http://bugzilla.mozilla.org/show_bug.cgi?id=17997">17997</a>
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>AIX PPC</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:jdunn@netscape.com">Jim Dunn &lt;jdunn@netscape.com&gt;</a></TD>
+<TD>Philip K. Warren writes: <BR>
+
+We have gone through several releases of AIX without any problems.
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Irix</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:jasonh@m7.engr.sgi.com">Jason Heirtzler &lt;jasonh@m7.engr.sgi.com&gt;</a><BR>
+</TD>
+<TD>Jason has declared this done. Jason is no longer working at SGI and will
+not be maintaining this code. There is some doubt as to whether or not this is
+working for everyone - see bug
+#<a href="http://bugzilla.mozilla.org/show_bug.cgi?id=10061">10061</a>.
+<a href="mailto:shaver@mozilla.org">Mike&nbsp;Shaver&nbsp;&lt;shaver@mozilla.org&gt;</a>
+is the interim maintainer until someone more suitable can be found.
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>BeOS x86</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:duncan@be.com">Duncan Wilcox &lt;duncan@be.com&gt;</a><BR>
+</TD>
+<TD>
+<a href="http://lxr.mozilla.org/mozilla/source/xpcom/reflect/xptcall/src/md/unix">unix</a> (yet another reuse of the Linux 86 code!)<BR>
+Duncan says this is all working. He did the code for old cfront style 'this' adjustment for others to use too!
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="red"><font color="white"><b>HELP!</b></font></TD>
+<TD>BeOS PPC</TD>
+<TD align="center">-</TD>
+<TD align="center">-</TD>
+</TR>
+
+<TR>
+<TD bgcolor="green"><font color="white"><b>Done</b></font></TD>
+<TD>Compaq Tru64 UNIX (Digital UNIX)</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:streeter@zk3.dec.com">Steve Streeter &lt;streeter@zk3.dec.com&gt;</a><BR>
+</TD>
+<TD>Code passes the tests and is checked in.</TD>
+</TR>
+
+<TR>
+<TD bgcolor="khaki"><font color="black"><b>Working</b></font></TD>
+<TD>Neutrio x86</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:Jerry.Kirk@Nexwarecorp.com">Jerry L. Kirk &lt;Jerry.Kirk@Nexwarecorp.com&gt;</a><BR>
+</TD>
+<TD>
+Patches for xptc*_unixish_x86.cpp checked in. Waiting for verification that this is really finished.
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="khaki"><font color="black"><b>Investigating</b></font></TD>
+<TD>SCO UW7 and OSR5</TD>
+<TD>
+<img alt="Investigating" title="Investigating" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:jkj@sco.com">J. Kean Johnston &lt;jkj@sco.com&gt;</a><BR>
+<img alt="Investigating" title="Investigating" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:evanh@sco.com">Evan Hunt &lt;evanh@sco.com&gt;</a><BR>
+</TD>
+<TD>Recent (Feb-2001) email from jkj@sco.com suggests that work will be occuring soon.</TD>
+</TR>
+
+<TR>
+<TD bgcolor="khaki"><font color="black"><b>Works</b></font></TD>
+<TD>NetBSD/m68k</TD>
+<TD><img alt="Contributed code!" title="Contributed code!" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:khym@bga.com">Dave Huang &lt;khym@bga.com&gt;</a><BR>
+</TD>
+<TD>
+Dave's changes are in the tree. Waiting for verification that it is really finished.</TD>
+</TR>
+
+<TR>
+<TD bgcolor="khaki"><font color="black"><b>Partially Working</b></font></TD>
+<TD>NetBSD/arm32</TD>
+<TD><img alt="Investigating" title="Investigating" src="http://tinderbox.mozilla.org/star.gif">
+<a href="mailto:mpumford@black-star.demon.co.uk">Mike Pumford &lt;mpumford@black-star.demon.co.uk&gt;</a>
+</TD>
+<TD>Mike writes:<BR>
+I have started porting to the platform based on the code for Linux ARM. The
+InvokeByIndex code works correctly when used with TestXPTCInvoke. I am
+currently working on making TestXPC function correctly.
+<P>
+I am doing the porting work with egcs-1.1.2 on NetBSD 1.4P (NetBSD-current
+snapshot from a couple of days ago).
+</TD>
+</TR>
+
+<TR>
+<TD bgcolor="red"><font color="white"><b>HELP!</b></font></TD>
+<TD>linux/ia64</TD>
+<TD align="center">-</TD>
+<TD>bug <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=40950">40950</a></TD>
+</TR>
+
+
+<TR>
+<TD bgcolor="red"><font color="white"><b>HELP!</b></font></TD>
+<TD>All others!</TD>
+<TD align="center">-</TD>
+<TD align="center">-</TD>
+</TR>
+
+
+</table>
+
+<p>
+
+<b>Note:</b> I've used the symbol (<font color="red"><b>?</b></font>) to
+indicate people who have expressed an interest in <i>possibly</i> contributing code.
+Just because these people are listed here does not mean that they have commited
+themselves to do the work. If <b>you</b> would like to contribute then let me
+know. Feel free to email these folks and offer to help or find out what's going
+on. We're all in this together.
+
+<p>
+
+<hr>
+<b>Author:</b> <a href="mailto:jband@netscape.com">John Bandhauer &lt;jband@netscape.com&gt;</a><br>
+<b>Last modified:</b> 3 February 2003
+
+</body>
+</html>
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/tests/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptcall/tests/.cvsignore
new file mode 100644
index 00000000..177fd905
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/tests/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+TestXPTCInvoke
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/tests/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptcall/tests/Makefile.in
new file mode 100644
index 00000000..a1bf16ca
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/tests/Makefile.in
@@ -0,0 +1,64 @@
+#
+# ***** 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 = TestXPTC
+SIMPLE_PROGRAMS = TestXPTCInvoke$(BIN_SUFFIX)
+REQUIRES = xpcom \
+ $(NULL)
+
+CPPSRCS = TestXPTCInvoke.cpp
+
+LIBS = \
+ $(XPCOM_LIBS) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+# For _write().
+ifeq ($(OS_ARCH),BSD_OS)
+OS_LIBS += -lgcc
+endif
+
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptcall/tests/TestXPTCInvoke.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptcall/tests/TestXPTCInvoke.cpp
new file mode 100644
index 00000000..79e4bc08
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptcall/tests/TestXPTCInvoke.cpp
@@ -0,0 +1,1464 @@
+/* -*- 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):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ * Stuart Parmenter <pavlov@netscape.com>
+ * Chris Seawood <cls@seawood.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 ***** */
+
+/* Invoke tests xptcall. */
+
+#include <stdio.h>
+#include "xptcall.h"
+#include "prlong.h"
+#include "prinrval.h"
+#include "nsMemory.h"
+
+// forward declration
+static int DoMultipleInheritenceTest(int rcExit);
+static int DoMultipleInheritenceTest2(int rcExit);
+static void DoSpeedTest();
+
+
+#include <iprt/string.h>
+
+static char g_szDirect[16384];
+static char g_szInvoke[16384];
+static char *g_pszBuffer = NULL;
+static void bufprintf(const char *pszFormat, ...)
+{
+ va_list va;
+ va_start(va, pszFormat);
+ vprintf(pszFormat, va);
+ va_end(va);
+ if (g_pszBuffer)
+ {
+ size_t cchBuf = strlen(g_pszBuffer);
+ ssize_t cbLeft = (ssize_t)sizeof(g_szDirect) - (ssize_t)cchBuf;
+ if (cbLeft > 0)
+ {
+ va_list va;
+ va_start(va, pszFormat);
+ vsnprintf(&g_pszBuffer[cchBuf], (size_t)cbLeft, pszFormat, va);
+ va_end(va);
+ }
+ }
+}
+
+static void setbuffer(bool fDirect)
+{
+ g_pszBuffer = fDirect ? g_szDirect : g_szInvoke;
+ *g_pszBuffer = '\0';
+}
+
+static int comparebuffers(int rcExit)
+{
+ if (strcmp(g_szDirect, g_szInvoke) == 0)
+ return rcExit;
+ size_t offLine = 0;
+ unsigned iLine = 1;
+ for (size_t off = 0; ; off++)
+ {
+ char chDirect = g_szDirect[off];
+ char chInvoke = g_szInvoke[off];
+ if (chDirect == chInvoke)
+ {
+ if (!chDirect)
+ return rcExit;
+ if (chDirect == '\n')
+ {
+ offLine = off + 1;
+ iLine++;
+ }
+ }
+ else
+ {
+ size_t cchDirectLine = RTStrOffCharOrTerm(&g_szDirect[offLine], '\n');
+ size_t cchInvokeLine = RTStrOffCharOrTerm(&g_szInvoke[offLine], '\n');
+ printf("direct and invoke runs differs on line %u!\n", iLine);
+ printf("direct: %*.*s\n", (int)cchDirectLine, (int)cchDirectLine, &g_szDirect[offLine]);
+ printf("invoke: %*.*s\n", (int)cchInvokeLine, (int)cchInvokeLine, &g_szInvoke[offLine]);
+
+ return 1;
+ }
+
+ }
+ printf("direct and invoke runs differs!\n");
+ return 1;
+}
+
+
+// {AAC1FB90-E099-11d2-984E-006008962422}
+#define INVOKETESTTARGET_IID \
+{ 0xaac1fb90, 0xe099, 0x11d2, \
+ { 0x98, 0x4e, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+
+
+class InvokeTestTargetInterface : public nsISupports
+{
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(INVOKETESTTARGET_IID)
+ NS_IMETHOD AddTwoInts(PRInt32 p1, PRInt32 p2, PRInt32* retval) = 0;
+ NS_IMETHOD MultTwoInts(PRInt32 p1, PRInt32 p2, PRInt32* retval) = 0;
+ NS_IMETHOD AddTwoLLs(PRInt64 p1, PRInt64 p2, PRInt64* retval) = 0;
+ NS_IMETHOD MultTwoLLs(PRInt64 p1, PRInt64 p2, PRInt64* retval) = 0;
+
+ NS_IMETHOD AddManyInts(PRInt32 p1, PRInt32 p2, PRInt32 p3, PRInt32 p4,
+ PRInt32 p5, PRInt32 p6, PRInt32 p7, PRInt32 p8,
+ PRInt32 p9, PRInt32 p10, PRInt32* retval) = 0;
+
+ NS_IMETHOD AddTwoFloats(float p1, float p2, float* retval) = 0;
+
+ NS_IMETHOD AddManyDoubles(double p1, double p2, double p3, double p4,
+ double p5, double p6, double p7, double p8,
+ double p9, double p10, double* retval) = 0;
+
+ NS_IMETHOD AddManyFloats(float p1, float p2, float p3, float p4,
+ float p5, float p6, float p7, float p8,
+ float p9, float p10, float* retval) = 0;
+
+ NS_IMETHOD AddManyManyFloats(float p1, float p2, float p3, float p4,
+ float p5, float p6, float p7, float p8,
+ float p9, float p10, float p11, float p12,
+ float p13, float p14, float p15, float p16,
+ float p17, float p18, float p19, float p20,
+ float *retval) = 0;
+
+ NS_IMETHOD AddMixedInts(PRInt64 p1, PRInt32 p2, PRInt64 p3, PRInt32 p4,
+ PRInt32 p5, PRInt64 p6, PRInt32 p7, PRInt32 p8,
+ PRInt64 p9, PRInt32 p10, PRInt64* retval) = 0;
+
+ NS_IMETHOD AddMixedInts2(PRInt32 p1, PRInt64 p2, PRInt32 p3, PRInt64 p4,
+ PRInt64 p5, PRInt32 p6, PRInt64 p7, PRInt64 p8,
+ PRInt32 p9, PRInt64 p10, PRInt64* retval) = 0;
+
+ NS_IMETHOD AddMixedFloats(float p1, float p2, double p3, double p4,
+ float p5, float p6, double p7, double p8,
+ float p9, double p10, float p11,
+ double *retval) = 0;
+
+ NS_IMETHOD PassTwoStrings(const char* s1, const char* s2, char** retval) = 0;
+
+};
+
+class InvokeTestTarget : public InvokeTestTargetInterface
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_IMETHOD AddTwoInts(PRInt32 p1, PRInt32 p2, PRInt32* retval);
+ NS_IMETHOD MultTwoInts(PRInt32 p1, PRInt32 p2, PRInt32* retval);
+ NS_IMETHOD AddTwoLLs(PRInt64 p1, PRInt64 p2, PRInt64* retval);
+ NS_IMETHOD MultTwoLLs(PRInt64 p1, PRInt64 p2, PRInt64* retval);
+
+ NS_IMETHOD AddManyInts(PRInt32 p1, PRInt32 p2, PRInt32 p3, PRInt32 p4,
+ PRInt32 p5, PRInt32 p6, PRInt32 p7, PRInt32 p8,
+ PRInt32 p9, PRInt32 p10, PRInt32* retval);
+
+ NS_IMETHOD AddTwoFloats(float p1, float p2, float* retval);
+
+ NS_IMETHOD AddManyDoubles(double p1, double p2, double p3, double p4,
+ double p5, double p6, double p7, double p8,
+ double p9, double p10, double* retval);
+
+ NS_IMETHOD AddManyFloats(float p1, float p2, float p3, float p4,
+ float p5, float p6, float p7, float p8,
+ float p9, float p10, float* retval);
+
+ NS_IMETHOD AddMixedInts(PRInt64 p1, PRInt32 p2, PRInt64 p3, PRInt32 p4,
+ PRInt32 p5, PRInt64 p6, PRInt32 p7, PRInt32 p8,
+ PRInt64 p9, PRInt32 p10, PRInt64* retval);
+
+ NS_IMETHOD AddMixedInts2(PRInt32 p1, PRInt64 p2, PRInt32 p3, PRInt64 p4,
+ PRInt64 p5, PRInt32 p6, PRInt64 p7, PRInt64 p8,
+ PRInt32 p9, PRInt64 p10, PRInt64* retval);
+
+ NS_IMETHOD AddMixedFloats(float p1, float p2, double p3, double p4,
+ float p5, float p6, double p7, double p8,
+ float p9, double p10, float p11,
+ double *retval);
+
+ NS_IMETHOD AddManyManyFloats(float p1, float p2, float p3, float p4,
+ float p5, float p6, float p7, float p8,
+ float p9, float p10, float p11, float p12,
+ float p13, float p14, float p15, float p16,
+ float p17, float p18, float p19, float p20,
+ float *retval);
+
+ NS_IMETHOD PassTwoStrings(const char* s1, const char* s2, char** retval);
+
+ InvokeTestTarget();
+};
+
+NS_IMPL_ISUPPORTS1(InvokeTestTarget, InvokeTestTargetInterface)
+
+InvokeTestTarget::InvokeTestTarget()
+{
+ NS_ADDREF_THIS();
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::AddTwoInts(PRInt32 p1, PRInt32 p2, PRInt32* retval)
+{
+ *retval = p1 + p2;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::MultTwoInts(PRInt32 p1, PRInt32 p2, PRInt32* retval)
+{
+ *retval = p1 * p2;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::AddTwoLLs(PRInt64 p1, PRInt64 p2, PRInt64* retval)
+{
+ LL_ADD(*retval, p1, p2);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::MultTwoLLs(PRInt64 p1, PRInt64 p2, PRInt64* retval)
+{
+ LL_MUL(*retval, p1, p2);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::AddManyInts(PRInt32 p1, PRInt32 p2, PRInt32 p3, PRInt32 p4,
+ PRInt32 p5, PRInt32 p6, PRInt32 p7, PRInt32 p8,
+ PRInt32 p9, PRInt32 p10, PRInt32* retval)
+{
+#ifdef DEBUG_TESTINVOKE
+ printf("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
+ p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
+#endif
+ *retval = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::AddTwoFloats(float p1, float p2, float *retval)
+{
+#ifdef DEBUG_TESTINVOKE
+ printf("%f, %f\n", p1, p2);
+#endif
+ *retval = p1 + p2;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::AddManyDoubles(double p1, double p2, double p3, double p4,
+ double p5, double p6, double p7, double p8,
+ double p9, double p10, double* retval)
+{
+#ifdef DEBUG_TESTINVOKE
+ printf("%lf, %lf, %lf, %lf, %lf, %lf, %lf, %lf, %lf, %lf\n",
+ p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
+#endif
+ *retval = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::AddManyFloats(float p1, float p2, float p3, float p4,
+ float p5, float p6, float p7, float p8,
+ float p9, float p10, float* retval)
+{
+#ifdef DEBUG_TESTINVOKE
+ printf("%f, %f, %f, %f, %f, %f, %f, %f, %f, %f\n",
+ p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
+#endif
+ *retval = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::AddMixedFloats(float p1, float p2, double p3, double p4,
+ float p5, float p6, double p7, double p8,
+ float p9, double p10, float p11,
+ double *retval)
+{
+#ifdef DEBUG_TESTINVOKE
+ printf("%f, %f, %lf, %lf, %f, %f, %lf, %lf, %f, %lf, %f\n",
+ p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
+#endif
+ *retval = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + p11;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::AddManyManyFloats(float p1, float p2, float p3, float p4,
+ float p5, float p6, float p7, float p8,
+ float p9, float p10, float p11, float p12,
+ float p13, float p14, float p15, float p16,
+ float p17, float p18, float p19, float p20,
+ float *retval)
+{
+#ifdef DEBUG_TESTINVOKE
+ printf("%f, %f, %f, %f, %f, %f, %f, %f, %f, %f, "
+ "%f, %f, %f, %f, %f, %f, %f, %f, %f, %f\n",
+ p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,
+ p11, p12, p13, p14, p15, p16, p17, p18, p19, p20);
+#endif
+ *retval = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 +
+ p11 + p12 + p13 + p14 + p15 + p16 + p17 + p18 + p19 + p20;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::AddMixedInts(PRInt64 p1, PRInt32 p2, PRInt64 p3, PRInt32 p4,
+ PRInt32 p5, PRInt64 p6, PRInt32 p7, PRInt32 p8,
+ PRInt64 p9, PRInt32 p10, PRInt64* retval)
+{
+ *retval = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::AddMixedInts2(PRInt32 p1, PRInt64 p2, PRInt32 p3, PRInt64 p4,
+ PRInt64 p5, PRInt32 p6, PRInt64 p7, PRInt64 p8,
+ PRInt32 p9, PRInt64 p10, PRInt64* retval)
+{
+ *retval = p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+InvokeTestTarget::PassTwoStrings(const char* s1, const char* s2, char** retval)
+{
+ const char milk[] = "milk";
+ char *ret = (char*)nsMemory::Alloc(sizeof(milk));
+ if (!ret)
+ return NS_ERROR_OUT_OF_MEMORY;
+ strncpy(ret, milk, sizeof(milk));
+ printf("\t%s %s", s1, s2);
+ *retval = ret;
+ return NS_OK;
+}
+
+int main()
+{
+ InvokeTestTarget *test = new InvokeTestTarget();
+
+ /* here we make the global 'check for alloc failure' checker happy */
+ if(!test)
+ return 1;
+
+ PRInt32 out, tmp32 = 0;
+ PRInt64 out64;
+ printf("calling direct:\n");
+ setbuffer(true);
+ if(NS_SUCCEEDED(test->AddTwoInts(1,1,&out)))
+ bufprintf("\t1 + 1 = %d\n", out);
+ else
+ bufprintf("\tFAILED");
+ PRInt64 one, two;
+ LL_I2L(one, 1);
+ LL_I2L(two, 2);
+ if(NS_SUCCEEDED(test->AddTwoLLs(one,one,&out64)))
+ {
+ LL_L2I(tmp32, out64);
+ bufprintf("\t1L + 1L = %d\n", (int)tmp32);
+ }
+ else
+ bufprintf("\tFAILED");
+ if(NS_SUCCEEDED(test->MultTwoInts(2,2,&out)))
+ bufprintf("\t2 * 2 = %d\n", out);
+ else
+ bufprintf("\tFAILED");
+ if(NS_SUCCEEDED(test->MultTwoLLs(two,two,&out64)))
+ {
+ LL_L2I(tmp32, out64);
+ bufprintf("\t2L * 2L = %d\n", (int)tmp32);
+ }
+ else
+ bufprintf("\tFAILED");
+
+ double outD;
+ float outF;
+ PRInt32 outI;
+ char *outS;
+
+ if(NS_SUCCEEDED(test->AddManyInts(1,2,3,4,5,6,7,8,9,10,&outI)))
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %d\n", outI);
+ else
+ bufprintf("\tFAILED");
+
+ if(NS_SUCCEEDED(test->AddTwoFloats(1,2,&outF)))
+ bufprintf("\t1 + 2 = %ff\n", (double)outF);
+ else
+ bufprintf("\tFAILED");
+
+ if(NS_SUCCEEDED(test->AddManyDoubles(1,2,3,4,5,6,7,8,9,10,&outD)))
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %f\n", outD);
+ else
+ bufprintf("\tFAILED");
+
+ if(NS_SUCCEEDED(test->AddManyFloats(1,2,3,4,5,6,7,8,9,10,&outF)))
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %ff\n", (double)outF);
+ else
+ bufprintf("\tFAILED");
+
+ if(NS_SUCCEEDED(test->AddManyManyFloats(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,&outF)))
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 = %ff\n", (double)outF);
+ else
+ bufprintf("\tFAILED");
+
+ if(NS_SUCCEEDED(test->AddMixedInts(1,2,3,4,5,6,7,8,9,10,&out64)))
+ {
+ LL_L2I(tmp32, out64);
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %d\n", (int)tmp32);
+ }
+ else
+ bufprintf("\tFAILED");
+
+ if(NS_SUCCEEDED(test->AddMixedInts2(1,2,3,4,5,6,7,8,9,10,&out64)))
+ {
+ LL_L2I(tmp32, out64);
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %d\n", (int)tmp32);
+ }
+ else
+ bufprintf("\tFAILED");
+
+ if(NS_SUCCEEDED(test->AddMixedFloats(1,2,3,4,5,6,7,8,9,10,11,&outD)))
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 = %f\n", (double)outD);
+ else
+ bufprintf("\tFAILED");
+
+ if (NS_SUCCEEDED(test->PassTwoStrings("moo","cow",&outS))) {
+ bufprintf(" = %s\n", outS);
+ nsMemory::Free(outS);
+ } else
+ bufprintf("\tFAILED");
+
+ printf("calling via invoke:\n");
+ setbuffer(false);
+
+ nsXPTCVariant var[21];
+
+ var[0].val.i32 = 1;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+
+ var[1].val.i32 = 1;
+ var[1].type = nsXPTType::T_I32;
+ var[1].flags = 0;
+
+ var[2].val.i32 = 0;
+ var[2].type = nsXPTType::T_I32;
+ var[2].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[2].ptr = &var[2].val.i32;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 3, 3, var)))
+ bufprintf("\t1 + 1 = %d\n", var[2].val.i32);
+ else
+ bufprintf("\tFAILED");
+
+ LL_I2L(var[0].val.i64, 1);
+ var[0].type = nsXPTType::T_I64;
+ var[0].flags = 0;
+
+ LL_I2L(var[1].val.i64, 1);
+ var[1].type = nsXPTType::T_I64;
+ var[1].flags = 0;
+
+ LL_I2L(var[2].val.i64, 0);
+ var[2].type = nsXPTType::T_I64;
+ var[2].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[2].ptr = &var[2].val.i64;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 5, 3, var)))
+ bufprintf("\t1L + 1L = %d\n", (int)var[2].val.i64);
+ else
+ bufprintf("\tFAILED");
+
+ var[0].val.i32 = 2;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+
+ var[1].val.i32 = 2;
+ var[1].type = nsXPTType::T_I32;
+ var[1].flags = 0;
+
+ var[2].val.i32 = 0;
+ var[2].type = nsXPTType::T_I32;
+ var[2].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[2].ptr = &var[2].val.i32;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 4, 3, var)))
+ bufprintf("\t2 * 2 = %d\n", var[2].val.i32);
+ else
+ bufprintf("\tFAILED");
+
+ LL_I2L(var[0].val.i64,2);
+ var[0].type = nsXPTType::T_I64;
+ var[0].flags = 0;
+
+ LL_I2L(var[1].val.i64,2);
+ var[1].type = nsXPTType::T_I64;
+ var[1].flags = 0;
+
+ LL_I2L(var[2].val.i64,0);
+ var[2].type = nsXPTType::T_I64;
+ var[2].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[2].ptr = &var[2].val.i64;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 6, 3, var)))
+ bufprintf("\t2L * 2L = %d\n", (int)var[2].val.i64);
+ else
+ bufprintf("\tFAILED");
+
+ var[0].val.i32 = 1;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+
+ var[1].val.i32 = 2;
+ var[1].type = nsXPTType::T_I32;
+ var[1].flags = 0;
+
+ var[2].val.i32 = 3;
+ var[2].type = nsXPTType::T_I32;
+ var[2].flags = 0;
+
+ var[3].val.i32 = 4;
+ var[3].type = nsXPTType::T_I32;
+ var[3].flags = 0;
+
+ var[4].val.i32 = 5;
+ var[4].type = nsXPTType::T_I32;
+ var[4].flags = 0;
+
+ var[5].val.i32 = 6;
+ var[5].type = nsXPTType::T_I32;
+ var[5].flags = 0;
+
+ var[6].val.i32 = 7;
+ var[6].type = nsXPTType::T_I32;
+ var[6].flags = 0;
+
+ var[7].val.i32 = 8;
+ var[7].type = nsXPTType::T_I32;
+ var[7].flags = 0;
+
+ var[8].val.i32 = 9;
+ var[8].type = nsXPTType::T_I32;
+ var[8].flags = 0;
+
+ var[9].val.i32 = 10;
+ var[9].type = nsXPTType::T_I32;
+ var[9].flags = 0;
+
+ var[10].val.i32 = 0;
+ var[10].type = nsXPTType::T_I32;
+ var[10].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[10].ptr = &var[10].val.i32;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 7, 11, var)))
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %d\n",
+ var[10].val.i32);
+
+ var[0].val.f = 1.0f;
+ var[0].type = nsXPTType::T_FLOAT;
+ var[0].flags = 0;
+
+ var[1].val.f = 2.0f;
+ var[1].type = nsXPTType::T_FLOAT;
+ var[1].flags = 0;
+
+ var[2].val.f = 0.0f;
+ var[2].type = nsXPTType::T_FLOAT;
+ var[2].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[2].ptr = &var[2].val.f;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 8, 3, var)))
+ bufprintf("\t1 + 2 = %ff\n",
+ (double) var[2].val.f);
+
+
+ var[0].val.d = 1.0;
+ var[0].type = nsXPTType::T_DOUBLE;
+ var[0].flags = 0;
+
+ var[1].val.d = 2.0;
+ var[1].type = nsXPTType::T_DOUBLE;
+ var[1].flags = 0;
+
+ var[2].val.d = 3.0;
+ var[2].type = nsXPTType::T_DOUBLE;
+ var[2].flags = 0;
+
+ var[3].val.d = 4.0;
+ var[3].type = nsXPTType::T_DOUBLE;
+ var[3].flags = 0;
+
+ var[4].val.d = 5.0;
+ var[4].type = nsXPTType::T_DOUBLE;
+ var[4].flags = 0;
+
+ var[5].val.d = 6.0;
+ var[5].type = nsXPTType::T_DOUBLE;
+ var[5].flags = 0;
+
+ var[6].val.d = 7.0;
+ var[6].type = nsXPTType::T_DOUBLE;
+ var[6].flags = 0;
+
+ var[7].val.d = 8.0;
+ var[7].type = nsXPTType::T_DOUBLE;
+ var[7].flags = 0;
+
+ var[8].val.d = 9.0;
+ var[8].type = nsXPTType::T_DOUBLE;
+ var[8].flags = 0;
+
+ var[9].val.d = 10.0;
+ var[9].type = nsXPTType::T_DOUBLE;
+ var[9].flags = 0;
+
+ var[10].val.d = 0.0;
+ var[10].type = nsXPTType::T_DOUBLE;
+ var[10].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[10].ptr = &var[10].val.d;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 9, 11, var)))
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %f\n",
+ var[10].val.d);
+ else
+ bufprintf("\tFAILED");
+
+ var[0].val.f = 1.0f;
+ var[0].type = nsXPTType::T_FLOAT;
+ var[0].flags = 0;
+
+ var[1].val.f = 2.0f;
+ var[1].type = nsXPTType::T_FLOAT;
+ var[1].flags = 0;
+
+ var[2].val.f = 3.0f;
+ var[2].type = nsXPTType::T_FLOAT;
+ var[2].flags = 0;
+
+ var[3].val.f = 4.0f;
+ var[3].type = nsXPTType::T_FLOAT;
+ var[3].flags = 0;
+
+ var[4].val.f = 5.0f;
+ var[4].type = nsXPTType::T_FLOAT;
+ var[4].flags = 0;
+
+ var[5].val.f = 6.0f;
+ var[5].type = nsXPTType::T_FLOAT;
+ var[5].flags = 0;
+
+ var[6].val.f = 7.0f;
+ var[6].type = nsXPTType::T_FLOAT;
+ var[6].flags = 0;
+
+ var[7].val.f = 8.0f;
+ var[7].type = nsXPTType::T_FLOAT;
+ var[7].flags = 0;
+
+ var[8].val.f = 9.0f;
+ var[8].type = nsXPTType::T_FLOAT;
+ var[8].flags = 0;
+
+ var[9].val.f = 10.0f;
+ var[9].type = nsXPTType::T_FLOAT;
+ var[9].flags = 0;
+
+ var[10].val.f = 0.0f;
+ var[10].type = nsXPTType::T_FLOAT;
+ var[10].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[10].ptr = &var[10].val.f;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 10, 11, var)))
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %ff\n",
+ (double) var[10].val.f);
+ else
+ bufprintf("\tFAILED");
+
+ var[0].val.f = 1.0f;
+ var[0].type = nsXPTType::T_FLOAT;
+ var[0].flags = 0;
+
+ var[1].val.f = 2.0f;
+ var[1].type = nsXPTType::T_FLOAT;
+ var[1].flags = 0;
+
+ var[2].val.f = 3.0f;
+ var[2].type = nsXPTType::T_FLOAT;
+ var[2].flags = 0;
+
+ var[3].val.f = 4.0f;
+ var[3].type = nsXPTType::T_FLOAT;
+ var[3].flags = 0;
+
+ var[4].val.f = 5.0f;
+ var[4].type = nsXPTType::T_FLOAT;
+ var[4].flags = 0;
+
+ var[5].val.f = 6.0f;
+ var[5].type = nsXPTType::T_FLOAT;
+ var[5].flags = 0;
+
+ var[6].val.f = 7.0f;
+ var[6].type = nsXPTType::T_FLOAT;
+ var[6].flags = 0;
+
+ var[7].val.f = 8.0f;
+ var[7].type = nsXPTType::T_FLOAT;
+ var[7].flags = 0;
+
+ var[8].val.f = 9.0f;
+ var[8].type = nsXPTType::T_FLOAT;
+ var[8].flags = 0;
+
+ var[9].val.f = 10.0f;
+ var[9].type = nsXPTType::T_FLOAT;
+ var[9].flags = 0;
+
+ var[10].val.f = 11.0f;
+ var[10].type = nsXPTType::T_FLOAT;
+ var[10].flags = 0;
+
+ var[11].val.f = 12.0f;
+ var[11].type = nsXPTType::T_FLOAT;
+ var[11].flags = 0;
+
+ var[12].val.f = 13.0f;
+ var[12].type = nsXPTType::T_FLOAT;
+ var[12].flags = 0;
+
+ var[13].val.f = 14.0f;
+ var[13].type = nsXPTType::T_FLOAT;
+ var[13].flags = 0;
+
+ var[14].val.f = 15.0f;
+ var[14].type = nsXPTType::T_FLOAT;
+ var[14].flags = 0;
+
+ var[15].val.f = 16.0f;
+ var[15].type = nsXPTType::T_FLOAT;
+ var[15].flags = 0;
+
+ var[16].val.f = 17.0f;
+ var[16].type = nsXPTType::T_FLOAT;
+ var[16].flags = 0;
+
+ var[17].val.f = 18.0f;
+ var[17].type = nsXPTType::T_FLOAT;
+ var[17].flags = 0;
+
+ var[18].val.f = 19.0f;
+ var[18].type = nsXPTType::T_FLOAT;
+ var[18].flags = 0;
+
+ var[19].val.f = 20.0f;
+ var[19].type = nsXPTType::T_FLOAT;
+ var[19].flags = 0;
+
+ var[20].val.f = 0.0f;
+ var[20].type = nsXPTType::T_FLOAT;
+ var[20].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[20].ptr = &var[20].val.f;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 11, 21, var)))
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 = %ff\n",
+ (double) var[20].val.f);
+
+ var[0].val.i64 = 1;
+ var[0].type = nsXPTType::T_I64;
+ var[0].flags = 0;
+
+ var[1].val.i32 = 2;
+ var[1].type = nsXPTType::T_I32;
+ var[1].flags = 0;
+
+ var[2].val.i64 = 3;
+ var[2].type = nsXPTType::T_I64;
+ var[2].flags = 0;
+
+ var[3].val.i32 = 4;
+ var[3].type = nsXPTType::T_I32;
+ var[3].flags = 0;
+
+ var[4].val.i32 = 5;
+ var[4].type = nsXPTType::T_I32;
+ var[4].flags = 0;
+
+ var[5].val.i64 = 6;
+ var[5].type = nsXPTType::T_I64;
+ var[5].flags = 0;
+
+ var[6].val.i32 = 7;
+ var[6].type = nsXPTType::T_I32;
+ var[6].flags = 0;
+
+ var[7].val.i32 = 8;
+ var[7].type = nsXPTType::T_I32;
+ var[7].flags = 0;
+
+ var[8].val.i64 = 9;
+ var[8].type = nsXPTType::T_I64;
+ var[8].flags = 0;
+
+ var[9].val.i32 = 10;
+ var[9].type = nsXPTType::T_I32;
+ var[9].flags = 0;
+
+ var[10].val.i64 = 0;
+ var[10].type = nsXPTType::T_I64;
+ var[10].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[10].ptr = &var[10].val.i64;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 12, 11, var)))
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %d\n",
+ (int)var[10].val.i64);
+ else
+ bufprintf("\tFAILED");
+
+ var[0].val.i32 = 1;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+
+ var[1].val.i64 = 2;
+ var[1].type = nsXPTType::T_I64;
+ var[1].flags = 0;
+
+ var[2].val.i32 = 3;
+ var[2].type = nsXPTType::T_I32;
+ var[2].flags = 0;
+
+ var[3].val.i64 = 4;
+ var[3].type = nsXPTType::T_I64;
+ var[3].flags = 0;
+
+ var[4].val.i64 = 5;
+ var[4].type = nsXPTType::T_I64;
+ var[4].flags = 0;
+
+ var[5].val.i32 = 6;
+ var[5].type = nsXPTType::T_I32;
+ var[5].flags = 0;
+
+ var[6].val.i64 = 7;
+ var[6].type = nsXPTType::T_I64;
+ var[6].flags = 0;
+
+ var[7].val.i64 = 8;
+ var[7].type = nsXPTType::T_I64;
+ var[7].flags = 0;
+
+ var[8].val.i32 = 9;
+ var[8].type = nsXPTType::T_I32;
+ var[8].flags = 0;
+
+ var[9].val.i64 = 10;
+ var[9].type = nsXPTType::T_I64;
+ var[9].flags = 0;
+
+ var[10].val.i64 = 0;
+ var[10].type = nsXPTType::T_I64;
+ var[10].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[10].ptr = &var[10].val.i64;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 13, 11, var)))
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = %d\n",
+ (int)var[10].val.i64);
+ else
+ bufprintf("\tFAILED");
+
+ var[0].val.f = 1.0f;
+ var[0].type = nsXPTType::T_FLOAT;
+ var[0].flags = 0;
+
+ var[1].val.f = 2.0f;
+ var[1].type = nsXPTType::T_FLOAT;
+ var[1].flags = 0;
+
+ var[2].val.d = 3.0;
+ var[2].type = nsXPTType::T_DOUBLE;
+ var[2].flags = 0;
+
+ var[3].val.d = 4.0;
+ var[3].type = nsXPTType::T_DOUBLE;
+ var[3].flags = 0;
+
+ var[4].val.f = 5.0f;
+ var[4].type = nsXPTType::T_FLOAT;
+ var[4].flags = 0;
+
+ var[5].val.f = 6.0f;
+ var[5].type = nsXPTType::T_FLOAT;
+ var[5].flags = 0;
+
+ var[6].val.d = 7.0;
+ var[6].type = nsXPTType::T_DOUBLE;
+ var[6].flags = 0;
+
+ var[7].val.d = 8.0;
+ var[7].type = nsXPTType::T_DOUBLE;
+ var[7].flags = 0;
+
+ var[8].val.f = 9.0f;
+ var[8].type = nsXPTType::T_FLOAT;
+ var[8].flags = 0;
+
+ var[9].val.d = 10.0;
+ var[9].type = nsXPTType::T_DOUBLE;
+ var[9].flags = 0;
+
+ var[10].val.f = 11.0f;
+ var[10].type = nsXPTType::T_FLOAT;
+ var[10].flags = 0;
+
+ var[11].val.d = 0.0;
+ var[11].type = nsXPTType::T_DOUBLE;
+ var[11].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[11].ptr = &var[11].val.d;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 14, 12, var)))
+ bufprintf("\t1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 = %f\n",
+ var[11].val.d);
+ else
+ bufprintf("\tFAILED");
+
+ var[0].val.p = (void*)"moo";
+ var[0].type = nsXPTType::T_CHAR_STR;
+ var[0].flags = 0;
+
+ var[1].val.p = (void*)"cow";
+ var[1].type = nsXPTType::T_CHAR_STR;
+ var[1].flags = 0;
+
+ var[2].val.p = 0;
+ var[2].type = nsXPTType::T_CHAR_STR;
+ var[2].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[2].ptr = &var[2].val.p;
+
+ if(NS_SUCCEEDED(XPTC_InvokeByIndex(test, 15, 3, var)))
+ {
+ bufprintf(" = %s\n", var[2].val.p);
+ nsMemory::Free(var[2].val.p);
+ }
+ else
+ bufprintf("\tFAILED");
+ int rcExit = comparebuffers(0);
+
+ rcExit = DoMultipleInheritenceTest(rcExit);
+ rcExit = DoMultipleInheritenceTest2(rcExit);
+ // Disabled by default - takes too much time on slow machines
+ //DoSpeedTest();
+
+ NS_RELEASE(test);
+
+ return rcExit;
+}
+
+/***************************************************************************/
+/***************************************************************************/
+/***************************************************************************/
+
+// {491C65A0-3317-11d3-9885-006008962422}
+#define FOO_IID \
+{ 0x491c65a0, 0x3317, 0x11d3, \
+ { 0x98, 0x85, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+
+// {491C65A1-3317-11d3-9885-006008962422}
+#define BAR_IID \
+{ 0x491c65a1, 0x3317, 0x11d3, \
+ { 0x98, 0x85, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
+
+/***************************/
+
+class nsIFoo : public nsISupports
+{
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(FOO_IID)
+ NS_IMETHOD FooMethod1(PRInt32 i) = 0;
+ NS_IMETHOD FooMethod2(PRInt32 i) = 0;
+};
+
+class nsIBar : public nsISupports
+{
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(BAR_IID)
+ NS_IMETHOD BarMethod1(PRInt32 i) = 0;
+ NS_IMETHOD BarMethod2(PRInt32 i) = 0;
+};
+
+/***************************/
+
+class FooImpl : public nsIFoo
+{
+public:
+ NS_IMETHOD FooMethod1(PRInt32 i);
+ NS_IMETHOD FooMethod2(PRInt32 i);
+
+ FooImpl();
+
+protected:
+ ~FooImpl() {}
+
+public:
+ virtual const char* ImplName() = 0;
+
+ int SomeData1;
+ int SomeData2;
+ const char* Name;
+};
+
+class BarImpl : public nsIBar
+{
+public:
+ NS_IMETHOD BarMethod1(PRInt32 i);
+ NS_IMETHOD BarMethod2(PRInt32 i);
+
+ BarImpl();
+
+protected:
+ ~BarImpl() {}
+
+public:
+ virtual const char * ImplName() = 0;
+
+ int SomeData1;
+ int SomeData2;
+ const char* Name;
+};
+
+/***************************/
+
+FooImpl::FooImpl() : Name("FooImpl")
+{
+}
+
+NS_IMETHODIMP FooImpl::FooMethod1(PRInt32 i)
+{
+ bufprintf("\tFooImpl::FooMethod1 called with i == %d, %s part of a %s\n",
+ i, Name, ImplName());
+ return NS_OK;
+}
+
+NS_IMETHODIMP FooImpl::FooMethod2(PRInt32 i)
+{
+ bufprintf("\tFooImpl::FooMethod2 called with i == %d, %s part of a %s\n",
+ i, Name, ImplName());
+ return NS_OK;
+}
+
+/***************************/
+
+BarImpl::BarImpl() : Name("BarImpl")
+{
+}
+
+NS_IMETHODIMP BarImpl::BarMethod1(PRInt32 i)
+{
+ bufprintf("\tBarImpl::BarMethod1 called with i == %d, %s part of a %s\n",
+ i, Name, ImplName());
+ return NS_OK;
+}
+
+NS_IMETHODIMP BarImpl::BarMethod2(PRInt32 i)
+{
+ bufprintf("\tBarImpl::BarMethod2 called with i == %d, %s part of a %s\n",
+ i, Name, ImplName());
+ return NS_OK;
+}
+
+/***************************/
+
+class FooBarImpl : public FooImpl, public BarImpl
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ const char* ImplName();
+
+ FooBarImpl();
+
+private:
+ ~FooBarImpl() {}
+
+public:
+ const char* MyName;
+};
+
+FooBarImpl::FooBarImpl() : MyName("FooBarImpl")
+{
+ NS_ADDREF_THIS();
+}
+
+const char* FooBarImpl::ImplName()
+{
+ return MyName;
+}
+
+NS_IMETHODIMP
+FooBarImpl::QueryInterface(REFNSIID aIID, void** aInstancePtr)
+{
+ if (NULL == aInstancePtr) {
+ return NS_ERROR_NULL_POINTER;
+ }
+
+ *aInstancePtr = NULL;
+
+
+ if (aIID.Equals(NS_GET_IID(nsIFoo))) {
+ *aInstancePtr = (void*) NS_STATIC_CAST(nsIFoo*,this);
+ NS_ADDREF_THIS();
+ return NS_OK;
+ }
+ if (aIID.Equals(NS_GET_IID(nsIBar))) {
+ *aInstancePtr = (void*) NS_STATIC_CAST(nsIBar*,this);
+ NS_ADDREF_THIS();
+ return NS_OK;
+ }
+
+ if (aIID.Equals(NS_GET_IID(nsISupports))) {
+ *aInstancePtr = (void*) NS_STATIC_CAST(nsISupports*,
+ NS_STATIC_CAST(nsIFoo*,this));
+ NS_ADDREF_THIS();
+ return NS_OK;
+ }
+ return NS_NOINTERFACE;
+}
+
+NS_IMPL_ADDREF(FooBarImpl)
+NS_IMPL_RELEASE(FooBarImpl)
+
+
+static int DoMultipleInheritenceTest(int rcExit)
+{
+ FooBarImpl* impl = new FooBarImpl();
+ if(!impl)
+ return 1;
+
+ nsIFoo* foo;
+ nsIBar* bar;
+
+ nsXPTCVariant var[1];
+
+ printf("\n");
+ if(NS_SUCCEEDED(impl->QueryInterface(NS_GET_IID(nsIFoo), (void**)&foo)) &&
+ NS_SUCCEEDED(impl->QueryInterface(NS_GET_IID(nsIBar), (void**)&bar)))
+ {
+ printf("impl == %p\n", impl);
+ printf("foo == %p\n", foo);
+ printf("bar == %p\n", bar);
+
+ printf("Calling Foo...\n");
+ printf("direct calls:\n");
+ setbuffer(true);
+ foo->FooMethod1(1);
+ foo->FooMethod2(2);
+
+ printf("invoke calls:\n");
+ setbuffer(false);
+ var[0].val.i32 = 1;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+ XPTC_InvokeByIndex(foo, 3, 1, var);
+
+ var[0].val.i32 = 2;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+ XPTC_InvokeByIndex(foo, 4, 1, var);
+
+ rcExit = comparebuffers(rcExit);
+ printf("\n");
+
+ printf("Calling Bar...\n");
+ printf("direct calls:\n");
+ setbuffer(true);
+ bar->BarMethod1(1);
+ bar->BarMethod2(2);
+
+ printf("invoke calls:\n");
+ setbuffer(false);
+ var[0].val.i32 = 1;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+ XPTC_InvokeByIndex(bar, 3, 1, var);
+
+ var[0].val.i32 = 2;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+ XPTC_InvokeByIndex(bar, 4, 1, var);
+
+ rcExit = comparebuffers(rcExit);
+ printf("\n");
+
+ NS_RELEASE(foo);
+ NS_RELEASE(bar);
+ }
+ else
+ rcExit = 1;
+ NS_RELEASE(impl);
+ return rcExit;
+}
+/***************************************************************************/
+/***************************************************************************/
+/***************************************************************************/
+/* This is a variation on the theme submitted by duncan@be.com (Duncan Wilcox).
+* He was seeing the other test work and this test not work. They should both
+* Work on any given platform
+*/
+
+class nsIFoo2 : public nsISupports
+{
+public:
+ NS_IMETHOD FooMethod1(PRInt32 i) = 0;
+ NS_IMETHOD FooMethod2(PRInt32 i) = 0;
+};
+
+class nsIBar2 : public nsISupports
+{
+public:
+ NS_IMETHOD BarMethod1(PRInt32 i) = 0;
+ NS_IMETHOD BarMethod2(PRInt32 i) = 0;
+};
+
+class FooBarImpl2 : public nsIFoo2, public nsIBar2
+{
+public:
+ // Foo interface
+ NS_IMETHOD FooMethod1(PRInt32 i);
+ NS_IMETHOD FooMethod2(PRInt32 i);
+
+ // Bar interface
+ NS_IMETHOD BarMethod1(PRInt32 i);
+ NS_IMETHOD BarMethod2(PRInt32 i);
+
+ NS_DECL_ISUPPORTS
+
+ FooBarImpl2();
+
+private:
+ ~FooBarImpl2() {}
+
+public:
+ PRInt32 value;
+};
+
+FooBarImpl2::FooBarImpl2() : value(0x12345678)
+{
+ NS_ADDREF_THIS();
+}
+
+NS_IMETHODIMP FooBarImpl2::FooMethod1(PRInt32 i)
+{
+ bufprintf("\tFooBarImpl2::FooMethod1 called with i == %d, local value = %x\n",
+ i, value);
+ return NS_OK;
+}
+
+NS_IMETHODIMP FooBarImpl2::FooMethod2(PRInt32 i)
+{
+ bufprintf("\tFooBarImpl2::FooMethod2 called with i == %d, local value = %x\n",
+ i, value);
+ return NS_OK;
+}
+
+NS_IMETHODIMP FooBarImpl2::BarMethod1(PRInt32 i)
+{
+ bufprintf("\tFooBarImpl2::BarMethod1 called with i == %d, local value = %x\n",
+ i, value);
+ return NS_OK;
+}
+
+NS_IMETHODIMP FooBarImpl2::BarMethod2(PRInt32 i)
+{
+ bufprintf("\tFooBarImpl2::BarMethod2 called with i == %d, local value = %x\n",
+ i, value);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+FooBarImpl2::QueryInterface(REFNSIID aIID, void** aInstancePtr)
+{
+ if (NULL == aInstancePtr) {
+ return NS_ERROR_NULL_POINTER;
+ }
+
+ *aInstancePtr = NULL;
+
+
+ if (aIID.Equals(NS_GET_IID(nsIFoo))) {
+ *aInstancePtr = (void*) NS_STATIC_CAST(nsIFoo2*,this);
+ NS_ADDREF_THIS();
+ return NS_OK;
+ }
+ if (aIID.Equals(NS_GET_IID(nsIBar))) {
+ *aInstancePtr = (void*) NS_STATIC_CAST(nsIBar2*,this);
+ NS_ADDREF_THIS();
+ return NS_OK;
+ }
+
+ if (aIID.Equals(NS_GET_IID(nsISupports))) {
+ *aInstancePtr = (void*) NS_STATIC_CAST(nsISupports*,
+ NS_STATIC_CAST(nsIFoo2*,this));
+ NS_ADDREF_THIS();
+ return NS_OK;
+ }
+ return NS_NOINTERFACE;
+}
+
+NS_IMPL_ADDREF(FooBarImpl2)
+NS_IMPL_RELEASE(FooBarImpl2)
+
+static int DoMultipleInheritenceTest2(int rcExit)
+{
+ FooBarImpl2* impl = new FooBarImpl2();
+ if(!impl)
+ return 1;
+
+ nsIFoo2* foo;
+ nsIBar2* bar;
+
+ nsXPTCVariant var[1];
+
+ printf("\n");
+ if(NS_SUCCEEDED(impl->QueryInterface(NS_GET_IID(nsIFoo), (void**)&foo)) &&
+ NS_SUCCEEDED(impl->QueryInterface(NS_GET_IID(nsIBar), (void**)&bar)))
+ {
+ printf("impl == %p\n", impl);
+ printf("foo == %p\n", foo);
+ printf("bar == %p\n", bar);
+
+ printf("Calling Foo...\n");
+ printf("direct calls:\n");
+ setbuffer(true);
+ foo->FooMethod1(1);
+ foo->FooMethod2(2);
+
+ printf("invoke calls:\n");
+ setbuffer(false);
+ var[0].val.i32 = 1;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+ XPTC_InvokeByIndex(foo, 3, 1, var);
+
+ var[0].val.i32 = 2;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+ XPTC_InvokeByIndex(foo, 4, 1, var);
+
+ rcExit = comparebuffers(rcExit);
+ printf("\n");
+
+ printf("Calling Bar...\n");
+ printf("direct calls:\n");
+ setbuffer(true);
+ bar->BarMethod1(1);
+ bar->BarMethod2(2);
+
+ printf("invoke calls:\n");
+ setbuffer(false);
+ var[0].val.i32 = 1;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+ XPTC_InvokeByIndex(bar, 3, 1, var);
+
+ var[0].val.i32 = 2;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+ XPTC_InvokeByIndex(bar, 4, 1, var);
+
+ rcExit = comparebuffers(rcExit);
+ printf("\n");
+
+ NS_RELEASE(foo);
+ NS_RELEASE(bar);
+ }
+ else
+ rcExit = 1;
+ NS_RELEASE(impl);
+ return rcExit;
+}
+
+static void DoSpeedTest()
+{
+ InvokeTestTarget *test = new InvokeTestTarget();
+
+ nsXPTCVariant var[3];
+
+ var[0].val.i32 = 1;
+ var[0].type = nsXPTType::T_I32;
+ var[0].flags = 0;
+
+ var[1].val.i32 = 1;
+ var[1].type = nsXPTType::T_I32;
+ var[1].flags = 0;
+
+ var[2].val.i32 = 0;
+ var[2].type = nsXPTType::T_I32;
+ var[2].flags = nsXPTCVariant::PTR_IS_DATA;
+ var[2].ptr = &var[2].val.i32;
+
+ PRInt32 in1 = 1;
+ PRInt32 in2 = 1;
+ PRInt32 out;
+
+ // Crank this number down if your platform is slow :)
+ static const int count = 100000000;
+ int i;
+ PRIntervalTime start;
+ PRIntervalTime interval_direct;
+ PRIntervalTime interval_invoke;
+
+ printf("Speed test...\n\n");
+ printf("Doing %d direct call iterations...\n", count);
+ start = PR_IntervalNow();
+ for(i = count; i; i--)
+ (void)test->AddTwoInts(in1, in2, &out);
+ interval_direct = PR_IntervalNow() - start;
+
+ printf("Doing %d invoked call iterations...\n", count);
+ start = PR_IntervalNow();
+ for(i = count; i; i--)
+ (void)XPTC_InvokeByIndex(test, 3, 3, var);
+ interval_invoke = PR_IntervalNow() - start;
+
+ printf(" direct took %0.2f seconds\n",
+ (double)interval_direct/(double)PR_TicksPerSecond());
+ printf(" invoke took %0.2f seconds\n",
+ (double)interval_invoke/(double)PR_TicksPerSecond());
+ printf(" So, invoke overhead was ~ %0.2f seconds (~ %0.0f%%)\n",
+ (double)(interval_invoke-interval_direct)/(double)PR_TicksPerSecond(),
+ (double)(interval_invoke-interval_direct)/(double)interval_invoke*100);
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/Makefile.in
new file mode 100644
index 00000000..d7e3b9c8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/Makefile.in
@@ -0,0 +1,49 @@
+#
+# ***** 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) 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 *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+DIRS = public src
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/Makefile.in
new file mode 100644
index 00000000..dbf13d8b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/Makefile.in
@@ -0,0 +1,66 @@
+#
+# ***** 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) 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 *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+
+XPIDL_MODULE = xpcom_xpti
+
+GRE_MODULE = 1
+
+EXPORTS = \
+ xptinfo.h \
+ $(NULL)
+
+XPIDLSRCS = \
+ nsIInterfaceInfo.idl \
+ nsIInterfaceInfoManager.idl \
+ nsIXPTLoader.idl \
+ $(NULL)
+
+EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
+
+include $(topsrcdir)/config/rules.mk
+
+CFLAGS += -DEXPORT_XPCI_API
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIInterfaceInfo.idl b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIInterfaceInfo.idl
new file mode 100644
index 00000000..f77dbcfc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIInterfaceInfo.idl
@@ -0,0 +1,137 @@
+/* -*- 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) 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 ***** */
+
+/* The nsIInterfaceInfo public declaration. */
+
+
+#include "nsISupports.idl"
+
+// forward declaration of non-XPCOM types
+
+[ptr] native nsXPTMethodInfoPtr(nsXPTMethodInfo);
+[ptr] native nsXPTConstantPtr(nsXPTConstant);
+[ptr] native nsXPTParamInfoPtr(nsXPTParamInfo);
+ native nsXPTType(nsXPTType);
+
+// We bend the rules to do a [shared] nsIID (but this is never scriptable)
+[ptr] native nsIIDPtrShared(nsIID);
+
+%{C++
+class nsXPTMethodInfo;
+class nsXPTConstant;
+class nsXPTParamInfo;
+class nsXPTType;
+%}
+
+/* this is NOT intended to be scriptable */
+[uuid(215DBE04-94A7-11d2-BA58-00805F8A5DD7)]
+interface nsIInterfaceInfo : nsISupports
+{
+ readonly attribute string name;
+ readonly attribute nsIIDPtr InterfaceIID;
+
+ PRBool isScriptable();
+
+ readonly attribute nsIInterfaceInfo parent;
+
+ /**
+ * These include counts for parent (and all ancestors).
+ */
+ readonly attribute PRUint16 methodCount;
+ readonly attribute PRUint16 constantCount;
+
+ /**
+ * These include methods and constants for parent (and all ancestors).
+ *
+ * These do *not* make copies ***explicit bending of XPCOM rules***.
+ */
+
+ void getMethodInfo(in PRUint16 index,
+ [shared, retval] out nsXPTMethodInfoPtr info);
+
+ void getMethodInfoForName(in string methodName, out PRUint16 index,
+ [shared, retval] out nsXPTMethodInfoPtr info);
+
+ void getConstant(in PRUint16 index,
+ [shared, retval] out nsXPTConstantPtr constant);
+
+
+ /**
+ * Get the interface information or iid associated with a param of some
+ * method in this interface.
+ */
+
+ nsIInterfaceInfo getInfoForParam(in PRUint16 methodIndex,
+ [const] in nsXPTParamInfoPtr param);
+
+ nsIIDPtr getIIDForParam(in PRUint16 methodIndex,
+ [const] in nsXPTParamInfoPtr param);
+
+
+ /**
+ * These do *not* make copies ***explicit bending of XPCOM rules***.
+ */
+
+ nsXPTType getTypeForParam(in PRUint16 methodIndex,
+ [const] in nsXPTParamInfoPtr param,
+ in PRUint16 dimension);
+
+ PRUint8 getSizeIsArgNumberForParam(in PRUint16 methodIndex,
+ [const] in nsXPTParamInfoPtr param,
+ in PRUint16 dimension);
+
+ PRUint8 getLengthIsArgNumberForParam(in PRUint16 methodIndex,
+ [const] in nsXPTParamInfoPtr param,
+ in PRUint16 dimension);
+
+ PRUint8 getInterfaceIsArgNumberForParam(in PRUint16 methodIndex,
+ [const] in nsXPTParamInfoPtr param);
+
+ PRBool isIID(in nsIIDPtr IID);
+
+ void getNameShared([shared,retval] out string name);
+ void getIIDShared([shared,retval] out nsIIDPtrShared iid);
+
+ PRBool isFunction();
+
+ PRBool hasAncestor(in nsIIDPtr iid);
+
+ [notxpcom] nsresult getIIDForParamNoAlloc(in PRUint16 methodIndex,
+ [const] in nsXPTParamInfoPtr param,
+ out nsIID iid);
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIInterfaceInfoManager.idl b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIInterfaceInfoManager.idl
new file mode 100644
index 00000000..48277691
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIInterfaceInfoManager.idl
@@ -0,0 +1,85 @@
+/* -*- 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) 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 ***** */
+
+/* The nsIInterfaceInfoManager public declaration. */
+
+
+#include "nsISupports.idl"
+#include "nsIInterfaceInfo.idl"
+#include "nsIEnumerator.idl"
+#include "nsISimpleEnumerator.idl"
+
+/* this is NOT intended to be scriptable */
+[uuid(8B161900-BE2B-11d2-9831-006008962422)]
+interface nsIInterfaceInfoManager : nsISupports
+{
+ nsIInterfaceInfo getInfoForIID(in nsIIDPtr iid);
+ nsIInterfaceInfo getInfoForName(in string name);
+
+ nsIIDPtr getIIDForName(in string name);
+ string getNameForIID(in nsIIDPtr iid);
+
+ nsIEnumerator enumerateInterfaces();
+
+ void autoRegisterInterfaces();
+
+ nsIEnumerator enumerateInterfacesWhoseNamesStartWith(in string prefix);
+};
+
+[uuid(0ee22850-bc6a-11d5-9134-0010a4e73d9a)]
+interface nsIInterfaceInfoSuperManager : nsIInterfaceInfoManager
+{
+ void addAdditionalManager(in nsIInterfaceInfoManager manager);
+ void removeAdditionalManager(in nsIInterfaceInfoManager manager);
+
+ PRBool hasAdditionalManagers();
+ nsISimpleEnumerator enumerateAdditionalManagers();
+};
+
+%{C++
+#define NS_INTERFACEINFOMANAGER_SERVICE_CLASSNAME \
+ "Interface Information Manager Service"
+
+#define NS_INTERFACEINFOMANAGER_SERVICE_CID \
+ { /* 13bef784-f8e0-4f96-85c1-09f9ef4f9a19 */ \
+ 0x13bef784, 0xf8e0, 0x4f96, \
+ {0x85, 0xc1, 0x09, 0xf9, 0xef, 0x4f, 0x9a, 0x19} }
+
+#define NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID \
+ "@mozilla.org/xpti/interfaceinfomanager-service;1"
+%}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIXPTLoader.idl b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIXPTLoader.idl
new file mode 100644
index 00000000..8918daa3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/nsIXPTLoader.idl
@@ -0,0 +1,100 @@
+/* -*- 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 the external XPT loader 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):
+ * John Bandhauer <jband@netscape.com>
+ * 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 "nsISupports.idl"
+#include "nsILocalFile.idl"
+#include "nsIInputStream.idl"
+
+/**
+ * Implement nsIXPTLoaderSink if you want to enumerate the entries in
+ * an XPT archive of some kind
+ */
+[scriptable, uuid(6E48C500-8682-4730-ADD6-7DB693B9E7BA)]
+interface nsIXPTLoaderSink : nsISupports {
+
+ /**
+ * called by the loader for each entry in the archive
+ * @param itemName the name of this particular item in the archive
+ * @param index the index of the item inthe archive
+ * @param stream contains the contents of the xpt file
+ */
+ void foundEntry(in string itemName,
+ in long index,
+ in nsIInputStream xptData);
+};
+
+/**
+ * The XPT loader interface: implemented by a loader to grab an input
+ * stream which will be consumed by the interface loader.
+ */
+[scriptable, uuid(368A15D9-17A9-4c2b-AC3D-A35B3A22B876)]
+interface nsIXPTLoader : nsISupports {
+ /**
+ * enumerate entries in the given archive
+ * for each entry found, the loader will call the sink's
+ * foundEntry() method with the appropriate information and a
+ * stream that the consumer can read from
+ * @param file the file to read from
+ * @param sink an object which will be called with each file found
+ * in the file
+ */
+ void enumerateEntries(in nsILocalFile file,
+ in nsIXPTLoaderSink sink );
+
+ /**
+ * Load a specific entry from the archive
+ * @param file the file to read from
+ * @param name the name of the xpt within the file
+ * @return an input stream that will read the raw xpt data from
+ * the file
+ */
+ nsIInputStream loadEntry(in nsILocalFile file,
+ in string name);
+};
+
+
+%{C++
+
+// the first part of the contractID for any loader
+// append the type of loader that you need, such as "zip"
+#define NS_XPTLOADER_CONTRACTID_PREFIX \
+ "@mozilla.org/xptinfo/loader;1&type="
+
+%}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/xptinfo.h b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/xptinfo.h
new file mode 100644
index 00000000..076482a6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/public/xptinfo.h
@@ -0,0 +1,281 @@
+/* -*- 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) 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 ***** */
+
+/* XPTI_PUBLIC_API and XPTI_GetInterfaceInfoManager declarations. */
+
+#ifndef xptiinfo_h___
+#define xptiinfo_h___
+
+#include "prtypes.h"
+#include "xpt_struct.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define XPTI_GetInterfaceInfoManager VBoxNsxpXPTI_GetInterfaceInfoManager
+#define XPTI_FreeInterfaceInfoManager VBoxNsxpXPTI_FreeInterfaceInfoManager
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+/*
+ * The linkage of XPTI API functions differs depending on whether the file is
+ * used within the XPTI library or not. Any source file within the XPTI
+ * library should define EXPORT_XPTI_API whereas any client of the library
+ * should not.
+ */
+#ifdef EXPORT_XPTI_API
+#define XPTI_PUBLIC_API(t) PR_IMPLEMENT(t)
+#define XPTI_PUBLIC_DATA(t) PR_IMPLEMENT_DATA(t)
+#if defined(_WIN32)
+# define XPTI_EXPORT __declspec(dllexport)
+#elif defined(XP_OS2) && defined(__declspec)
+# define XPTI_EXPORT __declspec(dllexport)
+#elif defined(XP_OS2_VACPP)
+# define XPTI_EXPORT extern
+#else
+# define XPTI_EXPORT
+#endif
+#else
+#if defined(_WIN32)
+# define XPTI_PUBLIC_API(t) __declspec(dllimport) t
+# define XPTI_PUBLIC_DATA(t) __declspec(dllimport) t
+# define XPTI_EXPORT __declspec(dllimport)
+#elif defined(XP_OS2) && defined(__declspec)
+# define XPTI_PUBLIC_API(t) __declspec(dllimport) t
+# define XPTI_PUBLIC_DATA(t) __declspec(dllimport) t
+# define XPTI_EXPORT __declspec(dllimport)
+#elif defined(XP_OS2_VACPP)
+# define XPTI_PUBLIC_API(t) extern t
+# define XPTI_PUBLIC_DATA(t) extern t
+# define XPTI_EXPORT extern
+#else
+# define XPTI_PUBLIC_API(t) PR_IMPLEMENT(t)
+# define XPTI_PUBLIC_DATA(t) t
+# define XPTI_EXPORT
+#endif
+#endif
+#define XPTI_FRIEND_API(t) XPTI_PUBLIC_API(t)
+#define XPTI_FRIEND_DATA(t) XPTI_PUBLIC_DATA(t)
+
+class nsIInterfaceInfoManager;
+PR_BEGIN_EXTERN_C
+// Even if this is a service, it is cool to provide a direct accessor
+XPTI_PUBLIC_API(nsIInterfaceInfoManager*)
+XPTI_GetInterfaceInfoManager();
+
+// Even if this is a service, it is cool to provide a direct accessor
+XPTI_PUBLIC_API(void)
+XPTI_FreeInterfaceInfoManager();
+PR_END_EXTERN_C
+
+
+
+// Flyweight wrapper classes for xpt_struct.h structs.
+// Everything here is dependent upon - and sensitive to changes in -
+// xpcom/typelib/xpt/public/xpt_struct.h!
+
+class nsXPTType : public XPTTypeDescriptorPrefix
+{
+// NO DATA - this a flyweight wrapper
+public:
+ nsXPTType()
+ {} // random contents
+ nsXPTType(const XPTTypeDescriptorPrefix& prefix)
+ {*(XPTTypeDescriptorPrefix*)this = prefix;}
+
+ nsXPTType(const uint8& prefix)
+ {*(uint8*)this = prefix;}
+
+ nsXPTType& operator=(uint8 val)
+ {flags = val; return *this;}
+
+ nsXPTType& operator=(const nsXPTType& other)
+ {flags = other.flags; return *this;}
+
+ operator uint8() const
+ {return flags;}
+
+ PRBool IsPointer() const
+ {return 0 != (XPT_TDP_IS_POINTER(flags));}
+
+ PRBool IsUniquePointer() const
+ {return 0 != (XPT_TDP_IS_UNIQUE_POINTER(flags));}
+
+ PRBool IsReference() const
+ {return 0 != (XPT_TDP_IS_REFERENCE(flags));}
+
+ PRBool IsArithmetic() const // terminology from Harbison/Steele
+ {return flags <= T_WCHAR;}
+
+ PRBool IsInterfacePointer() const
+ { switch (TagPart()) {
+ default:
+ return PR_FALSE;
+ case T_INTERFACE:
+ case T_INTERFACE_IS:
+ return PR_TRUE;
+ }
+ }
+
+ PRBool IsArray() const
+ {return (PRBool) TagPart() == T_ARRAY;}
+
+ // 'Dependent' means that params of this type are dependent upon other
+ // params. e.g. an T_INTERFACE_IS is dependent upon some other param at
+ // runtime to say what the interface type of this param really is.
+ PRBool IsDependent() const
+ { switch (TagPart()) {
+ default:
+ return PR_FALSE;
+ case T_INTERFACE_IS:
+ case TD_ARRAY:
+ case T_PSTRING_SIZE_IS:
+ case T_PWSTRING_SIZE_IS:
+ return PR_TRUE;
+ }
+ }
+
+ uint8 TagPart() const
+ {return (uint8) (flags & XPT_TDP_TAGMASK);}
+
+ enum
+ {
+ T_I8 = TD_INT8 ,
+ T_I16 = TD_INT16 ,
+ T_I32 = TD_INT32 ,
+ T_I64 = TD_INT64 ,
+ T_U8 = TD_UINT8 ,
+ T_U16 = TD_UINT16 ,
+ T_U32 = TD_UINT32 ,
+ T_U64 = TD_UINT64 ,
+ T_FLOAT = TD_FLOAT ,
+ T_DOUBLE = TD_DOUBLE ,
+ T_BOOL = TD_BOOL ,
+ T_CHAR = TD_CHAR ,
+ T_WCHAR = TD_WCHAR ,
+ T_VOID = TD_VOID ,
+ T_IID = TD_PNSIID ,
+ T_DOMSTRING = TD_DOMSTRING ,
+ T_CHAR_STR = TD_PSTRING ,
+ T_WCHAR_STR = TD_PWSTRING ,
+ T_INTERFACE = TD_INTERFACE_TYPE ,
+ T_INTERFACE_IS = TD_INTERFACE_IS_TYPE,
+ T_ARRAY = TD_ARRAY ,
+ T_PSTRING_SIZE_IS = TD_PSTRING_SIZE_IS ,
+ T_PWSTRING_SIZE_IS = TD_PWSTRING_SIZE_IS ,
+ T_UTF8STRING = TD_UTF8STRING ,
+ T_CSTRING = TD_CSTRING ,
+ T_ASTRING = TD_ASTRING
+ };
+// NO DATA - this a flyweight wrapper
+};
+
+class nsXPTParamInfo : public XPTParamDescriptor
+{
+// NO DATA - this a flyweight wrapper
+public:
+ nsXPTParamInfo(const XPTParamDescriptor& desc)
+ {*(XPTParamDescriptor*)this = desc;}
+
+
+ PRBool IsIn() const {return 0 != (XPT_PD_IS_IN(flags));}
+ PRBool IsOut() const {return 0 != (XPT_PD_IS_OUT(flags));}
+ PRBool IsRetval() const {return 0 != (XPT_PD_IS_RETVAL(flags));}
+ PRBool IsShared() const {return 0 != (XPT_PD_IS_SHARED(flags));}
+ PRBool IsDipper() const {return 0 != (XPT_PD_IS_DIPPER(flags));}
+ const nsXPTType GetType() const {return type.prefix;}
+
+ // NOTE: other activities on types are done via methods on nsIInterfaceInfo
+
+private:
+ nsXPTParamInfo(); // no implementation
+// NO DATA - this a flyweight wrapper
+};
+
+class nsXPTMethodInfo : public XPTMethodDescriptor
+{
+// NO DATA - this a flyweight wrapper
+public:
+ nsXPTMethodInfo(const XPTMethodDescriptor& desc)
+ {*(XPTMethodDescriptor*)this = desc;}
+
+ PRBool IsGetter() const {return 0 != (XPT_MD_IS_GETTER(flags) );}
+ PRBool IsSetter() const {return 0 != (XPT_MD_IS_SETTER(flags) );}
+ PRBool IsNotXPCOM() const {return 0 != (XPT_MD_IS_NOTXPCOM(flags));}
+ PRBool IsConstructor() const {return 0 != (XPT_MD_IS_CTOR(flags) );}
+ PRBool IsHidden() const {return 0 != (XPT_MD_IS_HIDDEN(flags) );}
+ const char* GetName() const {return name;}
+ uint8 GetParamCount() const {return num_args;}
+ /* idx was index before I got _sick_ of the warnings on Unix, sorry jband */
+ const nsXPTParamInfo GetParam(uint8 idx) const
+ {
+ NS_PRECONDITION(idx < GetParamCount(),"bad arg");
+ return params[idx];
+ }
+ const nsXPTParamInfo GetResult() const
+ {return *result;}
+private:
+ nsXPTMethodInfo(); // no implementation
+// NO DATA - this a flyweight wrapper
+};
+
+
+// forward declaration
+struct nsXPTCMiniVariant;
+
+class nsXPTConstant : public XPTConstDescriptor
+{
+// NO DATA - this a flyweight wrapper
+public:
+ nsXPTConstant(const XPTConstDescriptor& desc)
+ {*(XPTConstDescriptor*)this = desc;}
+
+ const char* GetName() const
+ {return name;}
+
+ const nsXPTType GetType() const
+ {return type.prefix;}
+
+ // XXX this is ugly. But sometimes you gotta do what you gotta do.
+ // A reinterpret_cast won't do the trick here. And this plain C cast
+ // works correctly and is safe enough.
+ // See http://bugzilla.mozilla.org/show_bug.cgi?id=49641
+ const nsXPTCMiniVariant* GetValue() const
+ {return (nsXPTCMiniVariant*) &value;}
+private:
+ nsXPTConstant(); // no implementation
+// NO DATA - this a flyweight wrapper
+};
+
+#endif /* xptiinfo_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/Makefile.in
new file mode 100644
index 00000000..de5fd9b1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/Makefile.in
@@ -0,0 +1,75 @@
+#
+# ***** 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
+LIBRARY_NAME = xptinfo
+REQUIRES = \
+ string \
+ $(NULL)
+
+CPPSRCS = \
+ xptiFile.cpp \
+ xptiInterfaceInfo.cpp \
+ xptiInterfaceInfoManager.cpp \
+ xptiManifest.cpp \
+ xptiMisc.cpp \
+ xptiTypelibGuts.cpp \
+ xptiWorkingSet.cpp \
+ xptiZipItem.cpp \
+ xptiZipLoader.cpp \
+ $(NULL)
+
+# 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
+
+# For nsManifestLineReader class.
+LOCAL_INCLUDES = -I$(srcdir)/../../../ds
+
+DEFINES += -DEXPORT_XPTI_API -DEXPORT_XPT_API -D_IMPL_NS_COM -D_IMPL_NS_BASE
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/TODO b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/TODO
new file mode 100644
index 00000000..c5bb1c64
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/TODO
@@ -0,0 +1,20 @@
+/* jband - 03/24/00 - */
+
+- DOCS
+- improve error handling
+ - should some errors really be warnings?
+ - should autoreg support additional channel to recieve warnings so that
+ an installer can decide whether or not to accept the consequences of
+ leaving the newly installed files in place?
+- verification of interfaces (warnings and/or errors)
+ - verify that repeated interfaces are identical in all ways
+ - verify that interface names are always one-to-one with iids
+- check for truncated xpt files and version problems
+ - http://bugzilla.mozilla.org/show_bug.cgi?id=33193
+- TESTS!
+ - e.g. verify the merge stuff really works for various inputs.
+ - we really need a set of .xpt and .zip files and code that does an array
+ of autoreg and interfaceinof use activitities to test various corners
+ of the system.
+- better autoreg logging
+- use only 32 bits for file size?
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiFile.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiFile.cpp
new file mode 100644
index 00000000..50362c75
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiFile.cpp
@@ -0,0 +1,113 @@
+/* -*- 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) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * 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 ***** */
+
+/* Implementation of xptiFile. */
+
+#include "xptiprivate.h"
+
+MOZ_DECL_CTOR_COUNTER(xptiFile)
+
+xptiFile::xptiFile()
+ :
+#ifdef DEBUG
+ mDEBUG_WorkingSet(nsnull),
+#endif
+ mSize(),
+ mDate(),
+ mName(nsnull),
+ mGuts(nsnull),
+ mDirectory(0)
+{
+ // empty
+ MOZ_COUNT_CTOR(xptiFile);
+}
+
+xptiFile::xptiFile(const nsInt64& aSize,
+ const nsInt64& aDate,
+ PRUint32 aDirectory,
+ const char* aName,
+ xptiWorkingSet* aWorkingSet)
+ :
+#ifdef DEBUG
+ mDEBUG_WorkingSet(aWorkingSet),
+#endif
+ mSize(aSize),
+ mDate(aDate),
+ mName(aName),
+ mGuts(nsnull),
+ mDirectory(aDirectory)
+{
+ NS_ASSERTION(aWorkingSet,"bad param");
+ mName = XPT_STRDUP(aWorkingSet->GetStringArena(), aName);
+
+ MOZ_COUNT_CTOR(xptiFile);
+}
+
+xptiFile::xptiFile(const xptiFile& r, xptiWorkingSet* aWorkingSet)
+ :
+#ifdef DEBUG
+ mDEBUG_WorkingSet(aWorkingSet),
+#endif
+ mSize(r.mSize),
+ mDate(r.mDate),
+ mName(nsnull),
+ mGuts(nsnull),
+ mDirectory(r.mDirectory)
+{
+ NS_ASSERTION(aWorkingSet,"bad param");
+ mName = XPT_STRDUP(aWorkingSet->GetStringArena(), r.mName);
+
+ MOZ_COUNT_CTOR(xptiFile);
+}
+
+xptiFile::~xptiFile()
+{
+ MOZ_COUNT_DTOR(xptiFile);
+}
+
+PRBool
+xptiFile::SetHeader(XPTHeader* aHeader, xptiWorkingSet* aWorkingSet)
+{
+ NS_ASSERTION(!mGuts,"bad state");
+ NS_ASSERTION(aHeader,"bad param");
+ NS_ASSERTION(aWorkingSet,"bad param");
+
+ mGuts = xptiTypelibGuts::NewGuts(aHeader, aWorkingSet);
+ return mGuts != nsnull;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiInterfaceInfo.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiInterfaceInfo.cpp
new file mode 100644
index 00000000..69bf86df
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiInterfaceInfo.cpp
@@ -0,0 +1,819 @@
+/* -*- 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) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * 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 ***** */
+
+/* Implementation of xptiInterfaceEntry and xptiInterfaceInfo. */
+
+#include "xptiprivate.h"
+
+/***************************************************************************/
+// Debug Instrumentation...
+
+#ifdef SHOW_INFO_COUNT_STATS
+static int DEBUG_TotalInfos = 0;
+static int DEBUG_CurrentInfos = 0;
+static int DEBUG_MaxInfos = 0;
+static int DEBUG_MonitorEntryCount = 0;
+
+#define LOG_INFO_CREATE(t) \
+ DEBUG_TotalInfos++; \
+ DEBUG_CurrentInfos++; \
+ if(DEBUG_MaxInfos < DEBUG_CurrentInfos) \
+ DEBUG_MaxInfos = DEBUG_CurrentInfos /* no ';' */
+
+#define LOG_INFO_DESTROY(t) \
+ DEBUG_CurrentInfos-- /* no ';' */
+
+#define LOG_INFO_MONITOR_ENTRY \
+ DEBUG_MonitorEntryCount++ /* no ';' */
+
+#else /* SHOW_INFO_COUNT_STATS */
+
+#define LOG_INFO_CREATE(t) ((void)0)
+#define LOG_INFO_DESTROY(t) ((void)0)
+#define LOG_INFO_MONITOR_ENTRY ((void)0)
+#endif /* SHOW_INFO_COUNT_STATS */
+
+#ifdef DEBUG
+// static
+void xptiInterfaceInfo::DEBUG_ShutdownNotification()
+{
+#ifdef SHOW_INFO_COUNT_STATS
+ printf("iiii %d total xptiInterfaceInfos created\n", DEBUG_TotalInfos);
+ printf("iiii %d max xptiInterfaceInfos alive at one time\n", DEBUG_MaxInfos);
+ printf("iiii %d xptiInterfaceInfos still alive\n", DEBUG_CurrentInfos);
+ printf("iiii %d times locked\n", DEBUG_MonitorEntryCount);
+#endif
+}
+#endif /* DEBUG */
+
+/***************************************************************************/
+
+// static
+xptiInterfaceEntry*
+xptiInterfaceEntry::NewEntry(const char* name,
+ int nameLength,
+ const nsID& iid,
+ const xptiTypelib& typelib,
+ xptiWorkingSet* aWorkingSet)
+{
+ void* place = XPT_MALLOC(aWorkingSet->GetStructArena(),
+ sizeof(xptiInterfaceEntry) + nameLength);
+ if(!place)
+ return nsnull;
+ return new(place) xptiInterfaceEntry(name, nameLength, iid, typelib);
+}
+
+// static
+xptiInterfaceEntry*
+xptiInterfaceEntry::NewEntry(const xptiInterfaceEntry& r,
+ const xptiTypelib& typelib,
+ xptiWorkingSet* aWorkingSet)
+{
+ size_t nameLength = PL_strlen(r.mName);
+ void* place = XPT_MALLOC(aWorkingSet->GetStructArena(),
+ sizeof(xptiInterfaceEntry) + nameLength);
+ if(!place)
+ return nsnull;
+ return new(place) xptiInterfaceEntry(r, nameLength, typelib);
+}
+
+
+xptiInterfaceEntry::xptiInterfaceEntry(const char* name,
+ size_t nameLength,
+ const nsID& iid,
+ const xptiTypelib& typelib)
+ : mIID(iid),
+ mTypelib(typelib),
+ mInfo(nsnull),
+ mFlags(uint8(0))
+{
+ memcpy(mName, name, nameLength);
+}
+
+xptiInterfaceEntry::xptiInterfaceEntry(const xptiInterfaceEntry& r,
+ size_t nameLength,
+ const xptiTypelib& typelib)
+ : mIID(r.mIID),
+ mTypelib(typelib),
+ mInfo(nsnull),
+ mFlags(r.mFlags)
+{
+ SetResolvedState(NOT_RESOLVED);
+ memcpy(mName, r.mName, nameLength);
+}
+
+PRBool
+xptiInterfaceEntry::Resolve(xptiWorkingSet* aWorkingSet /* = nsnull */)
+{
+ nsAutoLock lock(xptiInterfaceInfoManager::GetResolveLock());
+ return ResolveLocked(aWorkingSet);
+}
+
+PRBool
+xptiInterfaceEntry::ResolveLocked(xptiWorkingSet* aWorkingSet /* = nsnull */)
+{
+ int resolvedState = GetResolveState();
+
+ if(resolvedState == FULLY_RESOLVED)
+ return PR_TRUE;
+ if(resolvedState == RESOLVE_FAILED)
+ return PR_FALSE;
+
+ xptiInterfaceInfoManager* mgr =
+ xptiInterfaceInfoManager::GetInterfaceInfoManagerNoAddRef();
+
+ if(!mgr)
+ return PR_FALSE;
+
+ if(!aWorkingSet)
+ {
+ aWorkingSet = mgr->GetWorkingSet();
+ }
+
+ if(resolvedState == NOT_RESOLVED)
+ {
+ LOG_RESOLVE(("! begin resolve of %s\n", mName));
+ // Make a copy of mTypelib because the underlying memory will change!
+ xptiTypelib typelib = mTypelib;
+
+ // We expect our PartiallyResolveLocked() to get called before
+ // this returns.
+ if(!mgr->LoadFile(typelib, aWorkingSet))
+ {
+ SetResolvedState(RESOLVE_FAILED);
+ return PR_FALSE;
+ }
+ // The state was changed by LoadFile to PARTIALLY_RESOLVED, so this
+ // ...falls through...
+ }
+
+ NS_ASSERTION(GetResolveState() == PARTIALLY_RESOLVED, "bad state!");
+
+ // Finish out resolution by finding parent and Resolving it so
+ // we can set the info we get from it.
+
+ PRUint16 parent_index = mInterface->mDescriptor->parent_interface;
+
+ if(parent_index)
+ {
+ xptiInterfaceEntry* parent =
+ aWorkingSet->GetTypelibGuts(mInterface->mTypelib)->
+ GetEntryAt(parent_index - 1);
+
+ if(!parent || !parent->EnsureResolvedLocked())
+ {
+ xptiTypelib aTypelib = mInterface->mTypelib;
+ mInterface = nsnull;
+ mTypelib = aTypelib;
+ SetResolvedState(RESOLVE_FAILED);
+ return PR_FALSE;
+ }
+
+ mInterface->mParent = parent;
+
+ mInterface->mMethodBaseIndex =
+ parent->mInterface->mMethodBaseIndex +
+ parent->mInterface->mDescriptor->num_methods;
+
+ mInterface->mConstantBaseIndex =
+ parent->mInterface->mConstantBaseIndex +
+ parent->mInterface->mDescriptor->num_constants;
+
+ }
+ LOG_RESOLVE(("+ complete resolve of %s\n", mName));
+
+ SetResolvedState(FULLY_RESOLVED);
+ return PR_TRUE;
+}
+
+// This *only* gets called by xptiInterfaceInfoManager::LoadFile (while locked).
+PRBool
+xptiInterfaceEntry::PartiallyResolveLocked(XPTInterfaceDescriptor* aDescriptor,
+ xptiWorkingSet* aWorkingSet)
+{
+ NS_ASSERTION(GetResolveState() == NOT_RESOLVED, "bad state");
+
+ LOG_RESOLVE(("~ partial resolve of %s\n", mName));
+
+ xptiInterfaceGuts* iface =
+ xptiInterfaceGuts::NewGuts(aDescriptor, mTypelib, aWorkingSet);
+
+ if(!iface)
+ return PR_FALSE;
+
+ mInterface = iface;
+
+#ifdef DEBUG
+ if(!DEBUG_ScriptableFlagIsValid())
+ {
+ NS_ERROR("unexpected scriptable flag!");
+ SetScriptableFlag(XPT_ID_IS_SCRIPTABLE(mInterface->mDescriptor->flags));
+ }
+#endif
+
+ SetResolvedState(PARTIALLY_RESOLVED);
+ return PR_TRUE;
+}
+
+/**************************************************/
+// These non-virtual methods handle the delegated nsIInterfaceInfo methods.
+
+nsresult
+xptiInterfaceEntry::GetName(char **name)
+{
+ // It is not necessary to Resolve because this info is read from manifest.
+ *name = (char*) nsMemory::Clone(mName, PL_strlen(mName)+1);
+ return *name ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+nsresult
+xptiInterfaceEntry::GetIID(nsIID **iid)
+{
+ // It is not necessary to Resolve because this info is read from manifest.
+ *iid = (nsIID*) nsMemory::Clone(&mIID, sizeof(nsIID));
+ return *iid ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+nsresult
+xptiInterfaceEntry::IsScriptable(PRBool* result)
+{
+ // It is not necessary to Resolve because this info is read from manifest.
+ NS_ASSERTION(DEBUG_ScriptableFlagIsValid(), "scriptable flag out of sync!");
+ *result = GetScriptableFlag();
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::IsFunction(PRBool* result)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ *result = XPT_ID_IS_FUNCTION(GetInterfaceGuts()->mDescriptor->flags);
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetMethodCount(uint16* count)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ *count = mInterface->mMethodBaseIndex +
+ mInterface->mDescriptor->num_methods;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetConstantCount(uint16* count)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ *count = mInterface->mConstantBaseIndex +
+ mInterface->mDescriptor->num_constants;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetMethodInfo(uint16 index, const nsXPTMethodInfo** info)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(index < mInterface->mMethodBaseIndex)
+ return mInterface->mParent->GetMethodInfo(index, info);
+
+ if(index >= mInterface->mMethodBaseIndex +
+ mInterface->mDescriptor->num_methods)
+ {
+ NS_ERROR("bad param");
+ *info = NULL;
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ // else...
+ *info = NS_REINTERPRET_CAST(nsXPTMethodInfo*,
+ &mInterface->mDescriptor->
+ method_descriptors[index -
+ mInterface->mMethodBaseIndex]);
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetMethodInfoForName(const char* methodName, uint16 *index,
+ const nsXPTMethodInfo** result)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ // This is a slow algorithm, but this is not expected to be called much.
+ for(uint16 i = 0; i < mInterface->mDescriptor->num_methods; ++i)
+ {
+ const nsXPTMethodInfo* info;
+ info = NS_REINTERPRET_CAST(nsXPTMethodInfo*,
+ &mInterface->mDescriptor->
+ method_descriptors[i]);
+ if (PL_strcmp(methodName, info->GetName()) == 0) {
+ *index = i + mInterface->mMethodBaseIndex;
+ *result = info;
+ return NS_OK;
+ }
+ }
+
+ if(mInterface->mParent)
+ return mInterface->mParent->GetMethodInfoForName(methodName, index, result);
+ else
+ {
+ *index = 0;
+ *result = 0;
+ return NS_ERROR_INVALID_ARG;
+ }
+}
+
+nsresult
+xptiInterfaceEntry::GetConstant(uint16 index, const nsXPTConstant** constant)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(index < mInterface->mConstantBaseIndex)
+ return mInterface->mParent->GetConstant(index, constant);
+
+ if(index >= mInterface->mConstantBaseIndex +
+ mInterface->mDescriptor->num_constants)
+ {
+ NS_PRECONDITION(0, "bad param");
+ *constant = NULL;
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ // else...
+ *constant =
+ NS_REINTERPRET_CAST(nsXPTConstant*,
+ &mInterface->mDescriptor->
+ const_descriptors[index -
+ mInterface->mConstantBaseIndex]);
+ return NS_OK;
+}
+
+// this is a private helper
+
+nsresult
+xptiInterfaceEntry::GetEntryForParam(PRUint16 methodIndex,
+ const nsXPTParamInfo * param,
+ xptiInterfaceEntry** entry)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(methodIndex < mInterface->mMethodBaseIndex)
+ return mInterface->mParent->GetEntryForParam(methodIndex, param, entry);
+
+ if(methodIndex >= mInterface->mMethodBaseIndex +
+ mInterface->mDescriptor->num_methods)
+ {
+ NS_ERROR("bad param");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ const XPTTypeDescriptor *td = &param->type;
+
+ while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) {
+ td = &mInterface->mDescriptor->additional_types[td->type.additional_type];
+ }
+
+ if(XPT_TDP_TAG(td->prefix) != TD_INTERFACE_TYPE) {
+ NS_ERROR("not an interface");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ xptiInterfaceEntry* theEntry =
+ mInterface->mWorkingSet->GetTypelibGuts(mInterface->mTypelib)->
+ GetEntryAt(td->type.iface - 1);
+
+ // This can happen if a declared interface is not available at runtime.
+ if(!theEntry)
+ {
+ NS_WARNING("Declared InterfaceInfo not found");
+ *entry = nsnull;
+ return NS_ERROR_FAILURE;
+ }
+
+ *entry = theEntry;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetInfoForParam(uint16 methodIndex,
+ const nsXPTParamInfo *param,
+ nsIInterfaceInfo** info)
+{
+ xptiInterfaceEntry* entry;
+ nsresult rv = GetEntryForParam(methodIndex, param, &entry);
+ if(NS_FAILED(rv))
+ return rv;
+
+ xptiInterfaceInfo* theInfo;
+ rv = entry->GetInterfaceInfo(&theInfo);
+ if(NS_FAILED(rv))
+ return rv;
+
+ *info = NS_STATIC_CAST(nsIInterfaceInfo*, theInfo);
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetIIDForParam(uint16 methodIndex,
+ const nsXPTParamInfo* param, nsIID** iid)
+{
+ xptiInterfaceEntry* entry;
+ nsresult rv = GetEntryForParam(methodIndex, param, &entry);
+ if(NS_FAILED(rv))
+ return rv;
+ return entry->GetIID(iid);
+}
+
+nsresult
+xptiInterfaceEntry::GetIIDForParamNoAlloc(PRUint16 methodIndex,
+ const nsXPTParamInfo * param,
+ nsIID *iid)
+{
+ xptiInterfaceEntry* entry;
+ nsresult rv = GetEntryForParam(methodIndex, param, &entry);
+ if(NS_FAILED(rv))
+ return rv;
+ *iid = entry->mIID;
+ return NS_OK;
+}
+
+// this is a private helper
+nsresult
+xptiInterfaceEntry::GetTypeInArray(const nsXPTParamInfo* param,
+ uint16 dimension,
+ const XPTTypeDescriptor** type)
+{
+ NS_ASSERTION(IsFullyResolved(), "bad state");
+
+ const XPTTypeDescriptor *td = &param->type;
+ const XPTTypeDescriptor *additional_types =
+ mInterface->mDescriptor->additional_types;
+
+ for (uint16 i = 0; i < dimension; i++) {
+ if(XPT_TDP_TAG(td->prefix) != TD_ARRAY) {
+ NS_ERROR("bad dimension");
+ return NS_ERROR_INVALID_ARG;
+ }
+ td = &additional_types[td->type.additional_type];
+ }
+
+ *type = td;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetTypeForParam(uint16 methodIndex,
+ const nsXPTParamInfo* param,
+ uint16 dimension,
+ nsXPTType* type)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(methodIndex < mInterface->mMethodBaseIndex)
+ return mInterface->mParent->
+ GetTypeForParam(methodIndex, param, dimension, type);
+
+ if(methodIndex >= mInterface->mMethodBaseIndex +
+ mInterface->mDescriptor->num_methods)
+ {
+ NS_ERROR("bad index");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ const XPTTypeDescriptor *td;
+
+ if(dimension) {
+ nsresult rv = GetTypeInArray(param, dimension, &td);
+ if(NS_FAILED(rv))
+ return rv;
+ }
+ else
+ td = &param->type;
+
+ *type = nsXPTType(td->prefix);
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetSizeIsArgNumberForParam(uint16 methodIndex,
+ const nsXPTParamInfo* param,
+ uint16 dimension,
+ uint8* argnum)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(methodIndex < mInterface->mMethodBaseIndex)
+ return mInterface->mParent->
+ GetSizeIsArgNumberForParam(methodIndex, param, dimension, argnum);
+
+ if(methodIndex >= mInterface->mMethodBaseIndex +
+ mInterface->mDescriptor->num_methods)
+ {
+ NS_ERROR("bad index");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ const XPTTypeDescriptor *td;
+
+ if(dimension) {
+ nsresult rv = GetTypeInArray(param, dimension, &td);
+ if(NS_FAILED(rv))
+ return rv;
+ }
+ else
+ td = &param->type;
+
+ // verify that this is a type that has size_is
+ switch (XPT_TDP_TAG(td->prefix)) {
+ case TD_ARRAY:
+ case TD_PSTRING_SIZE_IS:
+ case TD_PWSTRING_SIZE_IS:
+ break;
+ default:
+ NS_ERROR("not a size_is");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ *argnum = td->argnum;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetLengthIsArgNumberForParam(uint16 methodIndex,
+ const nsXPTParamInfo* param,
+ uint16 dimension,
+ uint8* argnum)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(methodIndex < mInterface->mMethodBaseIndex)
+ return mInterface->mParent->
+ GetLengthIsArgNumberForParam(methodIndex, param, dimension, argnum);
+
+ if(methodIndex >= mInterface->mMethodBaseIndex +
+ mInterface->mDescriptor->num_methods)
+ {
+ NS_ERROR("bad index");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ const XPTTypeDescriptor *td;
+
+ if(dimension) {
+ nsresult rv = GetTypeInArray(param, dimension, &td);
+ if(NS_FAILED(rv)) {
+ return rv;
+ }
+ }
+ else
+ td = &param->type;
+
+ // verify that this is a type that has length_is
+ switch (XPT_TDP_TAG(td->prefix)) {
+ case TD_ARRAY:
+ case TD_PSTRING_SIZE_IS:
+ case TD_PWSTRING_SIZE_IS:
+ break;
+ default:
+ NS_ERROR("not a length_is");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ *argnum = td->argnum2;
+ return NS_OK;
+}
+
+nsresult
+xptiInterfaceEntry::GetInterfaceIsArgNumberForParam(uint16 methodIndex,
+ const nsXPTParamInfo* param,
+ uint8* argnum)
+{
+ if(!EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+
+ if(methodIndex < mInterface->mMethodBaseIndex)
+ return mInterface->mParent->
+ GetInterfaceIsArgNumberForParam(methodIndex, param, argnum);
+
+ if(methodIndex >= mInterface->mMethodBaseIndex +
+ mInterface->mDescriptor->num_methods)
+ {
+ NS_ERROR("bad index");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ const XPTTypeDescriptor *td = &param->type;
+
+ while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) {
+ td = &mInterface->mDescriptor->
+ additional_types[td->type.additional_type];
+ }
+
+ if(XPT_TDP_TAG(td->prefix) != TD_INTERFACE_IS_TYPE) {
+ NS_ERROR("not an iid_is");
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ *argnum = td->argnum;
+ return NS_OK;
+}
+
+/* PRBool isIID (in nsIIDPtr IID); */
+nsresult
+xptiInterfaceEntry::IsIID(const nsIID * IID, PRBool *_retval)
+{
+ // It is not necessary to Resolve because this info is read from manifest.
+ *_retval = mIID.Equals(*IID);
+ return NS_OK;
+}
+
+/* void getNameShared ([shared, retval] out string name); */
+nsresult
+xptiInterfaceEntry::GetNameShared(const char **name)
+{
+ // It is not necessary to Resolve because this info is read from manifest.
+ *name = mName;
+ return NS_OK;
+}
+
+/* void getIIDShared ([shared, retval] out nsIIDPtrShared iid); */
+nsresult
+xptiInterfaceEntry::GetIIDShared(const nsIID * *iid)
+{
+ // It is not necessary to Resolve because this info is read from manifest.
+ *iid = &mIID;
+ return NS_OK;
+}
+
+/* PRBool hasAncestor (in nsIIDPtr iid); */
+nsresult
+xptiInterfaceEntry::HasAncestor(const nsIID * iid, PRBool *_retval)
+{
+ *_retval = PR_FALSE;
+
+ for(xptiInterfaceEntry* current = this;
+ current;
+ current = current->mInterface->mParent)
+ {
+ if(current->mIID.Equals(*iid))
+ {
+ *_retval = PR_TRUE;
+ break;
+ }
+ if(!current->EnsureResolved())
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ return NS_OK;
+}
+
+/***************************************************/
+
+nsresult
+xptiInterfaceEntry::GetInterfaceInfo(xptiInterfaceInfo** info)
+{
+ nsAutoMonitor lock(xptiInterfaceInfoManager::GetInfoMonitor());
+ LOG_INFO_MONITOR_ENTRY;
+
+#ifdef SHOW_INFO_COUNT_STATS
+ static int callCount = 0;
+ if(!(++callCount%100))
+ printf("iiii %d xptiInterfaceInfos currently alive\n", DEBUG_CurrentInfos);
+#endif
+
+ if(!mInfo)
+ {
+ mInfo = new xptiInterfaceInfo(this);
+ if(!mInfo)
+ {
+ *info = nsnull;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+
+ NS_ADDREF(*info = mInfo);
+ return NS_OK;
+}
+
+void
+xptiInterfaceEntry::LockedInvalidateInterfaceInfo()
+{
+ if(mInfo)
+ {
+ mInfo->Invalidate();
+ mInfo = nsnull;
+ }
+}
+
+/***************************************************************************/
+
+NS_IMPL_QUERY_INTERFACE1(xptiInterfaceInfo, nsIInterfaceInfo)
+
+xptiInterfaceInfo::xptiInterfaceInfo(xptiInterfaceEntry* entry)
+ : mEntry(entry), mParent(nsnull)
+{
+ LOG_INFO_CREATE(this);
+}
+
+xptiInterfaceInfo::~xptiInterfaceInfo()
+{
+ LOG_INFO_DESTROY(this);
+ NS_IF_RELEASE(mParent);
+ NS_ASSERTION(!mEntry, "bad state in dtor");
+}
+
+nsrefcnt
+xptiInterfaceInfo::AddRef(void)
+{
+ nsrefcnt cnt = (nsrefcnt) PR_AtomicIncrement((PRInt32*)&mRefCnt);
+ NS_LOG_ADDREF(this, cnt, "xptiInterfaceInfo", sizeof(*this));
+ return cnt;
+}
+
+nsrefcnt
+xptiInterfaceInfo::Release(void)
+{
+ xptiInterfaceEntry* entry = mEntry;
+ nsrefcnt cnt = (nsrefcnt) PR_AtomicDecrement((PRInt32*)&mRefCnt);
+ NS_LOG_RELEASE(this, cnt, "xptiInterfaceInfo");
+ if(!cnt)
+ {
+ nsAutoMonitor lock(xptiInterfaceInfoManager::GetInfoMonitor());
+ LOG_INFO_MONITOR_ENTRY;
+
+ // If GetInterfaceInfo added and *released* a reference before we
+ // acquired the monitor then 'this' might already be dead. In that
+ // case we would not want to try to access any instance data. We
+ // would want to bail immediately. If 'this' is already dead then the
+ // entry will no longer have a pointer to 'this'. So, we can protect
+ // ourselves from danger without more aggressive locking.
+ if(entry && !entry->InterfaceInfoEquals(this))
+ return 0;
+
+ // If GetInterfaceInfo added a reference before we acquired the monitor
+ // then we want to bail out of here without destorying the object.
+ if(mRefCnt)
+ return 1;
+
+ if(mEntry)
+ {
+ mEntry->LockedInterfaceInfoDeathNotification();
+ mEntry = nsnull;
+ }
+
+ NS_DELETEXPCOM(this);
+ return 0;
+ }
+ return cnt;
+}
+
+/***************************************************************************/
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp
new file mode 100644
index 00000000..5ae06914
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp
@@ -0,0 +1,2126 @@
+/* -*- 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) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * 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 ***** */
+
+/* Implementation of xptiInterfaceInfoManager. */
+
+#include "xptiprivate.h"
+#include "nsDependentString.h"
+#include "nsString.h"
+
+#define NS_ZIPLOADER_CONTRACTID NS_XPTLOADER_CONTRACTID_PREFIX "zip"
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(xptiInterfaceInfoManager,
+ nsIInterfaceInfoManager,
+ nsIInterfaceInfoSuperManager)
+
+static xptiInterfaceInfoManager* gInterfaceInfoManager = nsnull;
+#ifdef DEBUG
+static int gCallCount = 0;
+#endif
+
+// static
+xptiInterfaceInfoManager*
+xptiInterfaceInfoManager::GetInterfaceInfoManagerNoAddRef()
+{
+ if(!gInterfaceInfoManager)
+ {
+ nsCOMPtr<nsISupportsArray> searchPath;
+ BuildFileSearchPath(getter_AddRefs(searchPath));
+ if(!searchPath)
+ {
+ NS_ERROR("can't get xpt search path!");
+ return nsnull;
+ }
+
+ gInterfaceInfoManager = new xptiInterfaceInfoManager(searchPath);
+ if(gInterfaceInfoManager)
+ NS_ADDREF(gInterfaceInfoManager);
+ if(!gInterfaceInfoManager->IsValid())
+ {
+ NS_RELEASE(gInterfaceInfoManager);
+ }
+ else
+ {
+ PRBool mustAutoReg =
+ !xptiManifest::Read(gInterfaceInfoManager,
+ &gInterfaceInfoManager->mWorkingSet);
+#ifdef DEBUG
+ {
+ // This sets what will be returned by GetOpenLogFile().
+ xptiAutoLog autoLog(gInterfaceInfoManager,
+ gInterfaceInfoManager->mAutoRegLogFile, PR_TRUE);
+ LOG_AUTOREG(("debug build forced autoreg after %s load of manifest\n", mustAutoReg ? "FAILED" : "successful"));
+
+ mustAutoReg = PR_TRUE;
+ }
+#endif // DEBUG
+ if(mustAutoReg)
+ gInterfaceInfoManager->AutoRegisterInterfaces();
+ }
+ }
+ return gInterfaceInfoManager;
+}
+
+void
+xptiInterfaceInfoManager::FreeInterfaceInfoManager()
+{
+ if(gInterfaceInfoManager)
+ gInterfaceInfoManager->LogStats();
+
+ NS_IF_RELEASE(gInterfaceInfoManager);
+}
+
+PRBool
+xptiInterfaceInfoManager::IsValid()
+{
+ return mWorkingSet.IsValid() &&
+ mResolveLock &&
+ mAutoRegLock &&
+ mInfoMonitor &&
+ mAdditionalManagersLock;
+}
+
+xptiInterfaceInfoManager::xptiInterfaceInfoManager(nsISupportsArray* aSearchPath)
+ : mWorkingSet(aSearchPath),
+ mOpenLogFile(nsnull),
+ mResolveLock(PR_NewLock()),
+ mAutoRegLock(PR_NewLock()),
+ mInfoMonitor(nsAutoMonitor::NewMonitor("xptiInfoMonitor")),
+ mAdditionalManagersLock(PR_NewLock()),
+ mSearchPath(aSearchPath)
+{
+ const char* statsFilename = PR_GetEnv("MOZILLA_XPTI_STATS");
+ if(statsFilename)
+ {
+ mStatsLogFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
+ if(mStatsLogFile &&
+ NS_SUCCEEDED(mStatsLogFile->InitWithNativePath(nsDependentCString(statsFilename))))
+ {
+ printf("* Logging xptinfo stats to: %s\n", statsFilename);
+ }
+ else
+ {
+ printf("* Failed to create xptinfo stats file: %s\n", statsFilename);
+ mStatsLogFile = nsnull;
+ }
+ }
+
+ const char* autoRegFilename = PR_GetEnv("MOZILLA_XPTI_REGLOG");
+ if(autoRegFilename)
+ {
+ mAutoRegLogFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
+ if(mAutoRegLogFile &&
+ NS_SUCCEEDED(mAutoRegLogFile->InitWithNativePath(nsDependentCString(autoRegFilename))))
+ {
+ printf("* Logging xptinfo autoreg to: %s\n", autoRegFilename);
+ }
+ else
+ {
+ printf("* Failed to create xptinfo autoreg file: %s\n", autoRegFilename);
+ mAutoRegLogFile = nsnull;
+ }
+ }
+}
+
+xptiInterfaceInfoManager::~xptiInterfaceInfoManager()
+{
+ // We only do this on shutdown of the service.
+ mWorkingSet.InvalidateInterfaceInfos();
+
+ if(mResolveLock)
+ PR_DestroyLock(mResolveLock);
+ if(mAutoRegLock)
+ PR_DestroyLock(mAutoRegLock);
+ if(mInfoMonitor)
+ nsAutoMonitor::DestroyMonitor(mInfoMonitor);
+ if(mAdditionalManagersLock)
+ PR_DestroyLock(mAdditionalManagersLock);
+
+ gInterfaceInfoManager = nsnull;
+#ifdef DEBUG
+ xptiInterfaceInfo::DEBUG_ShutdownNotification();
+ gCallCount = 0;
+#endif
+}
+
+static nsresult
+GetDirectoryFromDirService(const char* codename, nsILocalFile** aDir)
+{
+ NS_ASSERTION(codename,"loser!");
+ NS_ASSERTION(aDir,"loser!");
+
+ nsresult rv;
+ nsCOMPtr<nsIProperties> dirService =
+ do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
+ if (NS_FAILED(rv)) return rv;
+
+ return dirService->Get(codename, NS_GET_IID(nsILocalFile), (void**) aDir);
+}
+
+static PRBool
+AppendFromDirServiceList(const char* codename, nsISupportsArray* aPath)
+{
+ NS_ASSERTION(codename,"loser!");
+ NS_ASSERTION(aPath,"loser!");
+
+ nsCOMPtr<nsIProperties> dirService =
+ do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
+ if(!dirService)
+ return PR_FALSE;
+
+ nsCOMPtr<nsISimpleEnumerator> fileList;
+ dirService->Get(codename, NS_GET_IID(nsISimpleEnumerator),
+ getter_AddRefs(fileList));
+ if(!fileList)
+ return PR_FALSE;
+
+ PRBool more;
+ while(NS_SUCCEEDED(fileList->HasMoreElements(&more)) && more)
+ {
+ nsCOMPtr<nsILocalFile> dir;
+ fileList->GetNext(getter_AddRefs(dir));
+ if(!dir || !aPath->AppendElement(dir))
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+}
+
+// static
+PRBool xptiInterfaceInfoManager::BuildFileSearchPath(nsISupportsArray** aPath)
+{
+#ifdef DEBUG
+ NS_ASSERTION(!gCallCount++, "Expected only one call!");
+#endif
+
+ nsCOMPtr<nsISupportsArray> searchPath;
+ NS_NewISupportsArray(getter_AddRefs(searchPath));
+ if(!searchPath)
+ return PR_FALSE;
+
+ nsCOMPtr<nsILocalFile> compDir;
+
+ // Always put components directory first
+
+ if(NS_FAILED(GetDirectoryFromDirService(NS_XPCOM_COMPONENT_DIR,
+ getter_AddRefs(compDir))) ||
+ !searchPath->AppendElement(compDir))
+ {
+ return PR_FALSE;
+ }
+
+ // Add additional plugins dirs
+ // No error checking here since this is optional in some embeddings
+
+ // Add the GRE's component directory to searchPath if the
+ // application is using an GRE.
+ // An application indicates that it's using an GRE by returning
+ // a valid nsIFile via it's directory service provider interface.
+ //
+ // Please see http://www.mozilla.org/projects/embedding/MRE.html
+ // for more info. on GREs
+ //
+ nsCOMPtr<nsILocalFile> greComponentDirectory;
+ nsresult rv = GetDirectoryFromDirService(NS_GRE_COMPONENT_DIR,
+ getter_AddRefs(greComponentDirectory));
+ if(NS_SUCCEEDED(rv) && greComponentDirectory)
+ {
+ // make sure we only append a directory if its a different one
+ PRBool equalsCompDir = PR_FALSE;
+ greComponentDirectory->Equals(compDir, &equalsCompDir);
+
+ if(!equalsCompDir)
+ searchPath->AppendElement(greComponentDirectory);
+ }
+
+ (void)AppendFromDirServiceList(NS_XPCOM_COMPONENT_DIR_LIST, searchPath);
+ (void)AppendFromDirServiceList(NS_APP_PLUGINS_DIR_LIST, searchPath);
+
+ NS_ADDREF(*aPath = searchPath);
+ return PR_TRUE;
+}
+
+PRBool
+xptiInterfaceInfoManager::GetCloneOfManifestLocation(nsILocalFile** aFile)
+{
+ // We *trust* that this will not change!
+ nsCOMPtr<nsILocalFile> lf;
+ nsresult rv = GetDirectoryFromDirService(NS_XPCOM_XPTI_REGISTRY_FILE,
+ getter_AddRefs(lf));
+
+ if (NS_FAILED(rv)) return PR_FALSE;
+
+ rv = xptiCloneLocalFile(lf, aFile);
+ if (NS_FAILED(rv)) return PR_FALSE;
+ return PR_TRUE;
+}
+
+PRBool
+xptiInterfaceInfoManager::GetApplicationDir(nsILocalFile** aDir)
+{
+ // We *trust* that this will not change!
+ return NS_SUCCEEDED(GetDirectoryFromDirService(NS_XPCOM_CURRENT_PROCESS_DIR, aDir));
+}
+
+PRBool
+xptiInterfaceInfoManager::BuildFileList(nsISupportsArray* aSearchPath,
+ nsISupportsArray** aFileList)
+{
+ NS_ASSERTION(aFileList, "loser!");
+
+ nsresult rv;
+
+ nsCOMPtr<nsISupportsArray> fileList =
+ do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID);
+ if(!fileList)
+ return PR_FALSE;
+
+ PRUint32 pathCount;
+ if(NS_FAILED(aSearchPath->Count(&pathCount)))
+ return PR_FALSE;
+
+ for(PRUint32 i = 0; i < pathCount; i++)
+ {
+ nsCOMPtr<nsILocalFile> dir;
+ rv = xptiCloneElementAsLocalFile(aSearchPath, i, getter_AddRefs(dir));
+ if(NS_FAILED(rv) || !dir)
+ return PR_FALSE;
+
+ nsCOMPtr<nsISimpleEnumerator> entries;
+ rv = dir->GetDirectoryEntries(getter_AddRefs(entries));
+ if(NS_FAILED(rv) || !entries)
+ continue;
+
+ PRUint32 count = 0;
+ PRBool hasMore;
+ while(NS_SUCCEEDED(entries->HasMoreElements(&hasMore)) && hasMore)
+ {
+ nsCOMPtr<nsISupports> sup;
+ entries->GetNext(getter_AddRefs(sup));
+ if(!sup)
+ return PR_FALSE;
+ nsCOMPtr<nsILocalFile> file = do_QueryInterface(sup);
+ if(!file)
+ return PR_FALSE;
+
+ PRBool isFile;
+ if(NS_FAILED(file->IsFile(&isFile)) || !isFile)
+ {
+ continue;
+ }
+
+ nsCAutoString name;
+ if(NS_FAILED(file->GetNativeLeafName(name)))
+ return PR_FALSE;
+
+ if(xptiFileType::IsUnknown(name.get()))
+ continue;
+
+ LOG_AUTOREG(("found file: %s\n", name.get()));
+
+ if(!fileList->InsertElementAt(file, count))
+ return PR_FALSE;
+ ++count;
+ }
+ }
+
+ NS_ADDREF(*aFileList = fileList);
+ return PR_TRUE;
+}
+
+XPTHeader*
+xptiInterfaceInfoManager::ReadXPTFile(nsILocalFile* aFile,
+ xptiWorkingSet* aWorkingSet)
+{
+ NS_ASSERTION(aFile, "loser!");
+
+ XPTHeader *header = nsnull;
+ char *whole = nsnull;
+ PRFileDesc* fd = nsnull;
+ XPTState *state = nsnull;
+ XPTCursor cursor;
+ PRInt32 flen;
+ PRInt64 fileSize;
+
+ PRBool saveFollowLinks;
+ aFile->GetFollowLinks(&saveFollowLinks);
+ aFile->SetFollowLinks(PR_TRUE);
+
+ if(NS_FAILED(aFile->GetFileSize(&fileSize)) || !(flen = nsInt64(fileSize)))
+ {
+ aFile->SetFollowLinks(saveFollowLinks);
+ return nsnull;
+ }
+
+ whole = new char[flen];
+ if (!whole)
+ {
+ aFile->SetFollowLinks(saveFollowLinks);
+ return nsnull;
+ }
+
+ // all exits from on here should be via 'goto out'
+
+ if(NS_FAILED(aFile->OpenNSPRFileDesc(PR_RDONLY, 0444, &fd)) || !fd)
+ {
+ goto out;
+ }
+
+ if(flen > PR_Read(fd, whole, flen))
+ {
+ goto out;
+ }
+
+ if(!(state = XPT_NewXDRState(XPT_DECODE, whole, flen)))
+ {
+ goto out;
+ }
+
+ if(!XPT_MakeCursor(state, XPT_HEADER, 0, &cursor))
+ {
+ goto out;
+ }
+
+ if (!XPT_DoHeader(aWorkingSet->GetStructArena(), &cursor, &header))
+ {
+ header = nsnull;
+ goto out;
+ }
+
+ out:
+ if(fd)
+ PR_Close(fd);
+ if(state)
+ XPT_DestroyXDRState(state);
+ if(whole)
+ delete [] whole;
+ aFile->SetFollowLinks(saveFollowLinks);
+ return header;
+}
+
+PRBool
+xptiInterfaceInfoManager::LoadFile(const xptiTypelib& aTypelibRecord,
+ xptiWorkingSet* aWorkingSet)
+{
+ if(!aWorkingSet)
+ aWorkingSet = &mWorkingSet;
+
+ if(!aWorkingSet->IsValid())
+ return PR_FALSE;
+
+ xptiFile* fileRecord = &aWorkingSet->GetFileAt(aTypelibRecord.GetFileIndex());
+ xptiZipItem* zipItem = nsnull;
+
+ nsCOMPtr<nsILocalFile> file;
+ if(NS_FAILED(aWorkingSet->GetCloneOfDirectoryAt(fileRecord->GetDirectory(),
+ getter_AddRefs(file))) || !file)
+ return PR_FALSE;
+
+ if(NS_FAILED(file->AppendNative(nsDependentCString(fileRecord->GetName()))))
+ return PR_FALSE;
+
+ XPTHeader* header;
+
+ if(aTypelibRecord.IsZip())
+ {
+ zipItem = &aWorkingSet->GetZipItemAt(aTypelibRecord.GetZipItemIndex());
+
+ // See the big comment below in the 'non-zip' case...
+ if(zipItem->GetGuts())
+ {
+ NS_ERROR("Trying to load an xpt file from a zip twice");
+
+ // Force an autoreg on next run
+ (void) xptiManifest::Delete(this);
+
+ return PR_FALSE;
+ }
+
+ LOG_LOAD(("# loading zip item %s::%s\n", fileRecord->GetName(), zipItem->GetName()));
+
+ nsCOMPtr<nsIXPTLoader> loader =
+ do_GetService(NS_ZIPLOADER_CONTRACTID);
+
+ if (loader) {
+ nsresult rv;
+
+ nsCOMPtr<nsIInputStream> stream;
+ rv = loader->LoadEntry(file, zipItem->GetName(),
+ getter_AddRefs(stream));
+
+ if (NS_FAILED(rv))
+ return PR_FALSE;
+
+ header =
+ xptiZipLoader::ReadXPTFileFromInputStream(stream, aWorkingSet);
+ } else {
+ header = nsnull;
+ NS_WARNING("Could not load XPT Zip loader");
+ }
+ }
+ else
+ {
+ // The file would only have guts already if we previously failed to
+ // find an interface info in a file where the manifest claimed it was
+ // going to be.
+ //
+ // Normally, when the file gets loaded (and the guts set) then all
+ // interfaces would also be resolved. So, if we are here again for
+ // the same file then there must have been some interface that was
+ // expected but not present. Now we are explicitly trying to find it
+ // and it isn't going to be there this time either.
+ //
+ // This is an assertion style error in a DEBUG build because it shows
+ // that we failed to detect this in autoreg. For release builds (where
+ // autoreg is not run on every startup) it is just bad. But by returning
+ // PR_FALSE we mark this interface as RESOLVE_FAILED and get on with
+ // things without crashing or anything.
+ //
+ // We don't want to do an autoreg here because this is too much of an
+ // edge case (and in that odd case it might autoreg multiple times if
+ // many interfaces had been removed). But, by deleting the manifest we
+ // force the system to get it right on the next run.
+
+ if(fileRecord->GetGuts())
+ {
+ NS_ERROR("Trying to load an xpt file twice");
+
+ // Force an autoreg on next run
+ (void) xptiManifest::Delete(this);
+
+ return PR_FALSE;
+ }
+
+ LOG_LOAD(("^ loading file %s\n", fileRecord->GetName()));
+ header = ReadXPTFile(file, aWorkingSet);
+ }
+
+ if(!header)
+ return PR_FALSE;
+
+
+ if(aTypelibRecord.IsZip())
+ {
+ // This also allocs zipItem.GetGuts() used below.
+ if(!zipItem->SetHeader(header, aWorkingSet))
+ return PR_FALSE;
+ }
+ else
+ {
+ // This also allocs fileRecord.GetGuts() used below.
+ if(!fileRecord->SetHeader(header, aWorkingSet))
+ return PR_FALSE;
+ }
+
+ // For each interface in the header we want to find the xptiInterfaceInfo
+ // object and set its resolution info.
+
+ for(PRUint16 i = 0; i < header->num_interfaces; i++)
+ {
+ static const nsID zeroIID =
+ { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } };
+
+ XPTInterfaceDirectoryEntry* iface = header->interface_directory + i;
+
+ xptiHashEntry* hashEntry;
+
+ if(!iface->iid.Equals(zeroIID))
+ {
+ hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aWorkingSet->mIIDTable,
+ &iface->iid, PL_DHASH_LOOKUP);
+ }
+ else
+ {
+ hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aWorkingSet->mNameTable,
+ iface->name, PL_DHASH_LOOKUP);
+ }
+
+ xptiInterfaceEntry* entry =
+ PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
+
+ if(!entry)
+ {
+ // This one is just not resolved anywhere!
+ continue;
+ }
+
+ if(aTypelibRecord.IsZip())
+ zipItem->GetGuts()->SetEntryAt(i, entry);
+ else
+ fileRecord->GetGuts()->SetEntryAt(i, entry);
+
+ XPTInterfaceDescriptor* descriptor = iface->interface_descriptor;
+
+ if(descriptor && aTypelibRecord.Equals(entry->GetTypelibRecord()))
+ entry->PartiallyResolveLocked(descriptor, aWorkingSet);
+ }
+ return PR_TRUE;
+}
+
+static int
+IndexOfFileWithName(const char* aName, const xptiWorkingSet* aWorkingSet)
+{
+ NS_ASSERTION(aName, "loser!");
+
+ for(PRUint32 i = 0; i < aWorkingSet->GetFileCount(); ++i)
+ {
+ if(0 == PL_strcmp(aName, aWorkingSet->GetFileAt(i).GetName()))
+ return i;
+ }
+ return -1;
+}
+
+static int
+IndexOfDirectoryOfFile(nsISupportsArray* aSearchPath, nsILocalFile* aFile)
+{
+ nsCOMPtr<nsIFile> parent;
+ aFile->GetParent(getter_AddRefs(parent));
+ if(parent)
+ {
+ PRUint32 count = 0;
+ aSearchPath->Count(&count);
+ NS_ASSERTION(count, "broken search path! bad count");
+ for(PRUint32 i = 0; i < count; i++)
+ {
+ nsCOMPtr<nsIFile> current;
+ aSearchPath->QueryElementAt(i, NS_GET_IID(nsIFile),
+ getter_AddRefs(current));
+ NS_ASSERTION(current, "broken search path! bad element");
+ PRBool same;
+ if(NS_SUCCEEDED(parent->Equals(current, &same)) && same)
+ return (int) i;
+ }
+ }
+ NS_ERROR("file not in search directory!");
+ return -1;
+}
+
+struct SortData
+{
+ nsISupportsArray* mSearchPath;
+ xptiWorkingSet* mWorkingSet;
+};
+
+PR_STATIC_CALLBACK(int)
+xptiSortFileList(const void * p1, const void *p2, void * closure)
+{
+ nsILocalFile* pFile1 = *((nsILocalFile**) p1);
+ nsILocalFile* pFile2 = *((nsILocalFile**) p2);
+ SortData* data = (SortData*) closure;
+
+ nsCAutoString name1;
+ nsCAutoString name2;
+
+ if(NS_FAILED(pFile1->GetNativeLeafName(name1)))
+ {
+ NS_ERROR("way bad, with no happy out!");
+ return 0;
+ }
+ if(NS_FAILED(pFile2->GetNativeLeafName(name2)))
+ {
+ NS_ERROR("way bad, with no happy out!");
+ return 0;
+ }
+
+ int index1 = IndexOfFileWithName(name1.get(), data->mWorkingSet);
+ int index2 = IndexOfFileWithName(name2.get(), data->mWorkingSet);
+
+ // Get these now in case we need them later.
+ PRBool isXPT1 = xptiFileType::IsXPT(name1.get());
+ PRBool isXPT2 = xptiFileType::IsXPT(name2.get());
+ int nameOrder = Compare(name1, name2);
+
+ // both in workingSet, preserve old order
+ if(index1 != -1 && index2 != -1)
+ return index1 - index2;
+
+ if(index1 != -1)
+ return 1;
+
+ if(index2 != -1)
+ return -1;
+
+ // neither is in workingset
+
+ // check how they compare in search path order
+
+ int dirIndex1 = IndexOfDirectoryOfFile(data->mSearchPath, pFile1);
+ int dirIndex2 = IndexOfDirectoryOfFile(data->mSearchPath, pFile2);
+
+ if(dirIndex1 != dirIndex2)
+ return dirIndex1 - dirIndex2;
+
+ // .xpt files come before archives (.zip, .jar, etc)
+ if(isXPT1 &&!isXPT2)
+ return -1;
+
+ if(!isXPT1 && isXPT2)
+ return 1;
+
+ // neither element is in the workingSet and both are same type and in
+ // the same directory, sort by size
+
+ PRInt64 size1;
+ PRInt64 size2;
+
+ if(NS_FAILED(pFile1->GetFileSize(&size1)))
+ {
+ NS_ERROR("way bad, with no happy out!");
+ return 0;
+ }
+ if(NS_FAILED(pFile2->GetFileSize(&size2)))
+ {
+ NS_ERROR("way bad, with no happy out!");
+ return 0;
+ }
+
+ // by size with largest first, or by name if size is the same
+ int sizeDiff = int(PRInt32(nsInt64(size2) - nsInt64(size1)));
+ return sizeDiff != 0 ? sizeDiff : nameOrder;
+}
+
+nsILocalFile**
+xptiInterfaceInfoManager::BuildOrderedFileArray(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet)
+{
+ // We want to end up with a file list that starts with the files from
+ // aWorkingSet (but only those that are in aFileList) in the order in
+ // which they appeared in aWorkingSet-> Following those files will be those
+ // files in aFileList which are not in aWorkingSet-> These additional
+ // files will be ordered by file size (larger first) but all .xpt files
+ // will preceed all zipfile of those files not already in the working set.
+ // To do this we will do a fancy sort on a copy of aFileList.
+
+ nsILocalFile** orderedFileList = nsnull;
+ PRUint32 countOfFilesInFileList;
+ PRUint32 i;
+
+ NS_ASSERTION(aFileList, "loser!");
+ NS_ASSERTION(aWorkingSet, "loser!");
+ NS_ASSERTION(aWorkingSet->IsValid(), "loser!");
+
+ if(NS_FAILED(aFileList->Count(&countOfFilesInFileList)) ||
+ 0 == countOfFilesInFileList)
+ return nsnull;
+
+ orderedFileList = (nsILocalFile**)
+ XPT_MALLOC(aWorkingSet->GetStructArena(),
+ sizeof(nsILocalFile*) * countOfFilesInFileList);
+
+ if(!orderedFileList)
+ return nsnull;
+
+ // fill our list for sorting
+ for(i = 0; i < countOfFilesInFileList; ++i)
+ {
+ nsCOMPtr<nsILocalFile> file;
+ aFileList->QueryElementAt(i, NS_GET_IID(nsILocalFile), getter_AddRefs(file));
+ NS_ASSERTION(file, "loser!");
+
+ // Intentionally NOT addref'd cuz we know these are pinned in aFileList.
+ orderedFileList[i] = file.get();
+ }
+
+ // sort the filelist
+
+ SortData sortData = {aSearchPath, aWorkingSet};
+ NS_QuickSort(orderedFileList, countOfFilesInFileList, sizeof(nsILocalFile*),
+ xptiSortFileList, &sortData);
+
+ return orderedFileList;
+}
+
+xptiInterfaceInfoManager::AutoRegMode
+xptiInterfaceInfoManager::DetermineAutoRegStrategy(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet)
+{
+ NS_ASSERTION(aFileList, "loser!");
+ NS_ASSERTION(aWorkingSet, "loser!");
+ NS_ASSERTION(aWorkingSet->IsValid(), "loser!");
+
+ PRUint32 countOfFilesInWorkingSet = aWorkingSet->GetFileCount();
+ PRUint32 countOfFilesInFileList;
+ PRUint32 i;
+ PRUint32 k;
+
+ if(0 == countOfFilesInWorkingSet)
+ {
+ // Loading manifest might have failed. Better safe...
+ return FULL_VALIDATION_REQUIRED;
+ }
+
+ if(NS_FAILED(aFileList->Count(&countOfFilesInFileList)))
+ {
+ NS_ERROR("unexpected!");
+ return FULL_VALIDATION_REQUIRED;
+ }
+
+ if(countOfFilesInFileList == countOfFilesInWorkingSet)
+ {
+ // try to determine if *no* files are new or changed.
+
+ PRBool same = PR_TRUE;
+ for(i = 0; i < countOfFilesInFileList && same; ++i)
+ {
+ nsCOMPtr<nsILocalFile> file;
+ aFileList->QueryElementAt(i, NS_GET_IID(nsILocalFile), getter_AddRefs(file));
+ NS_ASSERTION(file, "loser!");
+
+ PRInt64 size;
+ PRInt64 date;
+ nsCAutoString name;
+ PRUint32 directory;
+
+ if(NS_FAILED(file->GetFileSize(&size)) ||
+ NS_FAILED(file->GetLastModifiedTime(&date)) ||
+ NS_FAILED(file->GetNativeLeafName(name)) ||
+ !aWorkingSet->FindDirectoryOfFile(file, &directory))
+ {
+ NS_ERROR("unexpected!");
+ return FULL_VALIDATION_REQUIRED;
+ }
+
+ for(k = 0; k < countOfFilesInWorkingSet; ++k)
+ {
+ xptiFile& target = aWorkingSet->GetFileAt(k);
+
+ if(directory == target.GetDirectory() &&
+ name.Equals(target.GetName()))
+ {
+ if(nsInt64(size) != target.GetSize() ||
+ nsInt64(date) != target.GetDate())
+ same = PR_FALSE;
+ break;
+ }
+ }
+ // failed to find our file in the workingset?
+ if(k == countOfFilesInWorkingSet)
+ same = PR_FALSE;
+ }
+ if(same)
+ return NO_FILES_CHANGED;
+ }
+ else if(countOfFilesInFileList > countOfFilesInWorkingSet)
+ {
+ // try to determine if the only changes are additional new files
+ // XXX Wimping out and doing this as a separate walk through the lists.
+
+ PRBool same = PR_TRUE;
+
+ for(i = 0; i < countOfFilesInWorkingSet && same; ++i)
+ {
+ xptiFile& target = aWorkingSet->GetFileAt(i);
+
+ for(k = 0; k < countOfFilesInFileList; ++k)
+ {
+ nsCOMPtr<nsILocalFile> file;
+ aFileList->QueryElementAt(k, NS_GET_IID(nsILocalFile), getter_AddRefs(file));
+ NS_ASSERTION(file, "loser!");
+
+ nsCAutoString name;
+ PRInt64 size;
+ PRInt64 date;
+ if(NS_FAILED(file->GetFileSize(&size)) ||
+ NS_FAILED(file->GetLastModifiedTime(&date)) ||
+ NS_FAILED(file->GetNativeLeafName(name)))
+ {
+ NS_ERROR("unexpected!");
+ return FULL_VALIDATION_REQUIRED;
+ }
+
+ PRBool sameName = name.Equals(target.GetName());
+ if(sameName)
+ {
+ if(nsInt64(size) != target.GetSize() ||
+ nsInt64(date) != target.GetDate())
+ same = PR_FALSE;
+ break;
+ }
+ }
+ // failed to find our file in the file list?
+ if(k == countOfFilesInFileList)
+ same = PR_FALSE;
+ }
+ if(same)
+ return FILES_ADDED_ONLY;
+ }
+
+ return FULL_VALIDATION_REQUIRED;
+}
+
+PRBool
+xptiInterfaceInfoManager::AddOnlyNewFilesFromFileList(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet)
+{
+ nsILocalFile** orderedFileArray;
+ PRUint32 countOfFilesInFileList;
+ PRUint32 i;
+
+ NS_ASSERTION(aFileList, "loser!");
+ NS_ASSERTION(aWorkingSet, "loser!");
+ NS_ASSERTION(aWorkingSet->IsValid(), "loser!");
+
+ if(NS_FAILED(aFileList->Count(&countOfFilesInFileList)))
+ return PR_FALSE;
+ NS_ASSERTION(countOfFilesInFileList, "loser!");
+ NS_ASSERTION(countOfFilesInFileList > aWorkingSet->GetFileCount(), "loser!");
+
+ orderedFileArray = BuildOrderedFileArray(aSearchPath, aFileList, aWorkingSet);
+
+ if(!orderedFileArray)
+ return PR_FALSE;
+
+ // Make enough space in aWorkingset for additions to xptiFile array.
+
+ if(!aWorkingSet->ExtendFileArray(countOfFilesInFileList))
+ return PR_FALSE;
+
+ // For each file that is not already in our working set, add any valid
+ // interfaces that don't conflict with previous interfaces added.
+ for(i = 0; i < countOfFilesInFileList; i++)
+ {
+ nsILocalFile* file = orderedFileArray[i];
+
+ nsCAutoString name;
+ PRInt64 size;
+ PRInt64 date;
+ PRUint32 dir;
+ if(NS_FAILED(file->GetFileSize(&size)) ||
+ NS_FAILED(file->GetLastModifiedTime(&date)) ||
+ NS_FAILED(file->GetNativeLeafName(name)) ||
+ !aWorkingSet->FindDirectoryOfFile(file, &dir))
+ {
+ return PR_FALSE;
+ }
+
+
+ if(xptiWorkingSet::NOT_FOUND != aWorkingSet->FindFile(dir, name.get()))
+ {
+ // This file was found in the working set, so skip it.
+ continue;
+ }
+
+ LOG_AUTOREG((" finding interfaces in new file: %s\n", name.get()));
+
+ xptiFile fileRecord;
+ fileRecord = xptiFile(nsInt64(size), nsInt64(date), dir,
+ name.get(), aWorkingSet);
+
+ if(xptiFileType::IsXPT(fileRecord.GetName()))
+ {
+ XPTHeader* header = ReadXPTFile(file, aWorkingSet);
+ if(!header)
+ {
+ // XXX do something!
+ NS_ERROR("");
+ continue;
+ }
+
+
+ xptiTypelib typelibRecord;
+ typelibRecord.Init(aWorkingSet->GetFileCount());
+
+ PRBool AddedFile = PR_FALSE;
+
+ if(header->major_version >= XPT_MAJOR_INCOMPATIBLE_VERSION)
+ {
+ NS_ASSERTION(!header->num_interfaces,"bad libxpt");
+ LOG_AUTOREG((" file is version %d.%d Type file of version %d.0 or higher can not be read.\n", (int)header->major_version, (int)header->minor_version, (int)XPT_MAJOR_INCOMPATIBLE_VERSION));
+ }
+
+ for(PRUint16 k = 0; k < header->num_interfaces; k++)
+ {
+ xptiInterfaceEntry* entry = nsnull;
+
+ if(!VerifyAndAddEntryIfNew(aWorkingSet,
+ header->interface_directory + k,
+ typelibRecord,
+ &entry))
+ return PR_FALSE;
+
+ if(!entry)
+ continue;
+
+ // If this is the first interface we found for this file then
+ // setup the fileRecord for the header and infos.
+ if(!AddedFile)
+ {
+ if(!fileRecord.SetHeader(header, aWorkingSet))
+ {
+ // XXX that would be bad.
+ return PR_FALSE;
+ }
+ AddedFile = PR_TRUE;
+ }
+ fileRecord.GetGuts()->SetEntryAt(k, entry);
+ }
+
+ // This will correspond to typelibRecord above.
+ aWorkingSet->AppendFile(fileRecord);
+ }
+ else // its another kind of archive
+ {
+ nsCOMPtr<nsIXPTLoader> loader =
+ do_GetService(NS_ZIPLOADER_CONTRACTID);
+
+ if (loader) {
+ nsresult rv;
+
+ nsCOMPtr<nsIXPTLoaderSink> sink =
+ new xptiZipLoaderSink(this, aWorkingSet);
+ if (!sink)
+ return PR_FALSE;
+
+ rv = loader->EnumerateEntries(file, sink);
+ if (NS_FAILED(rv))
+ return PR_FALSE;
+ // This will correspond to typelibRecord used in
+ // xptiInterfaceInfoManager::FoundEntry.
+ aWorkingSet->AppendFile(fileRecord);
+ } else {
+ NS_WARNING("Could not load XPT Zip loader");
+ }
+ }
+ }
+
+ return PR_TRUE;
+}
+
+PRBool
+xptiInterfaceInfoManager::DoFullValidationMergeFromFileList(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet)
+{
+ nsILocalFile** orderedFileArray;
+ PRUint32 countOfFilesInFileList;
+ PRUint32 i;
+
+ NS_ASSERTION(aFileList, "loser!");
+
+ if(!aWorkingSet->IsValid())
+ return PR_FALSE;
+
+ if(NS_FAILED(aFileList->Count(&countOfFilesInFileList)))
+ return PR_FALSE;
+
+ if(!countOfFilesInFileList)
+ {
+ // maybe there are no xpt files to register.
+ // a minimal install would have this case.
+ return PR_TRUE;
+ }
+
+ orderedFileArray = BuildOrderedFileArray(aSearchPath, aFileList, aWorkingSet);
+
+ if(!orderedFileArray)
+ return PR_FALSE;
+
+ // DEBUG_DumpFileArray(orderedFileArray, countOfFilesInFileList);
+
+ // Make space in aWorkingset for a new xptiFile array.
+
+ if(!aWorkingSet->NewFileArray(countOfFilesInFileList))
+ return PR_FALSE;
+
+ aWorkingSet->ClearZipItems();
+ aWorkingSet->ClearHashTables();
+
+ // For each file, add any valid interfaces that don't conflict with
+ // previous interfaces added.
+ for(i = 0; i < countOfFilesInFileList; i++)
+ {
+ nsILocalFile* file = orderedFileArray[i];
+
+ nsCAutoString name;
+ PRInt64 size;
+ PRInt64 date;
+ PRUint32 dir;
+ if(NS_FAILED(file->GetFileSize(&size)) ||
+ NS_FAILED(file->GetLastModifiedTime(&date)) ||
+ NS_FAILED(file->GetNativeLeafName(name)) ||
+ !aWorkingSet->FindDirectoryOfFile(file, &dir))
+ {
+ return PR_FALSE;
+ }
+
+ LOG_AUTOREG((" finding interfaces in file: %s\n", name.get()));
+
+ xptiFile fileRecord;
+ fileRecord = xptiFile(nsInt64(size), nsInt64(date), dir,
+ name.get(), aWorkingSet);
+
+// printf("* found %s\n", fileRecord.GetName());
+
+
+ if(xptiFileType::IsXPT(fileRecord.GetName()))
+ {
+ XPTHeader* header = ReadXPTFile(file, aWorkingSet);
+ if(!header)
+ {
+ // XXX do something!
+ NS_ERROR("Unable to read an XPT file, turn logging on to see which file");
+ LOG_AUTOREG((" unable to read file\n"));
+ continue;
+ }
+
+ xptiTypelib typelibRecord;
+ typelibRecord.Init(aWorkingSet->GetFileCount());
+
+ PRBool AddedFile = PR_FALSE;
+
+ if(header->major_version >= XPT_MAJOR_INCOMPATIBLE_VERSION)
+ {
+ NS_ASSERTION(!header->num_interfaces,"bad libxpt");
+ LOG_AUTOREG((" file is version %d.%d Type file of version %d.0 or higher can not be read.\n", (int)header->major_version, (int)header->minor_version, (int)XPT_MAJOR_INCOMPATIBLE_VERSION));
+ }
+
+ for(PRUint16 k = 0; k < header->num_interfaces; k++)
+ {
+ xptiInterfaceEntry* entry = nsnull;
+
+ if(!VerifyAndAddEntryIfNew(aWorkingSet,
+ header->interface_directory + k,
+ typelibRecord,
+ &entry))
+ return PR_FALSE;
+
+ if(!entry)
+ continue;
+
+ // If this is the first interface we found for this file then
+ // setup the fileRecord for the header and infos.
+ if(!AddedFile)
+ {
+ if(!fileRecord.SetHeader(header, aWorkingSet))
+ {
+ // XXX that would be bad.
+ return PR_FALSE;
+ }
+ AddedFile = PR_TRUE;
+ }
+ fileRecord.GetGuts()->SetEntryAt(k, entry);
+ }
+
+ // This will correspond to typelibRecord above.
+ aWorkingSet->AppendFile(fileRecord);
+ }
+
+ else
+ {
+ nsCOMPtr<nsIXPTLoader> loader =
+ do_GetService(NS_ZIPLOADER_CONTRACTID);
+
+ if (loader) {
+ nsresult rv;
+
+ nsCOMPtr<nsIXPTLoaderSink> sink =
+ new xptiZipLoaderSink(this, aWorkingSet);
+ if (!sink)
+ return PR_FALSE;
+
+ rv = loader->EnumerateEntries(file, sink);
+ if (NS_FAILED(rv))
+ return PR_FALSE;
+ // This will correspond to typelibRecord used in
+ // xptiInterfaceInfoManager::FoundEntry.
+ aWorkingSet->AppendFile(fileRecord);
+ } else {
+ NS_WARNING("Could not load XPT Zip loader");
+ }
+ }
+ }
+ return PR_TRUE;
+}
+
+NS_IMPL_ISUPPORTS1(xptiZipLoaderSink, nsIXPTLoaderSink)
+
+// implement nsIXPTLoader
+NS_IMETHODIMP
+xptiZipLoaderSink::FoundEntry(const char* entryName,
+ PRInt32 index,
+ nsIInputStream *aStream)
+{
+ XPTHeader *header =
+ xptiZipLoader::ReadXPTFileFromInputStream(aStream, mWorkingSet);
+ if (!header)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (!mManager->FoundZipEntry(entryName, index, header, mWorkingSet))
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+// implement xptiEntrySink
+PRBool
+xptiInterfaceInfoManager::FoundZipEntry(const char* entryName,
+ int index,
+ XPTHeader* header,
+ xptiWorkingSet* aWorkingSet)
+{
+
+ NS_ASSERTION(entryName, "loser!");
+ NS_ASSERTION(header, "loser!");
+ NS_ASSERTION(aWorkingSet, "loser!");
+
+ int countOfInterfacesAddedForItem = 0;
+ xptiZipItem zipItemRecord(entryName, aWorkingSet);
+
+ LOG_AUTOREG((" finding interfaces in file: %s\n", entryName));
+
+ if(header->major_version >= XPT_MAJOR_INCOMPATIBLE_VERSION)
+ {
+ NS_ASSERTION(!header->num_interfaces,"bad libxpt");
+ LOG_AUTOREG((" file is version %d.%d. Type file of version %d.0 or higher can not be read.\n", (int)header->major_version, (int)header->minor_version, (int)XPT_MAJOR_INCOMPATIBLE_VERSION));
+ }
+
+ if(!header->num_interfaces)
+ {
+ // We are not interested in files without interfaces.
+ return PR_TRUE;
+ }
+
+ xptiTypelib typelibRecord;
+ typelibRecord.Init(aWorkingSet->GetFileCount(),
+ aWorkingSet->GetZipItemCount());
+
+ for(PRUint16 k = 0; k < header->num_interfaces; k++)
+ {
+ xptiInterfaceEntry* entry = nsnull;
+
+ if(!VerifyAndAddEntryIfNew(aWorkingSet,
+ header->interface_directory + k,
+ typelibRecord,
+ &entry))
+ return PR_FALSE;
+
+ if(!entry)
+ continue;
+
+ // If this is the first interface we found for this item
+ // then setup the zipItemRecord for the header and infos.
+ if(!countOfInterfacesAddedForItem)
+ {
+ // XXX fix this!
+ if(!zipItemRecord.SetHeader(header, aWorkingSet))
+ {
+ // XXX that would be bad.
+ return PR_FALSE;
+ }
+ }
+
+ // zipItemRecord.GetGuts()->SetEntryAt(k, entry);
+ ++countOfInterfacesAddedForItem;
+ }
+
+ if(countOfInterfacesAddedForItem)
+ {
+ if(!aWorkingSet->GetZipItemFreeSpace())
+ {
+ if(!aWorkingSet->ExtendZipItemArray(
+ aWorkingSet->GetZipItemCount() + 20))
+ {
+ // out of space!
+ return PR_FALSE;
+ }
+ }
+ aWorkingSet->AppendZipItem(zipItemRecord);
+ }
+ return PR_TRUE;
+}
+
+PRBool
+xptiInterfaceInfoManager::VerifyAndAddEntryIfNew(xptiWorkingSet* aWorkingSet,
+ XPTInterfaceDirectoryEntry* iface,
+ const xptiTypelib& typelibRecord,
+ xptiInterfaceEntry** entryAdded)
+{
+ NS_ASSERTION(iface, "loser!");
+ NS_ASSERTION(entryAdded, "loser!");
+
+ *entryAdded = nsnull;
+
+ if(!iface->interface_descriptor)
+ {
+ // Not resolved, ignore this one.
+ // XXX full logging might note this...
+ return PR_TRUE;
+ }
+
+ xptiHashEntry* hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aWorkingSet->mIIDTable, &iface->iid, PL_DHASH_LOOKUP);
+
+ xptiInterfaceEntry* entry =
+ PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
+
+ if(entry)
+ {
+ // XXX validate this info to find possible inconsistencies
+ LOG_AUTOREG((" ignoring repeated interface: %s\n", iface->name));
+ return PR_TRUE;
+ }
+
+ // Build a new xptiInterfaceEntry object and hook it up.
+
+ entry = xptiInterfaceEntry::NewEntry(iface->name, strlen(iface->name),
+ iface->iid,
+ typelibRecord, aWorkingSet);
+ if(!entry)
+ {
+ // XXX bad!
+ return PR_FALSE;
+ }
+
+ //XXX We should SetHeader too as part of the validation, no?
+ entry->SetScriptableFlag(XPT_ID_IS_SCRIPTABLE(iface->interface_descriptor->flags));
+
+ // Add our entry to the iid hashtable.
+
+ hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aWorkingSet->mNameTable,
+ entry->GetTheName(), PL_DHASH_ADD);
+ if(hashEntry)
+ hashEntry->value = entry;
+
+ // Add our entry to the name hashtable.
+
+ hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aWorkingSet->mIIDTable,
+ entry->GetTheIID(), PL_DHASH_ADD);
+ if(hashEntry)
+ hashEntry->value = entry;
+
+ *entryAdded = entry;
+
+ LOG_AUTOREG((" added interface: %s\n", iface->name));
+
+ return PR_TRUE;
+}
+
+// local struct used to pass two pointers as one pointer
+struct TwoWorkingSets
+{
+ TwoWorkingSets(xptiWorkingSet* src, xptiWorkingSet* dest)
+ : aSrcWorkingSet(src), aDestWorkingSet(dest) {}
+
+ xptiWorkingSet* aSrcWorkingSet;
+ xptiWorkingSet* aDestWorkingSet;
+};
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+xpti_Merger(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg)
+{
+ xptiInterfaceEntry* srcEntry = ((xptiHashEntry*)hdr)->value;
+ xptiWorkingSet* aSrcWorkingSet = ((TwoWorkingSets*)arg)->aSrcWorkingSet;
+ xptiWorkingSet* aDestWorkingSet = ((TwoWorkingSets*)arg)->aDestWorkingSet;
+
+ xptiHashEntry* hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aDestWorkingSet->mIIDTable,
+ srcEntry->GetTheIID(), PL_DHASH_LOOKUP);
+
+ xptiInterfaceEntry* destEntry =
+ PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
+
+ if(destEntry)
+ {
+ // Let's see if this is referring to the same exact typelib
+
+ const char* destFilename =
+ aDestWorkingSet->GetTypelibFileName(destEntry->GetTypelibRecord());
+
+ const char* srcFilename =
+ aSrcWorkingSet->GetTypelibFileName(srcEntry->GetTypelibRecord());
+
+ if(0 == PL_strcmp(destFilename, srcFilename) &&
+ (destEntry->GetTypelibRecord().GetZipItemIndex() ==
+ srcEntry->GetTypelibRecord().GetZipItemIndex()))
+ {
+ // This is the same item.
+ // But... Let's make sure they didn't change the interface name.
+ // There are wacky developers that do stuff like that!
+ if(0 == PL_strcmp(destEntry->GetTheName(), srcEntry->GetTheName()))
+ return PL_DHASH_NEXT;
+ }
+ }
+
+ // Clone the xptiInterfaceEntry into our destination WorkingSet.
+
+ xptiTypelib typelibRecord;
+
+ uint16 fileIndex = srcEntry->GetTypelibRecord().GetFileIndex();
+ uint16 zipItemIndex = srcEntry->GetTypelibRecord().GetZipItemIndex();
+
+ fileIndex += aDestWorkingSet->mFileMergeOffsetMap[fileIndex];
+
+ // If it is not a zipItem, then the original index is fine.
+ if(srcEntry->GetTypelibRecord().IsZip())
+ zipItemIndex += aDestWorkingSet->mZipItemMergeOffsetMap[zipItemIndex];
+
+ typelibRecord.Init(fileIndex, zipItemIndex);
+
+ destEntry = xptiInterfaceEntry::NewEntry(*srcEntry, typelibRecord,
+ aDestWorkingSet);
+ if(!destEntry)
+ {
+ // XXX bad! should log
+ return PL_DHASH_NEXT;
+ }
+
+
+ // Add our entry to the iid hashtable.
+
+ hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aDestWorkingSet->mNameTable,
+ destEntry->GetTheName(), PL_DHASH_ADD);
+ if(hashEntry)
+ hashEntry->value = destEntry;
+
+ // Add our entry to the name hashtable.
+
+ hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aDestWorkingSet->mIIDTable,
+ destEntry->GetTheIID(), PL_DHASH_ADD);
+ if(hashEntry)
+ hashEntry->value = destEntry;
+
+ return PL_DHASH_NEXT;
+}
+
+PRBool
+xptiInterfaceInfoManager::MergeWorkingSets(xptiWorkingSet* aDestWorkingSet,
+ xptiWorkingSet* aSrcWorkingSet)
+{
+
+ PRUint32 i;
+
+ // Combine file lists.
+
+ PRUint32 originalFileCount = aDestWorkingSet->GetFileCount();
+ PRUint32 additionalFileCount = aSrcWorkingSet->GetFileCount();
+
+ // Create a new array big enough to hold both lists and copy existing files
+
+ if(additionalFileCount)
+ {
+ if(!aDestWorkingSet->ExtendFileArray(originalFileCount +
+ additionalFileCount))
+ return PR_FALSE;
+
+ // Now we are where we started, but we know we have enough space.
+
+ // Prepare offset array for later fixups.
+ // NOTE: Storing with dest, but alloc'ing from src. This is intentional.
+ aDestWorkingSet->mFileMergeOffsetMap = (PRUint32*)
+ XPT_CALLOC(aSrcWorkingSet->GetStructArena(),
+ additionalFileCount * sizeof(PRUint32));
+ if(!aDestWorkingSet->mFileMergeOffsetMap)
+ return PR_FALSE;
+ }
+
+ for(i = 0; i < additionalFileCount; ++i)
+ {
+ xptiFile& srcFile = aSrcWorkingSet->GetFileAt(i);
+ PRUint32 k;
+ for(k = 0; k < originalFileCount; ++k)
+ {
+ // If file (with same name, date, and time) is in both lists
+ // then reuse that record.
+ xptiFile& destFile = aDestWorkingSet->GetFileAt(k);
+ if(srcFile.Equals(destFile))
+ {
+ aDestWorkingSet->mFileMergeOffsetMap[i] = k - i;
+ break;
+ }
+ }
+ if(k == originalFileCount)
+ {
+ // No match found, tack it on the end.
+
+ PRUint32 newIndex = aDestWorkingSet->GetFileCount();
+
+ aDestWorkingSet->AppendFile(xptiFile(srcFile, aDestWorkingSet));
+
+ // Fixup the merge offset map.
+ aDestWorkingSet->mFileMergeOffsetMap[i] = newIndex - i;
+ }
+ }
+
+ // Combine ZipItem lists.
+
+ PRUint32 originalZipItemCount = aDestWorkingSet->GetZipItemCount();
+ PRUint32 additionalZipItemCount = aSrcWorkingSet->GetZipItemCount();
+
+ // Create a new array big enough to hold both lists and copy existing ZipItems
+
+ if(additionalZipItemCount)
+ {
+ if(!aDestWorkingSet->ExtendZipItemArray(originalZipItemCount +
+ additionalZipItemCount))
+ return PR_FALSE;
+
+ // Now we are where we started, but we know we have enough space.
+
+ // Prepare offset array for later fixups.
+ // NOTE: Storing with dest, but alloc'ing from src. This is intentional.
+ aDestWorkingSet->mZipItemMergeOffsetMap = (PRUint32*)
+ XPT_CALLOC(aSrcWorkingSet->GetStructArena(),
+ additionalZipItemCount * sizeof(PRUint32));
+ if(!aDestWorkingSet->mZipItemMergeOffsetMap)
+ return PR_FALSE;
+ }
+
+ for(i = 0; i < additionalZipItemCount; ++i)
+ {
+ xptiZipItem& srcZipItem = aSrcWorkingSet->GetZipItemAt(i);
+ PRUint32 k;
+ for(k = 0; k < originalZipItemCount; ++k)
+ {
+ // If ZipItem (with same name) is in both lists
+ // then reuse that record.
+ xptiZipItem& destZipItem = aDestWorkingSet->GetZipItemAt(k);
+ if(srcZipItem.Equals(destZipItem))
+ {
+ aDestWorkingSet->mZipItemMergeOffsetMap[i] = k - i;
+ break;
+ }
+ }
+ if(k == originalZipItemCount)
+ {
+ // No match found, tack it on the end.
+
+ PRUint32 newIndex = aDestWorkingSet->GetZipItemCount();
+
+ aDestWorkingSet->AppendZipItem(
+ xptiZipItem(srcZipItem, aDestWorkingSet));
+
+ // Fixup the merge offset map.
+ aDestWorkingSet->mZipItemMergeOffsetMap[i] = newIndex - i;
+ }
+ }
+
+ // Migrate xptiInterfaceInfos
+
+ TwoWorkingSets sets(aSrcWorkingSet, aDestWorkingSet);
+
+ PL_DHashTableEnumerate(aSrcWorkingSet->mNameTable, xpti_Merger, &sets);
+
+ return PR_TRUE;
+}
+
+PRBool
+xptiInterfaceInfoManager::DEBUG_DumpFileList(nsISupportsArray* aFileList)
+{
+ PRUint32 count;
+
+ if(NS_FAILED(aFileList->Count(&count)))
+ return PR_FALSE;
+
+ for(PRUint32 i = 0; i < count; i++)
+ {
+ nsCOMPtr<nsIFile> file;
+ aFileList->QueryElementAt(i, NS_GET_IID(nsILocalFile), getter_AddRefs(file));
+ if(!file)
+ return PR_FALSE;
+
+ nsCAutoString name;
+ if(NS_FAILED(file->GetNativeLeafName(name)))
+ return PR_FALSE;
+
+ printf("* found %s\n", name.get());
+ }
+ return PR_TRUE;
+}
+
+PRBool
+xptiInterfaceInfoManager::DEBUG_DumpFileListInWorkingSet(xptiWorkingSet* aWorkingSet)
+{
+ for(PRUint16 i = 0; i < aWorkingSet->GetFileCount(); ++i)
+ {
+ xptiFile& record = aWorkingSet->GetFileAt(i);
+
+ printf("! has %s\n", record.GetName());
+ }
+ return PR_TRUE;
+}
+
+PRBool
+xptiInterfaceInfoManager::DEBUG_DumpFileArray(nsILocalFile** aFileArray,
+ PRUint32 count)
+{
+ // dump the sorted list
+ for(PRUint32 i = 0; i < count; ++i)
+ {
+ nsILocalFile* file = aFileArray[i];
+
+ nsCAutoString name;
+ if(NS_FAILED(file->GetNativeLeafName(name)))
+ return PR_FALSE;
+
+ printf("found file: %s\n", name.get());
+ }
+ return PR_TRUE;
+}
+
+/***************************************************************************/
+
+// static
+void
+xptiInterfaceInfoManager::WriteToLog(const char *fmt, ...)
+{
+ if(!gInterfaceInfoManager)
+ return;
+
+ PRFileDesc* fd = gInterfaceInfoManager->GetOpenLogFile();
+ if(fd)
+ {
+ va_list ap;
+ va_start(ap, fmt);
+ PR_vfprintf(fd, fmt, ap);
+ va_end(ap);
+ }
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+xpti_ResolvedFileNameLogger(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg)
+{
+ xptiInterfaceEntry* entry = ((xptiHashEntry*)hdr)->value;
+ xptiInterfaceInfoManager* mgr = (xptiInterfaceInfoManager*) arg;
+
+ if(entry->IsFullyResolved())
+ {
+ xptiWorkingSet* aWorkingSet = mgr->GetWorkingSet();
+ PRFileDesc* fd = mgr->GetOpenLogFile();
+
+ const xptiTypelib& typelib = entry->GetTypelibRecord();
+ const char* filename =
+ aWorkingSet->GetFileAt(typelib.GetFileIndex()).GetName();
+
+ if(typelib.IsZip())
+ {
+ const char* zipItemName =
+ aWorkingSet->GetZipItemAt(typelib.GetZipItemIndex()).GetName();
+ PR_fprintf(fd, "xpti used interface: %s from %s::%s\n",
+ entry->GetTheName(), filename, zipItemName);
+ }
+ else
+ {
+ PR_fprintf(fd, "xpti used interface: %s from %s\n",
+ entry->GetTheName(), filename);
+ }
+ }
+ return PL_DHASH_NEXT;
+}
+
+void
+xptiInterfaceInfoManager::LogStats()
+{
+ PRUint32 i;
+
+ // This sets what will be returned by GetOpenLogFile().
+ xptiAutoLog autoLog(this, mStatsLogFile, PR_FALSE);
+
+ PRFileDesc* fd = GetOpenLogFile();
+ if(!fd)
+ return;
+
+ // Show names of xpt (only) files from which at least one interface
+ // was resolved.
+
+ PRUint32 fileCount = mWorkingSet.GetFileCount();
+ for(i = 0; i < fileCount; ++i)
+ {
+ xptiFile& f = mWorkingSet.GetFileAt(i);
+ if(f.GetGuts())
+ PR_fprintf(fd, "xpti used file: %s\n", f.GetName());
+ }
+
+ PR_fprintf(fd, "\n");
+
+ // Show names of xptfiles loaded from zips from which at least
+ // one interface was resolved.
+
+ PRUint32 zipItemCount = mWorkingSet.GetZipItemCount();
+ for(i = 0; i < zipItemCount; ++i)
+ {
+ xptiZipItem& zi = mWorkingSet.GetZipItemAt(i);
+ if(zi.GetGuts())
+ PR_fprintf(fd, "xpti used file from zip: %s\n", zi.GetName());
+ }
+
+ PR_fprintf(fd, "\n");
+
+ // Show name of each interface that was fully resolved and the name
+ // of the file and (perhaps) zip from which it was loaded.
+
+ PL_DHashTableEnumerate(mWorkingSet.mNameTable,
+ xpti_ResolvedFileNameLogger, this);
+
+}
+
+/***************************************************************************/
+
+// this is a private helper
+static nsresult
+EntryToInfo(xptiInterfaceEntry* entry, nsIInterfaceInfo **_retval)
+{
+ xptiInterfaceInfo* info;
+ nsresult rv;
+
+ if(!entry)
+ {
+ *_retval = nsnull;
+ return NS_ERROR_FAILURE;
+ }
+
+ rv = entry->GetInterfaceInfo(&info);
+ if(NS_FAILED(rv))
+ return rv;
+
+ // Transfer the AddRef done by GetInterfaceInfo.
+ *_retval = NS_STATIC_CAST(nsIInterfaceInfo*, info);
+ return NS_OK;
+}
+
+/* nsIInterfaceInfo getInfoForIID (in nsIIDPtr iid); */
+NS_IMETHODIMP xptiInterfaceInfoManager::GetInfoForIID(const nsIID * iid, nsIInterfaceInfo **_retval)
+{
+ NS_ASSERTION(iid, "bad param");
+ NS_ASSERTION(_retval, "bad param");
+
+ xptiHashEntry* hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(mWorkingSet.mIIDTable, iid, PL_DHASH_LOOKUP);
+
+ xptiInterfaceEntry* entry =
+ PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
+
+ return EntryToInfo(entry, _retval);
+}
+
+/* nsIInterfaceInfo getInfoForName (in string name); */
+NS_IMETHODIMP xptiInterfaceInfoManager::GetInfoForName(const char *name, nsIInterfaceInfo **_retval)
+{
+ NS_ASSERTION(name, "bad param");
+ NS_ASSERTION(_retval, "bad param");
+
+ xptiHashEntry* hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(mWorkingSet.mNameTable, name, PL_DHASH_LOOKUP);
+
+ xptiInterfaceEntry* entry =
+ PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
+
+ return EntryToInfo(entry, _retval);
+}
+
+/* nsIIDPtr getIIDForName (in string name); */
+NS_IMETHODIMP xptiInterfaceInfoManager::GetIIDForName(const char *name, nsIID * *_retval)
+{
+ NS_ASSERTION(name, "bad param");
+ NS_ASSERTION(_retval, "bad param");
+
+ xptiHashEntry* hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(mWorkingSet.mNameTable, name, PL_DHASH_LOOKUP);
+
+ xptiInterfaceEntry* entry =
+ PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
+
+ if(!entry)
+ {
+ *_retval = nsnull;
+ return NS_ERROR_FAILURE;
+ }
+
+ return entry->GetIID(_retval);
+}
+
+/* string getNameForIID (in nsIIDPtr iid); */
+NS_IMETHODIMP xptiInterfaceInfoManager::GetNameForIID(const nsIID * iid, char **_retval)
+{
+ NS_ASSERTION(iid, "bad param");
+ NS_ASSERTION(_retval, "bad param");
+
+ xptiHashEntry* hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(mWorkingSet.mIIDTable, iid, PL_DHASH_LOOKUP);
+
+ xptiInterfaceEntry* entry =
+ PL_DHASH_ENTRY_IS_FREE(hashEntry) ? nsnull : hashEntry->value;
+
+ if(!entry)
+ {
+ *_retval = nsnull;
+ return NS_ERROR_FAILURE;
+ }
+
+ return entry->GetName(_retval);
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+xpti_ArrayAppender(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg)
+{
+ xptiInterfaceEntry* entry = ((xptiHashEntry*)hdr)->value;
+ nsISupportsArray* array = (nsISupportsArray*) arg;
+
+ nsCOMPtr<nsIInterfaceInfo> ii;
+ if(NS_SUCCEEDED(EntryToInfo(entry, getter_AddRefs(ii))))
+ array->AppendElement(ii);
+ return PL_DHASH_NEXT;
+}
+
+/* nsIEnumerator enumerateInterfaces (); */
+NS_IMETHODIMP xptiInterfaceInfoManager::EnumerateInterfaces(nsIEnumerator **_retval)
+{
+ // I didn't want to incur the size overhead of using nsHashtable just to
+ // make building an enumerator easier. So, this code makes a snapshot of
+ // the table using an nsISupportsArray and builds an enumerator for that.
+ // We can afford this transient cost.
+
+ nsCOMPtr<nsISupportsArray> array;
+ NS_NewISupportsArray(getter_AddRefs(array));
+ if(!array)
+ return NS_ERROR_UNEXPECTED;
+
+ PL_DHashTableEnumerate(mWorkingSet.mNameTable, xpti_ArrayAppender, array);
+
+ return array->Enumerate(_retval);
+}
+
+struct ArrayAndPrefix
+{
+ nsISupportsArray* array;
+ const char* prefix;
+ PRUint32 length;
+};
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+xpti_ArrayPrefixAppender(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg)
+{
+ xptiInterfaceEntry* entry = ((xptiHashEntry*)hdr)->value;
+ ArrayAndPrefix* args = (ArrayAndPrefix*) arg;
+
+ const char* name = entry->GetTheName();
+ if(name != PL_strnstr(name, args->prefix, args->length))
+ return PL_DHASH_NEXT;
+
+ nsCOMPtr<nsIInterfaceInfo> ii;
+ if(NS_SUCCEEDED(EntryToInfo(entry, getter_AddRefs(ii))))
+ args->array->AppendElement(ii);
+ return PL_DHASH_NEXT;
+}
+
+/* nsIEnumerator enumerateInterfacesWhoseNamesStartWith (in string prefix); */
+NS_IMETHODIMP xptiInterfaceInfoManager::EnumerateInterfacesWhoseNamesStartWith(const char *prefix, nsIEnumerator **_retval)
+{
+ nsCOMPtr<nsISupportsArray> array;
+ NS_NewISupportsArray(getter_AddRefs(array));
+ if(!array)
+ return NS_ERROR_UNEXPECTED;
+
+ ArrayAndPrefix args = {array, prefix, PL_strlen(prefix)};
+ PL_DHashTableEnumerate(mWorkingSet.mNameTable, xpti_ArrayPrefixAppender, &args);
+
+ return array->Enumerate(_retval);
+}
+
+/* void autoRegisterInterfaces (); */
+NS_IMETHODIMP xptiInterfaceInfoManager::AutoRegisterInterfaces()
+{
+ nsCOMPtr<nsISupportsArray> fileList;
+ AutoRegMode mode;
+ PRBool ok;
+
+ nsAutoLock lock(xptiInterfaceInfoManager::GetAutoRegLock(this));
+
+ xptiWorkingSet workingSet(mSearchPath);
+ if(!workingSet.IsValid())
+ return NS_ERROR_UNEXPECTED;
+
+ // This sets what will be returned by GetOpenLogFile().
+ xptiAutoLog autoLog(this, mAutoRegLogFile, PR_TRUE);
+
+ LOG_AUTOREG(("start AutoRegister\n"));
+
+ // We re-read the manifest rather than muck with the 'live' one.
+ // It is OK if this fails.
+ // XXX But we should track failure as a warning.
+ ok = xptiManifest::Read(this, &workingSet);
+
+ LOG_AUTOREG(("read of manifest %s\n", ok ? "successful" : "FAILED"));
+
+ // Grovel for all the typelibs we can find (in .xpt or .zip, .jar,...).
+ if(!BuildFileList(mSearchPath, getter_AddRefs(fileList)) || !fileList)
+ return NS_ERROR_UNEXPECTED;
+
+ // DEBUG_DumpFileList(fileList);
+
+ // Check to see how much work we need to do.
+ mode = DetermineAutoRegStrategy(mSearchPath, fileList, &workingSet);
+
+ switch(mode)
+ {
+ case NO_FILES_CHANGED:
+ LOG_AUTOREG(("autoreg strategy: no files changed\n"));
+ LOG_AUTOREG(("successful end of AutoRegister\n"));
+ return NS_OK;
+ case FILES_ADDED_ONLY:
+ LOG_AUTOREG(("autoreg strategy: files added only\n"));
+ if(!AddOnlyNewFilesFromFileList(mSearchPath, fileList, &workingSet))
+ {
+ LOG_AUTOREG(("FAILED to add new files\n"));
+ return NS_ERROR_UNEXPECTED;
+ }
+ break;
+ case FULL_VALIDATION_REQUIRED:
+ LOG_AUTOREG(("autoreg strategy: doing full validation merge\n"));
+ if(!DoFullValidationMergeFromFileList(mSearchPath, fileList, &workingSet))
+ {
+ LOG_AUTOREG(("FAILED to do full validation\n"));
+ return NS_ERROR_UNEXPECTED;
+ }
+ break;
+ default:
+ NS_ERROR("switch missing a case");
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ // Failure to write the manifest is not fatal in production builds.
+ // However, this would require the next startup to find and read all the
+ // xpt files. This will make that startup slower. If this ever becomes a
+ // chronic problem for anyone, then we'll want to figure out why!
+
+ if(!xptiManifest::Write(this, &workingSet))
+ {
+ LOG_AUTOREG(("FAILED to write manifest\n"));
+ NS_ERROR("Failed to write xpti manifest!");
+ }
+
+ if(!MergeWorkingSets(&mWorkingSet, &workingSet))
+ {
+ LOG_AUTOREG(("FAILED to merge into live workingset\n"));
+ return NS_ERROR_UNEXPECTED;
+ }
+
+// DEBUG_DumpFileListInWorkingSet(mWorkingSet);
+
+ LOG_AUTOREG(("successful end of AutoRegister\n"));
+
+ return NS_OK;
+}
+
+/***************************************************************************/
+
+class xptiAdditionalManagersEnumerator : public nsISimpleEnumerator
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISIMPLEENUMERATOR
+
+ xptiAdditionalManagersEnumerator();
+
+ PRBool SizeTo(PRUint32 likelyCount) {return mArray.SizeTo(likelyCount);}
+ PRBool AppendElement(nsIInterfaceInfoManager* element);
+
+private:
+ ~xptiAdditionalManagersEnumerator() {}
+
+ nsSupportsArray mArray;
+ PRUint32 mIndex;
+ PRUint32 mCount;
+};
+
+NS_IMPL_ISUPPORTS1(xptiAdditionalManagersEnumerator, nsISimpleEnumerator)
+
+xptiAdditionalManagersEnumerator::xptiAdditionalManagersEnumerator()
+ : mIndex(0), mCount(0)
+{
+}
+
+PRBool xptiAdditionalManagersEnumerator::AppendElement(nsIInterfaceInfoManager* element)
+{
+ if(!mArray.AppendElement(NS_STATIC_CAST(nsISupports*, element)))
+ return PR_FALSE;
+ mCount++;
+ return PR_TRUE;
+}
+
+/* boolean hasMoreElements (); */
+NS_IMETHODIMP xptiAdditionalManagersEnumerator::HasMoreElements(PRBool *_retval)
+{
+ *_retval = mIndex < mCount;
+ return NS_OK;
+}
+
+/* nsISupports getNext (); */
+NS_IMETHODIMP xptiAdditionalManagersEnumerator::GetNext(nsISupports **_retval)
+{
+ if(!(mIndex < mCount))
+ {
+ NS_ERROR("Bad nsISimpleEnumerator caller!");
+ return NS_ERROR_FAILURE;
+ }
+
+ *_retval = mArray.ElementAt(mIndex++);
+ return *_retval ? NS_OK : NS_ERROR_FAILURE;
+}
+
+/***************************************************************************/
+
+/* void addAdditionalManager (in nsIInterfaceInfoManager manager); */
+NS_IMETHODIMP xptiInterfaceInfoManager::AddAdditionalManager(nsIInterfaceInfoManager *manager)
+{
+ nsCOMPtr<nsIWeakReference> weakRef = do_GetWeakReference(manager);
+ nsISupports* ptrToAdd = weakRef ?
+ NS_STATIC_CAST(nsISupports*, weakRef) :
+ NS_STATIC_CAST(nsISupports*, manager);
+ { // scoped lock...
+ nsAutoLock lock(mAdditionalManagersLock);
+ PRInt32 index;
+ nsresult rv = mAdditionalManagers.GetIndexOf(ptrToAdd, &index);
+ if(NS_FAILED(rv) || -1 != index)
+ return NS_ERROR_FAILURE;
+ if(!mAdditionalManagers.AppendElement(ptrToAdd))
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ return NS_OK;
+}
+
+/* void removeAdditionalManager (in nsIInterfaceInfoManager manager); */
+NS_IMETHODIMP xptiInterfaceInfoManager::RemoveAdditionalManager(nsIInterfaceInfoManager *manager)
+{
+ nsCOMPtr<nsIWeakReference> weakRef = do_GetWeakReference(manager);
+ nsISupports* ptrToRemove = weakRef ?
+ NS_STATIC_CAST(nsISupports*, weakRef) :
+ NS_STATIC_CAST(nsISupports*, manager);
+ { // scoped lock...
+ nsAutoLock lock(mAdditionalManagersLock);
+ if(!mAdditionalManagers.RemoveElement(ptrToRemove))
+ return NS_ERROR_FAILURE;
+ }
+ return NS_OK;
+}
+
+/* PRBool hasAdditionalManagers (); */
+NS_IMETHODIMP xptiInterfaceInfoManager::HasAdditionalManagers(PRBool *_retval)
+{
+ PRUint32 count;
+ nsresult rv = mAdditionalManagers.Count(&count);
+ *_retval = count != 0;
+ return rv;
+}
+
+/* nsISimpleEnumerator enumerateAdditionalManagers (); */
+NS_IMETHODIMP xptiInterfaceInfoManager::EnumerateAdditionalManagers(nsISimpleEnumerator **_retval)
+{
+ nsAutoLock lock(mAdditionalManagersLock);
+
+ PRUint32 count;
+ nsresult rv = mAdditionalManagers.Count(&count);
+ if(NS_FAILED(rv))
+ return rv;
+
+ nsCOMPtr<xptiAdditionalManagersEnumerator> enumerator =
+ new xptiAdditionalManagersEnumerator();
+ if(!enumerator)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ enumerator->SizeTo(count);
+
+ for(PRUint32 i = 0; i < count; /* i incremented in the loop body */)
+ {
+ nsCOMPtr<nsISupports> raw =
+ dont_AddRef(mAdditionalManagers.ElementAt(i++));
+ if(!raw)
+ return NS_ERROR_FAILURE;
+ nsCOMPtr<nsIWeakReference> weakRef = do_QueryInterface(raw);
+ if(weakRef)
+ {
+ nsCOMPtr<nsIInterfaceInfoManager> manager =
+ do_QueryReferent(weakRef);
+ if(manager)
+ {
+ if(!enumerator->AppendElement(manager))
+ return NS_ERROR_FAILURE;
+ }
+ else
+ {
+ // The manager is no more. Remove the element.
+ if(!mAdditionalManagers.RemoveElementAt(--i))
+ return NS_ERROR_FAILURE;
+ count--;
+ }
+ }
+ else
+ {
+ // We *know* we put a pointer to either a nsIWeakReference or
+ // an nsIInterfaceInfoManager into the array, so we can avoid an
+ // extra QI here and just do a cast.
+ if(!enumerator->AppendElement(
+ NS_REINTERPRET_CAST(nsIInterfaceInfoManager*, raw.get())))
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ NS_ADDREF(*_retval = enumerator);
+ return NS_OK;
+}
+
+/***************************************************************************/
+
+XPTI_PUBLIC_API(nsIInterfaceInfoManager*)
+XPTI_GetInterfaceInfoManager()
+{
+ nsIInterfaceInfoManager* iim =
+ xptiInterfaceInfoManager::GetInterfaceInfoManagerNoAddRef();
+ NS_IF_ADDREF(iim);
+ return iim;
+}
+
+XPTI_PUBLIC_API(void)
+XPTI_FreeInterfaceInfoManager()
+{
+ xptiInterfaceInfoManager::FreeInterfaceInfoManager();
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiManifest.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiManifest.cpp
new file mode 100644
index 00000000..03ab7029
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiManifest.cpp
@@ -0,0 +1,710 @@
+/* -*- 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) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * 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 ***** */
+
+/* Implementation of xptiManifest. */
+
+#include "xptiprivate.h"
+#include "nsManifestLineReader.h"
+#include "nsString.h"
+
+static const char g_Disclaimer[] = "# Generated file. ** DO NOT EDIT! **";
+
+static const char g_TOKEN_Files[] = "Files";
+static const char g_TOKEN_ArchiveItems[] = "ArchiveItems";
+static const char g_TOKEN_Interfaces[] = "Interfaces";
+static const char g_TOKEN_Header[] = "Header";
+static const char g_TOKEN_Version[] = "Version";
+static const char g_TOKEN_AppDir[] = "AppDir";
+static const char g_TOKEN_Directories[] = "Directories";
+
+static const int g_VERSION_MAJOR = 2;
+static const int g_VERSION_MINOR = 0;
+
+/***************************************************************************/
+
+static PRBool
+GetCurrentAppDirString(xptiInterfaceInfoManager* aMgr, nsACString &aStr)
+{
+ nsCOMPtr<nsILocalFile> appDir;
+ aMgr->GetApplicationDir(getter_AddRefs(appDir));
+ if(appDir)
+ return NS_SUCCEEDED(appDir->GetPersistentDescriptor(aStr));
+ return PR_FALSE;
+}
+
+static PRBool
+CurrentAppDirMatchesPersistentDescriptor(xptiInterfaceInfoManager* aMgr,
+ const char *inStr)
+{
+ nsCOMPtr<nsILocalFile> appDir;
+ aMgr->GetApplicationDir(getter_AddRefs(appDir));
+
+ nsCOMPtr<nsILocalFile> descDir;
+ nsresult rv = NS_NewNativeLocalFile(EmptyCString(), PR_FALSE, getter_AddRefs(descDir));
+ if(NS_FAILED(rv))
+ return PR_FALSE;
+
+ rv = descDir->SetPersistentDescriptor(nsDependentCString(inStr));
+ if(NS_FAILED(rv))
+ return PR_FALSE;
+
+ PRBool matches;
+ rv = appDir->Equals(descDir, &matches);
+ return NS_SUCCEEDED(rv) && matches;
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+xpti_InterfaceWriter(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg)
+{
+ xptiInterfaceEntry* entry = ((xptiHashEntry*)hdr)->value;
+ PRFileDesc* fd = (PRFileDesc*) arg;
+
+ char* iidStr = entry->GetTheIID()->ToString();
+ if(!iidStr)
+ return PL_DHASH_STOP;
+
+ const xptiTypelib& typelib = entry->GetTypelibRecord();
+
+ PRBool success = PR_fprintf(fd, "%d,%s,%s,%d,%d,%d\n",
+ (int) number,
+ entry->GetTheName(),
+ iidStr,
+ (int) typelib.GetFileIndex(),
+ (int) (typelib.IsZip() ?
+ typelib.GetZipItemIndex() : -1),
+ (int) entry->GetScriptableFlag());
+
+ nsCRT::free(iidStr);
+
+ return success ? PL_DHASH_NEXT : PL_DHASH_STOP;
+}
+
+
+// static
+PRBool xptiManifest::Write(xptiInterfaceInfoManager* aMgr,
+ xptiWorkingSet* aWorkingSet)
+{
+
+ PRBool succeeded = PR_FALSE;
+ PRFileDesc* fd = nsnull;
+ PRUint32 i;
+ PRUint32 size32;
+ PRIntn interfaceCount = 0;
+ nsCAutoString appDirString;
+
+ nsCOMPtr<nsILocalFile> tempFile;
+ if(!aMgr->GetCloneOfManifestLocation(getter_AddRefs(tempFile)) || !tempFile)
+ return PR_FALSE;
+
+ nsCAutoString originalLeafName;
+ tempFile->GetNativeLeafName(originalLeafName);
+
+ nsCAutoString leafName;
+ leafName.Assign(originalLeafName + NS_LITERAL_CSTRING(".tmp"));
+
+ tempFile->SetNativeLeafName(leafName);
+
+ // All exits via "goto out;" from here on...
+ if(NS_FAILED(tempFile->
+ OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+ 0600, &fd)) || !fd)
+ {
+ goto out;
+ }
+
+ // write file header comments
+
+ if(!PR_fprintf(fd, "%s\n", g_Disclaimer))
+ goto out;
+
+ // write the [Header] block, version number, and appdir.
+
+ if(!PR_fprintf(fd, "\n[%s,%d]\n", g_TOKEN_Header, 2))
+ goto out;
+
+ if(!PR_fprintf(fd, "%d,%s,%d,%d\n",
+ 0, g_TOKEN_Version, g_VERSION_MAJOR, g_VERSION_MINOR))
+ goto out;
+
+ GetCurrentAppDirString(aMgr, appDirString);
+ if(appDirString.IsEmpty())
+ goto out;
+
+ if(!PR_fprintf(fd, "%d,%s,%s\n",
+ 1, g_TOKEN_AppDir, appDirString.get()))
+ goto out;
+
+ // write Directories list
+
+ if(!PR_fprintf(fd, "\n[%s,%d]\n",
+ g_TOKEN_Directories,
+ (int) aWorkingSet->GetDirectoryCount()))
+ goto out;
+
+ for(i = 0; i < aWorkingSet->GetDirectoryCount(); i++)
+ {
+ nsCOMPtr<nsILocalFile> dir;
+ nsCAutoString str;
+
+ aWorkingSet->GetDirectoryAt(i, getter_AddRefs(dir));
+ if(!dir)
+ goto out;
+
+ dir->GetPersistentDescriptor(str);
+ if(str.IsEmpty())
+ goto out;
+
+ if(!PR_fprintf(fd, "%d,%s\n", (int) i, str.get()))
+ goto out;
+ }
+
+ // write Files list
+
+ if(!PR_fprintf(fd, "\n[%s,%d]\n",
+ g_TOKEN_Files,
+ (int) aWorkingSet->GetFileCount()))
+ goto out;
+
+ for(i = 0; i < aWorkingSet->GetFileCount(); i++)
+ {
+ const xptiFile& file = aWorkingSet->GetFileAt(i);
+
+ LL_L2UI(size32, file.GetSize());
+
+ if(!PR_fprintf(fd, "%d,%s,%d,%u,%lld\n",
+ (int) i,
+ file.GetName(),
+ (int) file.GetDirectory(),
+ size32, PRInt64(file.GetDate())))
+ goto out;
+ }
+
+ // write ArchiveItems list
+
+ if(!PR_fprintf(fd, "\n[%s,%d]\n",
+ g_TOKEN_ArchiveItems,
+ (int) aWorkingSet->GetZipItemCount()))
+ goto out;
+
+ for(i = 0; i < aWorkingSet->GetZipItemCount(); i++)
+ {
+ if(!PR_fprintf(fd, "%d,%s\n",
+ (int) i,
+ aWorkingSet->GetZipItemAt(i).GetName()))
+ goto out;
+ }
+
+ // write the Interfaces list
+
+ interfaceCount = aWorkingSet->mNameTable->entryCount;
+
+ if(!PR_fprintf(fd, "\n[%s,%d]\n",
+ g_TOKEN_Interfaces,
+ (int) interfaceCount))
+ goto out;
+
+ if(interfaceCount != (PRIntn)
+ PL_DHashTableEnumerate(aWorkingSet->mNameTable,
+ xpti_InterfaceWriter, fd))
+ goto out;
+
+
+ if(PR_SUCCESS == PR_Close(fd))
+ {
+ succeeded = PR_TRUE;
+ }
+ fd = nsnull;
+
+out:
+ if(fd)
+ PR_Close(fd);
+
+ if(succeeded)
+ {
+ // delete the old file and rename this
+ nsCOMPtr<nsILocalFile> mainFile;
+ if(!aMgr->GetCloneOfManifestLocation(getter_AddRefs(mainFile)) || !mainFile)
+ return PR_FALSE;
+
+ PRBool exists;
+ if(NS_FAILED(mainFile->Exists(&exists)))
+ return PR_FALSE;
+
+ if(exists && NS_FAILED(mainFile->Remove(PR_FALSE)))
+ return PR_FALSE;
+
+ nsCOMPtr<nsIFile> parent;
+ mainFile->GetParent(getter_AddRefs(parent));
+
+ // MoveTo means rename.
+ if(NS_FAILED(tempFile->MoveToNative(parent, originalLeafName)))
+ return PR_FALSE;
+ }
+
+ return succeeded;
+}
+
+/***************************************************************************/
+/***************************************************************************/
+
+static char*
+ReadManifestIntoMemory(xptiInterfaceInfoManager* aMgr,
+ PRUint32* pLength)
+{
+ PRFileDesc* fd = nsnull;
+ PRInt32 flen;
+ PRInt64 fileSize;
+ char* whole = nsnull;
+ PRBool success = PR_FALSE;
+
+ nsCOMPtr<nsILocalFile> aFile;
+ if(!aMgr->GetCloneOfManifestLocation(getter_AddRefs(aFile)) || !aFile)
+ return nsnull;
+
+#ifdef DEBUG
+ {
+ static PRBool shown = PR_FALSE;
+
+ nsCAutoString path;
+ if(!shown && NS_SUCCEEDED(aFile->GetNativePath(path)) && !path.IsEmpty())
+ {
+ fprintf(stderr, "Type Manifest File: %s\n", path.get());
+ shown = PR_TRUE;
+ }
+ }
+#endif
+
+ if(NS_FAILED(aFile->GetFileSize(&fileSize)) || !(flen = nsInt64(fileSize)))
+ return nsnull;
+
+ whole = new char[flen];
+ if (!whole)
+ return nsnull;
+
+ // All exits from on here should be via 'goto out'
+
+ if(NS_FAILED(aFile->OpenNSPRFileDesc(PR_RDONLY, 0444, &fd)) || !fd)
+ goto out;
+
+ if(flen > PR_Read(fd, whole, flen))
+ goto out;
+
+ success = PR_TRUE;
+
+ out:
+ if(fd)
+ PR_Close(fd);
+
+ if(!success)
+ {
+ delete [] whole;
+ return nsnull;
+ }
+
+ *pLength = flen;
+ return whole;
+}
+
+static
+PRBool ReadSectionHeader(nsManifestLineReader& reader,
+ const char *token, int minCount, int* count)
+{
+ while(1)
+ {
+ if(!reader.NextLine())
+ break;
+ if(*reader.LinePtr() == '[')
+ {
+ char* p = reader.LinePtr() + (reader.LineLength() - 1);
+ if(*p != ']')
+ break;
+ *p = 0;
+
+ char* values[2];
+ int lengths[2];
+ if(2 != reader.ParseLine(values, lengths, 2))
+ break;
+
+ // ignore the leading '['
+ if(0 != PL_strcmp(values[0]+1, token))
+ break;
+
+ if((*count = atoi(values[1])) < minCount)
+ break;
+
+ return PR_TRUE;
+ }
+ }
+ return PR_FALSE;
+}
+
+
+// static
+PRBool xptiManifest::Read(xptiInterfaceInfoManager* aMgr,
+ xptiWorkingSet* aWorkingSet)
+{
+ int i;
+ char* whole = nsnull;
+ PRBool succeeded = PR_FALSE;
+ PRUint32 flen = 0;
+ nsManifestLineReader reader;
+ xptiHashEntry* hashEntry;
+ int headerCount = 0;
+ int dirCount = 0;
+ int fileCount = 0;
+ int zipItemCount = -1;
+ int interfaceCount = 0;
+ int dir;
+ int flags;
+ char* values[6]; // 6 is currently the max items we need to parse
+ int lengths[6];
+ PRUint32 size32;
+ PRInt64 size;
+ PRInt64 date;
+
+ whole = ReadManifestIntoMemory(aMgr, &flen);
+ if(!whole)
+ return PR_FALSE;
+
+ reader.Init(whole, flen);
+
+ // All exits from here on should be via 'goto out'
+
+ // Look for "Header" section
+
+ // This version accepts only version 1,0. We also freak if the header
+ // has more than one entry. The rationale is that we want to force an
+ // autoreg if the xpti.dat file was written by *any* other version of
+ // the software. Future versions may wish to support updating older
+ // manifests in some interesting way.
+
+ if(!ReadSectionHeader(reader, g_TOKEN_Header, 2, &headerCount))
+ goto out;
+
+ if(headerCount != 2)
+ goto out;
+
+ // Verify the version number
+
+ if(!reader.NextLine())
+ goto out;
+
+ // index,VersionLiteral,major,minor
+ if(4 != reader.ParseLine(values, lengths, 4))
+ goto out;
+
+ // index
+ if(0 != atoi(values[0]))
+ goto out;
+
+ // VersionLiteral
+ if(0 != PL_strcmp(values[1], g_TOKEN_Version))
+ goto out;
+
+ // major
+ if(g_VERSION_MAJOR != atoi(values[2]))
+ goto out;
+
+ // minor
+ if(g_VERSION_MINOR != atoi(values[3]))
+ goto out;
+
+ // Verify the application directory
+
+ if(!reader.NextLine())
+ goto out;
+
+ // index,AppDirLiteral,directoryname
+ if(3 != reader.ParseLine(values, lengths, 3))
+ goto out;
+
+ // index
+ if(1 != atoi(values[0]))
+ goto out;
+
+ // AppDirLiteral
+ if(0 != PL_strcmp(values[1], g_TOKEN_AppDir))
+ goto out;
+
+ if(!CurrentAppDirMatchesPersistentDescriptor(aMgr, values[2]))
+ goto out;
+
+ // Look for "Directories" section
+
+ if(!ReadSectionHeader(reader, g_TOKEN_Directories, 1, &dirCount))
+ goto out;
+ else
+ {
+ // To validate that the directory list matches the current search path
+ // we first confirm that the list lengths match.
+
+ nsCOMPtr<nsISupportsArray> searchPath;
+ aMgr->GetSearchPath(getter_AddRefs(searchPath));
+
+ PRUint32 searchPathCount;
+ searchPath->Count(&searchPathCount);
+
+ if(dirCount != (int) searchPathCount)
+ goto out;
+ }
+
+ // Read the directory records
+
+ for(i = 0; i < dirCount; ++i)
+ {
+ if(!reader.NextLine())
+ goto out;
+
+ // index,directoryname
+ if(2 != reader.ParseLine(values, lengths, 2))
+ goto out;
+
+ // index
+ if(i != atoi(values[0]))
+ goto out;
+
+ // directoryname
+ if(!aWorkingSet->DirectoryAtMatchesPersistentDescriptor(i, values[1]))
+ goto out;
+ }
+
+ // Look for "Files" section
+
+ if(!ReadSectionHeader(reader, g_TOKEN_Files, 1, &fileCount))
+ goto out;
+
+
+ // Alloc room in the WorkingSet for the filearray.
+
+ if(!aWorkingSet->NewFileArray(fileCount))
+ goto out;
+
+ // Read the file records
+
+ for(i = 0; i < fileCount; ++i)
+ {
+ if(!reader.NextLine())
+ goto out;
+
+ // index,filename,dirIndex,dilesSize,filesDate
+ if(5 != reader.ParseLine(values, lengths, 5))
+ goto out;
+
+ // index
+ if(i != atoi(values[0]))
+ goto out;
+
+ // filename
+ if(!*values[1])
+ goto out;
+
+ // dirIndex
+ dir = atoi(values[2]);
+ if(dir < 0 || dir > dirCount)
+ goto out;
+
+ // fileSize
+ size32 = atoi(values[3]);
+ if(size32 <= 0)
+ goto out;
+ LL_UI2L(size, size32);
+
+ // fileDate
+ date = nsCRT::atoll(values[4]);
+ if(LL_IS_ZERO(date))
+ goto out;
+
+ // Append a new file record to the array.
+
+ aWorkingSet->AppendFile(
+ xptiFile(nsInt64(size), nsInt64(date), dir, values[1], aWorkingSet));
+ }
+
+ // Look for "ZipItems" section
+
+ if(!ReadSectionHeader(reader, g_TOKEN_ArchiveItems, 0, &zipItemCount))
+ goto out;
+
+ // Alloc room in the WorkingSet for the zipItemarray.
+
+ if(zipItemCount)
+ if(!aWorkingSet->NewZipItemArray(zipItemCount))
+ goto out;
+
+ // Read the zipItem records
+
+ for(i = 0; i < zipItemCount; ++i)
+ {
+ if(!reader.NextLine())
+ goto out;
+
+ // index,filename
+ if(2 != reader.ParseLine(values, lengths, 2))
+ goto out;
+
+ // index
+ if(i != atoi(values[0]))
+ goto out;
+
+ // filename
+ if(!*values[1])
+ goto out;
+
+ // Append a new zipItem record to the array.
+
+ aWorkingSet->AppendZipItem(xptiZipItem(values[1], aWorkingSet));
+ }
+
+ // Look for "Interfaces" section
+
+ if(!ReadSectionHeader(reader, g_TOKEN_Interfaces, 1, &interfaceCount))
+ goto out;
+
+ // Read the interface records
+
+ for(i = 0; i < interfaceCount; ++i)
+ {
+ int fileIndex;
+ int zipItemIndex;
+ nsIID iid;
+ xptiInterfaceEntry* entry;
+ xptiTypelib typelibRecord;
+
+ if(!reader.NextLine())
+ goto out;
+
+ // index,interfaceName,iid,fileIndex,zipIndex,flags
+ if(6 != reader.ParseLine(values, lengths, 6))
+ goto out;
+
+ // index
+ if(i != atoi(values[0]))
+ goto out;
+
+ // interfaceName
+ if(!*values[1])
+ goto out;
+
+ // iid
+ if(!iid.Parse(values[2]))
+ goto out;
+
+ // fileIndex
+ fileIndex = atoi(values[3]);
+ if(fileIndex < 0 || fileIndex >= fileCount)
+ goto out;
+
+ // zipIndex (NOTE: -1 is a valid value)
+ zipItemIndex = atoi(values[4]);
+ if(zipItemIndex < -1 || zipItemIndex >= zipItemCount)
+ goto out;
+
+ // flags
+ flags = atoi(values[5]);
+ if(flags != 0 && flags != 1)
+ goto out;
+
+ // Build an InterfaceInfo and hook it in.
+
+ if(zipItemIndex == -1)
+ typelibRecord.Init(fileIndex);
+ else
+ typelibRecord.Init(fileIndex, zipItemIndex);
+
+ entry = xptiInterfaceEntry::NewEntry(values[1], lengths[1],
+ iid, typelibRecord,
+ aWorkingSet);
+ if(!entry)
+ goto out;
+
+ entry->SetScriptableFlag(flags==1);
+
+ // Add our entry to the iid hashtable.
+
+ hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aWorkingSet->mNameTable,
+ entry->GetTheName(), PL_DHASH_ADD);
+ if(hashEntry)
+ hashEntry->value = entry;
+
+ // Add our entry to the name hashtable.
+
+ hashEntry = (xptiHashEntry*)
+ PL_DHashTableOperate(aWorkingSet->mIIDTable,
+ entry->GetTheIID(), PL_DHASH_ADD);
+ if(hashEntry)
+ hashEntry->value = entry;
+ }
+
+ // success!
+
+ succeeded = PR_TRUE;
+
+ out:
+ if(whole)
+ delete [] whole;
+
+ if(!succeeded)
+ {
+ // Cleanup the WorkingSet on failure.
+ aWorkingSet->InvalidateInterfaceInfos();
+ aWorkingSet->ClearHashTables();
+ aWorkingSet->ClearFiles();
+ }
+ return succeeded;
+}
+
+// static
+PRBool xptiManifest::Delete(xptiInterfaceInfoManager* aMgr)
+{
+ nsCOMPtr<nsILocalFile> aFile;
+ if(!aMgr->GetCloneOfManifestLocation(getter_AddRefs(aFile)) || !aFile)
+ return PR_FALSE;
+
+ PRBool exists;
+ if(NS_FAILED(aFile->Exists(&exists)))
+ return PR_FALSE;
+
+ if(exists && NS_FAILED(aFile->Remove(PR_FALSE)))
+ return PR_FALSE;
+
+ return PR_TRUE;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiMisc.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiMisc.cpp
new file mode 100644
index 00000000..a1dbf5c3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiMisc.cpp
@@ -0,0 +1,164 @@
+/* -*- 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) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * 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 ***** */
+
+/* Implementation of misc. xpti stuff. */
+
+#include "xptiprivate.h"
+
+struct xptiFileTypeEntry
+{
+ const char* name;
+ int len;
+ xptiFileType::Type type;
+};
+
+static const xptiFileTypeEntry g_Entries[] =
+ {
+ {".xpt", 4, xptiFileType::XPT},
+ {".zip", 4, xptiFileType::ZIP},
+ {".jar", 4, xptiFileType::ZIP},
+ {nsnull, 0, xptiFileType::UNKNOWN}
+ };
+
+// static
+xptiFileType::Type xptiFileType::GetType(const char* name)
+{
+ NS_ASSERTION(name, "loser!");
+ int len = PL_strlen(name);
+ for(const xptiFileTypeEntry* p = g_Entries; p->name; p++)
+ {
+ if(len > p->len && 0 == PL_strcasecmp(p->name, &(name[len - p->len])))
+ return p->type;
+ }
+ return UNKNOWN;
+}
+
+/***************************************************************************/
+
+MOZ_DECL_CTOR_COUNTER(xptiAutoLog)
+
+xptiAutoLog::xptiAutoLog(xptiInterfaceInfoManager* mgr,
+ nsILocalFile* logfile, PRBool append)
+ : mMgr(nsnull), mOldFileDesc(nsnull)
+{
+ MOZ_COUNT_CTOR(xptiAutoLog);
+
+ if(mgr && logfile)
+ {
+ PRFileDesc* fd;
+ if(NS_SUCCEEDED(logfile->
+ OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_APPEND |
+ (append ? 0 : PR_TRUNCATE),
+ 0600, &fd)) && fd)
+ {
+#ifdef DEBUG
+ m_DEBUG_FileDesc = fd;
+#endif
+ mMgr = mgr;
+ mOldFileDesc = mMgr->SetOpenLogFile(fd);
+ if(append)
+ PR_Seek(fd, 0, PR_SEEK_END);
+ WriteTimestamp(fd, "++++ start logging ");
+
+ }
+ else
+ {
+#ifdef DEBUG
+ printf("xpti failed to open log file for writing\n");
+#endif
+ }
+ }
+}
+
+xptiAutoLog::~xptiAutoLog()
+{
+ MOZ_COUNT_DTOR(xptiAutoLog);
+
+ if(mMgr)
+ {
+ PRFileDesc* fd = mMgr->SetOpenLogFile(mOldFileDesc);
+ NS_ASSERTION(fd == m_DEBUG_FileDesc, "bad unravel");
+ if(fd)
+ {
+ WriteTimestamp(fd, "---- end logging ");
+ PR_Close(fd);
+ }
+ }
+}
+
+void xptiAutoLog::WriteTimestamp(PRFileDesc* fd, const char* msg)
+{
+ PRExplodedTime expTime;
+ PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &expTime);
+ char time[128];
+ PR_FormatTimeUSEnglish(time, 128, "%Y-%m-%d-%H:%M:%S", &expTime);
+ PR_fprintf(fd, "\n%s %s\n\n", msg, time);
+}
+
+/***************************************************************************/
+
+nsresult
+xptiCloneLocalFile(nsILocalFile* aLocalFile,
+ nsILocalFile** aCloneLocalFile)
+{
+ nsresult rv;
+ nsCOMPtr<nsIFile> cloneRaw;
+
+ rv = aLocalFile->Clone(getter_AddRefs(cloneRaw));
+ if(NS_FAILED(rv))
+ return rv;
+
+ return CallQueryInterface(cloneRaw, aCloneLocalFile);
+}
+
+
+nsresult
+xptiCloneElementAsLocalFile(nsISupportsArray* aArray, PRUint32 aIndex,
+ nsILocalFile** aLocalFile)
+{
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> original;
+
+ rv = aArray->QueryElementAt(aIndex, NS_GET_IID(nsILocalFile),
+ getter_AddRefs(original));
+ if(NS_FAILED(rv))
+ return rv;
+
+ return xptiCloneLocalFile(original, aLocalFile);
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiTypelibGuts.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiTypelibGuts.cpp
new file mode 100644
index 00000000..50956585
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiTypelibGuts.cpp
@@ -0,0 +1,63 @@
+/* -*- 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) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * 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 ***** */
+
+/* Implementation of xptiTypelibGuts. */
+
+#include "xptiprivate.h"
+
+// static
+xptiTypelibGuts*
+xptiTypelibGuts::NewGuts(XPTHeader* aHeader,
+ xptiWorkingSet* aWorkingSet)
+{
+ NS_ASSERTION(aHeader, "bad param");
+ void* place = XPT_MALLOC(aWorkingSet->GetStructArena(),
+ sizeof(xptiTypelibGuts) +
+ (sizeof(xptiInterfaceEntry*) *
+ (aHeader->num_interfaces - 1)));
+ if(!place)
+ return nsnull;
+ return new(place) xptiTypelibGuts(aHeader);
+}
+
+xptiTypelibGuts::xptiTypelibGuts(XPTHeader* aHeader)
+ : mHeader(aHeader)
+{
+ // empty
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiWorkingSet.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiWorkingSet.cpp
new file mode 100644
index 00000000..b9602726
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiWorkingSet.cpp
@@ -0,0 +1,432 @@
+/* -*- 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) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * 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 ***** */
+
+/* Implementation of xptiWorkingSet. */
+
+#include "xptiprivate.h"
+#include "nsString.h"
+
+#define XPTI_STRING_ARENA_BLOCK_SIZE (1024 * 1)
+#define XPTI_STRUCT_ARENA_BLOCK_SIZE (1024 * 1)
+#define XPTI_HASHTABLE_SIZE 128
+
+/***************************************************************************/
+
+PR_STATIC_CALLBACK(const void*)
+IIDGetKey(PLDHashTable *table, PLDHashEntryHdr *entry)
+{
+ return ((xptiHashEntry*)entry)->value->GetTheIID();
+}
+
+PR_STATIC_CALLBACK(PLDHashNumber)
+IIDHash(PLDHashTable *table, const void *key)
+{
+ return (PLDHashNumber) ((const nsIID*)key)->m0;
+}
+
+PR_STATIC_CALLBACK(PRBool)
+IIDMatch(PLDHashTable *table,
+ const PLDHashEntryHdr *entry,
+ const void *key)
+{
+ const nsIID* iid1 = ((xptiHashEntry*)entry)->value->GetTheIID();
+ const nsIID* iid2 = (const nsIID*)key;
+
+ return iid1 == iid2 || iid1->Equals(*iid2);
+}
+
+const static struct PLDHashTableOps IIDTableOps =
+{
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ IIDGetKey,
+ IIDHash,
+ IIDMatch,
+ PL_DHashMoveEntryStub,
+ PL_DHashClearEntryStub,
+ PL_DHashFinalizeStub
+};
+
+/***************************************************************************/
+
+PR_STATIC_CALLBACK(const void*)
+NameGetKey(PLDHashTable *table, PLDHashEntryHdr *entry)
+{
+ return ((xptiHashEntry*)entry)->value->GetTheName();
+}
+
+PR_STATIC_CALLBACK(PRBool)
+NameMatch(PLDHashTable *table,
+ const PLDHashEntryHdr *entry,
+ const void *key)
+{
+ const char* str1 = ((xptiHashEntry*)entry)->value->GetTheName();
+ const char* str2 = (const char*) key;
+ return str1 == str2 || 0 == PL_strcmp(str1, str2);
+}
+
+static const struct PLDHashTableOps NameTableOps =
+{
+ PL_DHashAllocTable,
+ PL_DHashFreeTable,
+ NameGetKey,
+ PL_DHashStringKey,
+ NameMatch,
+ PL_DHashMoveEntryStub,
+ PL_DHashClearEntryStub,
+ PL_DHashFinalizeStub
+};
+
+/***************************************************************************/
+
+MOZ_DECL_CTOR_COUNTER(xptiWorkingSet)
+
+xptiWorkingSet::xptiWorkingSet(nsISupportsArray* aDirectories)
+ : mFileCount(0),
+ mMaxFileCount(0),
+ mFileArray(nsnull),
+ mZipItemCount(0),
+ mMaxZipItemCount(0),
+ mZipItemArray(nsnull),
+ mStringArena(XPT_NewArena(XPTI_STRING_ARENA_BLOCK_SIZE, sizeof(char),
+ "xptiWorkingSet strings")),
+ mStructArena(XPT_NewArena(XPTI_STRUCT_ARENA_BLOCK_SIZE, sizeof(double),
+ "xptiWorkingSet structs")),
+ mDirectories(aDirectories),
+ mNameTable(PL_NewDHashTable(&NameTableOps, nsnull, sizeof(xptiHashEntry),
+ XPTI_HASHTABLE_SIZE)),
+ mIIDTable(PL_NewDHashTable(&IIDTableOps, nsnull, sizeof(xptiHashEntry),
+ XPTI_HASHTABLE_SIZE)),
+ mFileMergeOffsetMap(nsnull),
+ mZipItemMergeOffsetMap(nsnull)
+{
+ MOZ_COUNT_CTOR(xptiWorkingSet);
+ // do nothing else...
+}
+
+PRBool
+xptiWorkingSet::IsValid() const
+{
+ return (mFileCount == 0 || mFileArray) &&
+ (mZipItemCount == 0 || mZipItemArray) &&
+ mStringArena &&
+ mStructArena &&
+ mNameTable &&
+ mIIDTable;
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+xpti_Remover(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg)
+{
+ return PL_DHASH_REMOVE;
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+xpti_Invalidator(PLDHashTable *table, PLDHashEntryHdr *hdr,
+ PRUint32 number, void *arg)
+{
+ xptiInterfaceEntry* entry = ((xptiHashEntry*)hdr)->value;
+ entry->LockedInvalidateInterfaceInfo();
+ return PL_DHASH_NEXT;
+}
+
+void
+xptiWorkingSet::InvalidateInterfaceInfos()
+{
+ if(mNameTable)
+ {
+ nsAutoMonitor lock(xptiInterfaceInfoManager::GetInfoMonitor());
+ PL_DHashTableEnumerate(mNameTable, xpti_Invalidator, nsnull);
+ }
+}
+
+void
+xptiWorkingSet::ClearHashTables()
+{
+ if(mNameTable)
+ PL_DHashTableEnumerate(mNameTable, xpti_Remover, nsnull);
+
+ if(mIIDTable)
+ PL_DHashTableEnumerate(mIIDTable, xpti_Remover, nsnull);
+}
+
+void
+xptiWorkingSet::ClearFiles()
+{
+ if(mFileArray)
+ delete [] mFileArray;
+ mFileArray = nsnull;
+ mMaxFileCount = 0;
+ mFileCount = 0;
+}
+
+void
+xptiWorkingSet::ClearZipItems()
+{
+ if(mZipItemArray)
+ delete [] mZipItemArray;
+ mZipItemArray = nsnull;
+ mMaxZipItemCount = 0;
+ mZipItemCount = 0;
+}
+
+xptiWorkingSet::~xptiWorkingSet()
+{
+ MOZ_COUNT_DTOR(xptiWorkingSet);
+
+ ClearFiles();
+ ClearZipItems();
+ ClearHashTables();
+
+ if(mNameTable)
+ PL_DHashTableDestroy(mNameTable);
+
+ if(mIIDTable)
+ PL_DHashTableDestroy(mIIDTable);
+
+ if(mFileArray)
+ delete [] mFileArray;
+
+ if(mZipItemArray)
+ delete [] mZipItemArray;
+
+ // Destroy arenas last in case they are referenced in other members' dtors.
+
+ if(mStringArena)
+ {
+#ifdef DEBUG
+ XPT_DumpStats(mStringArena);
+#endif
+ XPT_DestroyArena(mStringArena);
+ }
+
+ if(mStructArena)
+ {
+#ifdef DEBUG
+ XPT_DumpStats(mStructArena);
+#endif
+ XPT_DestroyArena(mStructArena);
+ }
+}
+
+PRUint32
+xptiWorkingSet::FindFile(PRUint32 dir, const char* name)
+{
+ if(mFileArray)
+ {
+ for(PRUint32 i = 0; i < mFileCount;++i)
+ {
+ xptiFile& file = mFileArray[i];
+ if(file.GetDirectory() == dir &&
+ 0 == PL_strcmp(name, file.GetName()))
+ {
+ return i;
+ }
+ }
+ }
+ return NOT_FOUND;
+}
+
+PRBool
+xptiWorkingSet::NewFileArray(PRUint32 count)
+{
+ if(mFileArray)
+ delete [] mFileArray;
+ mFileCount = 0;
+ mFileArray = new xptiFile[count];
+ if(!mFileArray)
+ {
+ mMaxFileCount = 0;
+ return PR_FALSE;
+ }
+ mMaxFileCount = count;
+ return PR_TRUE;
+}
+
+PRBool
+xptiWorkingSet::ExtendFileArray(PRUint32 count)
+{
+ if(mFileArray && count < mMaxFileCount)
+ return PR_TRUE;
+
+ xptiFile* newArray = new xptiFile[count];
+ if(!newArray)
+ return PR_FALSE;
+
+ if(mFileArray)
+ {
+ for(PRUint32 i = 0; i < mFileCount; ++i)
+ newArray[i] = mFileArray[i];
+ delete [] mFileArray;
+ }
+ mFileArray = newArray;
+ mMaxFileCount = count;
+ return PR_TRUE;
+}
+
+/***************************************************************************/
+
+PRUint32
+xptiWorkingSet::FindZipItemWithName(const char* name)
+{
+ if(mZipItemArray)
+ {
+ for(PRUint32 i = 0; i < mZipItemCount;++i)
+ if(0 == PL_strcmp(name, mZipItemArray[i].GetName()))
+ return i;
+ }
+ return NOT_FOUND;
+}
+
+PRBool
+xptiWorkingSet::NewZipItemArray(PRUint32 count)
+{
+ if(mZipItemArray)
+ delete [] mZipItemArray;
+ mZipItemCount = 0;
+ mZipItemArray = new xptiZipItem[count];
+ if(!mZipItemArray)
+ {
+ mMaxZipItemCount = 0;
+ return PR_FALSE;
+ }
+ mMaxZipItemCount = count;
+ return PR_TRUE;
+}
+
+PRBool
+xptiWorkingSet::ExtendZipItemArray(PRUint32 count)
+{
+ if(mZipItemArray && count < mMaxZipItemCount)
+ return PR_TRUE;
+
+ xptiZipItem* newArray = new xptiZipItem[count];
+ if(!newArray)
+ return PR_FALSE;
+
+ if(mZipItemArray)
+ {
+ for(PRUint32 i = 0; i < mZipItemCount; ++i)
+ newArray[i] = mZipItemArray[i];
+ delete [] mZipItemArray;
+ }
+ mZipItemArray = newArray;
+ mMaxZipItemCount = count;
+ return PR_TRUE;
+}
+
+/***************************************************************************/
+// Directory stuff...
+
+PRUint32 xptiWorkingSet::GetDirectoryCount()
+{
+ PRUint32 count = 0;
+ mDirectories->Count(&count);
+ return count;
+}
+
+nsresult xptiWorkingSet::GetCloneOfDirectoryAt(PRUint32 i, nsILocalFile** dir)
+{
+ return xptiCloneElementAsLocalFile(mDirectories, i, dir);
+}
+
+nsresult xptiWorkingSet::GetDirectoryAt(PRUint32 i, nsILocalFile** dir)
+{
+ return mDirectories->QueryElementAt(i, NS_GET_IID(nsILocalFile), (void**)dir);
+}
+
+PRBool xptiWorkingSet::FindDirectory(nsILocalFile* dir, PRUint32* index)
+{
+ PRUint32 count;
+ nsresult rv = mDirectories->Count(&count);
+ if(NS_FAILED(rv))
+ return PR_FALSE;
+
+ for(PRUint32 i = 0; i < count; i++)
+ {
+ PRBool same;
+ nsCOMPtr<nsILocalFile> current;
+ mDirectories->QueryElementAt(i, NS_GET_IID(nsILocalFile),
+ getter_AddRefs(current));
+ if(!current || NS_FAILED(current->Equals(dir, &same)))
+ break;
+ if(same)
+ {
+ *index = i;
+ return PR_TRUE;
+ }
+ }
+ return PR_FALSE;
+}
+
+PRBool xptiWorkingSet::FindDirectoryOfFile(nsILocalFile* file, PRUint32* index)
+{
+ nsCOMPtr<nsIFile> dirAbstract;
+ file->GetParent(getter_AddRefs(dirAbstract));
+ if(!dirAbstract)
+ return PR_FALSE;
+ nsCOMPtr<nsILocalFile> dir = do_QueryInterface(dirAbstract);
+ if(!dir)
+ return PR_FALSE;
+ return FindDirectory(dir, index);
+}
+
+PRBool xptiWorkingSet::DirectoryAtMatchesPersistentDescriptor(PRUint32 i,
+ const char* inDesc)
+{
+ nsCOMPtr<nsILocalFile> dir;
+ GetDirectoryAt(i, getter_AddRefs(dir));
+ if(!dir)
+ return PR_FALSE;
+
+ nsCOMPtr<nsILocalFile> descDir;
+ nsresult rv = NS_NewNativeLocalFile(EmptyCString(), PR_FALSE, getter_AddRefs(descDir));
+ if(NS_FAILED(rv))
+ return PR_FALSE;
+
+ rv = descDir->SetPersistentDescriptor(nsDependentCString(inDesc));
+ if(NS_FAILED(rv))
+ return PR_FALSE;
+
+ PRBool matches;
+ rv = dir->Equals(descDir, &matches);
+ return NS_SUCCEEDED(rv) && matches;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiZipItem.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiZipItem.cpp
new file mode 100644
index 00000000..c9a6178b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiZipItem.cpp
@@ -0,0 +1,102 @@
+/* -*- 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) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * 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 ***** */
+
+/* Implementation of xptiZipItem. */
+
+#include "xptiprivate.h"
+
+MOZ_DECL_CTOR_COUNTER(xptiZipItem)
+
+xptiZipItem::xptiZipItem()
+ :
+#ifdef DEBUG
+ mDEBUG_WorkingSet(nsnull),
+#endif
+ mName(nsnull),
+ mGuts(nsnull)
+{
+ MOZ_COUNT_CTOR(xptiZipItem);
+ // empty
+}
+
+xptiZipItem::xptiZipItem(const char* aName,
+ xptiWorkingSet* aWorkingSet)
+
+ :
+#ifdef DEBUG
+ mDEBUG_WorkingSet(aWorkingSet),
+#endif
+ mName(aName),
+ mGuts(nsnull)
+{
+ MOZ_COUNT_CTOR(xptiZipItem);
+
+ NS_ASSERTION(aWorkingSet,"bad param");
+ mName = XPT_STRDUP(aWorkingSet->GetStringArena(), aName);
+}
+
+xptiZipItem::xptiZipItem(const xptiZipItem& r, xptiWorkingSet* aWorkingSet)
+ :
+#ifdef DEBUG
+ mDEBUG_WorkingSet(aWorkingSet),
+#endif
+ mName(nsnull),
+ mGuts(nsnull)
+{
+ MOZ_COUNT_CTOR(xptiZipItem);
+
+ NS_ASSERTION(aWorkingSet,"bad param");
+ mName = XPT_STRDUP(aWorkingSet->GetStringArena(), r.mName);
+}
+
+xptiZipItem::~xptiZipItem()
+{
+ MOZ_COUNT_DTOR(xptiZipItem);
+}
+
+PRBool
+xptiZipItem::SetHeader(XPTHeader* aHeader, xptiWorkingSet* aWorkingSet)
+{
+ NS_ASSERTION(!mGuts,"bad state");
+ NS_ASSERTION(aHeader,"bad param");
+ NS_ASSERTION(aWorkingSet,"bad param");
+
+ mGuts = xptiTypelibGuts::NewGuts(aHeader, aWorkingSet);
+ return mGuts != nsnull;
+}
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiZipLoader.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiZipLoader.cpp
new file mode 100644
index 00000000..caba49d5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiZipLoader.cpp
@@ -0,0 +1,113 @@
+/* -*- 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) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * 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 ***** */
+
+/* Implementation of xptiZipLoader. */
+
+#include "xptiprivate.h"
+
+XPTHeader*
+xptiZipLoader::ReadXPTFileFromInputStream(nsIInputStream *stream,
+ xptiWorkingSet* aWorkingSet)
+{
+ XPTCursor cursor;
+ PRUint32 totalRead = 0;
+ XPTState *state = nsnull;
+ XPTHeader *header = nsnull;
+
+ PRUint32 flen;
+ stream->Available(&flen);
+
+ char *whole = new char[flen];
+ if (!whole)
+ {
+ return nsnull;
+ }
+
+ // all exits from on here should be via 'goto out'
+
+ while(flen - totalRead)
+ {
+ PRUint32 avail;
+ PRUint32 read;
+
+ if(NS_FAILED(stream->Available(&avail)))
+ {
+ goto out;
+ }
+
+ if(avail > flen)
+ {
+ goto out;
+ }
+
+ if(NS_FAILED(stream->Read(whole+totalRead, avail, &read)))
+ {
+ goto out;
+ }
+
+ totalRead += read;
+ }
+
+ // Go ahead and close the stream now.
+ stream = nsnull;
+
+ if(!(state = XPT_NewXDRState(XPT_DECODE, whole, flen)))
+ {
+ goto out;
+ }
+
+ if(!XPT_MakeCursor(state, XPT_HEADER, 0, &cursor))
+ {
+ goto out;
+ }
+
+ if (!XPT_DoHeader(aWorkingSet->GetStructArena(), &cursor, &header))
+ {
+ header = nsnull;
+ goto out;
+ }
+
+ out:
+ if(state)
+ XPT_DestroyXDRState(state);
+ if(whole)
+ delete [] whole;
+ return header;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiprivate.h b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiprivate.h
new file mode 100644
index 00000000..3d159c2c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiprivate.h
@@ -0,0 +1,981 @@
+/* -*- 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) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mike McCabe <mccabe@netscape.com>
+ * 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 ***** */
+
+/* Library-private header for Interface Info system. */
+
+#ifndef xptiprivate_h___
+#define xptiprivate_h___
+
+#include "nscore.h"
+#include "nsISupports.h"
+
+// this after nsISupports, to pick up IID
+// so that xpt stuff doesn't try to define it itself...
+#include "xpt_struct.h"
+#include "xpt_xdr.h"
+
+#include "nsIInterfaceInfo.h"
+#include "nsIInterfaceInfoManager.h"
+#include "xptinfo.h"
+#include "nsIXPTLoader.h"
+
+#include "nsIServiceManager.h"
+#include "nsILocalFile.h"
+#include "nsIDirectoryService.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsAppDirectoryServiceDefs.h"
+#include "nsIWeakReference.h"
+
+#include "nsCRT.h"
+#include "nsMemory.h"
+
+#include "nsISupportsArray.h"
+#include "nsSupportsArray.h"
+#include "nsInt64.h"
+
+#include "nsQuickSort.h"
+
+#include "nsXPIDLString.h"
+
+#include "nsIInputStream.h"
+
+#include "nsAutoLock.h"
+
+#include "pldhash.h"
+#include "plstr.h"
+#include "prprf.h"
+#include "prio.h"
+#include "prtime.h"
+#include "prenv.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+
+/***************************************************************************/
+
+#if 0 && defined(DEBUG_jband)
+#define LOG_RESOLVE(x) printf x
+#define LOG_LOAD(x) printf x
+#define LOG_AUTOREG(x) do{printf x; xptiInterfaceInfoManager::WriteToLog x;}while(0)
+#else
+#define LOG_RESOLVE(x) ((void)0)
+#define LOG_LOAD(x) ((void)0)
+#define LOG_AUTOREG(x) xptiInterfaceInfoManager::WriteToLog x
+#endif
+
+#if 1 && defined(DEBUG_jband)
+#define SHOW_INFO_COUNT_STATS
+#endif
+
+/***************************************************************************/
+
+class xptiFile;
+class xptiInterfaceInfo;
+class xptiInterfaceInfoManager;
+class xptiInterfaceEntry;
+class xptiInterfaceGuts;
+class xptiTypelibGuts;
+class xptiWorkingSet;
+
+/***************************************************************************/
+
+class xptiTypelib
+{
+public:
+ // No ctors or dtors so that we can be in a union in xptiInterfaceInfo.
+ // Allow automatic shallow copies.
+
+ uint16 GetFileIndex() const {return mFileIndex;}
+ uint16 GetZipItemIndex() const {return mZipItemIndex;}
+
+ enum {NOT_ZIP = 0xffff};
+
+ PRBool IsZip() const {return mZipItemIndex != NOT_ZIP;}
+
+ void Init(uint16 aFileIndex, uint16 aZipItemIndex = NOT_ZIP)
+ {mFileIndex = aFileIndex; mZipItemIndex = aZipItemIndex;}
+
+ PRBool Equals(const xptiTypelib& r) const
+ {return mFileIndex == r.mFileIndex &&
+ mZipItemIndex == r.mZipItemIndex;}
+
+private:
+ uint16 mFileIndex;
+ uint16 mZipItemIndex;
+};
+
+/***************************************************************************/
+
+// No virtuals.
+// These are always constructed in the struct arena using placement new.
+// dtor need not be called.
+
+class xptiTypelibGuts
+{
+public:
+ static xptiTypelibGuts* NewGuts(XPTHeader* aHeader,
+ xptiWorkingSet* aWorkingSet);
+
+ XPTHeader* GetHeader() {return mHeader;}
+ PRUint16 GetEntryCount() const {return mHeader->num_interfaces;}
+
+ void SetEntryAt(PRUint16 i, xptiInterfaceEntry* ptr)
+ {
+ NS_ASSERTION(mHeader,"bad state!");
+ NS_ASSERTION(i < GetEntryCount(),"bad param!");
+ mEntryArray[i] = ptr;
+ }
+
+ xptiInterfaceEntry* GetEntryAt(PRUint16 i) const
+ {
+ NS_ASSERTION(mHeader,"bad state!");
+ NS_ASSERTION(i < GetEntryCount(),"bad param!");
+ return mEntryArray[i];
+ }
+
+private:
+ xptiTypelibGuts(); // not implemented
+ xptiTypelibGuts(XPTHeader* aHeader);
+ ~xptiTypelibGuts() {}
+ void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
+
+private:
+ XPTHeader* mHeader; // hold pointer into arena
+ xptiInterfaceEntry* mEntryArray[1]; // Always last. Sized to fit.
+};
+
+/***************************************************************************/
+
+class xptiFile
+{
+public:
+ const nsInt64& GetSize() const {return mSize;}
+ const nsInt64& GetDate() const {return mDate;}
+ const char* GetName() const {return mName;}
+ /*const*/ PRUint32 GetDirectory() const {return mDirectory;}
+ xptiTypelibGuts* GetGuts() {return mGuts;}
+
+ xptiFile();
+
+ xptiFile(const nsInt64& aSize,
+ const nsInt64& aDate,
+ PRUint32 aDirectory,
+ const char* aName,
+ xptiWorkingSet* aWorkingSet);
+
+ xptiFile(const xptiFile& r, xptiWorkingSet* aWorkingSet);
+
+ ~xptiFile();
+
+ PRBool SetHeader(XPTHeader* aHeader, xptiWorkingSet* aWorkingSet);
+
+ PRBool Equals(const xptiFile& r) const
+ {
+ return mDirectory == r.mDirectory &&
+ mSize == r.mSize &&
+ mDate == r.mDate &&
+ 0 == PL_strcmp(mName, r.mName);
+ }
+
+ xptiFile(const xptiFile& r) {CopyFields(r);}
+ xptiFile& operator= (const xptiFile& r)
+ {
+ if(this != &r)
+ CopyFields(r);
+ return *this;
+ }
+
+private:
+ void CopyFields(const xptiFile& r)
+ {
+#ifdef DEBUG
+ // If 'this' has a workingset then it better match that of the assigner.
+ NS_ASSERTION(!mDEBUG_WorkingSet ||
+ mDEBUG_WorkingSet == r.mDEBUG_WorkingSet,
+ "illegal xptiFile assignment");
+ mDEBUG_WorkingSet = r.mDEBUG_WorkingSet;
+#endif
+
+ mSize = r.mSize;
+ mDate = r.mDate;
+ mName = r.mName;
+ mDirectory = r.mDirectory;
+ mGuts = r.mGuts;
+ }
+
+private:
+#ifdef DEBUG
+ xptiWorkingSet* mDEBUG_WorkingSet;
+#endif
+ nsInt64 mSize;
+ nsInt64 mDate;
+ const char* mName; // hold pointer into arena from initializer
+ xptiTypelibGuts* mGuts; // hold pointer into arena
+ PRUint32 mDirectory;
+};
+
+/***************************************************************************/
+
+class xptiZipItem
+{
+public:
+ const char* GetName() const {return mName;}
+ xptiTypelibGuts* GetGuts() {return mGuts;}
+
+ xptiZipItem();
+
+ xptiZipItem(const char* aName,
+ xptiWorkingSet* aWorkingSet);
+
+ xptiZipItem(const xptiZipItem& r, xptiWorkingSet* aWorkingSet);
+
+ ~xptiZipItem();
+
+ PRBool SetHeader(XPTHeader* aHeader, xptiWorkingSet* aWorkingSet);
+
+ PRBool Equals(const xptiZipItem& r) const
+ {
+ return 0 == PL_strcmp(mName, r.mName);
+ }
+
+ xptiZipItem(const xptiZipItem& r) {CopyFields(r);}
+ xptiZipItem& operator= (const xptiZipItem& r)
+ {
+ if(this != &r)
+ CopyFields(r);
+ return *this;
+ }
+
+private:
+ void CopyFields(const xptiZipItem& r)
+ {
+#ifdef DEBUG
+ // If 'this' has a workingset then it better match that of the assigner.
+ NS_ASSERTION(!mDEBUG_WorkingSet ||
+ mDEBUG_WorkingSet == r.mDEBUG_WorkingSet,
+ "illegal xptiFile assignment");
+ mDEBUG_WorkingSet = r.mDEBUG_WorkingSet;
+#endif
+
+ mName = r.mName;
+ mGuts = r.mGuts;
+ }
+
+private:
+#ifdef DEBUG
+ xptiWorkingSet* mDEBUG_WorkingSet;
+#endif
+ const char* mName; // hold pointer into arena from initializer
+ xptiTypelibGuts* mGuts; // hold pointer into arena
+};
+
+/***************************************************************************/
+
+class xptiWorkingSet
+{
+public:
+ xptiWorkingSet(); // not implmented
+ xptiWorkingSet(nsISupportsArray* aDirectories);
+ ~xptiWorkingSet();
+
+ PRBool IsValid() const;
+
+ void InvalidateInterfaceInfos();
+ void ClearHashTables();
+ void ClearFiles();
+ void ClearZipItems();
+
+ // utility methods...
+
+ xptiTypelibGuts* GetTypelibGuts(const xptiTypelib& typelib)
+ {
+ return typelib.IsZip() ?
+ GetZipItemAt(typelib.GetZipItemIndex()).GetGuts() :
+ GetFileAt(typelib.GetFileIndex()).GetGuts();
+ }
+
+ enum {NOT_FOUND = 0xffffffff};
+
+ // FileArray stuff...
+
+ PRUint32 GetFileCount() const {return mFileCount;}
+ PRUint32 GetFileFreeSpace()
+ {return mFileArray ? mMaxFileCount - mFileCount : 0;}
+
+ PRUint32 FindFile(PRUint32 dir, const char* name);
+
+ PRUint32 GetTypelibDirectoryIndex(const xptiTypelib& typelib)
+ {
+ return GetFileAt(typelib.GetFileIndex()).GetDirectory();
+ }
+
+ const char* GetTypelibFileName(const xptiTypelib& typelib)
+ {
+ return GetFileAt(typelib.GetFileIndex()).GetName();
+ }
+
+ xptiFile& GetFileAt(PRUint32 i) const
+ {
+ NS_ASSERTION(mFileArray, "bad state!");
+ NS_ASSERTION(i < mFileCount, "bad param!");
+ return mFileArray[i];
+ }
+
+ void SetFileAt(PRUint32 i, const xptiFile& r)
+ {
+ NS_ASSERTION(mFileArray, "bad state!");
+ NS_ASSERTION(i < mFileCount, "bad param!");
+ mFileArray[i] = r;
+ }
+
+ void AppendFile(const xptiFile& r)
+ {
+ NS_ASSERTION(mFileArray, "bad state!");
+ NS_ASSERTION(mFileCount < mMaxFileCount, "bad param!");
+ mFileArray[mFileCount++] = r;
+ }
+
+ PRBool NewFileArray(PRUint32 count);
+ PRBool ExtendFileArray(PRUint32 count);
+
+ // ZipItemArray stuff...
+
+ PRUint32 GetZipItemCount() const {return mZipItemCount;}
+ PRUint32 GetZipItemFreeSpace()
+ {return mZipItemArray ? mMaxZipItemCount - mZipItemCount : 0;}
+
+ PRUint32 FindZipItemWithName(const char* name);
+
+ xptiZipItem& GetZipItemAt(PRUint32 i) const
+ {
+ NS_ASSERTION(mZipItemArray, "bad state!");
+ NS_ASSERTION(i < mZipItemCount, "bad param!");
+ return mZipItemArray[i];
+ }
+
+ void SetZipItemAt(PRUint32 i, const xptiZipItem& r)
+ {
+ NS_ASSERTION(mZipItemArray, "bad state!");
+ NS_ASSERTION(i < mZipItemCount, "bad param!");
+ mZipItemArray[i] = r;
+ }
+
+ void AppendZipItem(const xptiZipItem& r)
+ {
+ NS_ASSERTION(mZipItemArray, "bad state!");
+ NS_ASSERTION(mZipItemCount < mMaxZipItemCount, "bad param!");
+ mZipItemArray[mZipItemCount++] = r;
+ }
+
+ PRBool NewZipItemArray(PRUint32 count);
+ PRBool ExtendZipItemArray(PRUint32 count);
+
+ // Directory stuff...
+
+ PRUint32 GetDirectoryCount();
+ nsresult GetCloneOfDirectoryAt(PRUint32 i, nsILocalFile** dir);
+ nsresult GetDirectoryAt(PRUint32 i, nsILocalFile** dir);
+ PRBool FindDirectory(nsILocalFile* dir, PRUint32* index);
+ PRBool FindDirectoryOfFile(nsILocalFile* file, PRUint32* index);
+ PRBool DirectoryAtMatchesPersistentDescriptor(PRUint32 i, const char* desc);
+
+ // Arena stuff...
+
+ XPTArena* GetStringArena() {return mStringArena;}
+ XPTArena* GetStructArena() {return mStructArena;}
+
+
+private:
+ PRUint32 mFileCount;
+ PRUint32 mMaxFileCount;
+ xptiFile* mFileArray; // using new[] and delete[]
+
+ PRUint32 mZipItemCount;
+ PRUint32 mMaxZipItemCount;
+ xptiZipItem* mZipItemArray; // using new[] and delete[]
+
+ XPTArena* mStringArena;
+ XPTArena* mStructArena;
+
+ nsCOMPtr<nsISupportsArray> mDirectories;
+
+public:
+ // XXX make these private with accessors
+ PLDHashTable* mNameTable;
+ PLDHashTable* mIIDTable;
+ PRUint32* mFileMergeOffsetMap; // always in an arena
+ PRUint32* mZipItemMergeOffsetMap; // always in an arena
+};
+
+/***************************************************************************/
+
+class xptiInterfaceGuts
+{
+public:
+ uint16 mMethodBaseIndex;
+ uint16 mConstantBaseIndex;
+ xptiInterfaceEntry* mParent;
+ XPTInterfaceDescriptor* mDescriptor;
+ xptiTypelib mTypelib;
+ xptiWorkingSet* mWorkingSet;
+
+ static xptiInterfaceGuts* NewGuts(XPTInterfaceDescriptor* aDescriptor,
+ const xptiTypelib& aTypelib,
+ xptiWorkingSet* aWorkingSet)
+ {
+ void* place = XPT_MALLOC(aWorkingSet->GetStructArena(),
+ sizeof(xptiInterfaceGuts));
+ if(!place)
+ return nsnull;
+ return new(place) xptiInterfaceGuts(aDescriptor, aTypelib, aWorkingSet);
+ }
+
+private:
+ void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
+ xptiInterfaceGuts(XPTInterfaceDescriptor* aDescriptor,
+ const xptiTypelib& aTypelib,
+ xptiWorkingSet* aWorkingSet)
+ : mMethodBaseIndex(0),
+ mConstantBaseIndex(0),
+ mParent(nsnull),
+ mDescriptor(aDescriptor),
+ mTypelib(aTypelib),
+ mWorkingSet(aWorkingSet) {}
+
+ ~xptiInterfaceGuts() {}
+};
+
+/***************************************************************************/
+
+// This class exists to help xptiInterfaceInfo store a 4-state (2 bit) value
+// and a set of bitflags in one 8bit value. See below.
+
+class xptiInfoFlags
+{
+ enum {STATE_MASK = 3};
+public:
+ xptiInfoFlags(uint8 n) : mData(n) {}
+ xptiInfoFlags(const xptiInfoFlags& r) : mData(r.mData) {}
+
+ static uint8 GetStateMask()
+ {return uint8(STATE_MASK);}
+
+ void Clear()
+ {mData = 0;}
+
+ uint8 GetData() const
+ {return mData;}
+
+ uint8 GetState() const
+ {return mData & GetStateMask();}
+
+ void SetState(uint8 state)
+ {mData &= ~GetStateMask(); mData |= state;}
+
+ void SetFlagBit(uint8 flag, PRBool on)
+ {if(on)
+ mData |= ~GetStateMask() & flag;
+ else
+ mData &= GetStateMask() | ~flag;}
+
+ PRBool GetFlagBit(uint8 flag) const
+ {return (mData & flag) ? PR_TRUE : PR_FALSE;}
+
+private:
+ uint8 mData;
+};
+
+/****************************************************/
+
+// No virtual methods.
+// We always create in the struct arena and construct using "placement new".
+// No members need dtor calls.
+
+class xptiInterfaceEntry
+{
+public:
+ static xptiInterfaceEntry* NewEntry(const char* name,
+ int nameLength,
+ const nsID& iid,
+ const xptiTypelib& typelib,
+ xptiWorkingSet* aWorkingSet);
+
+ static xptiInterfaceEntry* NewEntry(const xptiInterfaceEntry& r,
+ const xptiTypelib& typelib,
+ xptiWorkingSet* aWorkingSet);
+
+ enum {
+ NOT_RESOLVED = 0,
+ PARTIALLY_RESOLVED = 1,
+ FULLY_RESOLVED = 2,
+ RESOLVE_FAILED = 3
+ };
+
+ // Additional bit flags...
+ enum {SCRIPTABLE = 4};
+
+ uint8 GetResolveState() const {return mFlags.GetState();}
+
+ PRBool IsFullyResolved() const
+ {return GetResolveState() == (uint8) FULLY_RESOLVED;}
+
+ PRBool HasInterfaceRecord() const
+ {int s = (int) GetResolveState();
+ return (s == PARTIALLY_RESOLVED || s == FULLY_RESOLVED) && mInterface;}
+
+ const xptiTypelib& GetTypelibRecord() const
+ {return HasInterfaceRecord() ? mInterface->mTypelib : mTypelib;}
+
+ xptiInterfaceGuts* GetInterfaceGuts() const
+ {return HasInterfaceRecord() ? mInterface : nsnull;}
+
+#ifdef DEBUG
+ PRBool DEBUG_ScriptableFlagIsValid() const
+ {int s = (int) GetResolveState();
+ if((s == PARTIALLY_RESOLVED || s == FULLY_RESOLVED) && mInterface)
+ {
+ if(XPT_ID_IS_SCRIPTABLE(mInterface->mDescriptor->flags))
+ return GetScriptableFlag();
+ return !GetScriptableFlag();
+ }
+ return PR_TRUE;
+ }
+#endif
+
+ void SetScriptableFlag(PRBool on)
+ {mFlags.SetFlagBit(uint8(SCRIPTABLE),on);}
+ PRBool GetScriptableFlag() const
+ {return mFlags.GetFlagBit(uint8(SCRIPTABLE));}
+
+ const nsID* GetTheIID() const {return &mIID;}
+ const char* GetTheName() const {return mName;}
+
+ PRBool EnsureResolved(xptiWorkingSet* aWorkingSet = nsnull)
+ {return IsFullyResolved() ? PR_TRUE : Resolve(aWorkingSet);}
+
+ PRBool PartiallyResolveLocked(XPTInterfaceDescriptor* aDescriptor,
+ xptiWorkingSet* aWorkingSet);
+
+ nsresult GetInterfaceInfo(xptiInterfaceInfo** info);
+ PRBool InterfaceInfoEquals(const xptiInterfaceInfo* info) const
+ {return info == mInfo;}
+
+ void LockedInvalidateInterfaceInfo();
+ void LockedInterfaceInfoDeathNotification() {mInfo = nsnull;}
+
+ //////////////////////
+ // These non-virtual methods handle the delegated nsIInterfaceInfo methods.
+
+ nsresult GetName(char * *aName);
+ nsresult GetIID(nsIID * *aIID);
+ nsresult IsScriptable(PRBool *_retval);
+ // Except this one.
+ //nsresult GetParent(nsIInterfaceInfo * *aParent);
+ nsresult GetMethodCount(PRUint16 *aMethodCount);
+ nsresult GetConstantCount(PRUint16 *aConstantCount);
+ nsresult GetMethodInfo(PRUint16 index, const nsXPTMethodInfo * *info);
+ nsresult GetMethodInfoForName(const char *methodName, PRUint16 *index, const nsXPTMethodInfo * *info);
+ nsresult GetConstant(PRUint16 index, const nsXPTConstant * *constant);
+ nsresult GetInfoForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval);
+ nsresult GetIIDForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID * *_retval);
+ nsresult GetTypeForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, nsXPTType *_retval);
+ nsresult GetSizeIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval);
+ nsresult GetLengthIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval);
+ nsresult GetInterfaceIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint8 *_retval);
+ nsresult IsIID(const nsIID * IID, PRBool *_retval);
+ nsresult GetNameShared(const char **name);
+ nsresult GetIIDShared(const nsIID * *iid);
+ nsresult IsFunction(PRBool *_retval);
+ nsresult HasAncestor(const nsIID * iid, PRBool *_retval);
+ nsresult GetIIDForParamNoAlloc(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID *iid);
+
+ //////////////////////
+
+private:
+ xptiInterfaceEntry(); // not implemented
+
+ xptiInterfaceEntry(const char* name,
+ size_t nameLength,
+ const nsID& iid,
+ const xptiTypelib& typelib);
+
+ xptiInterfaceEntry(const xptiInterfaceEntry& r,
+ size_t nameLength,
+ const xptiTypelib& typelib);
+ ~xptiInterfaceEntry();
+
+ void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
+
+ void SetResolvedState(int state)
+ {mFlags.SetState(uint8(state));}
+
+ PRBool Resolve(xptiWorkingSet* aWorkingSet = nsnull);
+
+ // We only call these "*Locked" variants after locking. This is done to
+ // allow reentrace as files are loaded and various interfaces resolved
+ // without having to worry about the locked state.
+
+ PRBool EnsureResolvedLocked(xptiWorkingSet* aWorkingSet = nsnull)
+ {return IsFullyResolved() ? PR_TRUE : ResolveLocked(aWorkingSet);}
+ PRBool ResolveLocked(xptiWorkingSet* aWorkingSet = nsnull);
+
+ // private helpers
+
+ nsresult GetEntryForParam(PRUint16 methodIndex,
+ const nsXPTParamInfo * param,
+ xptiInterfaceEntry** entry);
+
+ nsresult GetTypeInArray(const nsXPTParamInfo* param,
+ uint16 dimension,
+ const XPTTypeDescriptor** type);
+
+private:
+ nsID mIID;
+ union {
+ xptiTypelib mTypelib; // Valid only until resolved.
+ xptiInterfaceGuts* mInterface; // Valid only after resolved.
+ };
+ xptiInterfaceInfo* mInfo; // May come and go.
+ xptiInfoFlags mFlags;
+ char mName[1]; // Always last. Sized to fit.
+};
+
+struct xptiHashEntry : public PLDHashEntryHdr
+{
+ xptiInterfaceEntry* value;
+};
+
+/****************************************************/
+
+class xptiInterfaceInfo : public nsIInterfaceInfo
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ // Use delegation to implement (most!) of nsIInterfaceInfo.
+ NS_IMETHOD GetName(char * *aName) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetName(aName); }
+ NS_IMETHOD GetInterfaceIID(nsIID * *aIID) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIID(aIID); }
+ NS_IMETHOD IsScriptable(PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsScriptable(_retval); }
+ // Except this one.
+ NS_IMETHOD GetParent(nsIInterfaceInfo * *aParent)
+ {
+ if(!EnsureResolved() || !EnsureParent())
+ return NS_ERROR_UNEXPECTED;
+ NS_IF_ADDREF(*aParent = mParent);
+ return NS_OK;
+ }
+ NS_IMETHOD GetMethodCount(PRUint16 *aMethodCount) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodCount(aMethodCount); }
+ NS_IMETHOD GetConstantCount(PRUint16 *aConstantCount) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstantCount(aConstantCount); }
+ NS_IMETHOD GetMethodInfo(PRUint16 index, const nsXPTMethodInfo * *info) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfo(index, info); }
+ NS_IMETHOD GetMethodInfoForName(const char *methodName, PRUint16 *index, const nsXPTMethodInfo * *info) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfoForName(methodName, index, info); }
+ NS_IMETHOD GetConstant(PRUint16 index, const nsXPTConstant * *constant) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstant(index, constant); }
+ NS_IMETHOD GetInfoForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInfoForParam(methodIndex, param, _retval); }
+ NS_IMETHOD GetIIDForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID * *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParam(methodIndex, param, _retval); }
+ NS_IMETHOD GetTypeForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, nsXPTType *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetTypeForParam(methodIndex, param, dimension, _retval); }
+ NS_IMETHOD GetSizeIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetSizeIsArgNumberForParam(methodIndex, param, dimension, _retval); }
+ NS_IMETHOD GetLengthIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetLengthIsArgNumberForParam(methodIndex, param, dimension, _retval); }
+ NS_IMETHOD GetInterfaceIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint8 *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInterfaceIsArgNumberForParam(methodIndex, param, _retval); }
+ NS_IMETHOD IsIID(const nsIID * IID, PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsIID(IID, _retval); }
+ NS_IMETHOD GetNameShared(const char **name) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetNameShared(name); }
+ NS_IMETHOD GetIIDShared(const nsIID * *iid) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDShared(iid); }
+ NS_IMETHOD IsFunction(PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsFunction(_retval); }
+ NS_IMETHOD HasAncestor(const nsIID * iid, PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->HasAncestor(iid, _retval); }
+ NS_IMETHOD GetIIDForParamNoAlloc(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID *iid) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParamNoAlloc(methodIndex, param, iid); }
+
+public:
+ xptiInterfaceInfo(xptiInterfaceEntry* entry);
+
+ void Invalidate()
+ {NS_IF_RELEASE(mParent); mEntry = nsnull;}
+
+#ifdef DEBUG
+ static void DEBUG_ShutdownNotification();
+#endif
+
+private:
+
+ ~xptiInterfaceInfo();
+
+ // Note that mParent might still end up as nsnull if we don't have one.
+ PRBool EnsureParent(xptiWorkingSet* aWorkingSet = nsnull)
+ {
+ NS_ASSERTION(mEntry && mEntry->IsFullyResolved(), "bad EnsureParent call");
+ return mParent || !mEntry->GetInterfaceGuts()->mParent || BuildParent();
+ }
+
+ PRBool EnsureResolved(xptiWorkingSet* aWorkingSet = nsnull)
+ {
+ return mEntry && mEntry->EnsureResolved(aWorkingSet);
+ }
+
+ PRBool BuildParent()
+ {
+ NS_ASSERTION(mEntry &&
+ mEntry->IsFullyResolved() &&
+ !mParent &&
+ mEntry->GetInterfaceGuts()->mParent,
+ "bad BuildParent call");
+ return NS_SUCCEEDED(mEntry->GetInterfaceGuts()->mParent->
+ GetInterfaceInfo(&mParent));
+ }
+
+ xptiInterfaceInfo(); // not implemented
+
+private:
+ xptiInterfaceEntry* mEntry;
+ xptiInterfaceInfo* mParent;
+};
+
+/***************************************************************************/
+
+class xptiManifest
+{
+public:
+ static PRBool Read(xptiInterfaceInfoManager* aMgr,
+ xptiWorkingSet* aWorkingSet);
+
+ static PRBool Write(xptiInterfaceInfoManager* aMgr,
+ xptiWorkingSet* aWorkingSet);
+
+ static PRBool Delete(xptiInterfaceInfoManager* aMgr);
+
+private:
+ xptiManifest(); // no implementation
+};
+
+/***************************************************************************/
+
+class xptiZipLoaderSink : public nsIXPTLoaderSink
+{
+public:
+ xptiZipLoaderSink(xptiInterfaceInfoManager* aMgr,
+ xptiWorkingSet* aWorkingSet) :
+ mManager(aMgr),
+ mWorkingSet(aWorkingSet) {}
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIXPTLOADERSINK
+
+private:
+ ~xptiZipLoaderSink() {}
+
+ xptiInterfaceInfoManager* mManager;
+ xptiWorkingSet* mWorkingSet;
+
+};
+
+class xptiZipLoader
+{
+public:
+ xptiZipLoader(); // not implemented
+
+ static XPTHeader*
+ ReadXPTFileFromInputStream(nsIInputStream *stream,
+ xptiWorkingSet* aWorkingSet);
+
+};
+
+
+/***************************************************************************/
+
+class xptiFileType
+{
+public:
+ enum Type {UNKNOWN = -1, XPT = 0, ZIP = 1 };
+
+ static Type GetType(const char* name);
+
+ static PRBool IsUnknown(const char* name)
+ {return GetType(name) == UNKNOWN;}
+
+ static PRBool IsXPT(const char* name)
+ {return GetType(name) == XPT;}
+
+ static PRBool IsZip(const char* name)
+ {return GetType(name) == ZIP;}
+private:
+ xptiFileType(); // no implementation
+};
+
+/***************************************************************************/
+
+// We use this is as a fancy way to open a logfile to be used within the scope
+// of some given function where it is instantiated.
+
+class xptiAutoLog
+{
+public:
+ xptiAutoLog(); // not implemented
+ xptiAutoLog(xptiInterfaceInfoManager* mgr,
+ nsILocalFile* logfile, PRBool append);
+ ~xptiAutoLog();
+private:
+ void WriteTimestamp(PRFileDesc* fd, const char* msg);
+
+ xptiInterfaceInfoManager* mMgr;
+ PRFileDesc* mOldFileDesc;
+#ifdef DEBUG
+ PRFileDesc* m_DEBUG_FileDesc;
+#endif
+};
+
+/***************************************************************************/
+
+class xptiInterfaceInfoManager
+ : public nsIInterfaceInfoSuperManager
+{
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIINTERFACEINFOMANAGER
+ NS_DECL_NSIINTERFACEINFOSUPERMANAGER
+
+ // helper
+ PRBool
+ FoundZipEntry(const char* entryName,
+ int index,
+ XPTHeader* header,
+ xptiWorkingSet* aWorkingSet);
+
+public:
+ static xptiInterfaceInfoManager* GetInterfaceInfoManagerNoAddRef();
+ static void FreeInterfaceInfoManager();
+
+ xptiWorkingSet* GetWorkingSet() {return &mWorkingSet;}
+ PRFileDesc* GetOpenLogFile() {return mOpenLogFile;}
+ PRFileDesc* SetOpenLogFile(PRFileDesc* fd)
+ {PRFileDesc* temp = mOpenLogFile; mOpenLogFile = fd; return temp;}
+
+ PRBool LoadFile(const xptiTypelib& aTypelibRecord,
+ xptiWorkingSet* aWorkingSet = nsnull);
+
+ PRBool GetApplicationDir(nsILocalFile** aDir);
+ PRBool GetCloneOfManifestLocation(nsILocalFile** aDir);
+
+ void GetSearchPath(nsISupportsArray** aSearchPath)
+ {NS_ADDREF(*aSearchPath = mSearchPath);}
+
+ static PRLock* GetResolveLock(xptiInterfaceInfoManager* self = nsnull)
+ {if(!self && !(self = GetInterfaceInfoManagerNoAddRef()))
+ return nsnull;
+ return self->mResolveLock;}
+
+ static PRLock* GetAutoRegLock(xptiInterfaceInfoManager* self = nsnull)
+ {if(!self && !(self = GetInterfaceInfoManagerNoAddRef()))
+ return nsnull;
+ return self->mAutoRegLock;}
+
+ static PRMonitor* GetInfoMonitor(xptiInterfaceInfoManager* self = nsnull)
+ {if(!self && !(self = GetInterfaceInfoManagerNoAddRef()))
+ return nsnull;
+ return self->mInfoMonitor;}
+
+ static void WriteToLog(const char *fmt, ...);
+
+private:
+ ~xptiInterfaceInfoManager();
+ xptiInterfaceInfoManager(); // not implmented
+ xptiInterfaceInfoManager(nsISupportsArray* aSearchPath);
+
+ enum AutoRegMode {
+ NO_FILES_CHANGED = 0,
+ FILES_ADDED_ONLY,
+ FULL_VALIDATION_REQUIRED
+ };
+
+ PRBool IsValid();
+
+ PRBool BuildFileList(nsISupportsArray* aSearchPath,
+ nsISupportsArray** aFileList);
+
+ nsILocalFile** BuildOrderedFileArray(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet);
+
+ XPTHeader* ReadXPTFile(nsILocalFile* aFile, xptiWorkingSet* aWorkingSet);
+
+ AutoRegMode DetermineAutoRegStrategy(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet);
+
+ PRBool AddOnlyNewFilesFromFileList(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet);
+
+ PRBool DoFullValidationMergeFromFileList(nsISupportsArray* aSearchPath,
+ nsISupportsArray* aFileList,
+ xptiWorkingSet* aWorkingSet);
+
+ PRBool VerifyAndAddEntryIfNew(xptiWorkingSet* aWorkingSet,
+ XPTInterfaceDirectoryEntry* iface,
+ const xptiTypelib& typelibRecord,
+ xptiInterfaceEntry** entryAdded);
+
+ PRBool MergeWorkingSets(xptiWorkingSet* aDestWorkingSet,
+ xptiWorkingSet* aSrcWorkingSet);
+
+ void LogStats();
+
+ PRBool DEBUG_DumpFileList(nsISupportsArray* aFileList);
+ PRBool DEBUG_DumpFileArray(nsILocalFile** aFileArray, PRUint32 count);
+ PRBool DEBUG_DumpFileListInWorkingSet(xptiWorkingSet* aWorkingSet);
+
+ static PRBool BuildFileSearchPath(nsISupportsArray** aPath);
+
+private:
+ xptiWorkingSet mWorkingSet;
+ nsCOMPtr<nsILocalFile> mStatsLogFile;
+ nsCOMPtr<nsILocalFile> mAutoRegLogFile;
+ PRFileDesc* mOpenLogFile;
+ PRLock* mResolveLock;
+ PRLock* mAutoRegLock;
+ PRMonitor* mInfoMonitor;
+ PRLock* mAdditionalManagersLock;
+ nsSupportsArray mAdditionalManagers;
+ nsCOMPtr<nsISupportsArray> mSearchPath;
+};
+
+/***************************************************************************/
+// utilities...
+
+nsresult xptiCloneLocalFile(nsILocalFile* aLocalFile,
+ nsILocalFile** aCloneLocalFile);
+
+nsresult xptiCloneElementAsLocalFile(nsISupportsArray* aArray, PRUint32 aIndex,
+ nsILocalFile** aLocalFile);
+
+#endif /* xptiprivate_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/.cvsignore b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/.cvsignore
new file mode 100644
index 00000000..f29041e6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+TestInterfaceInfo
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/Makefile.in b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/Makefile.in
new file mode 100644
index 00000000..9b7f1ed4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/Makefile.in
@@ -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.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
+
+SIMPLE_PROGRAMS = TestInterfaceInfo$(BIN_SUFFIX)
+
+CPPSRCS = TestInterfaceInfo.cpp
+
+LIBS = \
+ $(XPCOM_LIBS) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -DEXPORT_XPTI_API
diff --git a/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/TestInterfaceInfo.cpp b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/TestInterfaceInfo.cpp
new file mode 100644
index 00000000..75005c50
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/reflect/xptinfo/tests/TestInterfaceInfo.cpp
@@ -0,0 +1,146 @@
+/* -*- 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) 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 ***** */
+
+/* Some simple smoke tests of the typelib loader. */
+
+#include "nscore.h"
+
+#include "nsISupports.h"
+#include "nsIInterfaceInfo.h"
+#include "nsIInterfaceInfoManager.h"
+#include "xptinfo.h"
+
+#include <stdio.h>
+
+// This file expects the nsInterfaceInfoManager to be able to discover
+// .xpt files corresponding to those in xpcom/idl. Currently this
+// means setting XPTDIR in the environment to some directory
+// containing these files.
+
+int main (int argc, char **argv) {
+ int i;
+ nsIID *iid1, *iid2, *iid3;
+ char *name1, *name2, *name3;
+ nsIInterfaceInfo *info2, *info3, *info4, *info5;
+
+ nsIInterfaceInfoManager *iim = XPTI_GetInterfaceInfoManager();
+
+ fprintf(stderr, "\ngetting iid for 'nsISupports'\n");
+ iim->GetIIDForName("nsISupports", &iid1);
+ iim->GetNameForIID(iid1, &name1);
+ fprintf(stderr, "%s iid %s\n", name1, iid1->ToString());
+
+ fprintf(stderr, "\ngetting iid for 'nsIInputStream'\n");
+ iim->GetIIDForName("nsIInputStream", &iid2);
+ iim->GetNameForIID(iid2, &name2);
+ fprintf(stderr, "%s iid %s\n", name2, iid2->ToString());
+
+ fprintf(stderr, "iid: %s, name: %s\n", iid1->ToString(), name1);
+ fprintf(stderr, "iid: %s, name: %s\n", iid2->ToString(), name2);
+
+ fprintf(stderr, "\ngetting info for iid2 from above\n");
+ iim->GetInfoForIID(iid2, &info2);
+#ifdef DEBUG
+// ((nsInterfaceInfo *)info2)->print(stderr);
+#endif
+
+ fprintf(stderr, "\ngetting iid for 'nsIInputStream'\n");
+ iim->GetIIDForName("nsIInputStream", &iid3);
+ iim->GetNameForIID(iid3, &name3);
+ fprintf(stderr, "%s iid %s\n", name3, iid2->ToString());
+ iim->GetInfoForIID(iid3, &info3);
+#ifdef DEBUG
+// ((nsInterfaceInfo *)info3)->print(stderr);
+#endif
+
+ fprintf(stderr, "\ngetting info for name 'nsIBidirectionalEnumerator'\n");
+ iim->GetInfoForName("nsIBidirectionalEnumerator", &info4);
+#ifdef DEBUG
+// ((nsInterfaceInfo *)info4)->print(stderr);
+#endif
+
+ fprintf(stderr, "\nparams work?\n");
+ fprintf(stderr, "\ngetting info for name 'nsIServiceManager'\n");
+ iim->GetInfoForName("nsIServiceManager", &info5);
+#ifdef DEBUG
+// ((nsInterfaceInfo *)info5)->print(stderr);
+#endif
+
+ // XXX: nsIServiceManager is no more; what do we test with?
+ if (info5 == NULL) {
+ fprintf(stderr, "\nNo nsIServiceManager; cannot continue.\n");
+ return 1;
+ }
+
+ uint16 methodcount;
+ info5->GetMethodCount(&methodcount);
+ const nsXPTMethodInfo *mi;
+ for (i = 0; i < methodcount; i++) {
+ info5->GetMethodInfo(i, &mi);
+ fprintf(stderr, "method %d, name %s\n", i, mi->GetName());
+ }
+
+ // 7 is GetServiceWithListener, which has juicy params.
+ info5->GetMethodInfo(7, &mi);
+// uint8 paramcount = mi->GetParamCount();
+
+ nsXPTParamInfo param2 = mi->GetParam(2);
+ // should be IID for nsIShutdownListener
+ nsIID *nsISL;
+ info5->GetIIDForParam(7, &param2, &nsISL);
+// const nsIID *nsISL = param2.GetInterfaceIID(info5);
+ fprintf(stderr, "iid assoc'd with param 2 of method 7 of GetServiceWithListener - %s\n", nsISL->ToString());
+ // if we look up the name?
+ char *nsISLname;
+ iim->GetNameForIID(nsISL, &nsISLname);
+ fprintf(stderr, "which is called %s\n", nsISLname);
+
+ fprintf(stderr, "\nhow about one defined in a different typelib\n");
+ nsXPTParamInfo param3 = mi->GetParam(3);
+ // should be IID for nsIShutdownListener
+ nsIID *nsISS;
+ info5->GetIIDForParam(7, &param3, &nsISS);
+// const nsIID *nsISS = param3.GetInterfaceIID(info5);
+ fprintf(stderr, "iid assoc'd with param 3 of method 7 of GetServiceWithListener - %s\n", nsISS->ToString());
+ // if we look up the name?
+ char *nsISSname;
+ iim->GetNameForIID(nsISS, &nsISSname);
+ fprintf(stderr, "which is called %s\n", nsISSname);
+
+ return 0;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/sample/.cvsignore b/src/libs/xpcom18a4/xpcom/sample/.cvsignore
new file mode 100644
index 00000000..d1f93146
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/sample/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+nsTestSample
diff --git a/src/libs/xpcom18a4/xpcom/sample/Makefile.in b/src/libs/xpcom18a4/xpcom/sample/Makefile.in
new file mode 100644
index 00000000..5510e795
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/sample/Makefile.in
@@ -0,0 +1,113 @@
+#
+# ***** 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 = xpcomsample
+XPIDL_MODULE = xpcomsample
+LIBRARY_NAME = xpcomsample
+SHORT_LIBNAME = xpcomsmp
+
+IS_COMPONENT = 1
+MODULE_NAME = nsSampleModule
+
+# Ensure that the xpcom classes that we build
+# do not export themselves
+DEFINES += -DXPCOM_GLUE
+
+
+REQUIRES = string \
+ xpcom \
+ $(NULL)
+
+CPPSRCS = \
+ nsSample.cpp \
+ nsSampleModule.cpp \
+ $(NULL)
+
+XPIDLSRCS = nsISample.idl
+
+TESTCPPSRCS = nsTestSample.cpp
+
+CPPSRCS += $(TESTCPPSRCS)
+
+SIMPLE_PROGRAMS = $(TESTCPPSRCS:.cpp=$(BIN_SUFFIX))
+
+include $(topsrcdir)/config/config.mk
+
+EXTRA_COMPONENTS = nsSample.js
+
+# separate libraries linked in.
+EXTRA_DSO_LDOPTS = \
+ $(DIST)/lib/$(LIB_PREFIX)xpcomglue.$(LIB_SUFFIX) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+LIBS = \
+ $(DIST)/lib/$(LIB_PREFIX)xpcomglue.$(LIB_SUFFIX) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+# Needed to resolve __yylex (?)
+ifeq ($(OS_ARCH)$(OS_RELEASE),FreeBSD2)
+LIBS += -lpcap
+endif
+
+# Need to link with CoreFoundation on Mac
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+EXTRA_DSO_LDOPTS += \
+ $(TK_LIBS) \
+ $(NULL)
+
+LIBS += \
+ $(TK_LIBS) \
+ $(NULL)
+endif
+
+include $(topsrcdir)/config/rules.mk
+
+libs:: $(TARGETS)
+ $(INSTALL) $(srcdir)/xpconnect-sample.html $(DIST)/bin/res/samples
+
+install:: $(TARGETS)
+ $(SYSINSTALL) $(IFLAGS1) $(srcdir)/xpconnect-sample.html $(DESTDIR)$(mozappdir)/res/samples
+
diff --git a/src/libs/xpcom18a4/xpcom/sample/nsISample.idl b/src/libs/xpcom18a4/xpcom/sample/nsISample.idl
new file mode 100644
index 00000000..22454e7b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/sample/nsISample.idl
@@ -0,0 +1,66 @@
+/* -*- 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 ***** */
+
+/**
+ * A sample of XPConnect. This file contains a sample interface.
+ *
+ */
+
+#include "nsISupports.idl"
+
+/**
+ * The uuid is a unique number identifying the interface normally
+ * called IID. It can be generated as follows:
+ *
+ * Windows: guidgen.exe
+ * Unix: uuidgen which comes with e2fsprogs package
+ * Mac: ???
+ * All platform: Using irc, connect to irc.mozilla.org and type in
+ * /join #mozilla
+ * /msg mozbot uuid
+ *
+ */
+[scriptable, uuid(7CB5B7A1-07D7-11d3-BDE2-000064657374)]
+interface nsISample : nsISupports
+{
+ attribute string value;
+ void writeValue(in string aPrefix);
+ void poke(in string aValue);
+};
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/sample/nsSample.cpp b/src/libs/xpcom18a4/xpcom/sample/nsSample.cpp
new file mode 100644
index 00000000..ac3d8449
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/sample/nsSample.cpp
@@ -0,0 +1,181 @@
+/* -*- 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 ***** */
+
+
+/**
+ *
+ * A sample of XPConnect. This file contains an implementation nsSample
+ * of the interface nsISample.
+ *
+ */
+#include <stdio.h>
+
+#include "nsSample.h"
+#include "nsMemory.h"
+
+#include "nsEmbedString.h"
+////////////////////////////////////////////////////////////////////////
+
+nsSampleImpl::nsSampleImpl() : mValue(nsnull)
+{
+ mValue = (char*)nsMemory::Clone("initial value", 14);
+}
+
+nsSampleImpl::~nsSampleImpl()
+{
+ if (mValue)
+ nsMemory::Free(mValue);
+}
+
+/**
+ * NS_IMPL_ISUPPORTS1 expands to a simple implementation of the nsISupports
+ * interface. This includes a proper implementation of AddRef, Release,
+ * and QueryInterface. If this class supported more interfaces than just
+ * nsISupports,
+ * you could use NS_IMPL_ADDREF() and NS_IMPL_RELEASE() to take care of the
+ * simple stuff, but you would have to create QueryInterface on your own.
+ * nsSampleFactory.cpp is an example of this approach.
+ * Notice that the second parameter to the macro is name of the interface, and
+ * NOT the #defined IID.
+ *
+ * The _CI variant adds support for nsIClassInfo, which permits introspection
+ * and interface flattening.
+ */
+NS_IMPL_ISUPPORTS1_CI(nsSampleImpl, nsISample)
+
+/**
+ * Notice that in the protoype for this function, the NS_IMETHOD macro was
+ * used to declare the return type. For the implementation, the return
+ * type is declared by NS_IMETHODIMP
+ */
+NS_IMETHODIMP
+nsSampleImpl::GetValue(char** aValue)
+{
+ NS_PRECONDITION(aValue != nsnull, "null ptr");
+ if (! aValue)
+ return NS_ERROR_NULL_POINTER;
+
+ if (mValue) {
+ /**
+ * GetValue's job is to return data known by an instance of
+ * nsSampleImpl to the outside world. If we were to simply return
+ * a pointer to data owned by this instance, and the client were to
+ * free it, bad things would surely follow.
+ * On the other hand, if we create a new copy of the data for our
+ * client, and it turns out that client is implemented in JavaScript,
+ * there would be no way to free the buffer. The solution to the
+ * buffer ownership problem is the nsMemory singleton. Any buffer
+ * returned by an XPCOM method should be allocated by the nsMemory.
+ * This convention lets things like JavaScript reflection do their
+ * job, and simplifies the way C++ clients deal with returned buffers.
+ */
+ *aValue = (char*) nsMemory::Clone(mValue, strlen(mValue) + 1);
+ if (! *aValue)
+ return NS_ERROR_NULL_POINTER;
+ }
+ else {
+ *aValue = nsnull;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSampleImpl::SetValue(const char* aValue)
+{
+ NS_PRECONDITION(aValue != nsnull, "null ptr");
+ if (! aValue)
+ return NS_ERROR_NULL_POINTER;
+
+ if (mValue) {
+ nsMemory::Free(mValue);
+ }
+
+ /**
+ * Another buffer passing convention is that buffers passed INTO your
+ * object ARE NOT YOURS. Keep your hands off them, unless they are
+ * declared "inout". If you want to keep the value for posterity,
+ * you will have to make a copy of it.
+ */
+ mValue = (char*) nsMemory::Clone(aValue, strlen(aValue) + 1);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSampleImpl::Poke(const char* aValue)
+{
+ return SetValue((char*) aValue);
+}
+
+
+static void GetStringValue(nsACString& aValue)
+{
+ NS_CStringSetData(aValue, "GetValue");
+}
+
+NS_IMETHODIMP
+nsSampleImpl::WriteValue(const char* aPrefix)
+{
+ NS_PRECONDITION(aPrefix != nsnull, "null ptr");
+ if (! aPrefix)
+ return NS_ERROR_NULL_POINTER;
+
+ printf("%s %s\n", aPrefix, mValue);
+
+ // This next part illustrates the nsEmbedString:
+ nsEmbedString foopy;
+ foopy.Append(PRUnichar('f'));
+ foopy.Append(PRUnichar('o'));
+ foopy.Append(PRUnichar('o'));
+ foopy.Append(PRUnichar('p'));
+ foopy.Append(PRUnichar('y'));
+
+ const PRUnichar* f = foopy.get();
+ PRUint32 l = foopy.Length();
+ printf("%c%c%c%c%c %d\n", char(f[0]), char(f[1]), char(f[2]), char(f[3]), char(f[4]), l);
+
+ nsEmbedCString foopy2;
+ GetStringValue(foopy2);
+
+ //foopy2.AppendLiteral("foopy");
+ const char* f2 = foopy2.get();
+ PRUint32 l2 = foopy2.Length();
+
+ printf("%s %d\n", f2, l2);
+
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/sample/nsSample.h b/src/libs/xpcom18a4/xpcom/sample/nsSample.h
new file mode 100644
index 00000000..40dec0b3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/sample/nsSample.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 ***** */
+
+/**
+ * A sample of XPConnect. This file is the header of an implementation
+ * nsSample of the nsISample interface.
+ *
+ */
+
+#include "nsISample.h"
+
+/**
+ * SampleImpl is an implementation of the nsISample interface. In XPCOM,
+ * there can be more than one implementation of an given interface. Class
+ * IDs (CIDs) uniquely identify a particular implementation of an interface.
+ * Interface IDs (IIDs) uniquely identify an interface.
+ *
+ * The CID is also a unique number that looks just like an IID
+ * and uniquely identifies an implementation
+ * {7CB5B7A0-07D7-11d3-BDE2-000064657374}
+ */
+
+#define NS_SAMPLE_CID \
+{ 0x7cb5b7a0, 0x7d7, 0x11d3, { 0xbd, 0xe2, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
+
+#define NS_SAMPLE_CONTRACTID "@mozilla.org/sample;1"
+
+
+class nsSampleImpl : public nsISample
+{
+public:
+ nsSampleImpl();
+
+ /**
+ * This macro expands into a declaration of the nsISupports interface.
+ * Every XPCOM component needs to implement nsISupports, as it acts
+ * as the gateway to other interfaces this component implements. You
+ * could manually declare QueryInterface, AddRef, and Release instead
+ * of using this macro, but why?
+ */
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+
+ /**
+ * This macro is defined in the nsISample.h file, and is generated
+ * automatically by the xpidl compiler. It expands to
+ * declarations of all of the methods required to implement the
+ * interface. xpidl will generate a NS_DECL_[INTERFACENAME] macro
+ * for each interface that it processes.
+ *
+ * The methods of nsISample are discussed individually below, but
+ * commented out (because this macro already defines them.)
+ */
+ NS_DECL_NSISAMPLE
+
+ /**
+ * The following is an explanation of how the interface header
+ * file expands to for a c++ implementation. NS_DELC_NSISAMPLE
+ * takes care of defining the right c++ implementation.
+ *
+ * The following if provided for more understanding.
+ *
+ * NS_IMETHOD expands to the standard XPCOM return type. XPCOM methods
+ * should never return any other type. The return value is used
+ * behind the scenes by the XPConnect runtime to figure out if the call
+ * failed in any way.
+ * These methods were generated by "attribute string Value" in
+ * nsISample.idl. When reflected into JavaScript, XPCOM will use these
+ * calls as Getter/Setter ops, so that they can be called transparently
+ * as "sample.Value='foo';" and "var val = sample.Value"
+ */
+ /* NS_IMETHOD GetValue(char * *aValue); */
+ /* NS_IMETHOD SetValue(char * aValue); */
+
+ /**
+ * The const came from the "in" specifier in nsISample.idl. "in"
+ * specifies that the value of this parameter is used only for input,
+ * this method is not allowed to modify the contents of the buffer.
+ */
+ /* NS_IMETHOD WriteValue(const char *aPrefix); */
+
+ /**
+ * nsISample.idl specifies all of it's string types as string, instead
+ * of wstring (wide string), the Unicode type. If the world were a
+ * perfect place, all normal strings in XPCOM interfaces would be unicode.
+ * If this type had been specified as wstring, it would appear as
+ * PRUnichar * in C++, which is the NSPR type for unicode characters.
+ */
+ /* NS_IMETHOD Poke(const char* aValue); */
+
+private:
+ ~nsSampleImpl();
+
+ char* mValue;
+};
diff --git a/src/libs/xpcom18a4/xpcom/sample/nsSample.js b/src/libs/xpcom18a4/xpcom/sample/nsSample.js
new file mode 100644
index 00000000..1cc9a091
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/sample/nsSample.js
@@ -0,0 +1,130 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/*
+ * No magic constructor behaviour, as is de rigeur for XPCOM.
+ * If you must perform some initialization, and it could possibly fail (even
+ * due to an out-of-memory condition), you should use an Init method, which
+ * can convey failure appropriately (thrown exception in JS,
+ * NS_FAILED(nsresult) return in C++).
+ *
+ * In JS, you can actually cheat, because a thrown exception will cause the
+ * CreateInstance call to fail in turn, but not all languages are so lucky.
+ * (Though ANSI C++ provides exceptions, they are verboten in Mozilla code
+ * for portability reasons -- and even when you're building completely
+ * platform-specific code, you can't throw across an XPCOM method boundary.)
+ */
+function mySample() { /* big comment for no code, eh? */ }
+
+/* decorate prototype to provide ``class'' methods and property accessors */
+mySample.prototype = {
+ /*
+ * get and set are new Magic in JS1.5, borrowing the intent -- if not
+ * the exact syntax -- from the JS2 design. They define accessors for
+ * properties on the JS object, follow the expected rules for prototype
+ * delegation, and make a mean cup of coffee.
+ */
+ get value() { return this.val; },
+ set value(newval) { return this.val = newval; },
+
+ writeValue: function (aPrefix) {
+ debug("mySample::writeValue => " + aPrefix + this.val + "\n");
+ },
+ poke: function (aValue) { this.val = aValue; },
+
+ QueryInterface: function (iid) {
+ if (iid.equals(Components.interfaces.nsISample) ||
+ iid.equals(Components.interfaces.nsISupports))
+ return this;
+
+ Components.returnCode = Components.results.NS_ERROR_NO_INTERFACE;
+ return null;
+ },
+
+ val: "<default value>"
+}
+
+var myModule = {
+ firstTime: true,
+
+ /*
+ * RegisterSelf is called at registration time (component installation
+ * or the only-until-release startup autoregistration) and is responsible
+ * for notifying the component manager of all components implemented in
+ * this module. The fileSpec, location and type parameters are mostly
+ * opaque, and should be passed on to the registerComponent call
+ * unmolested.
+ */
+ registerSelf: function (compMgr, fileSpec, location, type) {
+ if (this.firstTime) {
+ debug("*** Deferring registration of sample JS components\n");
+ this.firstTime = false;
+ throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN;
+ }
+ debug("*** Registering sample JS components\n");
+ compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
+ compMgr.registerFactoryLocation(this.myCID,
+ "Sample JS Component",
+ this.myProgID,
+ fileSpec,
+ location,
+ type);
+ },
+
+ /*
+ * The GetClassObject method is responsible for producing Factory objects
+ */
+ getClassObject: function (compMgr, cid, iid) {
+ if (!cid.equals(this.myCID))
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+
+ if (!iid.equals(Components.interfaces.nsIFactory))
+ throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
+
+ return this.myFactory;
+ },
+
+ /* CID for this class */
+ myCID: Components.ID("{dea98e50-1dd1-11b2-9344-8902b4805a2e}"),
+
+ /* ProgID for this class */
+ myProgID: "@mozilla.org/jssample;1",
+
+ /* factory object */
+ myFactory: {
+ /*
+ * Construct an instance of the interface specified by iid, possibly
+ * aggregating it with the provided outer. (If you don't know what
+ * aggregation is all about, you don't need to. It reduces even the
+ * mightiest of XPCOM warriors to snivelling cowards.)
+ */
+ createInstance: function (outer, iid) {
+ debug("CI: " + iid + "\n");
+ if (outer != null)
+ throw Components.results.NS_ERROR_NO_AGGREGATION;
+
+ return (new mySample()).QueryInterface(iid);
+ }
+ },
+
+ /*
+ * The canUnload method signals that the component is about to be unloaded.
+ * C++ components can return false to indicate that they don't wish to be
+ * unloaded, but the return value from JS components' canUnload is ignored:
+ * mark-and-sweep will keep everything around until it's no longer in use,
+ * making unconditional ``unload'' safe.
+ *
+ * You still need to provide a (likely useless) canUnload method, though:
+ * it's part of the nsIModule interface contract, and the JS loader _will_
+ * call it.
+ */
+ canUnload: function(compMgr) {
+ debug("*** Unloading sample JS components\n");
+ return true;
+ }
+};
+
+function NSGetModule(compMgr, fileSpec) {
+ return myModule;
+}
+
+
diff --git a/src/libs/xpcom18a4/xpcom/sample/nsSampleModule.cpp b/src/libs/xpcom18a4/xpcom/sample/nsSampleModule.cpp
new file mode 100644
index 00000000..f02b9a5c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/sample/nsSampleModule.cpp
@@ -0,0 +1,131 @@
+/* -*- 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):
+ * Suresh Duddu <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 "nsIGenericFactory.h"
+
+#include "nsSample.h"
+
+////////////////////////////////////////////////////////////////////////
+// NOTE this file supercedes nsSampleFactory.cpp. nsSampleFactory has
+// extensive comments, but it has been CVS removed to reduce clutter
+// in this sample. It's available to the interested via CVS history:
+// cvs up nsSampleFactory.cpp -r 1.10
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+// With the below sample, you can define an implementation glue
+// that talks with xpcom for creation of component nsSampleImpl
+// that implement the interface nsISample. This can be extended for
+// any number of components.
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+// Define the contructor function for the object nsSampleImpl
+//
+// What this does is defines a function nsSampleImplConstructor which we
+// will specific in the nsModuleComponentInfo table. This function will
+// be used by the generic factory to create an instance of nsSampleImpl.
+//
+// NOTE: This creates an instance of nsSampleImpl by using the default
+// constructor nsSampleImpl::nsSampleImpl()
+//
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSampleImpl)
+
+////////////////////////////////////////////////////////////////////////
+// Define a table of CIDs implemented by this module along with other
+// information like the function to create an instance, contractid, and
+// class name.
+//
+// The Registration and Unregistration proc are optional in the structure.
+//
+static NS_METHOD nsSampleRegistrationProc(nsIComponentManager *aCompMgr,
+ nsIFile *aPath,
+ const char *registryLocation,
+ const char *componentType,
+ const nsModuleComponentInfo *info)
+{
+ // Do any registration specific activity like adding yourself to a
+ // category. The Generic Module will take care of registering your
+ // component with xpcom. You dont need to do that. Only any component
+ // specific additional activity needs to be done here.
+
+ // This functions is optional. If you dont need it, dont add it to the structure.
+
+ return NS_OK;
+}
+
+static NS_METHOD nsSampleUnregistrationProc(nsIComponentManager *aCompMgr,
+ nsIFile *aPath,
+ const char *registryLocation,
+ const nsModuleComponentInfo *info)
+{
+ // Undo any component specific registration like adding yourself to a
+ // category here. The Generic Module will take care of unregistering your
+ // component from xpcom. You dont need to do that. Only any component
+ // specific additional activity needs to be done here.
+
+ // This functions is optional. If you dont need it, dont add it to the structure.
+
+ // Return value is not used from this function.
+ return NS_OK;
+}
+
+// For each class that wishes to support nsIClassInfo, add a line like this
+NS_DECL_CLASSINFO(nsSampleImpl)
+
+static const nsModuleComponentInfo components[] =
+{
+ { "Sample Component", NS_SAMPLE_CID, NS_SAMPLE_CONTRACTID, nsSampleImplConstructor,
+ nsSampleRegistrationProc /* NULL if you dont need one */,
+ nsSampleUnregistrationProc /* NULL if you dont need one */,
+ NULL /* no factory destructor */,
+ NS_CI_INTERFACE_GETTER_NAME(nsSampleImpl),
+ NULL /* no language helper */,
+ &NS_CLASSINFO_NAME(nsSampleImpl)
+ }
+};
+
+////////////////////////////////////////////////////////////////////////
+// Implement the NSGetModule() exported function for your module
+// and the entire implementation of the module object.
+//
+// NOTE: If you want to use the module shutdown to release any
+// module specific resources, use the macro
+// NS_IMPL_NSGETMODULE_WITH_DTOR() instead of the vanilla
+// NS_IMPL_NSGETMODULE()
+//
+NS_IMPL_NSGETMODULE(nsSampleModule, components)
diff --git a/src/libs/xpcom18a4/xpcom/sample/nsTestSample.cpp b/src/libs/xpcom18a4/xpcom/sample/nsTestSample.cpp
new file mode 100644
index 00000000..edf9ce78
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/sample/nsTestSample.cpp
@@ -0,0 +1,158 @@
+/* -*- 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):
+ * 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 ***** */
+
+
+/**
+ * A Test application that exercises the sample moudule. This is intented
+ * to be a sample application for using xpcom standalone.
+ */
+
+#include <stdio.h>
+
+#include "nsISample.h"
+#include "nsIServiceManager.h"
+#include "nsIComponentRegistrar.h"
+
+#ifdef XPCOM_GLUE
+#include "nsXPCOMGlue.h"
+#include "nsMemory.h"
+#else
+#include "nsXPIDLString.h"
+#endif
+
+#define NS_SAMPLE_CONTRACTID "@mozilla.org/sample;1"
+
+int
+main(void)
+{
+ nsresult rv;
+
+#ifdef XPCOM_GLUE
+ XPCOMGlueStartup(nsnull);
+#endif
+
+ // Initialize XPCOM
+ nsCOMPtr<nsIServiceManager> servMan;
+ rv = NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull);
+ if (NS_FAILED(rv))
+ {
+ printf("ERROR: XPCOM intialization error [%x].\n", rv);
+ return -1;
+ }
+ // register all components in our default component directory
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan);
+ NS_ASSERTION(registrar, "Null nsIComponentRegistrar");
+ registrar->AutoRegister(nsnull);
+
+ nsCOMPtr<nsIComponentManager> manager = do_QueryInterface(registrar);
+ NS_ASSERTION(registrar, "Null nsIComponentManager");
+
+ // Create an instance of our component
+ nsCOMPtr<nsISample> mysample;
+ rv = manager->CreateInstanceByContractID(NS_SAMPLE_CONTRACTID,
+ nsnull,
+ NS_GET_IID(nsISample),
+ getter_AddRefs(mysample));
+ if (NS_FAILED(rv))
+ {
+ printf("ERROR: Cannot create instance of component " NS_SAMPLE_CONTRACTID " [%x].\n"
+ "Debugging hint:\n"
+ "\tsetenv NSPR_LOG_MODULES nsComponentManager:5\n"
+ "\tsetenv NSPR_LOG_FILE xpcom.log\n"
+ "\t./nsTestSample\n"
+ "\t<check the contents for xpcom.log for possible cause of error>.\n",
+ rv);
+ return -2;
+ }
+
+ // Call methods on our sample to test it out.
+ rv = mysample->WriteValue("Inital print:");
+ if (NS_FAILED(rv))
+ {
+ printf("ERROR: Calling nsISample::WriteValue() [%x]\n", rv);
+ return -3;
+ }
+
+ const char *testValue = "XPCOM defies gravity";
+ rv = mysample->SetValue(testValue);
+ if (NS_FAILED(rv))
+ {
+ printf("ERROR: Calling nsISample::SetValue() [%x]\n", rv);
+ return -3;
+ }
+ printf("Set value to: %s\n", testValue);
+#ifndef XPCOM_GLUE
+ nsXPIDLCString str;
+ rv = mysample->GetValue(getter_Copies(str));
+#else
+ char *str;
+ rv = mysample->GetValue(&str);
+#endif
+
+ if (NS_FAILED(rv))
+ {
+ printf("ERROR: Calling nsISample::GetValue() [%x]\n", rv);
+ return -3;
+ }
+ if (strcmp(str, testValue))
+ {
+ printf("Test FAILED.\n");
+ return -4;
+ }
+
+#ifdef XPCOM_GLUE
+ nsMemory::Free(str);
+#endif
+ rv = mysample->WriteValue("Final print :");
+ printf("Test passed.\n");
+
+ // All nsCOMPtr's must be deleted prior to calling shutdown XPCOM
+ // as we should not hold references passed XPCOM Shutdown.
+ servMan = 0;
+ registrar = 0;
+ manager = 0;
+ mysample = 0;
+
+ // Shutdown XPCOM
+ NS_ShutdownXPCOM(nsnull);
+
+#ifdef XPCOM_GLUE
+ XPCOMGlueShutdown();
+#endif
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/sample/win32.order b/src/libs/xpcom18a4/xpcom/sample/win32.order
new file mode 100644
index 00000000..bf181a81
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/sample/win32.order
@@ -0,0 +1 @@
+_NSGetModule ; 1
diff --git a/src/libs/xpcom18a4/xpcom/sample/xpconnect-sample.html b/src/libs/xpcom18a4/xpcom/sample/xpconnect-sample.html
new file mode 100644
index 00000000..78e91be1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/sample/xpconnect-sample.html
@@ -0,0 +1,220 @@
+
+<center><b><font size=+2>XPConnect Sample</font></b>
+
+<p>
+<a href="mailto:arielb@rice.edu">Ariel Blackenroth &lt;arielb@rice.edu&gt;</a>
+<br>
+<a href="mailto:mang@subcarrier.org">Michael Ang &lt;mang@subcarrier.org&gt;</a>
+<br>
+Last modified
+<script>
+document.write(document.lastModified);
+</script>
+</center>
+
+<p>In the spirit of "worse is better" this somewhat rough guide is being
+released to the world. It will be expanded upon and improved.
+
+<p>XPConnect allows JavaScript
+to transparantly access and manipulate XPCOM objects; this communication
+between JavaScript and
+native code is done by having their interfaces defined in the XPIDL interface
+definition language. See the <a href="http://www.mozilla.org/scriptable/roadmap.html">Roadmap
+for documentation on XPCOM, XPConnect, XPTCall and XPIDL</a> for more information.
+
+<p><b>Overview</b>
+
+<p>
+This sample demonstrates accessing a XPCOM object through XPConnect.
+The JavaScript executed when this page loads creates an instance
+of the object by
+using the <tt>Components</tt> object, then accesses it through
+the <a href="http://lxr.mozilla.org/seamonkey/source/xpcom/sample/nsISample.idl">nsISample</a> interface by calling <tt>QueryInterface</tt>:
+<br>
+<pre>
+netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+var sample = Components.classes["@mozilla.org/sample;1"].createInstance();
+sample = sample.QueryInterface(Components.interfaces.nsISample);
+</pre>
+
+<p>
+The buttons on the form are connected to JavaScript event handlers which
+call the methods defined in C++.
+
+
+<p><b><a href="http://lxr.mozilla.org/mozilla/source/xpcom/sample/nsISample.idl">nsISample.idl</a></b>
+<p>This is the interface declaration for the XPCOM object. It defines
+two functions, their parameters, and one attribute. It also defines
+the interface's id. The idl file is compiled by the xpidl compiler
+into a C++ header, nsISample.h and a .xpt file which is a binary representation
+of the interface used at runtime.
+<br><tt>attribute string value;</tt>
+<br><tt>void writeValue(in string aPrefix);</tt>
+<br><tt>void poke(in string aValue);</tt><b></b>
+<p><b><a href="http://lxr.mozilla.org/mozilla/source/xpcom/sample/nsSample.cpp">nsSample.cpp</a></b>
+<p>This contains the implementation of nsISample.idl. SampleImpl
+inherits from nsISample.h, the header dynamically created by the xpidl
+compiler. The attribute Value has been expanded into a get and set
+and the return values have been modified to NS_IMETHOD, a success status
+for the method. The macro NS_DECL_ISUPPORTS, defined in <a href="http://lxr.mozilla.org/mozilla/source/xpcom/base/nsISupportsUtils.h">mozilla/xpcom/public/nsISupportsUtils.h</a>
+defines the inherited methods from nsISupports.h.
+<br><tt>NS_IMPL_ISUPPORTS1(SampleImpl, nsISample)</tt>
+<br>In the constructor, the macro NS_INIT_REFCNT is called which sets the
+reference count to 0.<p>
+Note that the methods in the C++ bindings use InterCaps style, while the IDL
+and JavaScript versions should use interCaps naming. The JavaScript binding
+matches the case of the IDL, <b>except</b> <a
+href="http://bugzilla.mozilla.org/show_bug.cgi?id=14460">QueryInterface</a>.
+<p><b><a href="http://lxr.mozilla.org/mozilla/source/xpcom/sample/nsSampleFactory.cpp">nsSampleFactory.cpp</a></b>
+<p>This is the class which builds the instance of the nsSample class.
+The COM framework uses factories to create instance of implementations
+rather than having the implementations instatiate themselves in order to
+increase portability of code. This factory inherits from nsFactory,
+which is also an XPCOM object. To gain more knowledge of factories
+see the <a href="http://www.mozilla.org/projects/xpcom/generic-factory.html">generic
+factory document</a> or the <a href="http://www.mozilla.org/docs/modunote.htm#Basics">Modularization techniques document</a>.
+<p><b><a href="http://lxr.mozilla.org/mozilla/source/xpcom/sample/nsSample.js">nsSample.js</a></b>
+<p>This file implements the nsISample interface, and associated factory glue,
+in JavaScript.
+
+<p><b>Compiling the idl</b>
+
+<p>The XPIDL compiler (xpidl on Unix, xpidl.exe on Windows, and a CodeWarrior plugin on Mac)
+is compiled at build time (except on Mac) thus
+you will have to build mozilla in order to test this out. If you
+have already built mozilla then the compiler will be located at <tt>mozilla\dist\WIN32_D.OBJ\bin\xpidl.exe</tt>.
+
+<p>Once you have the XPIDL compiler enter the following command at your
+prompt:
+<br><tt>D:\mozilla\xpcom\sample>d:\mozilla\dist\WIN32_D.OBJ\bin\xpidl -I
+d:\mozilla\dist\idl -m header nsISample.idl</tt>
+
+<p>The <tt>-I d:\mozilla\dist\idl</tt> points the compiler to the folder
+containing the other idl files, needed because nsISample.idl inherits from
+nsISupports.idl. The <tt>-m header</tt> instruction tells the compiler
+to build the C++ header. To build the .xpt file substitute <tt>-m
+typelib</tt>.
+
+<p>
+For more information on compilation see the <a href="http://www.mozilla.org/scriptable/xpidl/">xpidl
+compiler page</a>.
+
+<p><b>Building the Sample</b>
+
+<p>To build the Sample just enter
+<br><tt>d:\mozilla\xpcom\sample>nmake /f makefile.win</tt>
+
+<p>In order to do this you need to have your environment variables set
+correctly. See the <a href="http://www.mozilla.org/build/">Build</a>
+page for more information.
+
+<p><b>Running the sample</b>
+<p>Using Mozilla, load
+<a href="resource://res/samples/xpconnect-sample.html">resource://res/samples/xpconnect-sample.html</a> (i.e. what
+you're reading now). Pay attention
+to the console when clicking "write". Notice that the value
+printed is calculated in C++ code defined in <a href="http://lxr.mozilla.org/seamonkey/source/xpcom/sample/nsSample.cpp">nsSample.cpp</a>.
+
+<!-- XXX keep in sync with stuff in pre tag below -->
+<script>
+/* to use nsSample.js version, use "@mozilla.org/jssample;1" */
+netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+var sample = Components.classes["@mozilla.org/sample;1"].createInstance();
+sample = sample.QueryInterface(Components.interfaces.nsISample);
+dump("sample = " + sample + "\n");
+
+function get()
+{
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ var field = document.getElementById('Value');
+ field.value = sample.value;
+}
+
+function set()
+{
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ var field = document.getElementById('Value');
+ sample.value = field.value;
+}
+
+function poke()
+{
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ var field = document.getElementById('Value');
+ sample.poke(field.value);
+}
+
+function sampleWrite()
+{
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ sample.writeValue("here is what I'm writing: ");
+}
+</script>
+
+<p>
+<form name="form">
+<input type="button" value="Get" onclick="get();">
+<input type="button" value="Set" onclick="set();">
+<input type="button" value="Poke" onclick="poke();">
+<input type="text" id="Value">
+<input type="button" value="Write" onclick="sampleWrite();">
+<form>
+
+<hr>
+
+<p>
+JavaScript and form source:
+
+<!-- XXX keep in sync with actual script -->
+<pre>
+&lt;script&gt;
+/* to use nsSample.js version, use "@mozilla.org/jssample;1" */
+netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+var sample = Components.classes["@mozilla.org/sample;1"].createInstance();
+sample = sample.QueryInterface(Components.interfaces.nsISample);
+dump("sample = " + sample + "\n");
+
+function get()
+{
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); var field = document.getElementById('Value');
+ field.value = sample.value;
+}
+
+function set()
+{
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); var field = document.getElementById('Value');
+ sample.value = field.value;
+}
+
+function poke()
+{
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); var field = document.getElementById('Value');
+ sample.poke(field.value);
+}
+
+function sampleWrite()
+{
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ sample.writeValue("here is what I'm writing: ");
+}
+&lt;/script&gt;
+
+&lt;form name=&quot;form&quot;&gt;
+&lt;input type=&quot;button&quot; value=&quot;Get&quot; onclick=&quot;get();&quot;&gt;
+&lt;input type=&quot;button&quot; value=&quot;Set&quot; onclick=&quot;set();&quot;&gt;
+&lt;input type=&quot;button&quot; value=&quot;Poke&quot; onclick=&quot;poke();&quot;&gt;
+&lt;input type=&quot;text&quot; id=&quot;Value&quot;&gt;
+&lt;input type=&quot;button&quot; value=&quot;Write&quot; onclick=&quot;sampleWrite();&quot;&gt;
+&lt;form>
+
+</pre>
+
+<p>
+<hr>
+<b>Resources:</b>
+<ul>
+<li><a href="http://lxr.mozilla.org/seamonkey/source/xpcom/sample/">mozilla/xpcom/sample source directory</a>
+</ul>
+<hr>
+<b>Comments to:</b>
+<a href="mailto:mang@subcarrier.org?Subject=XPCOM sample documentation">Michael Ang &lt;mang@subcarrier.org&gt;</a>
diff --git a/src/libs/xpcom18a4/xpcom/string/.cvsignore b/src/libs/xpcom18a4/xpcom/string/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/string/Makefile.in b/src/libs/xpcom18a4/xpcom/string/Makefile.in
new file mode 100644
index 00000000..6a664cb9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/Makefile.in
@@ -0,0 +1,54 @@
+#
+# ***** 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.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications.
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Johnny Stenback <jst@netscape.com> (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 *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = string
+DIRS = public src
+
+#ifdef ENABLE_TESTS
+#DIRS += \
+# tests
+#endif
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/xpcom/string/README.html b/src/libs/xpcom18a4/xpcom/string/README.html
new file mode 100644
index 00000000..1fdcfdd1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/README.html
@@ -0,0 +1,44 @@
+<html>
+<!-- ***** 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.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Scott Collins <scc@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 ***** -->
+<body>
+ <h1><span class="LXRSHORTDESC">managing sequences of characters</span></h1>
+<p>
+ <span class="LXRLONGDESC"></span>
+</p>
+</body>
+</html>
diff --git a/src/libs/xpcom18a4/xpcom/string/doc/README.html b/src/libs/xpcom18a4/xpcom/string/doc/README.html
new file mode 100644
index 00000000..154b7969
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/doc/README.html
@@ -0,0 +1,44 @@
+<html>
+<!-- ***** 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.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Scott Collins <scc@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 ***** -->
+<body>
+ <h1><span class="LXRSHORTDESC">documentation aimed at programmers who are clients of the string library</span></h1>
+<p>
+ <span class="LXRLONGDESC"></span>
+</p>
+</body>
+</html>
diff --git a/src/libs/xpcom18a4/xpcom/string/doc/string-guide.html b/src/libs/xpcom18a4/xpcom/string/doc/string-guide.html
new file mode 100644
index 00000000..41dbd217
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/doc/string-guide.html
@@ -0,0 +1,2508 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<html>
+ <head>
+ <title>an incomplete guide to mozilla/string</title>
+
+ <link rel="stylesheet" href="http://www.mozilla.org/projects/string/string-guide.css" title="remote stylesheet" type="text/css">
+ <link rel="alternate stylesheet" href="string-guide.css" title="local stylesheet" type="text/css">
+ </head>
+ <body>
+<!-- ----|---------|---------|---------|---------|---------|---------|---------| -->
+<!-- ...............................................................Front Matter -->
+<h1>an incomplete guide to <a class="exact-uri" href="http://lxr.mozilla.org/seamonkey/source/string/">mozilla/string</a></h1>
+ <h1><font color="red">This document is now deprecated in favor of <a href="http://www.mozilla.org/projects/xpcom/string-guide.html">The new string guide</a>.</font></h1>
+<div class="author-note">
+ <p>by <a href="http://ScottCollins.net/">Scott Collins</a><!-- /p -->
+ <p>last modified 8 April 2001<!-- /p -->
+</div>
+
+<div class="abstract">
+ <p>
+ <h1>Abstract</h1>
+ This document <span class="LXRSHORTDESC">provides
+ an <a href="#users_guide">introduction</a> to the design and use of the string classes in mozilla,
+ <a href="#implementors_guide">detailed information</a> on their implementation and how one may extend them,
+ and <a href="#faq">answers</a> to frequently asked questions about strings</span>.
+ </p>
+</div>
+
+
+
+<h2><a name="contents">contents</a></h2>
+
+<div class="contents">
+ <ul>
+ <li><a href="#users_guide" >user's guide</a></li>
+ <li><a href="#implementors_guide">implementor's guide</a></li>
+ <li><a href="#faq" >frequently asked questions</a></li>
+ </ul>
+</div>
+
+<p>
+ Please direct all comments, requests, and contributions to,
+ in order of preference,
+ the tracking bug <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=70076">#70076</a> for this document,
+ the author <a class="exact-uri" href="mailto:scc@mozilla.org?subject=string-guide">scc@mozilla.org</a>, and/or
+ the newsgroup <a class="exact-uri" href="news:netscape.public.mozilla.xpcom">news:netscape.public.mozilla.xpcom</a>
+ (should there be a strings newsgroup?)
+</p>
+
+<div class="author-note">
+ <p>
+ A note to potential editors:
+ don't even <strong>consider</strong> modifying this document with an HTML editor.
+ That would destroy the internal formatting,
+ and make patches unmanagable.
+ </p>
+</div>
+
+
+
+
+<!-- ...............................................................User's Guide -->
+<hr>
+<h1><a name="users_guide">user's guide</a></h1>
+
+<div class="author-note">
+ <p>
+ Strings in mozilla are a world apart from <span class="code">char*</span>s.
+ If you don't know why they are different,
+ this section is the place for you to start.
+ If you're already familiar with the hierarchy of string classes in mozilla,
+ then you might want to skip ahead to the <a href="#implementors_guide">implementor's guide</a>
+ or the <a href="#faq">FAQ</a>.
+ </p>
+</div>
+
+<div class="contents">
+ <ul>
+ <li><a href="#users_guide_introduction">introduction</a></li>
+ <li><a href="#users_guide_how_to" >using the string classes correctly; using the correct string class</a></li>
+ <li><a href="#users_guide_iterators" >using string iterators</a></li>
+ <li><a href="#users_guide_summary" >summary</a></li>
+ </ul>
+</div>
+
+<h2><a name="users_guide_introduction">introduction</a></h2>
+ <h3>what and what isn't a string?</h3>
+<p>
+ A string is an opaque container holding a, possibly zero length, linear sequence of characters.
+ Understanding the implications of this statement is the foundation for understanding all mozilla's string classes.
+</p>
+
+ <h3>readable and writable</h3>
+ <h3>dependent strings</h3>
+ <h3>flat strings</h3>
+ <h3>encoding</h3>
+ <h3>sharing</h3>
+
+<h2><a name="users_guide_how_to">using the string classes correctly; using the correct string class</a></h2>
+ <h3>basic string operations</h3>
+ <h4>comparison</h4>
+ <h4>concatenation</h4>
+ <h4>substrings</h4>
+ <h4>find and replace</h4>
+ <h3>conversions</h3>
+ <h4>calling a function that expects a different kind of string</h4>
+ <h4>converting between string classes</h4>
+ <h4>converting between encodings</h4>
+ <h3>selecting the right string class</h3>
+ <h4>user string classes</h4>
+ <h4>selecting the right string class for a parameter</h4>
+ <h4>selecting the right string class for a local variable</h4>
+ <h4>selecting the right string class for a member variable</h4>
+ <h4>selecting the right string class for a return value</h4>
+ <h4>selecting the right string class in IDL</h4>
+ <h3>dont's</h3>
+
+<h2><a name="users_guide_iterators">using string iterators</a></h2>
+ <h3>what is an iterator?</h3>
+ <h3>reading iterators and writing iterators</h3>
+ <h3>`chunky' iterating for efficiency</h3>
+ <h3><span class="code">copy_string</span>, character sources and sinks</h3>
+ <h3>encoding conversion iterators</h3>
+
+<h2><a name="users_guide_summary">summary</a></h2>
+
+
+<!-- ........................................................Implementor's Guide -->
+<hr>
+<h1><a name="implementors_guide">implementor's guide</a></h1>
+
+<div class="author-note">
+ <p>
+
+ </p>
+</div>
+
+<div class="contents">
+ <ul>
+ <!-- li></li -->
+ </ul>
+</div>
+
+
+
+<!-- ........................................................................FAQ -->
+<hr>
+<h1><a name="faq">frequently asked questions</a></h1>
+
+<div class="author-note">
+</div>
+
+<div class="contents">
+ <ul>
+<!--
+ <li>
+ I have a wide string, i.e., an instance of a class derived from <span class="code">nsAString</span>
+ <ul>
+ <li>I want a pointer to the characters</span>
+ <li>I want a narrow string</li>
+ <li>I want to <span class="code">printf</span> it</li>
+ </ul>
+ </li>
+ <li>
+ I have a <span class="code">PRUnichar*</span>
+ <ul>
+ <li>I want a wide string</span>
+ <li>I want a narrow string</span>
+ <li>I want to <span class="code">printf</span> it</li>
+ </ul>
+ </li>
+ <li>
+ I have a narrow string, i.e., an instance of a class derived from <span class="code">nsACString</span>
+ <ul>
+ <li>I want a pointer to the characters</span>
+ <li>I want a narrow string</li>
+ <li>I want to <span class="code">printf</span> it</li>
+ </ul>
+ </li>
+ <li>
+ I have a <span class="code">char*</span>
+ <ul>
+ <li>I want a wide string</span>
+ <li>I want a narrow string</span>
+ </ul>
+ </li>
+ <li>
+ I have a literal character sequence, e.g., <span class="code">"Hello, World!\n"</span>
+ <ul>
+ <li>I want a wide string</span>
+ <li>I want a narrow string</span>
+ </ul>
+ </li>
+ <li>What's the best way to return a string?</li>
+ <li>How can I get a pointer to the characters in a string?</li>
+ <li>How can I <span class="code">printf</span> a string?</li>
+ </ul>
+-->
+</div>
+
+
+<table class="chart">
+ <tr>
+ <th></th>
+ <th colspan="5">you have some <span class="code">char</span>s</th>
+ </tr>
+ <tr>
+ <th>you want</th>
+ <th><span class="code">'x'</span></th>
+ <th><span class="code">char c</span></th>
+ <th><span class="code">"foo"</span></th>
+ <th><span class="code">char* cp</span></th>
+ <th><span class="code">nsACString& cs</span></th>
+ </tr>
+ <tr>
+ <th class="row-label"><span class="code">char</span></th>
+ <td colspan="2">.</td>
+<!-- "foo" --> <td><span class="code">[]</span></td>
+<!-- char* cp --> <td><span class="code">[]</span></td>
+<!-- nsACString& cs --> <td><a href="#faq_how_to_extract_a_character">extract a character</a></td>
+ </tr>
+ <tr>
+ <th class="row-label"><span class="code">PRUnichar</span></th>
+<!-- 'x' --> <td><span class="code">PRUnichar('x')</span></td>
+<!-- char c --> <td><span class="code">PRUnichar(c)</span></td>
+ <td colspan="3"><a href="#faq_how_to_convert_encoding">convert encoding</a>, <a href="#faq_how_to_extract_a_character">extract a character</a></td>
+ </tr>
+ <tr>
+ <th class="row-label"><span class="code">char*</span></th>
+<!-- 'x' --> <td><span class="code">&amp;</span></td>
+<!-- char c --> <td><span class="code">&amp;</span></td>
+<!-- "foo" --> <td><span class="code">&amp;</span></td>
+<!-- char* cp --> <td>.</td>
+<!-- nsACString& cs --> <td><a href="#faq_how_to_get_a_pointer">get a pointer</a></td>
+ </tr>
+ <tr>
+ <th class="row-label"><span class="code">PRUnichar*</span></th>
+ <td colspan="5"><a href="#faq_how_to_convert_encoding">convert encoding</a>, <a href="#faq_how_to_get_a_pointer">get a pointer</a></td>
+ </tr>
+ <tr>
+ <th class="row-label"><span class="code">nsACString</span></th>
+<!-- 'x' --> <td><span class="code">NS_LITERAL_CSTRING("x")</span></td>
+<!-- char c --> <td><a href="#faq_how_to_make_a_string">make a string</a></td>
+<!-- "foo" --> <td><span class="code">NS_LITERAL_CSTRING("foo")</td>
+<!-- char* cp --> <td><a href="#faq_how_to_make_a_string">make a string</a></td>
+<!-- nsACString& cs --> <td>.</td>
+ </tr>
+ <tr>
+ <th class="row-label"><span class="code">nsAString</span></th>
+<!-- 'x' --> <td><span class="code">NS_LITERAL_STRING("x")</span></td>
+<!-- char c --> <td><a href="#faq_how_to_convert_encoding">convert encoding</a></td>
+<!-- "foo" --> <td><span class="code">NS_LITERAL_STRING("foo")</span></td>
+ <td colspan="2"><a href="#faq_how_to_convert_encoding">convert encoding</a></td>
+ </tr>
+ <tr>
+ <th class="row-label">to call <span class="code">printf</span></th>
+ <td colspan="4">.</td>
+<!-- nsACString& cs --> <td><a href="#faq_how_to_call_printf">call <span class="code">printf</span></a></td>
+ </tr>
+</table>
+
+<table class="chart">
+ <tr>
+ <th></th>
+ <th colspan="3">you have some <span class="code">PRUnichar</span>s</th>
+ </tr>
+ <tr>
+ <th>you want</th>
+ <th><span class="code">PRUnichar w</span></th>
+ <th><span class="code">PRUnichar* wp</span></th>
+ <th><span class="code">nsAString& s</span></th>
+ </tr>
+ <tr>
+ <th class="row-label"><span class="code">char</span></th>
+<!-- PRUnichar w --> <td></td>
+<!-- PRUnichar* wp --> <td></td>
+<!-- nsAString& s --> <td></td>
+ </tr>
+ <tr>
+ <th class="row-label"><span class="code">PRUnichar</span></th>
+<!-- PRUnichar w --> <td></td>
+<!-- PRUnichar* wp --> <td><span class="code">[]</span></td>
+<!-- nsAString& s --> <td><a href="#faq_how_to_extract_a_character">extract a character</a></td>
+ </tr>
+ <tr>
+ <th class="row-label"><span class="code">char*</span></th>
+<!-- PRUnichar w --> <td></td>
+<!-- PRUnichar* wp --> <td></td>
+<!-- nsAString& s --> <td></td>
+ </tr>
+ <tr>
+ <th class="row-label"><span class="code">PRUnichar*</span></th>
+<!-- PRUnichar w --> <td><span class="code">&amp;</span></td>
+<!-- PRUnichar* wp --> <td></td>
+<!-- nsAString& s --> <td><a href="#faq_how_to_get_a_pointer">get a pointer</a></td>
+ </tr>
+ <tr>
+ <th class="row-label"><span class="code">nsACString</span></th>
+<!-- PRUnichar w --> <td></td>
+<!-- PRUnichar* wp --> <td></td>
+<!-- nsAString& s --> <td></td>
+ </tr>
+ <tr>
+ <th class="row-label"><span class="code">nsAString</span></th>
+<!-- PRUnichar w --> <td></td>
+<!-- PRUnichar* wp --> <td></td>
+<!-- nsAString& s --> <td></td>
+ </tr>
+ <tr>
+ <th class="row-label">to call <span class="code">printf</span></th>
+<!-- PRUnichar w --> <td></td>
+<!-- PRUnichar* wp --> <td></td>
+<!-- nsAString& s --> <td><a href="#faq_how_to_call_printf">call <span class="code">printf</span></a></td>
+ </tr>
+</table>
+
+<div class="faq">
+ <dl>
+ <dt>
+ is there any string doc?
+ </dt>
+ <dd>
+ Yes, you're soaking in it!
+ </dd>
+
+
+
+<!-- getting a pointer -->
+ <dt>
+ <a name="faq_how_to_get_a_pointer">I have a string, how do I get a pointer to the characters?</a>
+ </dt>
+ <dd>
+ You want to avoid this situation.
+ In your own interfaces, prefer string types over raw pointers.
+ Any interface that wants to process a string using a single pointer is making two expensive assumptions.
+ First, that the string is stored in one contiguous hunk; and
+ second, that the string is zero-terminated.
+ If this isn't the case,
+ then to get a pointer, storage must be allocated and the entire string must be copied to it and zero-terminated.
+ You may not be able to avoid needing a pointer when interacting with system calls.
+ </dd>
+ <dd>
+ Some string classes guarantee that they are `flat'.
+ That is, that their data is stored in one contiguous zero-terminated hunk.
+ This <strong>does not</strong> imply that there are no embedded nulls. Caveat emptor.
+ All strings that explicitly promise flatness
+ inherit from the class <span class="code">nsAFlatString</span>
+ or <span class="code">nsAFlatCString</span>
+ and can produce a constant pointer to their data with the <span class="code">get()</span> member function.
+ Even strings that don't explicitly promise to be flat
+ may happen to be flat.
+ The helper function <span class="code">PromiseFlatString</span> will produce
+ a <span class="code">const</span> dependent string that is guaranteed to be flat.
+ If you use this on a string that already happens to be flat,
+ the result is simply a reference through to that string.
+ Otherwise,
+ <span class="code">PromiseFlatString</span> does the work to allocate, copy, terminate, and manage
+ a temporary flat string.
+ Since the result of <span class="code">PromiseFlatString</span> is a temporary,
+ you must be careful not to get and hold a pointer to its data for longer than the temporary itself lives.
+ </dd>
+ <dd>
+<div class="source-code">
+<pre>
+ /* I have a string, how do I get a pointer to the characters? */
+
+extern void EvilNarrowOSFunction( const char* ); // evil OS routines that want a pointers
+extern void EvilWideOSFunction( const PRUnichar* );
+
+void func( const nsAString&amp; aString, const nsACString&amp; aCString )
+ {
+ EvilWideOSFunction( NS_LITERAL_STRING("Hello, World!").<span class="notice">get()</span> );
+ // literal strings are flat already (as are |nsString|s, et al), just use |.get()|
+
+ EvilWideOSFunction( <span class="notice">PromiseFlatString(</span>aString<span class="notice">).get()</span> );
+ // for strings that don't explicitly guarantee flatness, use |PromiseFlatString|
+
+
+ // beware holding the pointer for longer than the life of the promise
+ <span class="warning">const PRUnichar* wp = PromiseFlatString(aString).get(); // BAD! |wp| dangles
+ EvilWideOSFunction(wp);</span>
+
+ // if you really need to use the pointer from |PromiseFlatString| in more than one expression...
+ const nsAFlatString&amp; flat = <span class="notice">PromiseFlatString(</span>aString<span class="notice">)</span>;
+ EvilWideOSFunction(flat.<span class="notice">get()</span>);
+ SomeOtherFunction(flat.<span class="notice">get()</span>);
+
+ // similarly for |char| strings
+ EvilNarrowOSFunction( <span class="notice">PromiseFlatCString(</span>aCString<span class="notice">).get()</span> );
+ }
+</pre>
+</div>
+ </dd>
+
+
+
+<!-- extracting a character -->
+ <dt>
+ <a name="faq_how_to_extract_a_character">How do I get a particular character out of a string?</a>
+ </dt>
+ <dd>
+ Flat strings provide <span class="code">operator[]</span> and <span class="code">CharAt()</span>.
+ All strings provide <span class="code">First()</span>, <span class="code">Last()</span>, and access with iterators.
+ <strong>Don't</strong> promise a string flat just to do character indexing.
+ Prefer, instead, to get an iterator and <span class="code">advance</span> it to the position you care about.
+ </dd>
+ <dd>
+<div class="source-code">
+<pre>
+ /* How do I get a particular character out of a string? */
+
+PRUnichar Get5thCharacterOf( const nsAString& aString )
+ {
+ if ( aString.Length() >= 5 )
+ {
+ nsAString::const_iterator iter;
+ aString.BeginReading(iter); // make |iter| point to the beginning of |aString|
+ iter.advance(5);
+ return *iter;
+ }
+
+ return PRUnichar(0);
+ }
+</pre>
+</div>
+ </dd>
+ <dd>
+ Using iterators isn't as bad as the example above makes it feel.
+ The typical use is for advancing through a string, examining many characters.
+ </dd>
+
+
+
+<!-- how to convert encoding -->
+ <dt>
+ <a name="faq_how_to_convert_encoding">How do I convert from one encoding to another?</a>
+ </dt>
+ <dd>
+ </dd>
+
+
+
+<!-- how to make a string -->
+ <dt>
+ <a name="faq_how_to_make_a_string">How do I create a string?</a>
+ </dt>
+ <dd>
+ </dd>
+
+
+<!-- how to return a string -->
+ <dt>
+ What is the best way to return a string?
+ </dt>
+ <dd>
+ <p>
+ There are several reasonable ways to produce a string result from a function.
+ If you are already holding the answer as a sharable string,
+ you can simply return that string (pass-by-value).
+ Otherwise,
+ the most efficient and flexible way to return a string is
+ to assign your result into a non-<span class="code">const</span> reference parameter.
+ Don't bother to create a sharable string from scratch with your generated result.
+ </p>
+ <p>
+ Why?
+ The two things you want to minimize in string manipulation are,
+ in order of importance,
+ heap allocation, and
+ moving characters around.
+ </p>
+ </dd>
+ <dd>
+<div class="source-code">
+<pre>
+ /* What is the best way to return a string? */
+
+class foo
+ {
+ public:
+ // ...
+ void GetShortName( nsAString&amp; aResult ) const;
+ nsCommonString GetFullName() const;
+
+ private:
+ nsCommonString mFullName;
+
+ const PRUnichar* mShortName;
+ PRUint32 mShortNameLength;
+
+ };
+
+nsCommonString
+foo::GetFullName() const
+ {
+ return mFullName;
+ }
+
+void
+foo::GetShortName( nsAString&amp; aResult ) const
+ {
+ aResult = DependentString(mShortName, mShortNameLength);
+ }
+</pre>
+</div>
+ </dd>
+
+
+ <dt>
+ <a name="faq_how_to_call_printf">How do I <span class="code">printf</span> a string, e.g., for debugging.</a>
+ </dt>
+ <dd>
+ If your string is already narrow, you just have to worry about <a href="#faq_how_to_get_a_pointer">making it flat, and then getting a pointer</a>.
+ </dd>
+ <dd>
+ If your string happens to be wide,
+ you'll need to convert it before you can <span class="code">printf</span> something reasonable.
+ If it's just for debugging,
+ you probably wouldn't care if something odd was printed in the case of a Unicode character that didn't have
+ an ASCII equivalent. (If you have a UTF-8 terminal, the result is
+ perfectly legible and nothing odd is printed.)
+ The simplest thing in this case is to make a temporary conversion using <span class="code">NS_ConvertUTF16toUTF8</span>.
+ The result is conveniently flat already, so getting the pointer is simple.
+ Remember not to hold onto the pointer you get out of this beyond the lifetime of temporary.
+ </dd>
+ <dd>
+<div class="source-code">
+<pre>
+ /* How do I |printf| a string? */
+
+
+void PrintSomeStrings( const nsAString& aString, const PRUnichar* aKey, const nsACString& aCString )
+ {
+ // |printf|ing a narrow string is easy
+ printf("%s\n", <span class="notice">PromiseFlatCString(</span>aCString<span class="notice">).get()</span>); // GOOD
+
+ // the simplest way to get a |printf|-able |const char*| out of a string
+ printf("%s\n", <span class="notice">NS_ConvertUTF16toUTF8(</span>aKey<span class="notice">).get()</span>); // GOOD
+
+ // works just as well with an formal wide string type...
+ printf("%s\n", <span class="notice">NS_ConvertUTF16toUTF8(</span>aString<span class="notice">).get()</span>);
+
+
+ // But don't hold onto the pointer longer than the lifetime of the temporary!
+ <span class="warning">const char* cstring = NS_ConvertUTF16toUTF8(aKey).get(); // BAD! |cstring| is dangling
+ printf("%s\n", cstring);</span>
+ }
+</pre>
+</div>
+ </dd>
+
+ </dl>
+
+<p>
+ Here are the email answers I have yet to format into the FAQ.
+ Some of the URLs may be out-dated or moved.
+ The messages are in order from oldest to newest.
+</p>
+<p class="editnote">[Note : In June, 2003, these emails were modified
+to better reflect what is stored in 'wide' string
+classes (UTF-16 string instead of UCS-2) and what
+related methods do as a part of the patch for <a href=
+"http://bugzilla.mozilla.org/show_bug.cgi?id=183156"
+title="replace UCS2 in function/class/method names with UTF16">bug 183156</a>.
+Therefore, they're a little different from the original emails
+written by <a href="http://ScottCollins.net/">Scott Collins</a>]
+</p>
+<hr>
+<pre>
+Date: Thu, 13 Apr 2000 19:41:47 -0400
+</pre>
+
+<p>Encoding Wars
+
+<p>This message is all about strings and the various encodings that might
+be used to interpret their contents, the ramifications of that, and
+where we're heading. The point of this message is to say what we're
+currently thinking, and get feedback. I apologize in advance for the
+rambling, and for the fact that this message may accidentally mix
+discussion of how things <strong>are</strong> and how they will be.
+
+<p>There are many different possible encodings. Three in common use in
+the Mozilla source base are: ASCII, UTF-16, and UTF-8. In ASCII, every
+<!--the Mozilla source base are: ASCII, UCS2, and UTF8. In ASCII, every-->
+character fits in 7-bits and is typically stored in an 8-bit byte. We
+usually represent ASCII strings with <span class="code">nsCString</span>s, <span class="code">nsXPIDLCString</span>s,
+or <span class="code">char</span> string literals. In UTF-16, characters occupy one 16-bit code unit (
+<a href="http://www.unicode.org/glossary/index.html#BMP_character">
+<abbr title="Basic Multilingual Plane">BMP</abbr>characters</a>)
+or two 16-bit code units
+(<a href="http://www.unicode.org/glossary/index.html#supplementary_character">
+<abbr title="Supplementary Plane : Plane 1 through 16">non-BMP</abbr> characters</a>).
+We usually represent UTF-16 strings as <span class="code">nsString</span>s, etc., i.e., two-byte
+or `wide' strings. UTF-8 is a multi-byte encoding. A character might
+occupy one, two, three, or four bytes. It is easiest to store and
+manipulate such a string within a single-byte or `narrow' string
+implementation.
+
+<p>None of our current string implementations know the encoding of the
+data they hold at any given moment. An <span class="code">nsCString</span> might legitimately
+hold data encoded in ASCII, UTF-8 or even EBCDIC for that matter.
+
+<p>Operations that convert from one encoding to another, or operations
+that are encoding sensitive (e.g., <span class="code">to_upper</span>), rightly belong in
+i18n. The fact that our current string interfaces automatically and
+implicitly convert between wide and narrow strings is actually the
+source of many errors in two particular categories: (1) unintended
+extra work, (2) mistaken re-encoding, e.g., accidentally `converting'
+a UTF-8 string to UTF-16 by pretending the UTF-8 string is ASCII and then
+padding with <span class="code">'\0'</span>s.
+
+<p>We've known these were bad for a long time, and have been trying to
+find the right way to fix them. The current thinking is to just byte
+the bullet and eliminate implicit conversions. That has interesting
+ramifications.
+
+<div class="source-code">
+<pre>
+void foo( const nsString&amp; aUTF16string );
+
+foo("hello"); // works! constructs a temporary |nsString| by
+ // converting the ASCII literal with padding.
+ // Note: this requires an allocation
+</pre>
+</div>
+
+<p>Though we've always hated this form since it requires a heap
+allocation. In current code, we recommend
+
+<div class="source-code">
+<pre>
+foo( nsAutoString("hello") );
+</pre>
+</div>
+
+<p>which still copy/converts, but at least it probably doesn't need to do
+a heap allocation. In the best of all worlds, no conversion, copying,
+or allocation would be necessary. To do that, you would need to be
+able to directly specify a UTF-16 string, e.g., with the <span class="code">L"hello"</span>
+notation, and wrap that in an interface that just held a pointer.
+E.g., something like
+
+<div class="source-code">
+<pre>
+void foo( const nsAReadableString&amp; aUTF16string );
+
+foo( nsLiteralString(L"hello") );
+</pre>
+</div>
+
+<p>There are problems with this example, however. The <span class="code">L</span> notation
+specifically makes objects that are arrays of <span class="code">wchar_t</span>, which under
+GCC is a 4-byte element. This leads to incompatibility with JS, and
+the annoyance of possibly bloated storage (I'm sort of minimizing the
+situation here. It's worse that I make it sound). More about tricks
+to get around this in a bit, but first, let me talk about what to do
+in the meantime while we're just getting rid of implicit constructors.
+ Initially to get around this problem (what problem? The problem that
+<span class="code">foo("hello")</span> stopped compiling on my machine when I threw the
+switch) I made a routine called <span class="code">NS_ConvertToString</span> which looked like
+this
+
+<div class="source-code">
+<pre>
+inline
+nsAutoString
+NS_ConvertToString( const char* anASCIIstring )
+ {
+ nsAutoString aUCS2string;
+ aUCS2string.AssignWithConversion(anASCIIstring);
+ return aUCS2string;
+ }
+</pre>
+</div>
+
+<p>Which lets me write
+
+<div class="source-code">
+<pre>
+foo( NS_ConvertToString("hello") );
+</pre>
+</div>
+
+<p>This was <strong>OK</strong>, but in discussion there were concerns about performance
+on machines that didn't <span class="code">inline</span> well, and issues about naming. In
+that meeting we came up with an alternate naming strategy that we
+think has room for growth and an implementation more likely to be
+efficient on every platform. The implementation is to define a new
+class that derives from <span class="code">nsAutoString</span>, but allows construction from a
+<span class="code">char*</span>
+
+<div class="source-code">
+<pre>
+class NS_ConvertASCIItoUTF16 : public nsAutoString
+ {
+ public:
+ NS_ConvertASCIItoUTF16( const char* );
+ // ...
+ };
+</pre>
+</div>
+
+<p>Which gives identical (though renamed) notation for calling <span class="code">foo</span>:
+
+<div class="source-code">
+<pre>
+foo( NS_ConvertASCIItoUTF16("hello") );
+</pre>
+</div>
+
+<p>It looks like a function call to an explicit encoding conversion. It
+acts like a function call to an explicit encoding conversion. It <strong>is</strong>
+a function call to an explicit encoding conversion. We think that
+this naming pattern has room for growth. In the meeting, we concluded
+that the best representation for encoding conversions is a family of
+functions, and <span class="code">NS_ConvertASCIItoUTF16</span> fits right in. We think that
+XPCOM probably can't live without the ASCII to UTF-16 conversion (though
+as explicit as possible) but that all others rightly belong in i18n
+land.
+
+<p>You can probably deduce from the clues in <span class="code">NS_ConvertToString</span>, above,
+that constructors weren't the only thing that became explicit.
+Assignment, appending, comparison, et al, got renamed so that when
+assigning, appending, or comparing to a value in a different encoding
+the `WithConversion' form must be used. E.g.,
+
+<div class="source-code">
+<pre>
+nsString aUTF16string;
+nsCString anASCIIstring;
+// ...
+
+aUTF16string += anASCIIstring; // Currently legal, but not for long
+aUTF16string.Append(anASCIIstring); // same
+
+aUTF16string.AppendWithConversion(anASCIIstring); // the new way
+
+if ( aUTF16string == anASCIIstring ) // Sorry, this is going away too
+ // ...
+
+if ( aUTF16string.EqualsWithConversion(anASCIIstring) )
+ // ...
+</pre>
+</div>
+
+<p>Yes, it's long and annoying. Just like the extra work you were
+implicitly asking to have done, perhaps incorrectly. There are other
+reasons to rename these functions. When <span class="code">nsString</span> and <span class="code">nsCString</span>
+defined a ton of, e.g., <span class="code">Append</span>s each there was no problem, because
+nobody wanted to override <span class="code">Append</span>. Now, with strings inheriting from
+abstract base classes we immediately run into the problem that
+overriding and overloading don't mix very well in C++. Because of a
+feature of C++ called name hiding, it is problematic to override only
+a single signature of a name overloaded in a base class. The base
+<span class="code">nsAWritableString</span> provides several <span class="code">Append</span>s, all for objects of
+(hopefully) the same encoding. <span class="code">nsString</span> can't easily add a bunch of
+new <span class="code">Append</span>s (the converting ones) without running face first into
+the name hiding problem. The discussion of the fix for this is mostly
+unrelated to encoding issues, so I'll defer it to another post.
+
+<p>In hindsight, after the meeting, it seemed clear that all the
+`WithConversion' forms would be better named
+
+<div class="source-code">
+<pre>
+xxxConvertingASCIItoUTF16
+xxxConvertingUTF16toASCII
+</pre>
+</div>
+
+<p>however, the <strong>real</strong> goal (probably) is to move most such conversions
+into i18n. Just bringing attention to the previously implicit
+conversions is a good first step. Renaming these conversions as just
+suggested is probably the right thing to do, though it sort of
+validates them, which I'm not sure we really want. This is a decision
+we need to discuss further.
+
+<p>Now, back to the string literal problem above. One possible solution
+is to use a macro. Imagine
+
+<div class="source-code">
+<pre>
+NS_LITERAL_STRING("Hello")
+</pre>
+</div>
+
+<p>which on a machine where the <span class="code">L</span> trick works, turns into
+
+<div class="source-code">
+<pre>
+nsLiteralString(L"Hello")
+</pre>
+</div>
+
+<p>but on a machine where there is trouble, turns into something less
+appealing, but more likely to work, like
+
+<div class="source-code">
+<pre>
+NS_ConvertASCIItoUTF16("Hello")
+</pre>
+</div>
+
+<p>Another solution is to add a compilation step that fixes <span class="code">L</span> strings
+on bad platforms to be non-<span class="code">L</span> strings, but padded with <span class="code">\0</span>s. E.g.,
+<span class="code">L"Hello"</span> gets preprocessed into <span class="code">"\000H\000e\000l\000l\000o\000"</span>.
+This solution is more annoying to the developer, where the prior
+solution is more annoying during the runtime.
+
+<p>Before we go to too much trouble on this specific feature, we will
+probably want to do more measurement to see just how much and how
+often we are converting constant literal strings, and why.
+
+
+<p>I'm currently ripping through the tree fixing things to use the
+`WithConversion' forms where appropriate. I was also converting
+things to use <span class="code">NS_ConvertToString</span> where appropriate; unless I get
+talked out of it, I want to switch midstream to
+<span class="code">NS_ConvertASCIItoUTF16</span>, then go back and fix up the
+<span class="code">NS_ConvertToString</span> instances later. I've set things up so I can
+check in as I go. After all these conversions have been done, I'll be
+able to throw the switch (what switch? NEW_STRING_APIS) which will
+make <span class="code">nsString</span> inherit from <span class="code">nsAWritableString</span>, etc. and allow us to
+start exploiting these other opportunities (e.g., for literal strings,
+shared strings, etc. See
+<a class="exact-uri" href="http://bugzilla.mozilla.org/show_bug.cgi?id=28221">http://bugzilla.mozilla.org/show_bug.cgi?id=28221</a> for details and
+reasoning.)
+
+<p>I guess I'm expecting comments on:
+
+<ul>
+ <li>how really annoying this whole topic is
+ <li>how bad <span class="code">L"xxx"</span> is
+ <li>whether to move forward with <span class="code">NS_ConvertASCIItoUTF16</span>
+ <li>whether we should move to xxxConvertingASCIItoUTF16 etc instead
+ of `WithConverting'
+ <li>arguments about where encoding conversions should live
+ <li>arguments about whether going between 1 and 2 byte storage is an
+ encoding conversion
+ <li>questions about stuff I didn't mention or didn't explain well
+ <li>pointing out stuff I'm just plain wrong about, or things I forgot
+ <li>etc
+</ul>
+
+<p>So as not to jumble the discussion, I'll be separately posting other
+requests for comments about specific features of the design of the new
+string hierarchy.
+
+<p>I hope this helps keep everybody filled in on what we're thinking and
+able to point out what we're forgetting or screwing up :-)
+
+
+
+
+
+<hr>
+<pre>
+Date: Wed, 19 Apr 2000 21:12:47 -0400
+Subject: more string info
+</pre>
+
+<p> <a class="exact-uri" href="news://news.mozilla.org/scc-705460.16423913042000@news.mozilla.org">news://news.mozilla.org/scc-705460.16423913042000@news.mozilla.org</a>
+
+
+
+
+
+<hr>
+<pre>
+Date: Fri, 26 May 2000 15:31:37 -0400
+Subject: Re: Question on ==
+</pre>
+
+<p>I would prefer you compare with <span class="code">Equals</span> (which should really be named
+<span class="code">IsEqualTo</span>) rather than <span class="code">operator==()</span> because of this:
+
+<div class="source-code">
+<pre>
+char* a;
+char* b;
+
+// ...
+
+if ( a == b )
+ // ...
+</pre>
+</div>
+
+<p>Comparing two raw `string' pointers doesn't compare the characters
+they point to, but instead compares the bits of the pointers. For
+this reason, I may eventually make comparison of a string with a
+pointer using operators just go away.
+
+
+
+
+
+<hr>
+<pre>
+Date: Wed, 14 Jun 2000 14:38:55 -0400
+Subject: Re: Fix to XprtDefs.h
+</pre>
+
+<p>Yes, we're aware that turning off <span class="code">wchar_t</span> support makes <span class="code">wchar_t</span> be
+a synonym for <span class="code">unsigned short</span> under Metrowerks. We know that the
+current version of VC++ also makes these types equivalent. In theory,
+though, the types are distinct even when they are the same size and
+shape. By using real <span class="code">wchar_t</span> support, we are forced to recognize
+the distinction and navigate it appropriately with <span class="code">reinterpret_cast</span>
+(via <span class="code">NS_REINTERPRET_CAST</span>). The win here is that we aren't caught by
+compiler changes that suddenly make some set of compilers compliant
+and therefore break our code. We will add an autoconf test that lets
+UNIX compilers opt in to our string scheme when they have an
+appropriately shaped <span class="code">wchar_t</span>. If these happen to be compliant
+compilers, all will be well. If they don't, the casts don't hurt,
+because they are type correct. We are writing our code to meet the
+standard as we move forward.
+
+<p>The win for us is realized by the following macros
+
+<div class="source-code">
+<pre>
+#ifdef HAVE_CPP_2BYTE_WCHAR_T
+ #define NS_LITERAL_STRING(s) nsLiteralString(L##s, \
+ (sizeof(L##s)/sizeof(wchar_t))-1)
+#else
+ #define NS_LITERAL_STRING(s) NS_ConvertASCIItoUTF16(s, \
+ sizeof(s)-1)
+#endif
+</pre>
+</div>
+
+<p>An <span class="code">nsLiteralString</span> points directly to the literal characters. No
+copying, no conversion, and the length calculation happens at compile
+time. This has turned out to be as large a savings as 15% of code
+space and 8% of data space, net, in our string test harness It's
+faster as well, again by eliminating the copying, conversion, and
+length calculation. We don't know yet what those numbers translate
+into in our real code base, but we have high hopes.
+
+<p>I don't want to be in the position to ask you to change your code. I
+don't think it's appropriate for me to do so. The AIM application
+that is your client is our client as well. They need to resolve this
+difference between us in whatever way they think best. That may mean
+asking you if changing your apis is the right thing to do. Or it may
+mean applying the casts. Our code-base and yours, Justin, are more
+like cousins. I don't think you should have to change just to conform
+to us. You may think my arguments for using real <span class="code">wchar_t</span> have
+merit, and adopt similar usage just because you agree; but I think the
+only obligation you have is to follow the technical solution you think
+is right for your code.
+
+<p>If you decide to make this api change, it will mean shipping a new
+binary (on Mac) for your library to clients who want to switch over to
+the new api (since the name mangling will be different, and therefore,
+the link requirements will change).
+
+<p>Hope this helps,
+
+
+
+
+
+<hr>
+<pre>
+Date: Thu, 15 Jun 2000 19:36:55 -0400
+Subject: Re: Checkin approval for bug 32336
+</pre>
+
+<div class="source-code">
+<pre>
+S.Equals(NS_LITERAL_STRING("bar"), PR_TRUE, 3)
+</pre>
+</div>
+
+<p>doesn't compile because there is no three parameter form for <span class="code">Equals</span>.
+ For all definitions of <span class="code">Equals</span> on strings, see "nsAReadableString.h"
+
+<p><a class="exact-uri" href="http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAReadableString.h">http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAReadableString.h</a>
+
+<p>There is an <span class="code">EqualsWithConversion</span> that takes three parameters.
+
+<p> <a class="exact-uri" href="http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsString2.h#731">http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsString2.h#731</a>
+
+<p>It is ``EqualsWithConversion'' because it admits the possibility of an
+encoding specific transformation, in this case to provide
+case-insensitive comparison. This also wouldn't compile, however,
+since, at the moment, an <span class="code">nsLiteralString</span> doesn't provide an operator
+to produce a <span class="code">const PRUnichar*</span> (though perhaps it should), and it
+doesn't satisfy the other interfaces that match this call, e.g., a
+<span class="code">const nsString&</span>.
+
+<p>Perhaps I need to move case-insensitive comparison up out of
+<span class="code">nsString</span> into a global encoding specific transformations and
+algorithms file (which was on its way anyway as Waterson, knows); this
+use is one bit of evidence to support this. In the short term, this
+can be fixed (if we think the current behavior is wrong) by providing
+<span class="code">operator const CharT*() const</span> on literal string.
+
+<p>If you can live with out case-folding, the earlier form is preferred
+
+<div class="source-code">
+<pre>
+S == NS_LITERAL_STRING("bar")
+</pre>
+</div>
+
+<p>if you can't, then one of the fixes I mentioned is in order.
+
+
+
+
+
+<hr>
+<pre>
+Date: Thu, 15 Jun 2000 19:47:12 -0400
+Subject: Re: [Fwd: how to use nsString ?]
+</pre>
+
+<pre class="email-quote">
+ >I see these same examples time and again in the embedding
+ >samples/docs, but I can't compile them.
+</pre>
+
+<p>Apologies. Documentation mentioning strings is getting out of date.
+Here are some specific answers.
+
+
+<pre class="email-quote">
+ >nsString URLString("http://www.mozilla.org");
+</pre>
+
+<p>...is now perhaps best expressed as
+
+ nsString URLString( NS_LITERAL_STRING("http://www.mozilla.org") );
+
+<p>since an <span class="code">nsString</span> is a sequence of 2-byte wide characters, and the
+routines that implicitly convert 1-byte sequences (like the literal
+sequence you specified, "http:...") are now gone.
+
+<p>Up until not too long ago, one would have had to say
+
+<div class="source-code">
+<pre>
+nsString URLString;
+URLString.AssignWithConversion("http://www.mozilla.org");
+</pre>
+</div>
+
+<p>The <span class="code">NS_LITERAL_STRING</span> construction is new machinery that has the
+potential to make many operations much more efficient.
+
+<pre class="email-quote">
+ >nsString URLString;
+ >URLString.SetString("www.mozilla.org");
+</pre>
+
+<p><span class="code">SetString</span> was a synonym for <span class="code">Assign</span> or assignment with
+<span class="code">operator=()</span>, it too went away. The equivalent is the second
+example I gave above, that is, the one with <span class="code">AssignWithConversion</span>.
+
+<p><span class="code">Assign</span> still exists. <span class="code">AssignWithConversion</span> takes on that
+functionality for assignments that require encoding transformations
+(e.g., from ASCII to UTF16). <span class="code">SetString</span> is gone, since it was always
+a synonym for <span class="code">Assign</span>.
+
+<p>Learn more about the general APIs for strings that we are trying to
+move to by examining
+
+<a class="exact-uri" href="http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAReadableString.h">http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAReadableString.h</a>
+<a class="exact-uri" href="http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAWritableString.h">http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAWritableString.h</a>
+
+<p>Hope this helps,
+
+
+
+
+
+<hr>
+<pre>
+Date: Thu, 15 Jun 2000 21:26:51 -0400
+Subject: Re: Checkin approval for bug 32336
+</pre>
+
+<pre class="email-quote">
+ >I *need* the count attribute, because I need to compare only the first
+ >chars (that's inherent to the logic).
+</pre>
+
+<p>This is what substrings are for. In that case, you could use
+
+<div class="source-code">
+<pre>
+Substring(S, 0, 3) == NS_LITERAL_STRING("bar")
+</pre>
+</div>
+
+<p>As for case-folding, it's best if you can case-fold everything up
+front, instead of doing it repeatedly. I'll have to get back to you
+on a general solution to that problem, or what my schedule for getting
+it checked in would be. I'm sorry, I know that's not what you needed
+to hear. If the source string is an <span class="code">nsString</span>, you can continue to
+exploit its implementation of these routines, e.g., <span class="code">ToLower</span> all
+up-front.
+
+<p>Hope this helps,
+
+
+
+
+
+<hr>
+<pre>
+Date: Mon, 19 Jun 2000 14:23:47 -0400
+Subject: Re: string fu
+</pre>
+
+<pre class="email-quote">
+ >It seems less convenient to have to first check path.IsEmpty, and
+ >then if false get path.Last and test it.
+</pre>
+
+<p>What would you prefer? That extracting a character not in the string
+always return <span class="code">CharT(0)</span>? Can't do it for two reasons: (1) <span class="code">0</span> may be
+a valid character in a particular encoding, so it can't be used in
+general as a ``no character at that position'' marker; and (2) I can't
+control what an individual string implementation does when asked to
+get an out-of-bounds fragment, it's explicitly undefined. That means
+the result of <span class="code">CharAt</span> is explicitly undefined for indexes outside the
+defined contents of the string. As a debugging convenience, I have
+made this assert, but it has always been the case that retrieving such
+a character had undefined results ... even in [the old] code.
+
+<p>OK, you might say, well at least let me ask for a character that is
+only off the end by one. E.g., <span class="code">Last</span> of an empty string. Reason (1)
+from above still applies. How bad is it to say, for the case you gave
+
+<div class="source-code">
+<pre>
+PRBool needsDelim = PR_FALSE;
+if ( !path.IsEmpty() )
+ {
+ PRUnichar last = path.Last();
+ needsDelim = !(last == '/' || last == '\\');
+ }
+</pre>
+</div>
+
+<p>In general, you probably want to opt out of a whole lot of work when
+the source string is empty. It is slightly less convenient, but it
+doesn't tie us to a bunch of implementation specific mojo.
+
+
+<pre class="email-quote">
+ >Can we fix GetUnicode in this case?
+</pre>
+
+<p>This is an annoying property of auto strings, e.g., that they always
+have an allocated buffer. I'm happy to fix this bug, however, be
+aware that <span class="code">GetUnicode</span> and <span class="code">GetBuffer</span> are artifacts of [the old]
+implementation that we don't want to support. They are not part of
+the abstract interface. We will keep them no longer than we have to.
+They don't support our multi-fragment paradigm. People who require a
+contiguous hunk of characters in the future, and are unwilling to
+switch over to chunky-iterators, may be forced to copy the string to
+their own buffer. There will be an implementation of narrow character
+string that guarantees contiguous allocation and a zero-terminator,
+much as <span class="code">nsCString</span> does now, for compatibility with platform uses,
+but this won't be the default string class.
+
+
+
+
+
+<hr>
+<pre>
+Date: Mon, 19 Jun 2000 17:22:31 -0400
+</pre>
+
+<p>Clarifying String Sematics
+
+<p>Recently, I added an assert to the string operations that extract
+characters, namely <span class="code">First()</span>, <span class="code">Last()</span>, <span class="code">CharAt()</span>, and
+<span class="code">operator[]()</span>. This assert fires when any of these routines are used
+to access a character outside the defined contents of the string. For
+<span class="code">First()</span> and <span class="code">Last()</span> that means whenever they are applied to an
+empty string. For <span class="code">CharAt()</span> and <span class="code">operator[]()</span>, that means whenever
+they are used to access an index outside the range of
+<span class="code">0</span>..<span class="code">Length()-1</span>. There have been some complaints, however, the
+result was always undefined. What follows is extracted from an email
+exchange between me and warren on this topic. I hope it clarifies
+strings semantics
+
+<p>Warren writes:
+<pre class="email-quote">
+ >I hit your funky CharAt assertion tonight in this piece of code:
+
+ >NS_IMETHODIMP
+ >nsIOService::ResolveRelativePath(
+ > const char *relativePath,
+ > const char* basePath,
+ > char **result )
+ > {
+ > nsCAutoString name;
+ > nsCAutoString path(basePath);
+ >
+ > PRUnichar last = path.Last();
+ > PRBool needsDelim = !(last == '/' || last == '\\' || last ==
+ > '\0');
+ > ...
+
+ >where basePath is null. It seems less convenient to have to first
+ >check path.IsEmpty, and then if false get path.Last and test it.
+</pre>
+
+<p>I replied:
+<pre class="email-quote">
+ >What would you prefer? That extracting a character not in the
+ >string always return <span class="code">CharT(0)</span>? Can't do it for two reasons:
+ >(1) <span class="code">0</span> may be a valid character in a particular encoding, so it
+ >can't be used in general as a ``no character at that position''
+ >marker; and (2) I can't control what an individual string
+ >implementation does when asked to get an out-of-bounds fragment,
+ >it's explicitly undefined. That means the result of <span class="code">CharAt</span> is
+ >explicitly undefined for indexes outside the defined contents of
+ >the string. As a debugging convenience, I have made this assert,
+ >but it has always been the case that retrieving such a character
+ >had undefined results ... even in [the old] code.
+
+ >OK, you might say, well at least let me ask for a character that
+ >is only off the end by one. E.g., <span class="code">Last</span> of an empty string.
+ >Reason (1) from above still applies. How bad is it to say, for the
+ >case you gave
+
+ > PRBool needsDelim = PR_FALSE;
+ > if ( !path.IsEmpty() )
+ > {
+ > PRUnichar last = path.Last();
+ > needsDelim = !(last == '/' || last == '\\');
+ > }
+
+ >In general, you probably want to opt out of a whole lot of work
+ >when the source string is empty. It is slightly less convenient,
+ >but it doesn't tie us to a bunch of implementation specific mojo.
+</pre>
+
+<p>Warren also asks:
+<pre class="email-quote">
+ >Here's another issue, perhaps more serious. If I say this:
+
+ > foo(const PRUnichar* s) {
+ > nsAutoString str(s);
+ > bar(str.get());
+ > }
+
+ >where s is null, bar will get passed a zero-length PRUnichar
+ >sequence instead of null. This makes it so that you can't just
+ >test for the argument == null. You have to nsCRT::strlen(arg) == 0
+ >which is much less efficient. Can we fix GetUnicode in this case?
+</pre>
+
+<p>And I reply:
+<pre class="email-quote">
+ >This is an annoying property of auto strings, e.g., that they
+ >always have an allocated buffer. I'm happy to fix this bug,
+ >however, be aware that <span class="code">GetUnicode</span> and <span class="code">GetBuffer</span> are artifacts
+ >of [the old] implementation that we don't want to support. They
+ >are not part of the abstract interface. We will keep them no
+ >longer than we have to. They don't support our multi-fragment
+ >paradigm. People who require a contiguous hunk of characters in
+ >the future, and are unwilling to switch over to chunky-iterators,
+ >may be forced to copy the string to their own buffer. There will
+ >be an implementation of narrow character string that guarantees
+ >contiguous allocation and a zero-terminator, much as <span class="code">nsCString</span>
+ >does now, for compatibility with platform uses, but this won't be
+ >the default string class.
+</pre>
+
+<p>In a later message, Chris Waterson asks a related question
+<pre class="email-quote">
+ >scc: should we add <span class="code">operator PRUnichar*()</span> to
+ >NS_ConvertASCIItoUTF16?
+</pre>
+
+<p>And I reply:
+<pre class="email-quote">
+ >It seems reasonable. A lot more reasonable that forcing people to
+ >call <span class="code">GetUnicode()</span>. I alluded to platform specific classes in an
+ >earlier message to warren that you were cc'd on, Chris. I imagine
+ >that the <span class="code">...Convert...</span> routines would be required to produce
+ >contiguous allocation 0-terminated strings (though the as yet
+ >unimplemented <span class="code">...Copy...</span> forms, of course wouldn't. So <span class="code">operator
+ >const PRUnichar*() const</span> makes perfect sense to me here.
+</pre>
+
+<p>Hope this makes sense,
+
+
+
+
+<hr>
+<pre>
+Date: Tue, 20 Jun 2000 04:05:31 -0400
+Subject: Re: NS_LITERAL_STRING is broken
+</pre>
+
+<p>The behavior you describe sounds exactly like when you say
+
+<div class="source-code">
+<pre>
+const char* foobar = "foobar";
+
+... NS_LITERAL_STRING(foobar).get() ...
+</pre>
+</div>
+
+<p>because in this case, the thing passed in is a <span class="code">const char*</span>.
+<span class="code">NS_LITERAL_STRING</span> is not meant to be used in this way. It is only
+meant to be used around a <span class="code">"</span> delimited string. The type of such is
+<span class="code">const char[N]</span> where N is the number of characters in the string + 1
+for the zero terminator it helpfully adds. <span class="code">sizeof</span> such a type is
+<span class="code">N</span>.
+
+<p>Are you sure you had the actual string as an argument, as in your
+example to me? Or could the actual code have been like my sample,
+above?
+
+
+
+
+
+<hr>
+<pre>
+Date: Thu, 29 Jun 2000 13:35:10 -0400
+Subject: Re: a fix
+</pre>
+
+<pre class="email-quote">
+ > + if (Length() == 0) { return nsnull; }
+</pre>
+
+
+<p>Dave,
+
+<p>please read
+
+ <a class="exact-uri" href="news://news.mozilla.org/scc-314ABF.14261619062000@news.mozilla.org">news://news.mozilla.org/scc-314ABF.14261619062000@news.mozilla.org</a>
+
+<p>It's just plain wrong to let people try to index into a string outside
+its defined contents. I can't just return <span class="code">'\0'</span> or <span class="code">PRUnichar('\0')</span>
+there as that <strong>could</strong> be a legal value to have somewhere in your
+string for some encodings ... and the encoding is not specified. So
+your patch has the basic problem of defeating my plan to stop people
+from doing this bad thing.
+
+<p>The second problem with your patch is that you use the symbolic
+constant <span class="code">nsnull</span>, which is ostensibly a pointer value; <span class="code">Last</span> returns
+a character. <span class="code">nsnull</span> is not appropriate for that purpose. In fact,
+C++ gurus pretty much eschew the use of symbolic constants for <span class="code">0</span>.
+<span class="code">NULL</span> is to be avoided. <span class="code">nsnull</span> is wrong-headed in that it presumes
+we could have some <strong>other</strong> application specific value for <span class="code">NULL</span>. We
+can't, it would never work. It's just wasted brain-print. Always use
+<span class="code">0</span> for these situations, and if you want to communicate the fact that
+something is a pointer type, either use a comment or a
+(construction-style) cast, like so (graded examples from worst to
+best:)
+
+<ul>
+ <li>F: FindChildByNameWithHint("Chuck", nsnull);
+
+ <li>D: FindChildByNameWithHint("Chuck", NULL);
+
+ <li>C: FindChildByNameWithHint("Chuck", /* Child* */ 0);
+
+ <li>B: typedef Child* Child_ptr;
+ FindChildByNameWithHint("Chuck", Child_ptr(0));
+
+ <li>A: FindChildByNameWithHint("Chuck", 0);
+</ul>
+
+<p>Don't let this discourage you; keep up the good work :-)
+
+
+
+
+
+<hr>
+<pre>
+Date: Tue, 8 Aug 2000 23:47:16 -0400
+Subject: Re: nsWritingIterator?
+</pre>
+
+<pre class="email-quote">
+ >Can you give me any pointers to examples, or docs, or just some
+ >general advice?
+</pre>
+
+ <a class="exact-uri" href="http://ScottCollins.net/Journal/discussion/string_iterators.html">http://ScottCollins.net/Journal/discussion/string_iterators.html</a>
+
+<p>does this help?
+
+<p>I can personally walk you through any specific scenario you need.
+
+
+
+
+
+<hr>
+<pre>
+Date: Wed, 9 Aug 2000 02:35:03 -0400
+Subject: Re: nsWritingIterator?
+</pre>
+
+<p>You got it right... it's <span class="code">nsWritingIterator<CharT></span> for whichever
+character type you care about, either <span class="code">char</span> or <span class="code">PRUnichar</span>. You
+_can_ use this iterator like a character pointer ... that is, you can
+dereference it, assign into its dereference, etc. It is more
+efficient, though, to directly address a particular range of
+characters around where it points by asking it for its actual
+character pointer with <span class="code">get</span>, and knowing that there are
+<span class="code">size_forward()</span> characters available ahead of that pointer and
+<span class="code">size_backward()</span> characters available behind it. After examining
+those characters by hand, you can advance the iterator beyond the
+characters you have examined (and possibly into the next chunk, should
+one exist) by adding into it (with +=) the count of the characters you
+have processed.
+
+<p>Here are three examples of running through a string and modifying some
+of the characters in it. All use <span class="code">nsWritingIterator</span>s.
+
+
+<div class="source-code">
+<pre>
+ // inefficient, but works in a pinch:
+ // iterators can hide all details of chunks by acting like
+ // a raw character pointer
+
+nsWritingIterator&lt;PRUnichar&gt; s = S.BeginWriting();
+nsWritingIterator&lt;PRUnichar&gt; done_with_string = S.EndWriting();
+
+ // for each character in the string |S|
+while ( s != done_with_string )
+ {
+ // if the character is lower case, capitalize it
+ if ( 'a' &lt;= *s &amp;&amp; *s &lt;= 'z' )
+ *s = *s -'a' + 'A';
+ }
+
+
+
+
+ // efficient
+ // iterators provide a mechanism by which you can process
+ // a chunk-at-a-time
+
+nsWritingIterator&lt;PRUnichar&gt; iter = S.BeginWriting();
+nsWritingIterator&lt;PRUnichar&gt; done_with_string = S.EndWriting();
+
+ // for each chunk of the string
+while ( iter != done_with_string )
+ {
+ size_t N = iter.size_forward(); // # of chars in this chunk
+ PRUnichar* s = iter.get();
+ PRUnichar* done_with_chunk = s + N;
+
+ // for each character in this chunk
+ for ( ; s &lt; done_with_chunk; ++s )
+ {
+ // if the character is lower case, capitalize it
+ if ( 'a' &lt;= *s &amp;&amp; *s &lt;= 'z' )
+ *s = *s - 'a' + 'A';
+ }
+
+ // advance the iterator past characters
+ // we examined (and into the next chunk, if any)
+ s += N;
+ }
+
+
+
+ // elegant
+ // pull your transformation into a `sink', and |copy_string|
+ // will efficiently pump any kind of string into it
+
+struct Capitalize
+ {
+ // inline
+ PRUint32
+ write( PRUnichar* s, PRUint32 N )
+ // processes one chunk, called repeatedly by |copy_string|
+ {
+ PRUnichar* done_with_chunk = s + N;
+
+ // for each character in this chunk
+ for ( ; s &lt; done_with_chunk; ++s )
+ {
+ // if the character is lower case, capitalize it
+ if ( 'a' &lt;= *s &amp;&amp; *s &lt;= 'z' )
+ *s = *s - 'a' + 'A';
+ }
+ }
+ };
+
+copy_string(S.BeginWriting(), S.EndWriting(), Capitalize());
+</pre>
+</div>
+
+
+
+<p>Does this show it better?
+
+
+
+
+
+<hr>
+<pre>
+Date: Thu, 17 Aug 2000 18:23:22 -0400
+</pre>
+
+<pre class="email-quote">
+ >I tried looking at the string header files but they
+ >are awfully complicated.
+</pre>
+
+<p>I'll explain things in a little <strong>more</strong> detail than you need, then so
+that some of the stuff you see in these headers will make more sense.
+I'll also answer your questions out of order.
+
+<p>First: the string hierarchy looks like this
+
+<a class="exact-uri" href="http://ScottCollins.net/Journal/discussion/string_hierarchy.gif">http://ScottCollins.net/Journal/discussion/string_hierarchy.gif</a>
+
+<p>The two most important headers are:
+
+<a class="exact-uri" href="http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAReadableString.h">http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAReadableString.h</a>
+<a class="exact-uri" href="http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAWritableString.h">http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAWritableString.h</a>
+
+<p>These abstract classes, <span class="code">nsAReadable[C]String</span>, and
+<span class="code">nsAWritable[C]String</span> are typically what you will want to use in the
+interfaces of new code. If you write a piece of code that takes a
+string for input, consider, e.g.,
+
+<div class="source-code">
+<pre>
+void consumes_a_string( const nsAReadableString&amp; aInput );
+</pre>
+</div>
+
+<p>If you write a piece of code that modifies a string, consider
+
+<div class="source-code">
+<pre>
+void modifies_a_string( nsAWritableString&amp; aResult );
+</pre>
+</div>
+
+
+<p>When creating your own classes, member strings will typically be
+<span class="code">nsString</span>s. When you can't avoid creating a short string that you
+need only temporarily during a function, you will typically use
+<span class="code">nsAutoString</span>. When someone passes you a raw pointer, or a raw
+pointer and a length, representing a buffer of characters that you may
+examine, but won't own, you can treat it like a string by wrapping it
+in an <span class="code">nsLiteralString</span>, e.g.,
+
+<div class="source-code">
+<pre>
+void
+reads_a_buffer( const PRUnichar* aInput, PRUint32 aInputLength )
+ {
+ nsLiteralString input(aInput, aInputLength);
+ // doesn't allocate or copy
+
+ // ...
+ }
+</pre>
+</div>
+
+<p>You will use <span class="code">nsLiteralString</span> around quoted constant strings as well,
+though typically through the <span class="code">NS_LITERAL_STRING</span> macro, to avoid doing
+a length calculation
+
+<div class="source-code">
+<pre>
+NS_LITERAL_STRING("x")
+</pre>
+</div>
+
+<p>expands to
+
+<div class="source-code">
+<pre>
+nsLiteralString(L"x", (sizeof(L"x")/sizeof(PRUnichar) - 1))
+</pre>
+</div>
+
+<p>if <span class="code">L</span> notation works as needed on your platform.
+
+Those are the basics. Now onto your questions:
+
+
+<pre class="email-quote">
+ >For example this won't compile. [...]
+
+ >str1 += L"abc " + str2 + L"def";
+</pre>
+
+
+<p><span class="code">L"abc "</span> makes a an object that is a <span class="code">const wchar_t[5]</span>, and none of
+the string code knows about <span class="code">wchar_t</span>. The main reason is that
+<span class="code">wchar_t</span> is not necessarily the right size (it can be 4 bytes under
+gcc). If you wrap these constant expressions in <span class="code">NS_LITERAL_STRING</span>,
+as described above, you should get the right thing, e.g.,
+
+<div class="source-code">
+<pre>
+str1 += NS_LITERAL_STRING("abc ") + str2 + NS_LITERAL_STRING("def");
+</pre>
+</div>
+
+
+<pre class="email-quote">
+ >Another one is:
+ >function(const PRUnichar *foo);
+ >call function(L"abc " + str2);
+
+ >It won't create a temporary nsString.
+</pre>
+
+<p>This one, I have a quick and easy explanation for. If <span class="code">function</span> was
+declared like this
+
+<div class="source-code">
+<pre>
+function( const nsAReadableString&amp; )
+</pre>
+</div>
+
+<p>then, no problem, since a <span class="code">nsPromiseConcatenation</span> (which was the
+result of adding those two things together) <strong>is</strong> a readable string.
+No other objects need to be created; no copying needs to be performed.
+
+<p>In all cases, we want the creation of <span class="code">nsString</span>s et al, to be
+<span class="code">explicit</span>, since creation is unbelievably expensive, requiring heap
+allocation, locks, copying, etc.
+
+<p>I hope this answers both your posts,
+
+
+
+
+
+<hr>
+<pre>
+Date: Thu, 17 Aug 2000 20:57:08 -0400
+Subject: re our conversation
+</pre>
+
+ return ToNewUnicode( nsLiteralCString(buffer) );
+
+
+
+
+
+
+<hr>
+<pre>
+Date: Fri, 18 Aug 2000 02:52:45 -0400
+Subject: Re: More questions and new string API
+</pre>
+
+<pre class="email-quote">
+ >1) How do I return a static string?
+
+ >const nsAReadableString&amp; foo() {return NS_LITERAL_STRING("x");}
+ >errors on taking the address of a temporary variable.
+</pre>
+
+<p>Unfortunately, <span class="code">NS_LITERAL_STRING</span>s definition is not particularly
+amenable to this use. Instead, you would have to say something like
+this:
+
+<div class="source-code">
+<pre>
+const nsAReadableString&
+foo()
+ {
+#ifdef HAVE_CPP_2BYTE_WCHAR_T
+ static nsLiteralString static_foo(L"x", 1);
+#else
+ static nsLiteralString static_foo;
+ static PRBool initialized = PR_FALSE;
+ if ( !initialized )
+ {
+ static_foo.AssignWithConversion("x", 1);
+ initialized = PR_TRUE;
+ }
+#endif
+ return static_foo;
+ }
+</pre>
+</div>
+
+
+<pre class="email-quote">
+ >2) I'm using these with the STL library in an XPCOM component.
+ >What type should I use with map? This doesn't work...
+
+ >typedef map<const nsAReadableString&, myType*> mapStringMyType;
+ >mapStringMyType foo;
+ >foo.find(nsAReadableString); - I want to find on a ReadableString
+</pre>
+
+<p>I don't know what errors you are getting; but it probably doesn't work
+because a reference isn't an assignable type. This is just a guess.
+You may need to use
+
+<div class="source-code">
+<pre>
+map<const nsAReadableString*, myType*>
+</pre>
+</div>
+
+<p>If you actually want the map to manage ownership of the keys, then
+you'll want to use a concrete type, e.g.,
+
+<div class="source-code">
+<pre>
+map<nsString, myType*>
+</pre>
+</div>
+
+<p>or perhaps
+
+<div class="source-code">
+<pre>
+map<nsSharedStringPtr, myType*>
+</pre>
+</div>
+
+<p>Or maybe there's something else wrong. Send me the error messages.
+If you end up using a pointer, then of course you'll have to supply a
+comparison function to the <span class="code">map</span> template. You won't be satisfied
+with the default comparison of pointers :-) Sorry I couldn't answer
+this one more completely.
+
+
+<pre class="email-quote">
+ >3) How do a get a raw PRUnichar pointer out of nsAReadableString
+ >when I need to call something that wants 'unsigned short *'?
+</pre>
+
+<p>The problem with this scenario is that an <span class="code">nsAReadableString</span> doesn't
+promise that all its data is contiguous, nor that it is
+zero-terminated, which is what I suspect you want in this case. If
+the function you want to call can take {pointer, length} tuples, and
+can consume the string in hunks without zero termination ... then you
+can use <span class="code">copy_string</span> to pump the string into your function, see
+
+ <a class="exact-uri" href="http://ScottCollins.net/Journal/discussion/string_iterators.html">http://ScottCollins.net/Journal/discussion/string_iterators.html</a>
+
+<p>If not, and you absolutely have to have a contiguous zero-terminated
+buffer, then there is a new facility (part of the DOMAPI branch) that
+does what you need. It's not checked in on the trunk; it should
+be in early next week. It is <span class="code">nsPromiseFlatString</span>. This class
+promises a contiguous zero-terminated buffer; and has an <span class="code">operator
+PRUnichar*</span> to produce a pointer to that buffer automatically. If the
+underlying class <strong>is</strong> one that happens to be a single fragment and
+zero-terminated, then, like <span class="code">nsPromiseSubstring</span> and
+<span class="code">nsPromiseConcatenation</span>, this class merely holds a reference into the
+original data. If, however, the underlying string is multi-fragment
+or not zero-terminated, then <span class="code">nsPromiseFlatString</span> allocates a
+contiguous buffer of appropriate size and copies the fragmented string
+data to it. So given
+
+<div class="source-code">
+<pre>
+void ReadBuffer( PRUnichar* );
+</pre>
+</div>
+
+<p>You can call this as efficiently as possible with an arbitrary string
+like so
+
+<div class="source-code">
+<pre>
+ReadBuffer( nsPromiseFlatString(aString) );
+</pre>
+</div>
+
+
+<p>If the function you are calling needs to take ownership of the buffer
+you hand it, then you will probably call <span class="code">ToNewUnicode</span> like so
+
+<div class="source-code">
+<pre>
+void ConsumeBuffer( PRUnichar* );
+
+ConsumeBuffer( ToNewUnicode(aString) );
+</pre>
+</div>
+
+<p>The global function <span class="code">ToNewUnicode</span> is declared in "nsReadableUtils.h",
+and was only recently added to the build. It is currently being used
+in the DOMAPI branch. It is part of the build, but the file
+"dlldeps.c" in XPCOM may need to be modified to ensure it is exported
+on your platform if you are building the tip.
+
+Needless to say, you want to avoid functions that require bare
+pointers for several reasons: (a) they typically assume
+zero-termination, which is not guaranteed by the normal encodings; (b)
+they require contiguous allocation, which may not be possible; (c)
+they scan for the end of the string, at linear cost (if the encoding
+makes it possible at all), when the length could be known in advance.
+If you have to do it, the above mechanisms work, but be aware of the
+cost and the potential need to copy.
+
+
+<pre class="email-quote">
+ >4) How do I declare a local variable to hold a nsAReadableString?
+ >and a member variable?
+</pre>
+
+<p><span class="code">nsAReadableString</span> is an abstract type. So you can't have a concrete
+instance of it. All strings in the hierarchy are readable strings.
+If you just want a reference to a readable string, you can say, e.g.,
+
+<div class="source-code">
+<pre>
+struct foo
+ {
+ const nsAReadableString&amp; mString;
+ // ...
+
+ foo( const nsAReadableString&amp; aString ) : mString(aString) { }
+ };
+</pre>
+</div>
+
+<p>...similarly with pointers; but I suspect you are looking for
+something more concrete. An <span class="code">nsString</span> is a <span class="code">nsAReadableString</span>, and
+is the typical thing you want as a member variable. An <span class="code">nsAutoString</span>
+is also an <span class="code">nsAReadableString</span> and is typically what you would use for
+a short (in length) temporary (in lifetime) local variable, as I
+mentioned in my previous post.
+
+
+<pre class="email-quote">
+ >5) If I call a function that returns a PRUnichar* and I want t
+ >use it as a nsAReadableString should I wrap it in a
+ >nsLiteralString?
+</pre>
+
+<p>Yes, though remember, an <span class="code">nsLiteralString</span> assumes the lifetime of the
+underlying data is under someone else's control. If the called
+function gives you a buffer that you need to <span class="code">delete</span>, you will have
+to manage that yourself. Currently, people often use <span class="code">nsXPIDLString</span>
+to handle that. XPIDL strings are <strong>not</strong> part of the hierarchy. They
+are only used as a sort of string-<span class="code">auto_ptr</span>. However, I'm
+integrating their functionality into <span class="code">nsString</span>. There is no problem
+in wrapping the same pointer in both as two separate local variables,
+one to give you the readable interface, and one to manage the
+lifetime.
+
+<p>If it's OK with you, I'd like to post this reply (including your
+quoted questions) to n.p.m.xpcom and also put a copy near the string
+iterator discussion I provided a link to above, so that other people
+with similar questions can see these answers.
+
+<p>Hope this helps,
+
+
+
+
+
+<hr>
+<pre>
+Date: Sun, 3 Sep 2000 03:52:17 -0400
+</pre>
+
+<p>In article <8nu9m2$eo14@secnews.netscape.com>, "Jon Smirl"
+<jonsmirl@mediaone.com> wrote:
+
+> I have the new strings up and running in my app. They work as
+> advertised and
+> I haven't found any bugs. Thanks for the good job in designing and
+> implementing them. Here's are a summary of issues I've encountered
+> so far...
+
+<p>Thanks, and I appreciate your comments and insights.
+
+
+>
+> 1) Should there be a nsSegmentedString derived from nsString instead
+> of building segment support into nsString? None of my strings are
+> segmented but
+> I keep executing code that is supports it. nsPromiseFlatString would
+> be trivial in the non-segmented case.
+
+<p>The general case is that a string does not promise to have contiguous
+data. A specific case is that, for some implementations, it does.
+You couldn't do it the other way around, because a segmented string
+couldn't satisfy all the promises of a flat string. However, through
+the use of chunky iterators, operating on strings that happen to be
+flat is very efficient. In fact, <span class="code">nsPromiseFlatString</span> is trivial in
+the non-segmented case. In addition, I'll be adding an abstract flat
+class into the hierarchy, which will present additional interface ...
+in your local routines where you actually have declared a concrete
+string instance that happens to be flat, the compiler will give you
+the benefit of using the flat specific routines (e.g., a substring
+object over a flat string is simpler than the general purpose
+substring). I need to be cautious about this, though, since I don't
+automatically want people propagating the flat type through their
+interfaces. That would put us in the same boat we're in right now ...
+where routines only work on a specific kind of string, which denies
+other parts of the code the opportunity to use an implementation
+beneficial to its specific needs, and typically for no good reason.
+
+>
+> 2) Should nsAWritableString have a way to get the buffer and then
+> return it?
+> I need to get the buffer to pass it to OS calls. I'm doing this now
+> by passing around nsStrings instead of the interface. If I just use
+> the interface I encur an extra copy since I have to use a temporary
+> buffer.
+
+<p>A specific string implementation could promise this, but in general, a
+writable could not. After all, a writable doesn't even guarantee
+contiguous storage. To some degree, this is what
+<span class="code">nsPromiseFlatString</span> is for. However, this is a readable promise
+only. It will also be the case that <span class="code">ns[C]String</span>s, in the very near
+future will be able to just assume ownership of an arbitrary buffer
+allocated on the free store with the XPCOM allocators ... getting one
+to give up its buffer, on the other hand, presents some problems. Do
+you have a lot of places where the system writes into your string
+buffer space? Or do you have a lot of system routines that return you
+new buffers? I can imagine using <span class="code">nsPromiseFlatString</span> for this, but
+what happens when the OS alters the underlying data? If the promise
+had generated that flat data on behalf of a multi-fragment string,
+should it now put the changes back? It's possible to do, I just want
+to know if it's correct to allow this situation to happen.
+
+
+
+>
+> 3) There needs to be a NS_LITERAL_CHAR() to go along with
+> NS_LITERAL_STRING().
+
+<p>OK.
+
+
+
+> Having NS_LITERAL_STRING() all over the code clutters
+> it up and makes it hard to tell what the code is doing, could we
+> have a standard short alias for this?
+
+<p>Yes, I'll try to think of something ... perhaps <span class="code">NS_LSTR</span>?
+
+
+> 4) nsLiteralString should support n.ToInteger(&error);
+
+<p><span class="code">ToInteger</span> is actually a bad interface. It's only good if your
+entire string is the number; this encourages you to edit your string
+until it is one, or perhaps copy the numeric part to another string.
+Better if you just <span class="code">sscanf</span> a string (don't know if I can provide
+that in the general case, but I'm thinking about it), or else use
+regular C++ extractors (which wouldn't be too hard for me to
+provide), or else I could give you a <span class="code">ToInteger</span> that works on a pair
+of iterators, extracting the integer from the digits between them.
+
+>
+> 5) There should be a global define for an interface to a readonly
+> empty string.
+
+<p>Yes, there will be.
+
+
+>
+> 6) Something is wrong with concatenation....
+
+<p>Hopefully I've fixed this now.
+
+
+
+> 8) A forward definition is missing in the h files
+
+<p>I'll check it out.
+
+
+
+<p>My understanding is that you have already found the answers to your
+other questions.
+
+<p>I hope this helps,
+
+
+
+
+<hr>
+<pre>
+Date: Wed, 20 Sep 2000 17:32:13 -0400
+Subject: Re: how to free an nsString::ToNewCString
+</pre>
+
+<pre class="email-quote">
+ >What's the current approved way to free an nsString::ToNewCString?
+</pre>
+
+<p><span class="code">nsMemory::Free</span>
+
+
+
+
+
+<hr>
+
+<p>You use several <span class="code">NS_ConvertASCIItoUTF16("...").get()</span>, these should be
+
+ NS_LITERAL_STRING("...").get()
+
+<p>Don't do this to the very first case where you aren't wrapping an actual literal string.
+The first instance would should exploit <span class="code">NS_LITERAL_STRING</span> technology as well,
+around the initial declarations of the strings ... probably want to do this with
+<span class="code">NS_NAMED_LITERAL_STRING</span>.
+
+
+
+<hr>
+<pre>
+Date: Thu, 12 Oct 2000 00:57:28 -0400
+Subject: string answers
+</pre>
+
+<div class="source-code">
+<pre>
+nsresult
+DoSomething( nsAWritableString&amp; answer )
+ {
+ nsresult rv;
+
+ nsXPIDLString registry_data;
+ Fetch("key", getter_Shares(registry_data));
+
+ nsLiteralString path(not_my_string);
+
+ PRInt32 first_colon = path.FindChar(PRUnichar(':'));
+ if ( first_colon != -1 )
+ {
+ // convert ... extract path from |path|
+ nsCOMPtr<nsILocalFile> localFile( do_CreateInstance(CID, &rv)
+);
+ if ( localFile )
+ {
+
+localFile->SetPersistentDescriptor(NS_ConvertUTF16toUTF8(path));
+
+ nsXPIDLString converted_path;
+ localFile->GetUnicodePath(getter_Copies(converted_path));
+ answer = converted_path.get();
+ }
+ }
+ else
+ {
+ answer = path;
+ }
+
+
+ return rv;
+ }
+</pre>
+</div>
+
+
+
+
+
+<hr>
+<pre>
+Date: Thu, 12 Oct 2000 02:03:49 -0400
+Subject: Re: and the answer is ...
+</pre>
+
+<p>You can see from the line of code that you're on, that this should
+have been fine. <span class="code">nsMemory::Alloc</span> would be asked to allocate a 1 byte
+object. But it failed trying to allocate that. Which suggests that
+the allocator was busy and non-reentrant and the debugger tried to
+misuse it. Yes?
+
+<p>Of course, this doesn't solve your problem. Perhaps we need to go
+back to the idea of a function that returns a pointer to the first
+hunk of the string.
+
+<div class="source-code">
+<pre>
+const char*
+debug_string( const nsAReadableCString& aCString )
+ {
+ nsReadingIterator&lt;char&gt; iter;
+ aCString.BeginReading(iter);
+ return aCString.IsEmpty() ? "" : iter.get();
+ }
+</pre>
+</div>
+
+<p>This code should work regardless of what the allocator is doing. The
+downsides are (a) it only returns the first hunk of the string, in the
+case of a multi-fragment string; and (b) that hunk <strong>might</strong> not be
+zero-terminated.
+
+<p>Hope this helps,
+
+
+
+
+
+<hr>
+<pre>
+Date: Thu, 12 Oct 2000 08:30:32 -0400
+Subject: Re: Self healing the cache :-)
+</pre>
+
+<p>At 3:04 PM -0400 10/11/00, Mike Shaver wrote:
+<pre class="email-quote">
+ >NS_LITERAL_STRING(NS_XPCOM_SHUTDOWN_OBSERVER_ID);
+</pre>
+
+<p>Macro ugliness makes <span class="code">NS_LITERAL_STRING</span> inappropriate for use over
+other macros. In other words:
+
+<div class="source-code">
+<pre>
+NS_LITERAL_STRING("foo")
+</pre>
+</div>
+
+<p>is <strong>good</strong>.
+
+<div class="source-code">
+<pre>
+#define FOO "foo"
+NS_LITERAL_STRING(FOO)
+</pre>
+</div>
+
+<p>is <strong>bad</strong>. Why? Because it turns into
+
+<div class="source-code">
+<pre>
+nsLiteralString(LFOO, sizeof(LFOO)...
+</pre>
+</div>
+
+<p>and there is no <span class="code">LFOO</span>. Sorry. If you have to do this to a
+macro-ized string, do the magic by hand, e.g.,
+
+<div class="source-code">
+<pre>
+nsLiteralString(FOO, sizeof(FOO)/sizeof(PRUnichar)
+ + sizeof(PRUnichar('\0')))
+</pre>
+</div>
+
+<p>or else if you don't care that <span class="code">nsLiteralString</span> will scan for the
+length, just say
+
+<div class="source-code">
+<pre>
+nsLiteralString(FOO)
+</pre>
+</div>
+
+<p>Hope this helps,
+
+
+
+
+
+<hr>
+<pre>
+Date: Thu, 12 Oct 2000 08:36:14 -0400
+Subject: Re: Self healing the cache :-)
+</pre>
+
+<p>Actually, I'm not even sure you can do it by hand, since you didn't
+
+<div class="source-code">
+<pre>
+#define FOO L"foo"
+</pre>
+</div>
+
+<p>and <strong>can't</strong> do that cross-platform. The other way around this is to
+define a global instead of a macro, that is, instead of saying
+
+<div class="source-code">
+<pre>
+#define FOO "foo"
+</pre>
+</div>
+
+<p>at the top of your file, say
+
+<div class="source-code">
+<pre>
+NS_NAMED_LITERAL_STRING(FOO, "foo")
+</pre>
+</div>
+
+<p>or else, if the macro was used only in one spot ... perhaps you could
+just eliminate the macro in favor of <span class="code">NS_NAMED_LITERAL</span> in situ.
+
+<p>Arghh. In this case, you may be stuck with the extra work of
+<span class="code">AssignWithConversion</span>.
+
+
+
+
+
+<hr>
+<pre>
+Date: Sun, 3 Dec 2000 16:38:07 -0400
+Subject: Re: another copy_string question
+</pre>
+
+<pre class="email-quote">
+ >Is there a way to tell, inside the write() sink, if one is in the
+ >final hunk? I need to do some special processing at the end.
+</pre>
+
+<p>No, there isn't. But you could move such special processing into the
+destructor of the sink. Remember, the sink is passed by reference, so
+you can exactly control its lifetime.
+
+<div class="source-code">
+<pre>
+{
+ MySink sink;
+ nsReadingIterator&lt;PRUnichar&gt; sourceStart = aStr.BeginReading();
+ nsReadingIterator&lt;PRUnichar&gt; sourceEnd = aStr.EndReading();
+ copy_string(sourceStart, sourceEnd, sink);
+ // |sink| destructor executed here
+}
+</pre>
+</div>
+
+<p>Hope this helps,
+
+
+
+
+
+<hr>
+<pre>
+Date: Fri, 15 Dec 2000 20:02:08 -0400
+Subject: fragment of code
+</pre>
+
+<div class="source-code">
+<pre>
+nsPromiseFlatString flatKey(aReadable);
+
+flatKey.get()
+</pre>
+</div>
+
+
+
+
+
+
+<hr>
+<pre>
+Date: Tue, 16 Jan 2001 16:47:37 -0400
+Subject: Re: a few string questions...
+</pre>
+
+>I've accumulated a few questions I've been wanting to ask you, mostly
+>about string stuff. Nothing urgent, but I want to ask them before I
+>forget. So here goes...:
+>
+>1) Is it acceptable to use nsLiteralCString or nsLiteralString on
+>something that's not a literal? This can be useful in some places,
+>for example, to convert a char* to PRUnichar*:
+>
+>PRUnichar* new = ToNewUnicode(nsLiteralCString(myCharPtr));
+
+<p>This is explicitly allowed. That's why I'm proposing to change the
+names of those classes to <span class="code">nsLocal[C]String</span>.
+
+
+>2) Should nsString2x.h and nsString2x.cpp go away? They look like a
+>never-completed rewrite or something...
+
+<p>Yes. They should go away. They are uncompleted [old] bullshit,
+exactly as you diagnosed.
+
+<p>I'll look into the other two questions.
+
+
+
+
+
+<hr>
+<pre>
+Date: Thu, 1 Feb 2001 15:12:41 -0400
+Subject: Re: [Fwd: bad string, bad string]
+</pre>
+
+<p>We've been removing implicit conversion operators because they
+_always_ lead to trouble. Usually they make it harder to pick the
+right function when overloading is involved and in the past they have
+led to huge performance suckage because we ended up doing conversions
+when we didn't need to because the implicit operator made us pick the
+wrong function.
+
+<p>It's borderline when the class implements something that is <strong>so</strong>
+close, as with a guaranteed flat string or an <span class="code">nsCOMPtr</span> ... but the
+general recommendation is to avoid implicit conversions.
+
+<p>See bug #53057.
+
+
+
+
+
+<hr>
+<pre>
+Date: Tue, 6 Feb 2001 18:52:23 -0400
+Subject: seeking review for bug #57087
+</pre>
+
+<p> bug:
+ <a class="exact-uri" href="http://bugzilla.mozilla.org/show_bug.cgi?id=57087">http://bugzilla.mozilla.org/show_bug.cgi?id=57087</a>
+
+ patch:
+ <a class="exact-uri" href="http://bugzilla.mozilla.org/showattachment.cgi?attach_id=24576">http://bugzilla.mozilla.org/showattachment.cgi?attach_id=24576</a>
+
+<p>This patch is supposed to add the ability to define very long literal
+strings more easily by breaking lines, e.g.,
+
+<div class="source-code">
+<pre>
+NS_MULTILINE_LITERAL( NS_L("This is the start of a very long line")
+ NS_L(" which actually continues across")
+ NS_L(" a couple more.") )
+</pre>
+</div>
+
+<p>The main danger in this scheme is callers who omit the inner <span class="code">NS_L</span>
+wrapping. Though I believe this will be caught at compile time as the
+wrong type initializer.
+
+<p>Seeking input from everybody, and waterson in particular.
+
+
+
+
+
+<hr>
+<pre>
+Date: Wed, 14 Feb 2001 16:09:10 -0400
+Subject: Re: Question...
+</pre>
+
+<p>There are some utilities in "xpcom/ds/nsReadableUtils.h". In
+particular, if you want to get back a new heap-allocated ASCII string
+with the minimal work, you would say
+
+<div class="source-code">
+<pre>
+PRUnichar* sourceChars = ...;
+
+char* destChars = ToNewCString(nsLiteralString(sourceChars));
+</pre>
+</div>
+
+
+<p>It's more efficient if you happen to already know the length. If you
+don't, don't bother counting, that's what I'll do in the constructor
+for <span class="code">nsLiteralString</span>. If you do, then call like this
+
+<div class="source-code">
+<pre>
+destChars = ToNewCString( nsLiteralString(sourceChars, length) );
+</pre>
+</div>
+
+<p>Other routines in that file will help you if, for instance, you wanted
+to translate into a buffer you had already allocated.
+
+<p>Hope this helps,
+
+
+
+
+
+<hr>
+<pre>
+Date: Fri, 23 Feb 2001 03:12:58 -0400
+Subject: string snippet
+</pre>
+
+<div class="source-code">
+<pre>
+nsCString aInput;
+
+
+
+nsReadingIterator&lt;char&gt; search_start;
+aInput.BeginReading(search_start);
+
+nsReadingIterator&lt;char&gt; search_end;
+aInput.EndReading(search_end);
+
+if ( FindCharInReadable(':', search_start, search_end) )
+ {
+ ++search_start;
+ return ToNewCString( Substring(aInput, search_start, search_end)
+);
+ }
+</pre>
+</div>
+
+
+
+
+
+
+<hr>
+<pre>
+Date: Wed, 7 Mar 2001 19:44:08 -0400
+Subject: string help
+</pre>
+
+<p>Here you go, Mike:
+
+ http://scottcollins.net/journal/discussion/mjudge-scratch.cpp
+
+
+
+
+
+
+<hr>
+<pre>
+Date: Fri, 9 Mar 2001 20:56:07 -0400
+Subject: Re: string assertions
+</pre>
+
+<p>If you get an iterator into a string and you advance it all the way to
+the end of the string, and then <strong>keep</strong> trying to advance it, you hit
+this assert. This could happen, for example if you tried to copy 10
+characters out of a 9 character string. I've tried to make this
+impossible to get to. As far as I know, all my routines trim requests
+in advance of manipulating iterators. When you see this, you should
+get the stack. That will take you right to the bad spot.
+
+
+
+
+
+<hr>
+<pre>
+Date: Sat, 31 Mar 2001 11:04:03 -0400
+Subject: Re: Sun bustage and string advice
+</pre>
+
+<p>You do know you are comparing two pointers now? It seems unlikely
+those two pointers would ever be the same pointer. You probably want
+to say something like
+
+<div class="source-code">
+<pre>
+NS_LITERAL_STRING("foo").Equals(aTopic) // or
+
+NS_LITERAL_STRING("foo") == nsLiteralString(aTopic)
+</pre>
+</div>
+
+<p>...so that you compare the <strong>contents</strong> of two strings. Right now,
+you're just testing to see if two pointers both point to the same
+location in memory. A lot of people make this mistake. I would like
+to make it obvious to people that comparing two pointers does not
+compare strings. Can you tell me what gave you that impression so
+that I can figure out how to better educate people not to do this? By
+the way, it's not that I don't <strong>want</strong> to make this compare two
+strings; it's that in C++, you can't override operations for built-in
+types. And pointers are built-in types. So I can't make
+<span class="code">operator==(const PRUnichar*, const PRUnichar*)</span> do anything different
+than it already does, which is the same thing it does for any other
+pointer.
+
+
+
+
+
+
+</div>
+
+
+
+<!-- .................................................................End Matter -->
+
+
+
+ </body>
+</html>
diff --git a/src/libs/xpcom18a4/xpcom/string/public/.cvsignore b/src/libs/xpcom18a4/xpcom/string/public/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/string/public/Makefile.in b/src/libs/xpcom18a4/xpcom/string/public/Makefile.in
new file mode 100644
index 00000000..d3582bcc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/Makefile.in
@@ -0,0 +1,86 @@
+# vim:set ts=8 sw=8 sts=8 noet:
+#
+# ***** 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.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications.
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Johnny Stenback <jst@netscape.com> (original author)
+# Scott Collins <scc@mozilla.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 *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = string
+
+EXPORTS = \
+ nsAString.h \
+ nsAlgorithm.h \
+ nsCharTraits.h \
+ nsDependentString.h \
+ nsDependentSubstring.h \
+ nsLiteralString.h \
+ nsObsoleteAString.h \
+ nsPrintfCString.h \
+ nsPromiseFlatString.h \
+ nsReadableUtils.h \
+ nsString.h \
+ nsStringFwd.h \
+ nsStringIterator.h \
+ nsSubstring.h \
+ nsSubstringTuple.h \
+ nsTAString.h \
+ nsTDependentString.h \
+ nsTDependentSubstring.h \
+ nsTObsoleteAString.h \
+ nsTPromiseFlatString.h \
+ nsTString.h \
+ nsTSubstring.h \
+ nsTSubstringTuple.h \
+ nsUTF8Utils.h \
+ nsXPIDLString.h \
+ string-template-def-unichar.h \
+ string-template-def-char.h \
+ string-template-undef.h \
+ $(NULL)
+
+SDK_HEADERS = \
+ nsStringAPI.h \
+ nsEmbedString.h \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsAString.h b/src/libs/xpcom18a4/xpcom/string/public/nsAString.h
new file mode 100644
index 00000000..3675989c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsAString.h
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 nsAString_h___
+#define nsAString_h___
+
+#ifndef nsStringFwd_h___
+#include "nsStringFwd.h"
+#endif
+
+#ifndef nsStringIterator_h___
+#include "nsStringIterator.h"
+#endif
+
+#ifndef nsObsoleteAString_h___
+#include "nsObsoleteAString.h"
+#endif
+
+// If some platform(s) can't handle our template that matches literal strings,
+// then we'll disable it on those platforms.
+#ifndef NS_DISABLE_LITERAL_TEMPLATE
+# if (defined(_MSC_VER) && (_MSC_VER < 1310)) || (defined(__SUNPRO_CC) & (__SUNPRO_CC < 0x560)) || (defined(__HP_aCC) && (__HP_aCC <= 012100))
+# define NS_DISABLE_LITERAL_TEMPLATE
+# endif
+#endif /* !NS_DISABLE_LITERAL_TEMPLATE */
+
+#include <string.h>
+
+ // declare nsAString
+#include "string-template-def-unichar.h"
+#include "nsTAString.h"
+#include "string-template-undef.h"
+
+
+ // declare nsACString
+#include "string-template-def-char.h"
+#include "nsTAString.h"
+#include "string-template-undef.h"
+
+
+ /**
+ * ASCII case-insensitive comparator. (for Unicode case-insensitive
+ * comparision, see nsUnicharUtils.h)
+ */
+class NS_COM nsCaseInsensitiveCStringComparator
+ : public nsCStringComparator
+ {
+ public:
+ typedef char char_type;
+
+ virtual int operator()( const char_type*, const char_type*, PRUint32 length ) const;
+ virtual int operator()( char_type, char_type ) const;
+ };
+
+
+ // included here for backwards compatibility
+#ifndef nsSubstringTuple_h___
+#include "nsSubstringTuple.h"
+#endif
+
+#endif // !defined(nsAString_h___)
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsAlgorithm.h b/src/libs/xpcom18a4/xpcom/string/public/nsAlgorithm.h
new file mode 100644
index 00000000..e81e6f57
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsAlgorithm.h
@@ -0,0 +1,131 @@
+/* -*- 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):
+ * Scott Collins <scc@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 nsAlgorithm_h___
+#define nsAlgorithm_h___
+
+#ifndef nsCharTraits_h___
+#include "nsCharTraits.h"
+ // for |nsCharSourceTraits|, |nsCharSinkTraits|
+#endif
+
+#ifndef prtypes_h___
+#include "prtypes.h"
+ // for |PRUint32|...
+#endif
+
+#ifndef nsDebug_h___
+#include "nsDebug.h"
+ // for NS_ASSERTION
+#endif
+
+template <class T>
+inline
+const T&
+NS_MIN( const T& a, const T& b )
+ {
+ return b < a ? b : a;
+ }
+
+template <class T>
+inline
+const T&
+NS_MAX( const T& a, const T& b )
+ {
+ return a > b ? a : b;
+ }
+
+template <class InputIterator, class T>
+inline
+PRUint32
+NS_COUNT( InputIterator& first, const InputIterator& last, const T& value )
+ {
+ PRUint32 result = 0;
+ for ( ; first != last; ++first )
+ if ( *first == value )
+ ++result;
+ return result;
+ }
+
+template <class InputIterator, class OutputIterator>
+inline
+OutputIterator&
+copy_string( InputIterator& first, const InputIterator& last, OutputIterator& result )
+ {
+ typedef nsCharSourceTraits<InputIterator> source_traits;
+ typedef nsCharSinkTraits<OutputIterator> sink_traits;
+
+ while ( first != last )
+ {
+ PRInt32 count_copied = PRInt32(sink_traits::write(result, source_traits::read(first), source_traits::readable_distance(first, last)));
+ NS_ASSERTION(count_copied > 0, "|copy_string| will never terminate");
+ source_traits::advance(first, count_copied);
+ }
+
+ return result;
+ }
+
+template <class InputIterator, class OutputIterator>
+OutputIterator&
+copy_string_backward( const InputIterator& first, InputIterator& last, OutputIterator& result )
+ {
+ while ( first != last )
+ {
+ last.normalize_backward();
+ result.normalize_backward();
+ PRUint32 lengthToCopy = PRUint32( NS_MIN(last.size_backward(), result.size_backward()) );
+ if ( first.fragment().mStart == last.fragment().mStart )
+ lengthToCopy = NS_MIN(lengthToCopy, PRUint32(last.get() - first.get()));
+
+ NS_ASSERTION(lengthToCopy, "|copy_string_backward| will never terminate");
+
+#ifdef _MSC_VER
+ // XXX Visual C++ can't stomach 'typename' where it rightfully should
+ nsCharTraits<OutputIterator::value_type>::move(result.get()-lengthToCopy, last.get()-lengthToCopy, lengthToCopy);
+#else
+ nsCharTraits<typename OutputIterator::value_type>::move(result.get()-lengthToCopy, last.get()-lengthToCopy, lengthToCopy);
+#endif
+
+ last.advance( -PRInt32(lengthToCopy) );
+ result.advance( -PRInt32(lengthToCopy) );
+ }
+
+ return result;
+ }
+
+#endif // !defined(nsAlgorithm_h___)
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsCharTraits.h b/src/libs/xpcom18a4/xpcom/string/public/nsCharTraits.h
new file mode 100644
index 00000000..e7713c95
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsCharTraits.h
@@ -0,0 +1,784 @@
+/* -*- 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@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 nsCharTraits_h___
+#define nsCharTraits_h___
+
+#include <ctype.h>
+ // for |EOF|, |WEOF|
+
+#define FORCED_CPP_2BYTE_WCHAR_T
+ // disable special optimizations for now through this hack
+
+#if defined(HAVE_CPP_2BYTE_WCHAR_T) && !defined(FORCED_CPP_2BYTE_WCHAR_T)
+#define USE_CPP_WCHAR_FUNCS
+#endif
+
+#ifdef USE_CPP_WCHAR_FUNCS
+#include <wchar.h>
+ // for |wmemset|, et al
+#endif
+
+#include <string.h>
+ // for |memcpy|, et al
+
+#ifndef nscore_h___
+#include "nscore.h"
+ // for |PRUnichar|
+#endif
+
+#ifndef nsDebug_h__
+#include "nsDebug.h"
+ // for NS_ASSERTION
+#endif
+
+#ifdef HAVE_CPP_BOOL
+ typedef bool nsCharTraits_bool;
+#else
+ typedef PRBool nsCharTraits_bool;
+#endif
+
+template <class CharT> struct nsCharTraits {};
+
+NS_SPECIALIZE_TEMPLATE
+struct nsCharTraits<PRUnichar>
+ {
+ typedef PRUnichar char_type;
+ typedef PRUint16 unsigned_char_type;
+ typedef char incompatible_char_type;
+
+ NS_COM static const char_type *sEmptyBuffer;
+
+ static
+ void
+ assign( char_type& lhs, char_type rhs )
+ {
+ lhs = rhs;
+ }
+
+
+ // integer representation of characters:
+
+#ifdef USE_CPP_WCHAR_FUNCS
+ typedef wint_t int_type;
+#else
+ typedef int int_type;
+#endif
+
+ static
+ char_type
+ to_char_type( int_type c )
+ {
+ return char_type(c);
+ }
+
+ static
+ int_type
+ to_int_type( char_type c )
+ {
+ return int_type( NS_STATIC_CAST(unsigned_char_type, c) );
+ }
+
+ static
+ nsCharTraits_bool
+ eq_int_type( int_type lhs, int_type rhs )
+ {
+ return lhs == rhs;
+ }
+
+
+ // |char_type| comparisons:
+
+ static
+ nsCharTraits_bool
+ eq( char_type lhs, char_type rhs )
+ {
+ return lhs == rhs;
+ }
+
+ static
+ nsCharTraits_bool
+ lt( char_type lhs, char_type rhs )
+ {
+ return lhs < rhs;
+ }
+
+
+ // operations on s[n] arrays:
+
+ static
+ char_type*
+ move( char_type* s1, const char_type* s2, size_t n )
+ {
+ return NS_STATIC_CAST(char_type*, memmove(s1, s2, n * sizeof(char_type)));
+ }
+
+ static
+ char_type*
+ copy( char_type* s1, const char_type* s2, size_t n )
+ {
+ return NS_STATIC_CAST(char_type*, memcpy(s1, s2, n * sizeof(char_type)));
+ }
+
+ static
+ char_type*
+ copyASCII( char_type* s1, const char* s2, size_t n )
+ {
+ for (char_type* s = s1; n--; ++s, ++s2) {
+ NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
+ *s = *s2;
+ }
+ return s1;
+ }
+
+ static
+ char_type*
+ assign( char_type* s, size_t n, char_type c )
+ {
+#ifdef USE_CPP_WCHAR_FUNCS
+ return NS_STATIC_CAST(char_type*, wmemset(s, to_int_type(c), n));
+#else
+ char_type* result = s;
+ while ( n-- )
+ assign(*s++, c);
+ return result;
+#endif
+ }
+
+ static
+ int
+ compare( const char_type* s1, const char_type* s2, size_t n )
+ {
+#ifdef USE_CPP_WCHAR_FUNCS
+ return wmemcmp(s1, s2, n);
+#else
+ for ( ; n--; ++s1, ++s2 )
+ {
+ if ( !eq(*s1, *s2) )
+ return to_int_type(*s1) - to_int_type(*s2);
+ }
+
+ return 0;
+#endif
+ }
+
+ static
+ int
+ compareASCII( const char_type* s1, const char* s2, size_t n )
+ {
+ for ( ; n--; ++s1, ++s2 )
+ {
+ NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
+ if ( !eq_int_type(to_int_type(*s1), to_int_type(*s2)) )
+ return to_int_type(*s1) - to_int_type(*s2);
+ }
+
+ return 0;
+ }
+
+ // this version assumes that s2 is null-terminated and s1 has length n.
+ // if s1 is shorter than s2 then we return -1; if s1 is longer than s2,
+ // we return 1.
+ static
+ int
+ compareASCIINullTerminated( const char_type* s1, size_t n, const char* s2 )
+ {
+ for ( ; n--; ++s1, ++s2 )
+ {
+ if ( !*s2 )
+ return 1;
+ NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
+ if ( !eq_int_type(to_int_type(*s1), to_int_type(*s2)) )
+ return to_int_type(*s1) - to_int_type(*s2);
+ }
+
+ if ( *s2 )
+ return -1;
+
+ return 0;
+ }
+
+ /**
+ * Convert c to its lower-case form, but only if the lower-case form is
+ * ASCII. Otherwise leave it alone.
+ *
+ * There are only two non-ASCII Unicode characters whose lowercase
+ * equivalents are ASCII: KELVIN SIGN and LATIN CAPITAL LETTER I WITH
+ * DOT ABOVE. So it's a simple matter to handle those explicitly.
+ */
+ static
+ char_type
+ ASCIIToLower( char_type c )
+ {
+ if (c < 0x100)
+ return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c;
+ else
+ {
+ if (c == 0x212A) // KELVIN SIGN
+ return 'k';
+ if (c == 0x0130) // LATIN CAPITAL LETTER I WITH DOT ABOVE
+ return 'i';
+ return c;
+ }
+ }
+
+ static
+ int
+ compareLowerCaseToASCII( const char_type* s1, const char* s2, size_t n )
+ {
+ for ( ; n--; ++s1, ++s2 )
+ {
+ NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
+ NS_ASSERTION(!(*s2 >= 'A' && *s2 <= 'Z'),
+ "Unexpected uppercase character");
+ char_type lower_s1 = ASCIIToLower(*s1);
+ if ( lower_s1 != to_char_type(*s2) )
+ return to_int_type(lower_s1) - to_int_type(*s2);
+ }
+
+ return 0;
+ }
+
+ // this version assumes that s2 is null-terminated and s1 has length n.
+ // if s1 is shorter than s2 then we return -1; if s1 is longer than s2,
+ // we return 1.
+ static
+ int
+ compareLowerCaseToASCIINullTerminated( const char_type* s1, size_t n, const char* s2 )
+ {
+ for ( ; n--; ++s1, ++s2 )
+ {
+ if ( !*s2 )
+ return 1;
+ NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
+ NS_ASSERTION(!(*s2 >= 'A' && *s2 <= 'Z'),
+ "Unexpected uppercase character");
+ char_type lower_s1 = ASCIIToLower(*s1);
+ if ( lower_s1 != to_char_type(*s2) )
+ return to_int_type(lower_s1) - to_int_type(*s2);
+ }
+
+ if ( *s2 )
+ return -1;
+
+ return 0;
+ }
+
+ static
+ size_t
+ length( const char_type* s )
+ {
+#ifdef USE_CPP_WCHAR_FUNCS
+ return wcslen(s);
+#else
+ size_t result = 0;
+ while ( !eq(*s++, char_type(0)) )
+ ++result;
+ return result;
+#endif
+ }
+
+ static
+ const char_type*
+ find( const char_type* s, size_t n, char_type c )
+ {
+#ifdef USE_CPP_WCHAR_FUNCS
+ return NS_REINTERPRET_CAST(const char_type*, wmemchr(s, to_int_type(c), n));
+#else
+ while ( n-- )
+ {
+ if ( eq(*s, c) )
+ return s;
+ ++s;
+ }
+
+ return 0;
+#endif
+ }
+
+#if 0
+ // I/O related:
+
+ typedef streamoff off_type;
+ typedef streampos pos_type;
+ typedef mbstate_t state_type;
+
+ static
+ int_type
+ eof()
+ {
+#ifdef USE_CPP_WCHAR_FUNCS
+ return WEOF;
+#else
+ return EOF;
+#endif
+ }
+
+ static
+ int_type
+ not_eof( int_type c )
+ {
+ return eq_int_type(c, eof()) ? ~eof() : c;
+ }
+
+ // static state_type get_state( pos_type );
+#endif
+ };
+
+NS_SPECIALIZE_TEMPLATE
+struct nsCharTraits<char>
+ {
+ typedef char char_type;
+ typedef unsigned char unsigned_char_type;
+ typedef PRUnichar incompatible_char_type;
+
+ NS_COM static const char_type *sEmptyBuffer;
+
+ static
+ void
+ assign( char_type& lhs, char_type rhs )
+ {
+ lhs = rhs;
+ }
+
+
+ // integer representation of characters:
+
+ typedef int int_type;
+
+ static
+ char_type
+ to_char_type( int_type c )
+ {
+ return char_type(c);
+ }
+
+ static
+ int_type
+ to_int_type( char_type c )
+ {
+ return int_type( NS_STATIC_CAST(unsigned_char_type, c) );
+ }
+
+ static
+ nsCharTraits_bool
+ eq_int_type( int_type lhs, int_type rhs )
+ {
+ return lhs == rhs;
+ }
+
+
+ // |char_type| comparisons:
+
+ static
+ nsCharTraits_bool
+ eq( char_type lhs, char_type rhs )
+ {
+ return lhs == rhs;
+ }
+
+ static
+ nsCharTraits_bool
+ lt( char_type lhs, char_type rhs )
+ {
+ return lhs < rhs;
+ }
+
+
+ // operations on s[n] arrays:
+
+ static
+ char_type*
+ move( char_type* s1, const char_type* s2, size_t n )
+ {
+ return NS_STATIC_CAST(char_type*, memmove(s1, s2, n * sizeof(char_type)));
+ }
+
+ static
+ char_type*
+ copy( char_type* s1, const char_type* s2, size_t n )
+ {
+ return NS_STATIC_CAST(char_type*, memcpy(s1, s2, n * sizeof(char_type)));
+ }
+
+ static
+ char_type*
+ copyASCII( char_type* s1, const char* s2, size_t n )
+ {
+ return copy(s1, s2, n);
+ }
+
+ static
+ char_type*
+ assign( char_type* s, size_t n, char_type c )
+ {
+ return NS_STATIC_CAST(char_type*, memset(s, to_int_type(c), n));
+ }
+
+ static
+ int
+ compare( const char_type* s1, const char_type* s2, size_t n )
+ {
+ return memcmp(s1, s2, n);
+ }
+
+ static
+ int
+ compareASCII( const char_type* s1, const char* s2, size_t n )
+ {
+#ifdef DEBUG
+ for (size_t i = 0; i < n; ++i)
+ {
+ NS_ASSERTION(!(s2[i] & ~0x7F), "Unexpected non-ASCII character");
+ }
+#endif
+ return compare(s1, s2, n);
+ }
+
+ // this version assumes that s2 is null-terminated and s1 has length n.
+ // if s1 is shorter than s2 then we return -1; if s1 is longer than s2,
+ // we return 1.
+ static
+ int
+ compareASCIINullTerminated( const char_type* s1, size_t n, const char* s2 )
+ {
+ // can't use strcmp here because we don't want to stop when s1
+ // contains a null
+ for ( ; n--; ++s1, ++s2 )
+ {
+ if ( !*s2 )
+ return 1;
+ NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
+ if ( *s1 != *s2 )
+ return to_int_type(*s1) - to_int_type(*s2);
+ }
+
+ if ( *s2 )
+ return -1;
+
+ return 0;
+ }
+
+ /**
+ * Convert c to its lower-case form, but only if c is ASCII.
+ */
+ static
+ char_type
+ ASCIIToLower( char_type c )
+ {
+ return (c >= 'A' && c <= 'Z') ? (c + ('a' - 'A')) : c;
+ }
+
+ static
+ int
+ compareLowerCaseToASCII( const char_type* s1, const char* s2, size_t n )
+ {
+ for ( ; n--; ++s1, ++s2 )
+ {
+ NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
+ NS_ASSERTION(!(*s2 >= 'A' && *s2 <= 'Z'),
+ "Unexpected uppercase character");
+ char_type lower_s1 = ASCIIToLower(*s1);
+ if ( lower_s1 != *s2 )
+ return to_int_type(lower_s1) - to_int_type(*s2);
+ }
+ return 0;
+ }
+
+ // this version assumes that s2 is null-terminated and s1 has length n.
+ // if s1 is shorter than s2 then we return -1; if s1 is longer than s2,
+ // we return 1.
+ static
+ int
+ compareLowerCaseToASCIINullTerminated( const char_type* s1, size_t n, const char* s2 )
+ {
+ for ( ; n--; ++s1, ++s2 )
+ {
+ if ( !*s2 )
+ return 1;
+ NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character");
+ NS_ASSERTION(!(*s2 >= 'A' && *s2 <= 'Z'),
+ "Unexpected uppercase character");
+ char_type lower_s1 = ASCIIToLower(*s1);
+ if ( lower_s1 != *s2 )
+ return to_int_type(lower_s1) - to_int_type(*s2);
+ }
+
+ if ( *s2 )
+ return -1;
+
+ return 0;
+ }
+
+ static
+ size_t
+ length( const char_type* s )
+ {
+ return strlen(s);
+ }
+
+ static
+ const char_type*
+ find( const char_type* s, size_t n, char_type c )
+ {
+ return NS_REINTERPRET_CAST(const char_type*, memchr(s, to_int_type(c), n));
+ }
+
+#if 0
+ // I/O related:
+
+ typedef streamoff off_type;
+ typedef streampos pos_type;
+ typedef mbstate_t state_type;
+
+ static
+ int_type
+ eof()
+ {
+ return EOF;
+ }
+
+ static
+ int_type
+ not_eof( int_type c )
+ {
+ return eq_int_type(c, eof()) ? ~eof() : c;
+ }
+
+ // static state_type get_state( pos_type );
+#endif
+ };
+
+template <class InputIterator>
+struct nsCharSourceTraits
+ {
+ typedef typename InputIterator::difference_type difference_type;
+
+ static
+ PRUint32
+ readable_distance( const InputIterator& first, const InputIterator& last )
+ {
+ // assumes single fragment
+ return last.get() - first.get();
+ }
+
+ static
+ const typename InputIterator::value_type*
+ read( const InputIterator& iter )
+ {
+ return iter.get();
+ }
+
+ static
+ void
+ advance( InputIterator& s, difference_type n )
+ {
+ s.advance(n);
+ }
+ };
+
+#ifdef HAVE_CPP_PARTIAL_SPECIALIZATION
+
+template <class CharT>
+struct nsCharSourceTraits<CharT*>
+ {
+ typedef ptrdiff_t difference_type;
+
+ static
+ PRUint32
+ readable_distance( CharT* s )
+ {
+ return PRUint32(nsCharTraits<CharT>::length(s));
+// return numeric_limits<PRUint32>::max();
+ }
+
+ static
+ PRUint32
+ readable_distance( CharT* first, CharT* last )
+ {
+ return PRUint32(last-first);
+ }
+
+ static
+ const CharT*
+ read( CharT* s )
+ {
+ return s;
+ }
+
+ static
+ void
+ advance( CharT*& s, difference_type n )
+ {
+ s += n;
+ }
+ };
+
+#else
+
+NS_SPECIALIZE_TEMPLATE
+struct nsCharSourceTraits<const char*>
+ {
+ typedef ptrdiff_t difference_type;
+
+ static
+ PRUint32
+ readable_distance( const char* s )
+ {
+ return PRUint32(nsCharTraits<char>::length(s));
+// return numeric_limits<PRUint32>::max();
+ }
+
+ static
+ PRUint32
+ readable_distance( const char* first, const char* last )
+ {
+ return PRUint32(last-first);
+ }
+
+ static
+ const char*
+ read( const char* s )
+ {
+ return s;
+ }
+
+ static
+ void
+ advance( const char*& s, difference_type n )
+ {
+ s += n;
+ }
+ };
+
+
+NS_SPECIALIZE_TEMPLATE
+struct nsCharSourceTraits<const PRUnichar*>
+ {
+ typedef ptrdiff_t difference_type;
+
+ static
+ PRUint32
+ readable_distance( const PRUnichar* s )
+ {
+ return PRUint32(nsCharTraits<PRUnichar>::length(s));
+// return numeric_limits<PRUint32>::max();
+ }
+
+ static
+ PRUint32
+ readable_distance( const PRUnichar* first, const PRUnichar* last )
+ {
+ return PRUint32(last-first);
+ }
+
+ static
+ const PRUnichar*
+ read( const PRUnichar* s )
+ {
+ return s;
+ }
+
+ static
+ void
+ advance( const PRUnichar*& s, difference_type n )
+ {
+ s += n;
+ }
+ };
+
+#endif
+
+
+template <class OutputIterator>
+struct nsCharSinkTraits
+ {
+ static
+ PRUint32
+ write( OutputIterator& iter, const typename OutputIterator::value_type* s, PRUint32 n )
+ {
+ return iter.write(s, n);
+ }
+ };
+
+#ifdef HAVE_CPP_PARTIAL_SPECIALIZATION
+
+template <class CharT>
+struct nsCharSinkTraits<CharT*>
+ {
+ static
+ PRUint32
+ write( CharT*& iter, const CharT* s, PRUint32 n )
+ {
+ nsCharTraits<CharT>::move(iter, s, n);
+ iter += n;
+ return n;
+ }
+ };
+
+#else
+
+NS_SPECIALIZE_TEMPLATE
+struct nsCharSinkTraits<char*>
+ {
+ static
+ PRUint32
+ write( char*& iter, const char* s, PRUint32 n )
+ {
+ nsCharTraits<char>::move(iter, s, n);
+ iter += n;
+ return n;
+ }
+ };
+
+NS_SPECIALIZE_TEMPLATE
+struct nsCharSinkTraits<PRUnichar*>
+ {
+ static
+ PRUint32
+ write( PRUnichar*& iter, const PRUnichar* s, PRUint32 n )
+ {
+ nsCharTraits<PRUnichar>::move(iter, s, n);
+ iter += n;
+ return n;
+ }
+ };
+
+#endif
+
+#endif // !defined(nsCharTraits_h___)
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsDependentString.h b/src/libs/xpcom18a4/xpcom/string/public/nsDependentString.h
new file mode 100644
index 00000000..22e05b31
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsDependentString.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 nsDependentString_h___
+#define nsDependentString_h___
+
+#ifndef nsString_h___
+#include "nsString.h"
+#endif
+
+#ifndef nsDebug_h___
+#include "nsDebug.h"
+#endif
+
+ // declare nsDependentString
+#include "string-template-def-unichar.h"
+#include "nsTDependentString.h"
+#include "string-template-undef.h"
+
+ // declare nsDependentCString
+#include "string-template-def-char.h"
+#include "nsTDependentString.h"
+#include "string-template-undef.h"
+
+#endif /* !defined(nsDependentString_h___) */
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsDependentSubstring.h b/src/libs/xpcom18a4/xpcom/string/public/nsDependentSubstring.h
new file mode 100644
index 00000000..c6459436
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsDependentSubstring.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 nsDependentSubstring_h___
+#define nsDependentSubstring_h___
+
+#ifndef nsSubstring_h___
+#include "nsSubstring.h"
+#endif
+
+ // declare nsDependentSubstring
+#include "string-template-def-unichar.h"
+#include "nsTDependentSubstring.h"
+#include "string-template-undef.h"
+
+ // declare nsDependentCSubstring
+#include "string-template-def-char.h"
+#include "nsTDependentSubstring.h"
+#include "string-template-undef.h"
+
+#endif /* !defined(nsDependentSubstring_h___) */
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsEmbedString.h b/src/libs/xpcom18a4/xpcom/string/public/nsEmbedString.h
new file mode 100644
index 00000000..7af03ee3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsEmbedString.h
@@ -0,0 +1,158 @@
+/* -*- 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 a small implementation of the nsAString and nsACString.
+ *
+ * The Initial Developer of the Original Code is
+ * Peter Annema <jaggernaut@netscape.com>.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 nsEmbedString_h___
+#define nsEmbedString_h___
+
+#include "nsStringAPI.h"
+
+class nsEmbedString : public nsStringContainer
+ {
+ public:
+ typedef nsEmbedString self_type;
+ typedef nsAString abstract_string_type;
+
+ nsEmbedString()
+ {
+ NS_StringContainerInit(*this);
+ }
+
+ nsEmbedString(const self_type& aString)
+#ifdef VBOX
+ : nsStringContainer()
+#endif
+ {
+ NS_StringContainerInit(*this);
+ NS_StringCopy(*this, aString);
+ }
+
+ explicit
+ nsEmbedString(const abstract_string_type& aReadable)
+ {
+ NS_StringContainerInit(*this);
+ NS_StringCopy(*this, aReadable);
+ }
+
+ explicit
+ nsEmbedString(const char_type* aData, size_type aLength = PR_UINT32_MAX)
+ {
+ NS_StringContainerInit(*this);
+ NS_StringSetData(*this, aData, aLength);
+ }
+
+ ~nsEmbedString()
+ {
+ NS_StringContainerFinish(*this);
+ }
+
+ const char_type* get() const
+ {
+ const char_type* data;
+ NS_StringGetData(*this, &data);
+ return data;
+ }
+
+ self_type& operator=(const self_type& aString) { Assign(aString); return *this; }
+ self_type& operator=(const abstract_string_type& aReadable) { Assign(aReadable); return *this; }
+ self_type& operator=(const char_type* aPtr) { Assign(aPtr); return *this; }
+ self_type& operator=(char_type aChar) { Assign(aChar); return *this; }
+ };
+
+class nsEmbedCString : public nsCStringContainer
+ {
+ public:
+ typedef nsEmbedCString self_type;
+ typedef nsACString abstract_string_type;
+
+ nsEmbedCString()
+#ifdef VBOX
+ : nsCStringContainer()
+#endif
+ {
+ NS_CStringContainerInit(*this);
+ }
+
+ nsEmbedCString(const self_type& aString)
+#ifdef VBOX
+ : nsCStringContainer()
+#endif
+ {
+ NS_CStringContainerInit(*this);
+ NS_CStringCopy(*this, aString);
+ }
+
+ explicit
+ nsEmbedCString(const abstract_string_type& aReadable)
+#ifdef VBOX
+ : nsCStringContainer()
+#endif
+ {
+ NS_CStringContainerInit(*this);
+ NS_CStringCopy(*this, aReadable);
+ }
+
+ explicit
+ nsEmbedCString(const char_type* aData, size_type aLength = PR_UINT32_MAX)
+#ifdef VBOX
+ : nsCStringContainer()
+#endif
+ {
+ NS_CStringContainerInit(*this);
+ NS_CStringSetData(*this, aData, aLength);
+ }
+
+ ~nsEmbedCString()
+ {
+ NS_CStringContainerFinish(*this);
+ }
+
+ const char_type* get() const
+ {
+ const char_type* data;
+ NS_CStringGetData(*this, &data);
+ return data;
+ }
+
+ self_type& operator=(const self_type& aString) { Assign(aString); return *this; }
+ self_type& operator=(const abstract_string_type& aReadable) { Assign(aReadable); return *this; }
+ self_type& operator=(const char_type* aPtr) { Assign(aPtr); return *this; }
+ self_type& operator=(char_type aChar) { Assign(aChar); return *this; }
+ };
+
+#endif // !defined(nsEmbedString_h___)
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsLiteralString.h b/src/libs/xpcom18a4/xpcom/string/public/nsLiteralString.h
new file mode 100644
index 00000000..ba536297
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsLiteralString.h
@@ -0,0 +1,116 @@
+/* -*- 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.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@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 nsLiteralString_h___
+#define nsLiteralString_h___
+
+#ifndef nscore_h___
+#include "nscore.h"
+#endif
+
+#ifndef nsDependentString_h___
+#include "nsDependentString.h"
+#endif
+
+
+#if 0
+inline
+const nsDependentString
+literal_string( const nsAString::char_type* aPtr )
+ {
+ return nsDependentString(aPtr);
+ }
+
+inline
+const nsDependentString
+literal_string( const nsAString::char_type* aPtr, PRUint32 aLength )
+ {
+ return nsDependentString(aPtr, aLength);
+ }
+
+inline
+const nsDependentCString
+literal_string( const nsACString::char_type* aPtr )
+ {
+ return nsDependentCString(aPtr);
+ }
+
+inline
+const nsDependentCString
+literal_string( const nsACString::char_type* aPtr, PRUint32 aLength )
+ {
+ return nsDependentCString(aPtr, aLength);
+ }
+#endif
+
+#ifdef HAVE_CPP_2BYTE_WCHAR_T
+ #define NS_LL(s) L##s
+ #define NS_MULTILINE_LITERAL_STRING(s) nsDependentString(NS_REINTERPRET_CAST(const nsAString::char_type*, s), PRUint32((sizeof(s)/sizeof(wchar_t))-1))
+ #define NS_MULTILINE_LITERAL_STRING_INIT(n,s) n(NS_REINTERPRET_CAST(const nsAString::char_type*, s), PRUint32((sizeof(s)/sizeof(wchar_t))-1))
+ #define NS_NAMED_MULTILINE_LITERAL_STRING(n,s) const nsDependentString n(NS_REINTERPRET_CAST(const nsAString::char_type*, s), PRUint32((sizeof(s)/sizeof(wchar_t))-1))
+ typedef nsDependentString nsLiteralString;
+#else
+ #define NS_LL(s) s
+ #define NS_MULTILINE_LITERAL_STRING(s) NS_ConvertASCIItoUTF16(s, PRUint32(sizeof(s)-1))
+ #define NS_MULTILINE_LITERAL_STRING_INIT(n,s) n(s, PRUint32(sizeof(s)-1))
+ #define NS_NAMED_MULTILINE_LITERAL_STRING(n,s) const NS_ConvertASCIItoUTF16 n(s, PRUint32(sizeof(s)-1))
+ typedef NS_ConvertASCIItoUTF16 nsLiteralString;
+#endif
+
+/*
+ * Macro arguments used in concatenation or stringification won't be expanded.
+ * Therefore, in order for |NS_L(FOO)| to work as expected (which is to expand
+ * |FOO| before doing whatever |NS_L| needs to do to it) a helper macro needs
+ * to be inserted in between to allow the macro argument to expand.
+ * See "3.10.6 Separate Expansion of Macro Arguments" of the CPP manual for a
+ * more accurate and precise explanation.
+ */
+
+#define NS_L(s) NS_LL(s)
+
+#define NS_LITERAL_STRING(s) NS_STATIC_CAST(const nsAFlatString&, NS_MULTILINE_LITERAL_STRING(NS_LL(s)))
+#define NS_LITERAL_STRING_INIT(n,s) NS_MULTILINE_LITERAL_STRING_INIT(n, NS_LL(s))
+#define NS_NAMED_LITERAL_STRING(n,s) NS_NAMED_MULTILINE_LITERAL_STRING(n, NS_LL(s))
+
+#define NS_LITERAL_CSTRING(s) NS_STATIC_CAST(const nsDependentCString&, nsDependentCString(s, PRUint32(sizeof(s)-1)))
+#define NS_LITERAL_CSTRING_INIT(n,s) n(s, PRUint32(sizeof(s)-1))
+#define NS_NAMED_LITERAL_CSTRING(n,s) const nsDependentCString n(s, PRUint32(sizeof(s)-1))
+
+typedef nsDependentCString nsLiteralCString;
+
+#endif /* !defined(nsLiteralString_h___) */
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsObsoleteAString.h b/src/libs/xpcom18a4/xpcom/string/public/nsObsoleteAString.h
new file mode 100644
index 00000000..00d5892e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsObsoleteAString.h
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 nsObsoleteAString_h___
+#define nsObsoleteAString_h___
+
+/*
+ STRING INTERNALS
+
+ This file defines nsObsoleteAString and nsObsoleteACString. These are
+ abstract classes (interfaces), containing only virtual functions
+ corresponding to the FROZEN nsA[C]String classes. They exist to provide
+ the new non-abstract nsA[C]String classes with a mechanism to maintain
+ backwards binary compatability.
+
+ From a binary point-of-view, the new nsA[C]String classes appear to have a
+ vtable pointer to the vtable of nsObsoleteA[C]StringThunk.
+ nsObsoleteA[C]StringThunk is a subclass of nsObsoleteA[C]String that serves
+ as a simple bridge between the virtual functions that make up the FROZEN
+ nsA[C]String contract and the new ns[C]Substring, which is now our only
+ subclass of nsA[C]String.
+
+ The methods on the new nsA[C]String are now all non-virtual. This reduces
+ codesize at the callsite, and reduces the number of memory dereferences and
+ jumps required to invoke a method on nsA[C]String. The result is improved
+ performance and reduced codesize. However, to maintain binary
+ compatibility, each method on nsA[C]String must check the value of its
+ vtable to determine if it corresponds to the built-in implementation of
+ nsObsoleteA[C]String (i.e., the address of the canonical vtable). If it
+ does, then the vtable can be ignored, and the nsA[C]String object (i.e.,
+ |this|) can be cast to ns[C]Substring directly. In which case, the
+ nsA[C]String methods can be satisfied by invoking the corresponding methods
+ directly on ns[C]Substring. If the vtable address does not correspond to
+ the built-in implementation, then the virtual functions on
+ nsObsoleteA[C]String must be invoked instead.
+
+ So, if a nsA[C]String reference corresponds to an external implementation
+ (such as the old nsEmbed[C]String that shipped with previous versions of
+ Mozilla), then methods invoked on that nsA[C]String will still act like
+ virtual function calls. This ensures binary compatibility while avoiding
+ virtual function calls in most cases.
+
+ Finally, nsObsoleteA[C]String (i.e., the FROZEN nsA[C]String vtable) is
+ now a DEPRECATED interface. See nsStringAPI.h and nsEmbedString.h for
+ the new preferred way to access nsA[C]String references in an external
+ component or Gecko embedding application.
+ */
+
+#ifndef nsStringFwd_h___
+#include "nsStringFwd.h"
+#endif
+
+#ifndef nscore_h___
+#include "nscore.h"
+#endif
+
+ // declare nsObsoleteAString
+#include "string-template-def-unichar.h"
+#include "nsTObsoleteAString.h"
+#include "string-template-undef.h"
+
+ // declare nsObsoleteACString
+#include "string-template-def-char.h"
+#include "nsTObsoleteAString.h"
+#include "string-template-undef.h"
+
+#endif // !defined(nsObsoleteAString_h___)
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsPrintfCString.h b/src/libs/xpcom18a4/xpcom/string/public/nsPrintfCString.h
new file mode 100644
index 00000000..3f3d04d3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsPrintfCString.h
@@ -0,0 +1,87 @@
+/* -*- 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) 1994-2000
+ * 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 nsPrintfCString_h___
+#define nsPrintfCString_h___
+
+#ifndef nsString_h___
+#include "nsString.h"
+#endif
+
+
+ /**
+ * |nsPrintfCString| lets you use a formated |printf| string as an |const nsACString|.
+ *
+ * myCStr += nsPrintfCString("%f", 13.917);
+ * // ...a general purpose substitute for |AppendFloat|
+ *
+ * For longer patterns, you'll want to use the constructor that takes a length
+ *
+ * nsPrintfCString(128, "%f, %f, %f, %f, %f, %f, %f, %i, %f", x, y, z, 3.2, j, k, l, 3, 3.1);
+ *
+ * Exceding the default size (which you must specify in the constructor, it is not determined)
+ * causes an allocation, so avoid that. If your formatted string exceeds the allocated space, it is
+ * cut off at the size of the buffer, no error is reported (and no out-of-bounds writing occurs).
+ * This class is intended to be useful for numbers and short
+ * strings, not arbitrary formatting of other strings (e.g., with %s). There is currently no
+ * wide version of this class, since wide |printf| is not generally available. That means
+ * to get a wide version of your formatted data, you must, e.g.,
+ *
+ * CopyASCIItoUTF16(nsPrintfCString("%f", 13.917"), myStr);
+ *
+ * That's another good reason to avoid this class for anything but numbers ... as strings can be
+ * much more efficiently handled with |NS_LITERAL_[C]STRING| and |nsLiteral[C]String|.
+ */
+
+class NS_COM nsPrintfCString : public nsCString
+ {
+ typedef nsCString string_type;
+
+ enum { kLocalBufferSize=15 };
+ // ought to be large enough for most things ... a |long long| needs at most 20 (so you'd better ask)
+ // pinkerton suggests 7. We should measure and decide what's appropriate
+
+ public:
+ // XXX don't these need to be declared CDECL ??
+ explicit nsPrintfCString( const char_type* format, ... );
+ nsPrintfCString( size_type n, const char_type* format, ...);
+
+ private:
+ char_type mLocalBuffer[ kLocalBufferSize + 1 ];
+ };
+
+#endif // !defined(nsPrintfCString_h___)
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsPromiseFlatString.h b/src/libs/xpcom18a4/xpcom/string/public/nsPromiseFlatString.h
new file mode 100644
index 00000000..b98aa1a2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsPromiseFlatString.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 nsPromiseFlatString_h___
+#define nsPromiseFlatString_h___
+
+#ifndef nsString_h___
+#include "nsString.h"
+#endif
+
+ // declare nsPromiseFlatString
+#include "string-template-def-unichar.h"
+#include "nsTPromiseFlatString.h"
+#include "string-template-undef.h"
+
+ // declare nsPromiseFlatCString
+#include "string-template-def-char.h"
+#include "nsTPromiseFlatString.h"
+#include "string-template-undef.h"
+
+#endif /* !defined(nsPromiseFlatString_h___) */
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsReadableUtils.h b/src/libs/xpcom18a4/xpcom/string/public/nsReadableUtils.h
new file mode 100644
index 00000000..13f94c09
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsReadableUtils.h
@@ -0,0 +1,370 @@
+/* -*- 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@mozilla.org> (original author)
+ * Johnny Stenbeck <jst@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 nsReadableUtils_h___
+#define nsReadableUtils_h___
+
+ /**
+ * I guess all the routines in this file are all mis-named.
+ * According to our conventions, they should be |NS_xxx|.
+ */
+
+#ifndef nsAString_h___
+#include "nsAString.h"
+#endif
+
+inline size_t Distance( const nsReadingIterator<PRUnichar>& start, const nsReadingIterator<PRUnichar>& end )
+ {
+ return end.get() - start.get();
+ }
+inline size_t Distance( const nsReadingIterator<char>& start, const nsReadingIterator<char>& end )
+ {
+ return end.get() - start.get();
+ }
+
+NS_COM void LossyCopyUTF16toASCII( const nsAString& aSource, nsACString& aDest );
+NS_COM void CopyASCIItoUTF16( const nsACString& aSource, nsAString& aDest );
+
+NS_COM void LossyCopyUTF16toASCII( const PRUnichar* aSource, nsACString& aDest );
+NS_COM void CopyASCIItoUTF16( const char* aSource, nsAString& aDest );
+
+NS_COM void CopyUTF16toUTF8( const nsAString& aSource, nsACString& aDest );
+NS_COM void CopyUTF8toUTF16( const nsACString& aSource, nsAString& aDest );
+
+NS_COM void CopyUTF16toUTF8( const PRUnichar* aSource, nsACString& aDest );
+NS_COM void CopyUTF8toUTF16( const char* aSource, nsAString& aDest );
+
+NS_COM void LossyAppendUTF16toASCII( const nsAString& aSource, nsACString& aDest );
+NS_COM void AppendASCIItoUTF16( const nsACString& aSource, nsAString& aDest );
+
+NS_COM void LossyAppendUTF16toASCII( const PRUnichar* aSource, nsACString& aDest );
+NS_COM void AppendASCIItoUTF16( const char* aSource, nsAString& aDest );
+
+NS_COM void AppendUTF16toUTF8( const nsAString& aSource, nsACString& aDest );
+NS_COM void AppendUTF8toUTF16( const nsACString& aSource, nsAString& aDest );
+
+NS_COM void AppendUTF16toUTF8( const PRUnichar* aSource, nsACString& aDest );
+NS_COM void AppendUTF8toUTF16( const char* aSource, nsAString& aDest );
+
+// Backward compatibility
+inline
+NS_COM void CopyUCS2toASCII( const nsAString& aSource, nsACString& aDest )
+{ LossyCopyUTF16toASCII(aSource, aDest); }
+inline
+NS_COM void CopyASCIItoUCS2( const nsACString& aSource, nsAString& aDest )
+{ CopyASCIItoUTF16(aSource, aDest); }
+
+ /**
+ * Returns a new |char| buffer containing a zero-terminated copy of |aSource|.
+ *
+ * Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
+ * Performs a lossy encoding conversion by chopping 16-bit wide characters down to 8-bits wide while copying |aSource| to your new buffer.
+ * This conversion is not well defined; but it reproduces legacy string behavior.
+ * The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
+ *
+ * @param aSource a 16-bit wide string
+ * @return a new |char| buffer you must free with |nsMemory::Free|.
+ */
+NS_COM char* ToNewCString( const nsAString& aSource );
+
+
+ /**
+ * Returns a new |char| buffer containing a zero-terminated copy of |aSource|.
+ *
+ * Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|.
+ * The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
+ *
+ * @param aSource an 8-bit wide string
+ * @return a new |char| buffer you must free with |nsMemory::Free|.
+ */
+NS_COM char* ToNewCString( const nsACString& aSource );
+
+ /**
+ * Returns a new |char| buffer containing a zero-terminated copy of |aSource|.
+ *
+ * Allocates and returns a new |char| buffer which you must free with
+ * |nsMemory::Free|.
+ * Performs an encoding conversion from a UTF-16 string to a UTF-8 string
+ * copying |aSource| to your new buffer.
+ * The new buffer is zero-terminated, but that may not help you if |aSource|
+ * contains embedded nulls.
+ *
+ * @param aSource a UTF-16 string (made of PRUnichar's)
+ * @param aUTF8Count the number of 8-bit units that was returned
+ * @return a new |char| buffer you must free with |nsMemory::Free|.
+ */
+
+NS_COM char* ToNewUTF8String( const nsAString& aSource, PRUint32 *aUTF8Count = nsnull );
+
+
+ /**
+ * Returns a new |PRUnichar| buffer containing a zero-terminated copy of
+ * |aSource|.
+ *
+ * Allocates and returns a new |PRUnichar| buffer which you must free with
+ * |nsMemory::Free|.
+ * The new buffer is zero-terminated, but that may not help you if |aSource|
+ * contains embedded nulls.
+ *
+ * @param aSource a UTF-16 string
+ * @return a new |PRUnichar| buffer you must free with |nsMemory::Free|.
+ */
+NS_COM PRUnichar* ToNewUnicode( const nsAString& aSource );
+
+
+ /**
+ * Returns a new |PRUnichar| buffer containing a zero-terminated copy of |aSource|.
+ *
+ * Allocates and returns a new |PRUnichar| buffer which you must free with |nsMemory::Free|.
+ * Performs an encoding conversion by 0-padding 8-bit wide characters up to 16-bits wide while copying |aSource| to your new buffer.
+ * This conversion is not well defined; but it reproduces legacy string behavior.
+ * The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.
+ *
+ * @param aSource an 8-bit wide string (a C-string, NOT UTF-8)
+ * @return a new |PRUnichar| buffer you must free with |nsMemory::Free|.
+ */
+NS_COM PRUnichar* ToNewUnicode( const nsACString& aSource );
+
+ /**
+ * Returns a new |PRUnichar| buffer containing a zero-terminated copy
+ * of |aSource|.
+ *
+ * Allocates and returns a new |char| buffer which you must free with
+ * |nsMemory::Free|. Performs an encoding conversion from UTF-8 to UTF-16
+ * while copying |aSource| to your new buffer. This conversion is well defined
+ * for a valid UTF-8 string. The new buffer is zero-terminated, but that
+ * may not help you if |aSource| contains embedded nulls.
+ *
+ * @param aSource an 8-bit wide string, UTF-8 encoded
+ * @param aUTF16Count the number of 16-bit units that was returned
+ * @return a new |PRUnichar| buffer you must free with |nsMemory::Free|.
+ * (UTF-16 encoded)
+ */
+NS_COM PRUnichar* UTF8ToNewUnicode( const nsACString& aSource, PRUint32 *aUTF16Count = nsnull );
+
+ /**
+ * Copies |aLength| 16-bit code units from the start of |aSource| to the
+ * |PRUnichar| buffer |aDest|.
+ *
+ * After this operation |aDest| is not null terminated.
+ *
+ * @param aSource a UTF-16 string
+ * @param aSrcOffset start offset in the source string
+ * @param aDest a |PRUnichar| buffer
+ * @param aLength the number of 16-bit code units to copy
+ * @return pointer to destination buffer - identical to |aDest|
+ */
+NS_COM PRUnichar* CopyUnicodeTo( const nsAString& aSource,
+ PRUint32 aSrcOffset,
+ PRUnichar* aDest,
+ PRUint32 aLength );
+
+
+ /**
+ * Copies 16-bit characters between iterators |aSrcStart| and
+ * |aSrcEnd| to the writable string |aDest|. Similar to the
+ * |nsString::Mid| method.
+ *
+ * After this operation |aDest| is not null terminated.
+ *
+ * @param aSrcStart start source iterator
+ * @param aSrcEnd end source iterator
+ * @param aDest destination for the copy
+ */
+NS_COM void CopyUnicodeTo( const nsAString::const_iterator& aSrcStart,
+ const nsAString::const_iterator& aSrcEnd,
+ nsAString& aDest );
+
+ /**
+ * Appends 16-bit characters between iterators |aSrcStart| and
+ * |aSrcEnd| to the writable string |aDest|.
+ *
+ * After this operation |aDest| is not null terminated.
+ *
+ * @param aSrcStart start source iterator
+ * @param aSrcEnd end source iterator
+ * @param aDest destination for the copy
+ */
+NS_COM void AppendUnicodeTo( const nsAString::const_iterator& aSrcStart,
+ const nsAString::const_iterator& aSrcEnd,
+ nsAString& aDest );
+
+ /**
+ * Returns |PR_TRUE| if |aString| contains only ASCII characters, that is, characters in the range (0x00, 0x7F).
+ *
+ * @param aString a 16-bit wide string to scan
+ */
+NS_COM PRBool IsASCII( const nsAString& aString );
+
+ /**
+ * Returns |PR_TRUE| if |aString| contains only ASCII characters, that is, characters in the range (0x00, 0x7F).
+ *
+ * @param aString a 8-bit wide string to scan
+ */
+NS_COM PRBool IsASCII( const nsACString& aString );
+
+
+ /**
+ * Returns |PR_TRUE| if |aString| is a valid UTF-8 string.
+ * XXX This is not bullet-proof and nor an all-purpose UTF-8 validator.
+ * It is mainly written to replace and roughly equivalent to
+ *
+ * str.Equals(NS_ConvertUTF16toUTF8(NS_ConvertUTF8toUTF16(str)))
+ *
+ * (see bug 191541)
+ * As such, it does not check for non-UTF-8 7bit encodings such as
+ * ISO-2022-JP and HZ. However, it filters out UTF-8 representation
+ * of surrogate codepoints and non-characters ( 0xFFFE and 0xFFFF
+ * in planes 0 through 16.) as well as overlong UTF-8 sequences.
+ * Also note that it regards UTF-8 sequences corresponding to
+ * codepoints above 0x10FFFF as invalid in accordance with
+ * http://www.ietf.org/internet-drafts/draft-yergeau-rfc2279bis-04.txt
+ *
+ * @param aString an 8-bit wide string to scan
+ */
+NS_COM PRBool IsUTF8( const nsACString& aString );
+
+
+ /**
+ * Converts case in place in the argument string.
+ */
+NS_COM void ToUpperCase( nsACString& );
+
+NS_COM void ToLowerCase( nsACString& );
+
+NS_COM void ToUpperCase( nsCSubstring& );
+
+NS_COM void ToLowerCase( nsCSubstring& );
+
+ /**
+ * Converts case from string aSource to aDest.
+ */
+NS_COM void ToUpperCase( const nsACString& aSource, nsACString& aDest );
+
+NS_COM void ToLowerCase( const nsACString& aSource, nsACString& aDest );
+
+ /**
+ * Finds the leftmost occurance of |aPattern|, if any in the range |aSearchStart|..|aSearchEnd|.
+ *
+ * Returns |PR_TRUE| if a match was found, and adjusts |aSearchStart| and |aSearchEnd| to
+ * point to the match. If no match was found, returns |PR_FALSE| and makes |aSearchStart == aSearchEnd|.
+ *
+ * Currently, this is equivalent to the O(m*n) implementation previously on |ns[C]String|.
+ * If we need something faster, then we can implement that later.
+ */
+
+NS_COM PRBool FindInReadable( const nsAString& aPattern, nsAString::const_iterator&, nsAString::const_iterator&, const nsStringComparator& = nsDefaultStringComparator() );
+NS_COM PRBool FindInReadable( const nsACString& aPattern, nsACString::const_iterator&, nsACString::const_iterator&, const nsCStringComparator& = nsDefaultCStringComparator() );
+
+/* sometimes we don't care about where the string was, just that we
+ * found it or not */
+inline PRBool FindInReadable( const nsAString& aPattern, const nsAString& aSource, const nsStringComparator& compare = nsDefaultStringComparator() )
+{
+ nsAString::const_iterator start, end;
+ aSource.BeginReading(start);
+ aSource.EndReading(end);
+ return FindInReadable(aPattern, start, end, compare);
+}
+
+inline PRBool FindInReadable( const nsACString& aPattern, const nsACString& aSource, const nsCStringComparator& compare = nsDefaultCStringComparator() )
+{
+ nsACString::const_iterator start, end;
+ aSource.BeginReading(start);
+ aSource.EndReading(end);
+ return FindInReadable(aPattern, start, end, compare);
+}
+
+
+NS_COM PRBool CaseInsensitiveFindInReadable( const nsACString& aPattern, nsACString::const_iterator&, nsACString::const_iterator& );
+
+ /**
+ * Finds the rightmost occurance of |aPattern|
+ * Returns |PR_TRUE| if a match was found, and adjusts |aSearchStart| and |aSearchEnd| to
+ * point to the match. If no match was found, returns |PR_FALSE| and makes |aSearchStart == aSearchEnd|.
+ *
+ * Currently, this is equivalent to the O(m*n) implementation previously on |ns[C]String|.
+ * If we need something faster, then we can implement that later.
+ */
+NS_COM PRBool RFindInReadable( const nsAString& aPattern, nsAString::const_iterator&, nsAString::const_iterator&, const nsStringComparator& = nsDefaultStringComparator() );
+NS_COM PRBool RFindInReadable( const nsACString& aPattern, nsACString::const_iterator&, nsACString::const_iterator&, const nsCStringComparator& = nsDefaultCStringComparator() );
+
+ /**
+ * Finds the leftmost occurance of |aChar|, if any in the range
+ * |aSearchStart|..|aSearchEnd|.
+ *
+ * Returns |PR_TRUE| if a match was found, and adjusts |aSearchStart| to
+ * point to the match. If no match was found, returns |PR_FALSE| and
+ * makes |aSearchStart == aSearchEnd|.
+ */
+NS_COM PRBool FindCharInReadable( PRUnichar aChar, nsAString::const_iterator& aSearchStart, const nsAString::const_iterator& aSearchEnd );
+NS_COM PRBool FindCharInReadable( char aChar, nsACString::const_iterator& aSearchStart, const nsACString::const_iterator& aSearchEnd );
+
+ /**
+ * Finds the number of occurences of |aChar| in the string |aStr|
+ */
+NS_COM PRUint32 CountCharInReadable( const nsAString& aStr,
+ PRUnichar aChar );
+NS_COM PRUint32 CountCharInReadable( const nsACString& aStr,
+ char aChar );
+
+NS_COM PRBool
+StringBeginsWith( const nsAString& aSource, const nsAString& aSubstring,
+ const nsStringComparator& aComparator =
+ nsDefaultStringComparator() );
+NS_COM PRBool
+StringBeginsWith( const nsACString& aSource, const nsACString& aSubstring,
+ const nsCStringComparator& aComparator =
+ nsDefaultCStringComparator() );
+NS_COM PRBool
+StringEndsWith( const nsAString& aSource, const nsAString& aSubstring,
+ const nsStringComparator& aComparator =
+ nsDefaultStringComparator() );
+NS_COM PRBool
+StringEndsWith( const nsACString& aSource, const nsACString& aSubstring,
+ const nsCStringComparator& aComparator =
+ nsDefaultCStringComparator() );
+
+NS_COM PRUint32 HashString( const nsAString& aStr );
+NS_COM PRUint32 HashString( const nsACString& aStr );
+
+NS_COM const nsAFlatString& EmptyString();
+NS_COM const nsAFlatCString& EmptyCString();
+
+
+#endif // !defined(nsReadableUtils_h___)
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsString.h b/src/libs/xpcom18a4/xpcom/string/public/nsString.h
new file mode 100644
index 00000000..67376d19
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsString.h
@@ -0,0 +1,237 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 nsString_h___
+#define nsString_h___
+
+
+#ifndef nsSubstring_h___
+#include "nsSubstring.h"
+#endif
+
+#ifndef nsDependentSubstring_h___
+#include "nsDependentSubstring.h"
+#endif
+
+#ifndef nsReadableUtils_h___
+#include "nsReadableUtils.h"
+#endif
+
+#include NEW_H
+
+ // enable support for the obsolete string API if not explicitly disabled
+#ifndef MOZ_STRING_WITH_OBSOLETE_API
+#define MOZ_STRING_WITH_OBSOLETE_API 1
+#endif
+
+#if MOZ_STRING_WITH_OBSOLETE_API
+ // radix values for ToInteger/AppendInt
+#define kRadix10 (10)
+#define kRadix16 (16)
+#define kAutoDetect (100)
+#define kRadixUnknown (kAutoDetect+1)
+#define IGNORE_CASE (PR_TRUE)
+#endif
+
+
+ // declare nsString, et. al.
+#include "string-template-def-unichar.h"
+#include "nsTString.h"
+#include "string-template-undef.h"
+
+ // declare nsCString, et. al.
+#include "string-template-def-char.h"
+#include "nsTString.h"
+#include "string-template-undef.h"
+
+
+ /**
+ * A helper class that converts a UTF-16 string to ASCII in a lossy manner
+ */
+class NS_LossyConvertUTF16toASCII : public nsCAutoString
+ {
+ public:
+ explicit
+ NS_LossyConvertUTF16toASCII( const PRUnichar* aString )
+ {
+ LossyAppendUTF16toASCII(aString, *this);
+ }
+
+ NS_LossyConvertUTF16toASCII( const PRUnichar* aString, PRUint32 aLength )
+ {
+ LossyAppendUTF16toASCII(Substring(aString, aString + aLength), *this);
+ }
+
+ explicit
+ NS_LossyConvertUTF16toASCII( const nsAString& aString )
+ {
+ LossyAppendUTF16toASCII(aString, *this);
+ }
+
+ private:
+ // NOT TO BE IMPLEMENTED
+ NS_LossyConvertUTF16toASCII( char );
+ };
+
+
+class NS_ConvertASCIItoUTF16 : public nsAutoString
+ {
+ public:
+ explicit
+ NS_ConvertASCIItoUTF16( const char* aCString )
+ {
+ AppendASCIItoUTF16(aCString, *this);
+ }
+
+ NS_ConvertASCIItoUTF16( const char* aCString, PRUint32 aLength )
+ {
+ AppendASCIItoUTF16(Substring(aCString, aCString + aLength), *this);
+ }
+
+ explicit
+ NS_ConvertASCIItoUTF16( const nsACString& aCString )
+ {
+ AppendASCIItoUTF16(aCString, *this);
+ }
+
+ private:
+ // NOT TO BE IMPLEMENTED
+ NS_ConvertASCIItoUTF16( PRUnichar );
+ };
+
+
+ /**
+ * A helper class that converts a UTF-16 string to UTF-8
+ */
+class NS_ConvertUTF16toUTF8 : public nsCAutoString
+ {
+ public:
+ explicit
+ NS_ConvertUTF16toUTF8( const PRUnichar* aString )
+ {
+ AppendUTF16toUTF8(aString, *this);
+ }
+
+ NS_ConvertUTF16toUTF8( const PRUnichar* aString, PRUint32 aLength )
+ {
+ AppendUTF16toUTF8(Substring(aString, aString + aLength), *this);
+ }
+
+ explicit
+ NS_ConvertUTF16toUTF8( const nsAString& aString )
+ {
+ AppendUTF16toUTF8(aString, *this);
+ }
+
+ private:
+ // NOT TO BE IMPLEMENTED
+ NS_ConvertUTF16toUTF8( char );
+ };
+
+
+class NS_ConvertUTF8toUTF16 : public nsAutoString
+ {
+ public:
+ explicit
+ NS_ConvertUTF8toUTF16( const char* aCString )
+ {
+ AppendUTF8toUTF16(aCString, *this);
+ }
+
+ NS_ConvertUTF8toUTF16( const char* aCString, PRUint32 aLength )
+ {
+ AppendUTF8toUTF16(Substring(aCString, aCString + aLength), *this);
+ }
+
+ explicit
+ NS_ConvertUTF8toUTF16( const nsACString& aCString )
+ {
+ AppendUTF8toUTF16(aCString, *this);
+ }
+
+ private:
+ // NOT TO BE IMPLEMENTED
+ NS_ConvertUTF8toUTF16( PRUnichar );
+ };
+
+
+// the following are included/declared for backwards compatibility
+
+typedef NS_ConvertUTF16toUTF8 NS_ConvertUCS2toUTF8;
+typedef NS_LossyConvertUTF16toASCII NS_LossyConvertUCS2toASCII;
+typedef NS_ConvertASCIItoUTF16 NS_ConvertASCIItoUCS2;
+typedef NS_ConvertUTF8toUTF16 NS_ConvertUTF8toUCS2;
+typedef nsAutoString nsVoidableString;
+
+#ifndef nsDependentString_h___
+#include "nsDependentString.h"
+#endif
+
+#ifndef nsLiteralString_h___
+#include "nsLiteralString.h"
+#endif
+
+#ifndef nsPromiseFlatString_h___
+#include "nsPromiseFlatString.h"
+#endif
+
+// need to include these for backwards compatibility
+#include "nsMemory.h"
+#include <string.h>
+#include <stdio.h>
+#include "plhash.h"
+
+inline PRInt32 MinInt(PRInt32 x, PRInt32 y)
+ {
+ return NS_MIN(x, y);
+ }
+
+inline PRInt32 MaxInt(PRInt32 x, PRInt32 y)
+ {
+ return NS_MAX(x, y);
+ }
+
+/**
+ * Deprecated: don't use |Recycle|, just call |nsMemory::Free| directly
+ *
+ * Return the given buffer to the heap manager. Calls allocator::Free()
+ */
+inline void Recycle( char* aBuffer) { nsMemory::Free(aBuffer); }
+inline void Recycle( PRUnichar* aBuffer) { nsMemory::Free(aBuffer); }
+
+#endif // !defined(nsString_h___)
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsStringAPI.h b/src/libs/xpcom18a4/xpcom/string/public/nsStringAPI.h
new file mode 100644
index 00000000..cc0818b6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsStringAPI.h
@@ -0,0 +1,853 @@
+/* vim:set ts=2 sw=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 nsStringAPI_h__
+#define nsStringAPI_h__
+
+/**
+ * nsStringAPI.h
+ *
+ * This file describes a minimal API for working with XPCOM's abstract
+ * string classes. It divorces the consumer from having any run-time
+ * dependency on the implementation details of the abstract string types.
+ */
+
+#include "nscore.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define NS_CStringContainerInit VBoxNsxpNS_CStringContainerInit
+#define NS_CStringContainerFinish VBoxNsxpNS_CStringContainerFinish
+#define NS_CStringCloneData VBoxNsxpNS_CStringCloneData
+#define NS_CStringCopy VBoxNsxpNS_CStringCopy
+#define NS_CStringGetData VBoxNsxpNS_CStringGetData
+#define NS_CStringSetData VBoxNsxpNS_CStringSetData
+#define NS_CStringSetDataRange VBoxNsxpNS_CStringSetDataRange
+#define NS_UTF16ToCString VBoxNsxpNS_UTF16ToCString
+#define NS_CStringToUTF16 VBoxNsxpNS_CStringToUTF16
+#define NS_StringContainerInit VBoxNsxpNS_StringContainerInit
+#define NS_StringContainerFinish VBoxNsxpNS_StringContainerFinish
+#define NS_StringCloneData VBoxNsxpNS_StringCloneData
+#define NS_StringCopy VBoxNsxpNS_StringCopy
+#define NS_StringGetData VBoxNsxpNS_StringGetData
+#define NS_StringSetData VBoxNsxpNS_StringSetData
+#define NS_StringSetDataRange VBoxNsxpNS_StringSetDataRange
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+#define NS_STRINGAPI(x) extern "C" NS_COM x
+
+/* The base string types */
+class nsAString;
+class nsACString;
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * nsStringContainer
+ *
+ * This is an opaque data type that is large enough to hold the canonical
+ * implementation of nsAString. The binary structure of this class is an
+ * implementation detail.
+ *
+ * The string data stored in a string container is always single fragment
+ * and null-terminated.
+ *
+ * Typically, string containers are allocated on the stack for temporary
+ * use. However, they can also be malloc'd if necessary. In either case,
+ * a string container is not useful until it has been initialized with a
+ * call to NS_StringContainerInit. The following example shows how to use
+ * a string container to call a function that takes a |nsAString &| out-param.
+ *
+ * NS_METHOD GetBlah(nsAString &aBlah);
+ *
+ * nsresult MyCode()
+ * {
+ * nsresult rv;
+ *
+ * nsStringContainer sc;
+ * rv = NS_StringContainerInit(sc);
+ * if (NS_FAILED(rv))
+ * return rv;
+ *
+ * rv = GetBlah(sc);
+ * if (NS_SUCCEEDED(rv))
+ * {
+ * const PRUnichar *data;
+ * NS_StringGetData(sc, &data);
+ * //
+ * // |data| now points to the result of the GetBlah function
+ * //
+ * }
+ *
+ * NS_StringContainerFinish(sc);
+ * return rv;
+ * }
+ *
+ * The following example show how to use a string container to pass a string
+ * parameter to a function taking a |const nsAString &| in-param.
+ *
+ * NS_METHOD SetBlah(const nsAString &aBlah);
+ *
+ * nsresult MyCode()
+ * {
+ * nsresult rv;
+ *
+ * nsStringContainer sc;
+ * rv = NS_StringContainerInit(sc);
+ * if (NS_FAILED(rv))
+ * return rv;
+ *
+ * const PRUnichar kData[] = {'x','y','z','\0'};
+ * rv = NS_StringSetData(sc, kData, sizeof(kData)/2 - 1);
+ * if (NS_SUCCEEDED(rv))
+ * rv = SetBlah(sc);
+ *
+ * NS_StringContainerFinish(sc);
+ * return rv;
+ * }
+ */
+class nsStringContainer;
+
+/**
+ * NS_StringContainerInit
+ *
+ * @param aContainer string container reference
+ * @return NS_OK if string container successfully initialized
+ *
+ * This function may allocate additional memory for aContainer. When
+ * aContainer is no longer needed, NS_StringContainerFinish should be called.
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(nsresult)
+NS_StringContainerInit(nsStringContainer &aContainer);
+
+/**
+ * NS_StringContainerFinish
+ *
+ * @param aContainer string container reference
+ *
+ * This function frees any memory owned by aContainer.
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(void)
+NS_StringContainerFinish(nsStringContainer &aContainer);
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * NS_StringGetData
+ *
+ * This function returns a const character pointer to the string's internal
+ * buffer, the length of the string, and a boolean value indicating whether
+ * or not the buffer is null-terminated.
+ *
+ * @param aStr abstract string reference
+ * @param aData out param that will hold the address of aStr's
+ * internal buffer
+ * @param aTerminated if non-null, this out param will be set to indicate
+ * whether or not aStr's internal buffer is null-
+ * terminated
+ * @return length of aStr's internal buffer
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(PRUint32)
+NS_StringGetData
+ (const nsAString &aStr, const PRUnichar **aData,
+ PRBool *aTerminated = nsnull);
+
+/**
+ * NS_StringCloneData
+ *
+ * This function returns a null-terminated copy of the string's
+ * internal buffer.
+ *
+ * @param aStr abstract string reference
+ * @return null-terminated copy of the string's internal buffer
+ * (it must be free'd using using nsMemory::Free)
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(PRUnichar *)
+NS_StringCloneData
+ (const nsAString &aStr);
+
+/**
+ * NS_StringSetData
+ *
+ * This function copies aData into aStr.
+ *
+ * @param aStr abstract string reference
+ * @param aData character buffer
+ * @param aDataLength number of characters to copy from source string (pass
+ * PR_UINT32_MAX to copy until end of aData, designated by
+ * a null character)
+ * @return NS_OK if function succeeded
+ *
+ * This function does not necessarily null-terminate aStr after copying data
+ * from aData. The behavior depends on the implementation of the abstract
+ * string, aStr. If aStr is a reference to a nsStringContainer, then its data
+ * will be null-terminated by this function.
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(nsresult)
+NS_StringSetData
+ (nsAString &aStr, const PRUnichar *aData,
+ PRUint32 aDataLength = PR_UINT32_MAX);
+
+/**
+ * NS_StringSetDataRange
+ *
+ * This function copies aData into a section of aStr. As a result it can be
+ * used to insert new characters into the string.
+ *
+ * @param aStr abstract string reference
+ * @param aCutOffset starting index where the string's existing data
+ * is to be overwritten (pass PR_UINT32_MAX to cause
+ * aData to be appended to the end of aStr, in which
+ * case the value of aCutLength is ignored).
+ * @param aCutLength number of characters to overwrite starting at
+ * aCutOffset (pass PR_UINT32_MAX to overwrite until the
+ * end of aStr).
+ * @param aData character buffer (pass null to cause this function
+ * to simply remove the "cut" range)
+ * @param aDataLength number of characters to copy from source string (pass
+ * PR_UINT32_MAX to copy until end of aData, designated by
+ * a null character)
+ * @return NS_OK if function succeeded
+ *
+ * This function does not necessarily null-terminate aStr after copying data
+ * from aData. The behavior depends on the implementation of the abstract
+ * string, aStr. If aStr is a reference to a nsStringContainer, then its data
+ * will be null-terminated by this function.
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(nsresult)
+NS_StringSetDataRange
+ (nsAString &aStr, PRUint32 aCutOffset, PRUint32 aCutLength,
+ const PRUnichar *aData, PRUint32 aDataLength = PR_UINT32_MAX);
+
+/**
+ * NS_StringCopy
+ *
+ * This function makes aDestStr have the same value as aSrcStr. It is
+ * provided as an optimization.
+ *
+ * @param aDestStr abstract string reference to be modified
+ * @param aSrcStr abstract string reference containing source string
+ * @return NS_OK if function succeeded
+ *
+ * This function does not necessarily null-terminate aDestStr after copying
+ * data from aSrcStr. The behavior depends on the implementation of the
+ * abstract string, aDestStr. If aDestStr is a reference to a
+ * nsStringContainer, then its data will be null-terminated by this function.
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(nsresult)
+NS_StringCopy
+ (nsAString &aDestStr, const nsAString &aSrcStr);
+
+/**
+ * NS_StringAppendData
+ *
+ * This function appends data to the existing value of aStr.
+ *
+ * @param aStr abstract string reference to be modified
+ * @param aData character buffer
+ * @param aDataLength number of characters to append (pass PR_UINT32_MAX to
+ * append until a null-character is encountered)
+ * @return NS_OK if function succeeded
+ *
+ * This function does not necessarily null-terminate aStr upon completion.
+ * The behavior depends on the implementation of the abstract string, aStr.
+ * If aStr is a reference to a nsStringContainer, then its data will be null-
+ * terminated by this function.
+ */
+inline NS_HIDDEN_(nsresult)
+NS_StringAppendData(nsAString &aStr, const PRUnichar *aData,
+ PRUint32 aDataLength = PR_UINT32_MAX)
+{
+ return NS_StringSetDataRange(aStr, PR_UINT32_MAX, 0, aData, aDataLength);
+}
+
+/**
+ * NS_StringInsertData
+ *
+ * This function inserts data into the existing value of aStr at the specified
+ * offset.
+ *
+ * @param aStr abstract string reference to be modified
+ * @param aOffset specifies where in the string to insert aData
+ * @param aData character buffer
+ * @param aDataLength number of characters to append (pass PR_UINT32_MAX to
+ * append until a null-character is encountered)
+ * @return NS_OK if function succeeded
+ *
+ * This function does not necessarily null-terminate aStr upon completion.
+ * The behavior depends on the implementation of the abstract string, aStr.
+ * If aStr is a reference to a nsStringContainer, then its data will be null-
+ * terminated by this function.
+ */
+inline NS_HIDDEN_(nsresult)
+NS_StringInsertData(nsAString &aStr, PRUint32 aOffset, const PRUnichar *aData,
+ PRUint32 aDataLength = PR_UINT32_MAX)
+{
+ return NS_StringSetDataRange(aStr, aOffset, 0, aData, aDataLength);
+}
+
+/**
+ * NS_StringCutData
+ *
+ * This function shortens the existing value of aStr, by removing characters
+ * at the specified offset.
+ *
+ * @param aStr abstract string reference to be modified
+ * @param aCutOffset specifies where in the string to insert aData
+ * @param aCutLength number of characters to remove
+ * @return NS_OK if function succeeded
+ */
+inline NS_HIDDEN_(nsresult)
+NS_StringCutData(nsAString &aStr, PRUint32 aCutOffset, PRUint32 aCutLength)
+{
+ return NS_StringSetDataRange(aStr, aCutOffset, aCutLength, nsnull, 0);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * nsCStringContainer
+ *
+ * This is an opaque data type that is large enough to hold the canonical
+ * implementation of nsACString. The binary structure of this class is an
+ * implementation detail.
+ *
+ * The string data stored in a string container is always single fragment
+ * and null-terminated.
+ *
+ * @see nsStringContainer for use cases and further documentation.
+ */
+class nsCStringContainer;
+
+/**
+ * NS_CStringContainerInit
+ *
+ * @param aContainer string container reference
+ * @return NS_OK if string container successfully initialized
+ *
+ * This function may allocate additional memory for aContainer. When
+ * aContainer is no longer needed, NS_CStringContainerFinish should be called.
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(nsresult)
+NS_CStringContainerInit(nsCStringContainer &aContainer);
+
+/**
+ * NS_CStringContainerFinish
+ *
+ * @param aContainer string container reference
+ *
+ * This function frees any memory owned by aContainer.
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(void)
+NS_CStringContainerFinish(nsCStringContainer &aContainer);
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * NS_CStringGetData
+ *
+ * This function returns a const character pointer to the string's internal
+ * buffer, the length of the string, and a boolean value indicating whether
+ * or not the buffer is null-terminated.
+ *
+ * @param aStr abstract string reference
+ * @param aData out param that will hold the address of aStr's
+ * internal buffer
+ * @param aTerminated if non-null, this out param will be set to indicate
+ * whether or not aStr's internal buffer is null-
+ * terminated
+ * @return length of aStr's internal buffer
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(PRUint32)
+NS_CStringGetData
+ (const nsACString &aStr, const char **aData,
+ PRBool *aTerminated = nsnull);
+
+/**
+ * NS_CStringCloneData
+ *
+ * This function returns a null-terminated copy of the string's
+ * internal buffer.
+ *
+ * @param aStr abstract string reference
+ * @return null-terminated copy of the string's internal buffer
+ * (it must be free'd using using nsMemory::Free)
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(char *)
+NS_CStringCloneData
+ (const nsACString &aStr);
+
+/**
+ * NS_CStringSetData
+ *
+ * This function copies aData into aStr.
+ *
+ * @param aStr abstract string reference
+ * @param aData character buffer
+ * @param aDataLength number of characters to copy from source string (pass
+ * PR_UINT32_MAX to copy until end of aData, designated by
+ * a null character)
+ * @return NS_OK if function succeeded
+ *
+ * This function does not necessarily null-terminate aStr after copying data
+ * from aData. The behavior depends on the implementation of the abstract
+ * string, aStr. If aStr is a reference to a nsStringContainer, then its data
+ * will be null-terminated by this function.
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(nsresult)
+NS_CStringSetData
+ (nsACString &aStr, const char *aData,
+ PRUint32 aDataLength = PR_UINT32_MAX);
+
+/**
+ * NS_CStringSetDataRange
+ *
+ * This function copies aData into a section of aStr. As a result it can be
+ * used to insert new characters into the string.
+ *
+ * @param aStr abstract string reference
+ * @param aCutOffset starting index where the string's existing data
+ * is to be overwritten (pass PR_UINT32_MAX to cause
+ * aData to be appended to the end of aStr, in which
+ * case the value of aCutLength is ignored).
+ * @param aCutLength number of characters to overwrite starting at
+ * aCutOffset (pass PR_UINT32_MAX to overwrite until the
+ * end of aStr).
+ * @param aData character buffer (pass null to cause this function
+ * to simply remove the "cut" range)
+ * @param aDataLength number of characters to copy from source string (pass
+ * PR_UINT32_MAX to copy until end of aData, designated by
+ * a null character)
+ * @return NS_OK if function succeeded
+ *
+ * This function does not necessarily null-terminate aStr after copying data
+ * from aData. The behavior depends on the implementation of the abstract
+ * string, aStr. If aStr is a reference to a nsStringContainer, then its data
+ * will be null-terminated by this function.
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(nsresult)
+NS_CStringSetDataRange
+ (nsACString &aStr, PRUint32 aCutOffset, PRUint32 aCutLength,
+ const char *aData, PRUint32 aDataLength = PR_UINT32_MAX);
+
+/**
+ * NS_CStringCopy
+ *
+ * This function makes aDestStr have the same value as aSrcStr. It is
+ * provided as an optimization.
+ *
+ * @param aDestStr abstract string reference to be modified
+ * @param aSrcStr abstract string reference containing source string
+ * @return NS_OK if function succeeded
+ *
+ * This function does not necessarily null-terminate aDestStr after copying
+ * data from aSrcStr. The behavior depends on the implementation of the
+ * abstract string, aDestStr. If aDestStr is a reference to a
+ * nsStringContainer, then its data will be null-terminated by this function.
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(nsresult)
+NS_CStringCopy
+ (nsACString &aDestStr, const nsACString &aSrcStr);
+
+/**
+ * NS_CStringAppendData
+ *
+ * This function appends data to the existing value of aStr.
+ *
+ * @param aStr abstract string reference to be modified
+ * @param aData character buffer
+ * @param aDataLength number of characters to append (pass PR_UINT32_MAX to
+ * append until a null-character is encountered)
+ * @return NS_OK if function succeeded
+ *
+ * This function does not necessarily null-terminate aStr upon completion.
+ * The behavior depends on the implementation of the abstract string, aStr.
+ * If aStr is a reference to a nsStringContainer, then its data will be null-
+ * terminated by this function.
+ */
+inline NS_HIDDEN_(nsresult)
+NS_CStringAppendData(nsACString &aStr, const char *aData,
+ PRUint32 aDataLength = PR_UINT32_MAX)
+{
+ return NS_CStringSetDataRange(aStr, PR_UINT32_MAX, 0, aData, aDataLength);
+}
+
+/**
+ * NS_CStringInsertData
+ *
+ * This function inserts data into the existing value of aStr at the specified
+ * offset.
+ *
+ * @param aStr abstract string reference to be modified
+ * @param aOffset specifies where in the string to insert aData
+ * @param aData character buffer
+ * @param aDataLength number of characters to append (pass PR_UINT32_MAX to
+ * append until a null-character is encountered)
+ * @return NS_OK if function succeeded
+ *
+ * This function does not necessarily null-terminate aStr upon completion.
+ * The behavior depends on the implementation of the abstract string, aStr.
+ * If aStr is a reference to a nsStringContainer, then its data will be null-
+ * terminated by this function.
+ */
+inline NS_HIDDEN_(nsresult)
+NS_CStringInsertData(nsACString &aStr, PRUint32 aOffset, const char *aData,
+ PRUint32 aDataLength = PR_UINT32_MAX)
+{
+ return NS_CStringSetDataRange(aStr, aOffset, 0, aData, aDataLength);
+}
+
+/**
+ * NS_CStringCutData
+ *
+ * This function shortens the existing value of aStr, by removing characters
+ * at the specified offset.
+ *
+ * @param aStr abstract string reference to be modified
+ * @param aCutOffset specifies where in the string to insert aData
+ * @param aCutLength number of characters to remove
+ * @return NS_OK if function succeeded
+ */
+inline NS_HIDDEN_(nsresult)
+NS_CStringCutData(nsACString &aStr, PRUint32 aCutOffset, PRUint32 aCutLength)
+{
+ return NS_CStringSetDataRange(aStr, aCutOffset, aCutLength, nsnull, 0);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * Encodings that can be used with the following conversion routines.
+ */
+enum nsCStringEncoding {
+ /* Conversion between ASCII and UTF-16 assumes that all bytes in the source
+ * string are 7-bit ASCII and can be inflated to UTF-16 by inserting null
+ * bytes. Reverse conversion is done by truncating every other byte. The
+ * conversion may result in loss and/or corruption of information if the
+ * strings do not strictly contain ASCII data. */
+ NS_CSTRING_ENCODING_ASCII = 0,
+
+ /* Conversion between UTF-8 and UTF-16 is non-lossy. */
+ NS_CSTRING_ENCODING_UTF8 = 1,
+
+ /* Conversion from UTF-16 to the native filesystem charset may result in a
+ * loss of information. No attempt is made to protect against data loss in
+ * this case. The native filesystem charset applies to strings passed to
+ * the "Native" method variants on nsIFile and nsILocalFile. */
+ NS_CSTRING_ENCODING_NATIVE_FILESYSTEM = 2
+};
+
+/**
+ * NS_CStringToUTF16
+ *
+ * This function converts the characters in a nsACString to an array of UTF-16
+ * characters, in the platform endianness. The result is stored in a nsAString
+ * object.
+ *
+ * @param aSource abstract string reference containing source string
+ * @param aSrcEncoding character encoding of the source string
+ * @param aDest abstract string reference to hold the result
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(nsresult)
+NS_CStringToUTF16(const nsACString &aSource, nsCStringEncoding aSrcEncoding,
+ nsAString &aDest);
+
+/**
+ * NS_UTF16ToCString
+ *
+ * This function converts the UTF-16 characters in a nsAString to a single-byte
+ * encoding. The result is stored in a nsACString object. In some cases this
+ * conversion may be lossy. In such cases, the conversion may succeed with a
+ * return code indicating loss of information. The exact behavior is not
+ * specified at this time.
+ *
+ * @param aSource abstract string reference containing source string
+ * @param aDestEncoding character encoding of the resulting string
+ * @param aDest abstract string reference to hold the result
+ *
+ * @status FROZEN
+ */
+NS_STRINGAPI(nsresult)
+NS_UTF16ToCString(const nsAString &aSource, nsCStringEncoding aDestEncoding,
+ nsACString &aDest);
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * Below we define nsAString and nsACString. The "_external" suffix is an
+ * implementation detail. nsAString_external is the name of the external
+ * representation of nsAString from the point of view of the Mozilla codebase.
+ * To a user of this API, nsAString_external is exactly nsAString.
+ *
+ * These classes should be treated as abstract classes with unspecified
+ * structure. The inline methods are provided as helper functions around the
+ * C-style API provided above.
+ *
+ * Do not try to mix these definitions of nsAString and nsACString with the
+ * internal definition of these classes from nsAString.h in the Mozilla tree.
+ */
+
+#ifndef NS_STRINGAPI_IMPL
+#define nsAString_external nsAString
+#define nsACString_external nsACString
+#endif
+
+class nsAString_external
+{
+#ifndef NS_STRINGAPI_IMPL
+
+public:
+ typedef PRUnichar char_type;
+ typedef nsAString_external self_type;
+ typedef PRUint32 size_type;
+ typedef PRUint32 index_type;
+
+ NS_HIDDEN_(const char_type*) BeginReading() const
+ {
+ const char_type *data;
+ NS_StringGetData(*this, &data);
+ return data;
+ }
+
+ NS_HIDDEN_(const char_type*) EndReading() const
+ {
+ const char_type *data;
+ PRUint32 len = NS_StringGetData(*this, &data);
+ return data + len;
+ }
+
+ NS_HIDDEN_(size_type) Length() const
+ {
+ const char_type* data;
+ return NS_StringGetData(*this, &data);
+ }
+
+ NS_HIDDEN_(void) Assign(const self_type& aString)
+ {
+ NS_StringCopy(*this, aString);
+ }
+ NS_HIDDEN_(void) Assign(const char_type* aData, size_type aLength = PR_UINT32_MAX)
+ {
+ NS_StringSetData(*this, aData, aLength);
+ }
+ NS_HIDDEN_(void) Assign(char_type aChar)
+ {
+ NS_StringSetData(*this, &aChar, 1);
+ }
+
+ NS_HIDDEN_(self_type&) operator=(const self_type& aString) { Assign(aString); return *this; }
+ NS_HIDDEN_(self_type&) operator=(const char_type* aPtr) { Assign(aPtr); return *this; }
+ NS_HIDDEN_(self_type&) operator=(char_type aChar) { Assign(aChar); return *this; }
+
+ NS_HIDDEN_(void) Replace( index_type cutStart, size_type cutLength, const char_type* data, size_type length = size_type(-1) )
+ {
+ NS_StringSetDataRange(*this, cutStart, cutLength, data, length);
+ }
+ NS_HIDDEN_(void) Replace( index_type cutStart, size_type cutLength, char_type c )
+ {
+ Replace(cutStart, cutLength, &c, 1);
+ }
+ NS_HIDDEN_(void) Replace( index_type cutStart, size_type cutLength, const self_type& readable )
+ {
+ const char_type* data;
+ PRUint32 dataLen = NS_StringGetData(readable, &data);
+ NS_StringSetDataRange(*this, cutStart, cutLength, data, dataLen);
+ }
+
+ NS_HIDDEN_(void) Append( char_type c ) { Replace(size_type(-1), 0, c); }
+ NS_HIDDEN_(void) Append( const char_type* data, size_type length = size_type(-1) ) { Replace(size_type(-1), 0, data, length); }
+ NS_HIDDEN_(void) Append( const self_type& readable ) { Replace(size_type(-1), 0, readable); }
+
+ NS_HIDDEN_(self_type&) operator+=( char_type c ) { Append(c); return *this; }
+ NS_HIDDEN_(self_type&) operator+=( const char_type* data ) { Append(data); return *this; }
+ NS_HIDDEN_(self_type&) operator+=( const self_type& readable ) { Append(readable); return *this; }
+
+ NS_HIDDEN_(void) Insert( char_type c, index_type pos ) { Replace(pos, 0, c); }
+ NS_HIDDEN_(void) Insert( const char_type* data, index_type pos, size_type length = size_type(-1) ) { Replace(pos, 0, data, length); }
+ NS_HIDDEN_(void) Insert( const self_type& readable, index_type pos ) { Replace(pos, 0, readable); }
+
+ NS_HIDDEN_(void) Cut( index_type cutStart, size_type cutLength ) { Replace(cutStart, cutLength, nsnull, 0); }
+
+#endif // NS_STRINGAPI_IMPL
+
+private:
+ void *v;
+};
+
+class nsACString_external
+{
+#ifndef NS_STRINGAPI_IMPL
+
+public:
+ typedef char char_type;
+ typedef nsACString_external self_type;
+ typedef PRUint32 size_type;
+ typedef PRUint32 index_type;
+
+ NS_HIDDEN_(const char_type*) BeginReading() const
+ {
+ const char_type *data;
+ NS_CStringGetData(*this, &data);
+ return data;
+ }
+
+ NS_HIDDEN_(const char_type*) EndReading() const
+ {
+ const char_type *data;
+ PRUint32 len = NS_CStringGetData(*this, &data);
+ return data + len;
+ }
+
+ NS_HIDDEN_(size_type) Length() const
+ {
+ const char_type* data;
+ return NS_CStringGetData(*this, &data);
+ }
+
+ NS_HIDDEN_(void) Assign(const self_type& aString)
+ {
+ NS_CStringCopy(*this, aString);
+ }
+ NS_HIDDEN_(void) Assign(const char_type* aData, size_type aLength = PR_UINT32_MAX)
+ {
+ NS_CStringSetData(*this, aData, aLength);
+ }
+ NS_HIDDEN_(void) Assign(char_type aChar)
+ {
+ NS_CStringSetData(*this, &aChar, 1);
+ }
+
+ NS_HIDDEN_(self_type&) operator=(const self_type& aString) { Assign(aString); return *this; }
+ NS_HIDDEN_(self_type&) operator=(const char_type* aPtr) { Assign(aPtr); return *this; }
+ NS_HIDDEN_(self_type&) operator=(char_type aChar) { Assign(aChar); return *this; }
+
+ NS_HIDDEN_(void) Replace( index_type cutStart, size_type cutLength, const char_type* data, size_type length = size_type(-1) )
+ {
+ NS_CStringSetDataRange(*this, cutStart, cutLength, data, length);
+ }
+ NS_HIDDEN_(void) Replace( index_type cutStart, size_type cutLength, char_type c )
+ {
+ Replace(cutStart, cutLength, &c, 1);
+ }
+ NS_HIDDEN_(void) Replace( index_type cutStart, size_type cutLength, const self_type& readable )
+ {
+ const char_type* data;
+ PRUint32 dataLen = NS_CStringGetData(readable, &data);
+ NS_CStringSetDataRange(*this, cutStart, cutLength, data, dataLen);
+ }
+
+ NS_HIDDEN_(void) Append( char_type c ) { Replace(size_type(-1), 0, c); }
+ NS_HIDDEN_(void) Append( const char_type* data, size_type length = size_type(-1) ) { Replace(size_type(-1), 0, data, length); }
+ NS_HIDDEN_(void) Append( const self_type& readable ) { Replace(size_type(-1), 0, readable); }
+
+ NS_HIDDEN_(self_type&) operator+=( char_type c ) { Append(c); return *this; }
+ NS_HIDDEN_(self_type&) operator+=( const char_type* data ) { Append(data); return *this; }
+ NS_HIDDEN_(self_type&) operator+=( const self_type& readable ) { Append(readable); return *this; }
+
+ NS_HIDDEN_(void) Insert( char_type c, index_type pos ) { Replace(pos, 0, c); }
+ NS_HIDDEN_(void) Insert( const char_type* data, index_type pos, size_type length = size_type(-1) ) { Replace(pos, 0, data, length); }
+ NS_HIDDEN_(void) Insert( const self_type& readable, index_type pos ) { Replace(pos, 0, readable); }
+
+ NS_HIDDEN_(void) Cut( index_type cutStart, size_type cutLength ) { Replace(cutStart, cutLength, nsnull, 0); }
+
+#endif // NS_STRINGAPI_IMPL
+
+private:
+ void *v;
+};
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * Below we define nsStringContainer and nsCStringContainer. These classes
+ * have unspecified structure. In most cases, your code should use
+ * nsEmbedString instead of these classes; however, if you prefer C-style
+ * programming, then look no further...
+ */
+
+class nsStringContainer : public nsAString_external
+{
+private:
+ void *d1;
+ PRUint32 d2;
+ void *d3;
+
+public:
+ nsStringContainer() {} // MSVC6 needs this
+};
+
+class nsCStringContainer : public nsACString_external
+{
+private:
+ void *d1;
+ PRUint32 d2;
+ void *d3;
+
+public:
+ nsCStringContainer() {} // MSVC6 needs this
+};
+
+#endif // nsStringAPI_h__
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsStringFwd.h b/src/libs/xpcom18a4/xpcom/string/public/nsStringFwd.h
new file mode 100644
index 00000000..4c664011
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsStringFwd.h
@@ -0,0 +1,96 @@
+/* -*- 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.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@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 ***** */
+
+/* nsStringFwd.h --- forward declarations for string classes */
+
+#ifndef nsStringFwd_h___
+#define nsStringFwd_h___
+
+#ifndef nscore_h___
+#include "nscore.h"
+#endif
+
+
+ /**
+ * double-byte (PRUnichar) string types
+ */
+
+class nsAString;
+class nsObsoleteAString;
+class nsSubstring;
+class nsSubstringTuple;
+class nsString;
+class nsAutoString;
+class nsDependentString;
+class nsDependentSubstring;
+class nsPromiseFlatString;
+class nsStringComparator;
+class nsDefaultStringComparator;
+class nsXPIDLString;
+
+
+ /**
+ * single-byte (char) string types
+ */
+
+class nsACString;
+class nsObsoleteACString;
+class nsCSubstring;
+class nsCSubstringTuple;
+class nsCString;
+class nsCAutoString;
+class nsDependentCString;
+class nsDependentCSubstring;
+class nsPromiseFlatCString;
+class nsCStringComparator;
+class nsDefaultCStringComparator;
+class nsXPIDLCString;
+
+
+ /**
+ * typedefs for backwards compatibility
+ */
+
+typedef nsString nsAFlatString;
+typedef nsSubstring nsASingleFragmentString;
+
+typedef nsCString nsAFlatCString;
+typedef nsCSubstring nsASingleFragmentCString;
+
+
+#endif /* !defined(nsStringFwd_h___) */
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsStringIterator.h b/src/libs/xpcom18a4/xpcom/string/public/nsStringIterator.h
new file mode 100644
index 00000000..1848594c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsStringIterator.h
@@ -0,0 +1,373 @@
+/* -*- 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.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@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 nsStringIterator_h___
+#define nsStringIterator_h___
+
+#ifndef nsCharTraits_h___
+#include "nsCharTraits.h"
+#endif
+
+#ifndef nsAlgorithm_h___
+#include "nsAlgorithm.h"
+#endif
+
+#ifndef nsDebug_h___
+#include "nsDebug.h"
+#endif
+
+ /**
+ * @see nsTAString
+ */
+
+template <class CharT>
+class nsReadingIterator
+ {
+ public:
+ typedef nsReadingIterator<CharT> self_type;
+ typedef ptrdiff_t difference_type;
+ typedef CharT value_type;
+ typedef const CharT* pointer;
+ typedef const CharT& reference;
+
+ private:
+ friend class nsAString;
+ friend class nsACString;
+ friend class nsSubstring;
+ friend class nsCSubstring;
+
+ // unfortunately, the API for nsReadingIterator requires that the
+ // iterator know its start and end positions. this was needed when
+ // we supported multi-fragment strings, but now it is really just
+ // extra baggage. we should remove mStart and mEnd at some point.
+
+ const CharT* mStart;
+ const CharT* mEnd;
+ const CharT* mPosition;
+
+ public:
+ nsReadingIterator() { }
+ // nsReadingIterator( const nsReadingIterator<CharT>& ); // auto-generated copy-constructor OK
+ // nsReadingIterator<CharT>& operator=( const nsReadingIterator<CharT>& ); // auto-generated copy-assignment operator OK
+
+ inline void normalize_forward() {}
+ inline void normalize_backward() {}
+
+ pointer
+ start() const
+ {
+ return mStart;
+ }
+
+ pointer
+ end() const
+ {
+ return mEnd;
+ }
+
+ pointer
+ get() const
+ {
+ return mPosition;
+ }
+
+ CharT
+ operator*() const
+ {
+ return *get();
+ }
+
+#if 0
+ // An iterator really deserves this, but some compilers (notably IBM VisualAge for OS/2)
+ // don't like this when |CharT| is a type without members.
+ pointer
+ operator->() const
+ {
+ return get();
+ }
+#endif
+
+ self_type&
+ operator++()
+ {
+ ++mPosition;
+ return *this;
+ }
+
+ self_type
+ operator++( int )
+ {
+ self_type result(*this);
+ ++mPosition;
+ return result;
+ }
+
+ self_type&
+ operator--()
+ {
+ --mPosition;
+ return *this;
+ }
+
+ self_type
+ operator--( int )
+ {
+ self_type result(*this);
+ --mPosition;
+ return result;
+ }
+
+ difference_type
+ size_forward() const
+ {
+ return mEnd - mPosition;
+ }
+
+ difference_type
+ size_backward() const
+ {
+ return mPosition - mStart;
+ }
+
+ self_type&
+ advance( difference_type n )
+ {
+ if (n > 0)
+ {
+ difference_type step = NS_MIN(n, size_forward());
+
+ NS_ASSERTION(step>0, "can't advance a reading iterator beyond the end of a string");
+
+ mPosition += step;
+ }
+ else if (n < 0)
+ {
+ difference_type step = NS_MAX(n, -size_backward());
+
+ NS_ASSERTION(step<0, "can't advance (backward) a reading iterator beyond the end of a string");
+
+ mPosition += step;
+ }
+ return *this;
+ }
+ };
+
+ /**
+ * @see nsTAString
+ */
+
+template <class CharT>
+class nsWritingIterator
+ {
+ public:
+ typedef nsWritingIterator<CharT> self_type;
+ typedef ptrdiff_t difference_type;
+ typedef CharT value_type;
+ typedef CharT* pointer;
+ typedef CharT& reference;
+
+ private:
+ friend class nsAString;
+ friend class nsACString;
+ friend class nsSubstring;
+ friend class nsCSubstring;
+
+ // unfortunately, the API for nsWritingIterator requires that the
+ // iterator know its start and end positions. this was needed when
+ // we supported multi-fragment strings, but now it is really just
+ // extra baggage. we should remove mStart and mEnd at some point.
+
+ CharT* mStart;
+ CharT* mEnd;
+ CharT* mPosition;
+
+ public:
+ nsWritingIterator() { }
+ // nsWritingIterator( const nsWritingIterator<CharT>& ); // auto-generated copy-constructor OK
+ // nsWritingIterator<CharT>& operator=( const nsWritingIterator<CharT>& ); // auto-generated copy-assignment operator OK
+
+ inline void normalize_forward() {}
+ inline void normalize_backward() {}
+
+ pointer
+ start() const
+ {
+ return mStart;
+ }
+
+ pointer
+ end() const
+ {
+ return mEnd;
+ }
+
+ pointer
+ get() const
+ {
+ return mPosition;
+ }
+
+ reference
+ operator*() const
+ {
+ return *get();
+ }
+
+#if 0
+ // An iterator really deserves this, but some compilers (notably IBM VisualAge for OS/2)
+ // don't like this when |CharT| is a type without members.
+ pointer
+ operator->() const
+ {
+ return get();
+ }
+#endif
+
+ self_type&
+ operator++()
+ {
+ ++mPosition;
+ return *this;
+ }
+
+ self_type
+ operator++( int )
+ {
+ self_type result(*this);
+ ++mPosition;
+ return result;
+ }
+
+ self_type&
+ operator--()
+ {
+ --mPosition;
+ return *this;
+ }
+
+ self_type
+ operator--( int )
+ {
+ self_type result(*this);
+ --mPosition;
+ return result;
+ }
+
+ difference_type
+ size_forward() const
+ {
+ return mEnd - mPosition;
+ }
+
+ difference_type
+ size_backward() const
+ {
+ return mPosition - mStart;
+ }
+
+ self_type&
+ advance( difference_type n )
+ {
+ if (n > 0)
+ {
+ difference_type step = NS_MIN(n, size_forward());
+
+ NS_ASSERTION(step>0, "can't advance a writing iterator beyond the end of a string");
+
+ mPosition += step;
+ }
+ else if (n < 0)
+ {
+ difference_type step = NS_MAX(n, -size_backward());
+
+ NS_ASSERTION(step<0, "can't advance (backward) a writing iterator beyond the end of a string");
+
+ mPosition += step;
+ }
+ return *this;
+ }
+
+ PRUint32
+ write( const value_type* s, PRUint32 n )
+ {
+ NS_ASSERTION(size_forward() > 0, "You can't |write| into an |nsWritingIterator| with no space!");
+
+ nsCharTraits<value_type>::move(mPosition, s, n);
+ advance( difference_type(n) );
+ return n;
+ }
+ };
+
+template <class CharT>
+inline
+PRBool
+operator==( const nsReadingIterator<CharT>& lhs, const nsReadingIterator<CharT>& rhs )
+ {
+ return lhs.get() == rhs.get();
+ }
+
+template <class CharT>
+inline
+PRBool
+operator!=( const nsReadingIterator<CharT>& lhs, const nsReadingIterator<CharT>& rhs )
+ {
+ return lhs.get() != rhs.get();
+ }
+
+
+ //
+ // |nsWritingIterator|s
+ //
+
+template <class CharT>
+inline
+PRBool
+operator==( const nsWritingIterator<CharT>& lhs, const nsWritingIterator<CharT>& rhs )
+ {
+ return lhs.get() == rhs.get();
+ }
+
+template <class CharT>
+inline
+PRBool
+operator!=( const nsWritingIterator<CharT>& lhs, const nsWritingIterator<CharT>& rhs )
+ {
+ return lhs.get() != rhs.get();
+ }
+
+#endif /* !defined(nsStringIterator_h___) */
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsSubstring.h b/src/libs/xpcom18a4/xpcom/string/public/nsSubstring.h
new file mode 100644
index 00000000..35a1a568
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsSubstring.h
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 nsSubstring_h___
+#define nsSubstring_h___
+
+#ifndef nsAString_h___
+#include "nsAString.h"
+#endif
+
+#define kNotFound -1
+
+// If some platform(s) can't handle our template that matches literal strings,
+// then we'll disable it on those platforms.
+#ifndef NS_DISABLE_LITERAL_TEMPLATE
+# if (defined(_MSC_VER) && (_MSC_VER < 1310)) || (defined(__SUNPRO_CC) & (__SUNPRO_CC < 0x560)) || (defined(__HP_aCC) && (__HP_aCC <= 012100))
+# define NS_DISABLE_LITERAL_TEMPLATE
+# endif
+#endif /* !NS_DISABLE_LITERAL_TEMPLATE */
+
+#include <string.h>
+
+ // declare nsSubstring
+#include "string-template-def-unichar.h"
+#include "nsTSubstring.h"
+#include "string-template-undef.h"
+
+
+ // declare nsCSubstring
+#include "string-template-def-char.h"
+#include "nsTSubstring.h"
+#include "string-template-undef.h"
+
+
+#ifndef nsSubstringTuple_h___
+#include "nsSubstringTuple.h"
+#endif
+
+#endif // !defined(nsSubstring_h___)
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsSubstringTuple.h b/src/libs/xpcom18a4/xpcom/string/public/nsSubstringTuple.h
new file mode 100644
index 00000000..8cf6f803
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsSubstringTuple.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 nsSubstringTuple_h___
+#define nsSubstringTuple_h___
+
+#ifndef nsSubstring_h___
+#include "nsSubstring.h"
+#endif
+
+ // declare nsSubstringTuple
+#include "string-template-def-unichar.h"
+#include "nsTSubstringTuple.h"
+#include "string-template-undef.h"
+
+ // declare nsCSubstringTuple
+#include "string-template-def-char.h"
+#include "nsTSubstringTuple.h"
+#include "string-template-undef.h"
+
+#endif // !defined(nsSubstringTuple_h___)
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsTAString.h b/src/libs/xpcom18a4/xpcom/string/public/nsTAString.h
new file mode 100644
index 00000000..93b88443
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsTAString.h
@@ -0,0 +1,618 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@mozilla.org> (original author)
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+ /**
+ * The base for string comparators
+ */
+class NS_COM nsTStringComparator_CharT
+ {
+ public:
+ typedef CharT char_type;
+
+ nsTStringComparator_CharT() {}
+
+ virtual int operator()( const char_type*, const char_type*, PRUint32 length ) const = 0;
+ virtual int operator()( char_type, char_type ) const = 0;
+ };
+
+
+ /**
+ * The default string comparator (case-sensitive comparision)
+ */
+class NS_COM nsTDefaultStringComparator_CharT
+ : public nsTStringComparator_CharT
+ {
+ public:
+ typedef CharT char_type;
+
+ nsTDefaultStringComparator_CharT() {}
+
+ virtual int operator()( const char_type*, const char_type*, PRUint32 length ) const;
+ virtual int operator()( char_type, char_type ) const;
+ };
+
+
+ /**
+ * nsTAString is the most abstract class in the string hierarchy.
+ *
+ * In its original inception, nsTAString was designed to allow the data
+ * storage for a string to be separated into multiple fragments. This was
+ * intended to enable lazy string flattening or avoid string flattening
+ * altogether in some cases. This abstraction, however, meant that every
+ * single string operation (including simple operations such as IsEmpty() and
+ * BeginReading()) required virtual function calls. A virtual destructor was
+ * also required. This not only meant additional overhead for invoking
+ * string methods but also added to additional codesize at every callsite (to
+ * load the virtual function address).
+ *
+ * Today nsTAString exists mainly for backwards compatibility of the string
+ * API. It is restricted to representing a contiguous array of characters,
+ * where the character array is not necessarily null-terminated. Moreover,
+ * since nsTAString's virtual function table was frozen for Mozilla 1.0,
+ * nsTAString necessarily maintains ABI compatibility with older versions of
+ * Gecko. (nsTObsoleteAString provides that frozen ABI. See
+ * nsObsoleteAString.h for a description of how we solve the ABI
+ * compatibility requirement while eliminating virtual function calls on
+ * nsTAString.)
+ *
+ * XPIDL still generates C++ header files with references to nsTAStrings, so
+ * nsTAString will still be heavily used in real code.
+ *
+ * If the opportunity to break ABI compatibility with Mozilla 1.0 were to
+ * ever arise, our first move should be to make nsTAString equate to
+ * nsTSubstring. This may in fact be an option today for some Gecko-based
+ * products.
+ */
+class nsTAString_CharT
+ {
+ public:
+
+ typedef CharT char_type;
+ typedef nsCharTraits<char_type> char_traits;
+
+ typedef char_traits::incompatible_char_type incompatible_char_type;
+
+ typedef nsTAString_CharT self_type;
+ typedef nsTAString_CharT abstract_string_type;
+ typedef nsTObsoleteAString_CharT obsolete_string_type;
+ typedef nsTSubstring_CharT substring_type;
+ typedef nsTSubstringTuple_CharT substring_tuple_type;
+
+ typedef nsReadingIterator<char_type> const_iterator;
+ typedef nsWritingIterator<char_type> iterator;
+
+ typedef nsTStringComparator_CharT comparator_type;
+
+ typedef PRUint32 size_type;
+ typedef PRUint32 index_type;
+
+ public:
+
+ // this acts like a virtual destructor
+ NS_COM NS_FASTCALL ~nsTAString_CharT();
+
+
+ /**
+ * BeginReading/EndReading can be used to get immutable access to the
+ * string's underlying buffer. EndReading returns a pointer to the
+ * end of the string's buffer. nsReadableUtils.h provides a collection
+ * of utility functions that work with these iterators.
+ */
+
+ inline const_iterator& BeginReading( const_iterator& iter ) const
+ {
+ size_type len = GetReadableBuffer(&iter.mStart);
+ iter.mEnd = iter.mStart + len;
+ iter.mPosition = iter.mStart;
+ return iter;
+ }
+
+ inline const_iterator& EndReading( const_iterator& iter ) const
+ {
+ size_type len = GetReadableBuffer(&iter.mStart);
+ iter.mEnd = iter.mStart + len;
+ iter.mPosition = iter.mEnd;
+ return iter;
+ }
+
+
+ /**
+ * BeginWriting/EndWriting can be used to get mutable access to the
+ * string's underlying buffer. EndWriting returns a pointer to the
+ * end of the string's buffer. This iterator API cannot be used to
+ * grow a buffer. Use SetLength to resize the string's buffer.
+ */
+
+ inline iterator& BeginWriting( iterator& iter )
+ {
+ size_type len = GetWritableBuffer(&iter.mStart);
+ iter.mEnd = iter.mStart + len;
+ iter.mPosition = iter.mStart;
+ return iter;
+ }
+
+ inline iterator& EndWriting( iterator& iter )
+ {
+ size_type len = GetWritableBuffer(&iter.mStart);
+ iter.mEnd = iter.mStart + len;
+ iter.mPosition = iter.mEnd;
+ return iter;
+ }
+
+
+ /**
+ * Length checking functions. IsEmpty is a helper function to avoid
+ * writing code like: |if (str.Length() == 0)|
+ */
+
+ NS_COM size_type NS_FASTCALL Length() const;
+ PRBool IsEmpty() const { return Length() == 0; }
+
+
+ /**
+ * String equality tests. Pass a string comparator if you want to
+ * control how the strings are compared. By default, a binary
+ * "case-sensitive" comparision is performed.
+ */
+
+ NS_COM PRBool NS_FASTCALL Equals( const self_type& ) const;
+ NS_COM PRBool NS_FASTCALL Equals( const self_type&, const comparator_type& ) const;
+ NS_COM PRBool NS_FASTCALL Equals( const char_type* ) const;
+ NS_COM PRBool NS_FASTCALL Equals( const char_type*, const comparator_type& ) const;
+
+ /**
+ * An efficient comparison with ASCII that can be used even
+ * for wide strings. Call this version when you know the
+ * length of 'data'.
+ */
+ NS_COM PRBool NS_FASTCALL EqualsASCII( const char* data, size_type len ) const;
+ /**
+ * An efficient comparison with ASCII that can be used even
+ * for wide strings. Call this version when 'data' is
+ * null-terminated.
+ */
+ NS_COM PRBool NS_FASTCALL EqualsASCII( const char* data ) const;
+
+ // EqualsLiteral must ONLY be applied to an actual literal string.
+ // Do not attempt to use it with a regular char* pointer, or with a char
+ // array variable.
+ // The template trick to acquire the array length at compile time without
+ // using a macro is due to Corey Kosak, with much thanks.
+#ifdef NS_DISABLE_LITERAL_TEMPLATE
+ inline PRBool EqualsLiteral( const char* str ) const
+ {
+ return EqualsASCII(str);
+ }
+#else
+ template<int N>
+ inline PRBool EqualsLiteral( const char (&str)[N] ) const
+ {
+ return EqualsASCII(str, N-1);
+ }
+ template<int N>
+ inline PRBool EqualsLiteral( char (&str)[N] ) const
+ {
+ const char* s = str;
+ return EqualsASCII(s, N-1);
+ }
+#endif
+
+ // The LowerCaseEquals methods compare the lower case version of
+ // this string to some ASCII/Literal string. The ASCII string is
+ // *not* lowercased for you. If you compare to an ASCII or literal
+ // string that contains an uppercase character, it is guaranteed to
+ // return false. We will throw assertions too.
+ NS_COM PRBool NS_FASTCALL LowerCaseEqualsASCII( const char* data, size_type len ) const;
+ NS_COM PRBool NS_FASTCALL LowerCaseEqualsASCII( const char* data ) const;
+
+ // LowerCaseEqualsLiteral must ONLY be applied to an actual
+ // literal string. Do not attempt to use it with a regular char*
+ // pointer, or with a char array variable. Use
+ // LowerCaseEqualsASCII for them.
+#ifdef NS_DISABLE_LITERAL_TEMPLATE
+ inline PRBool LowerCaseEqualsLiteral( const char* str ) const
+ {
+ return LowerCaseEqualsASCII(str);
+ }
+#else
+ template<int N>
+ inline PRBool LowerCaseEqualsLiteral( const char (&str)[N] ) const
+ {
+ return LowerCaseEqualsASCII(str, N-1);
+ }
+ template<int N>
+ inline PRBool LowerCaseEqualsLiteral( char (&str)[N] ) const
+ {
+ const char* s = str;
+ return LowerCaseEqualsASCII(s, N-1);
+ }
+#endif
+
+ /**
+ * A string always references a non-null data pointer. In some
+ * applications (e.g., the DOM) it is necessary for a string class
+ * to have some way to distinguish an empty string from a null (or
+ * void) string. These methods enable support for the concept of
+ * a void string.
+ */
+
+ NS_COM PRBool NS_FASTCALL IsVoid() const;
+ NS_COM void NS_FASTCALL SetIsVoid( PRBool );
+
+
+ /**
+ * This method returns true if the string's underlying buffer is
+ * null-terminated. This should rarely be needed by applications.
+ * The PromiseFlatTString method should be used to ensure that a
+ * string's underlying buffer is null-terminated.
+ */
+
+ NS_COM PRBool NS_FASTCALL IsTerminated() const;
+
+
+ /**
+ * These are contant time since nsTAString uses flat storage
+ */
+ NS_COM char_type NS_FASTCALL First() const;
+ NS_COM char_type NS_FASTCALL Last() const;
+
+
+ /**
+ * Returns the number of occurances of the given character.
+ */
+ NS_COM size_type NS_FASTCALL CountChar( char_type ) const;
+
+
+ /**
+ * Locates the offset of the first occurance of the character. Pass a
+ * non-zero offset to control where the search begins.
+ */
+
+ NS_COM PRInt32 NS_FASTCALL FindChar( char_type, index_type offset = 0 ) const;
+
+
+ /**
+ * SetCapacity is not required to do anything; however, it can be used
+ * as a hint to the implementation to reduce allocations.
+ *
+ * SetCapacity(0) is a suggestion to discard all associated storage.
+ */
+ NS_COM void NS_FASTCALL SetCapacity( size_type );
+
+
+ /**
+ * XXX talk to dbaron about this comment. we do need a method that
+ * XXX allows someone to resize a string's buffer so that it can be
+ * XXX populated using writing iterators. SetLength seems to be the
+ * XXX right method for the job, and we do use it in this capacity
+ * XXX in certain places.
+ *
+ * SetLength is used in two ways:
+ * 1) to |Cut| a suffix of the string;
+ * 2) to prepare to |Append| or move characters around.
+ *
+ * External callers are not allowed to use |SetLength| in this
+ * latter capacity, and should prefer |Truncate| for the former.
+ * In other words, |SetLength| is deprecated for all use outside
+ * of the string library and the internal use may at some point
+ * be replaced as well.
+ *
+ * This distinction makes me think the two different uses should
+ * be split into two distinct functions.
+ */
+ NS_COM void NS_FASTCALL SetLength( size_type );
+
+
+ /**
+ * Can't use |Truncate| to make a string longer!
+ */
+ void Truncate( size_type aNewLength=0 )
+ {
+ NS_ASSERTION(aNewLength <= Length(), "Truncate cannot make string longer");
+ SetLength(aNewLength);
+ }
+
+
+ /**
+ * |Assign| and |operator=| make |this| equivalent to the string or
+ * buffer given as an argument. If possible, they do this by sharing
+ * a reference counted buffer (see |nsTSubstring|). If not, they copy
+ * the buffer into their own buffer.
+ */
+
+ NS_COM void NS_FASTCALL Assign( const self_type& readable );
+ NS_COM void NS_FASTCALL Assign( const substring_tuple_type& tuple );
+ NS_COM void NS_FASTCALL Assign( const char_type* data );
+ NS_COM void NS_FASTCALL Assign( const char_type* data, size_type length );
+ NS_COM void NS_FASTCALL Assign( char_type c );
+
+ NS_COM void NS_FASTCALL AssignASCII( const char* data, size_type length );
+ NS_COM void NS_FASTCALL AssignASCII( const char* data );
+
+ // AssignLiteral must ONLY be applied to an actual literal string.
+ // Do not attempt to use it with a regular char* pointer, or with a char
+ // array variable. Use AssignASCII for those.
+#ifdef NS_DISABLE_LITERAL_TEMPLATE
+ void AssignLiteral( const char* str )
+ { AssignASCII(str); }
+#else
+ template<int N>
+ void AssignLiteral( const char (&str)[N] )
+ { AssignASCII(str, N-1); }
+ template<int N>
+ void AssignLiteral( char (&str)[N] )
+ { AssignASCII(str, N-1); }
+#endif
+
+ // copy-assignment operator. I must define my own if I don't want the compiler to make me one
+ self_type& operator=( const self_type& readable ) { Assign(readable); return *this; }
+ self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; }
+ self_type& operator=( const char_type* data ) { Assign(data); return *this; }
+ self_type& operator=( char_type c ) { Assign(c); return *this; }
+
+
+
+ /**
+ * |Append|, |operator+=| are used to add characters to the end of this string.
+ */
+
+ NS_COM void NS_FASTCALL Append( const self_type& readable );
+ NS_COM void NS_FASTCALL Append( const substring_tuple_type& tuple );
+ NS_COM void NS_FASTCALL Append( const char_type* data );
+ NS_COM void NS_FASTCALL Append( const char_type* data, size_type length );
+ NS_COM void NS_FASTCALL Append( char_type c );
+
+ NS_COM void NS_FASTCALL AppendASCII( const char* data, size_type length );
+ NS_COM void NS_FASTCALL AppendASCII( const char* data );
+
+ // AppendLiteral must ONLY be applied to an actual literal string.
+ // Do not attempt to use it with a regular char* pointer, or with a char
+ // array variable. Use AppendASCII for those.
+#ifdef NS_DISABLE_LITERAL_TEMPLATE
+ void AppendLiteral( const char* str )
+ { AppendASCII(str); }
+#else
+ template<int N>
+ void AppendLiteral( const char (&str)[N] )
+ { AppendASCII(str, N-1); }
+ template<int N>
+ void AppendLiteral( char (&str)[N] )
+ { AppendASCII(str, N-1); }
+#endif
+
+ self_type& operator+=( const self_type& readable ) { Append(readable); return *this; }
+ self_type& operator+=( const substring_tuple_type& tuple ) { Append(tuple); return *this; }
+ self_type& operator+=( const char_type* data ) { Append(data); return *this; }
+ self_type& operator+=( char_type c ) { Append(c); return *this; }
+
+
+ /**
+ * |Insert| is used to add characters into this string at a given position.
+ * NOTE: It's a shame the |pos| parameter isn't at the front of the arg list.
+ */
+
+ NS_COM void NS_FASTCALL Insert( const self_type& readable, index_type pos );
+ NS_COM void NS_FASTCALL Insert( const substring_tuple_type& tuple, index_type pos );
+ NS_COM void NS_FASTCALL Insert( const char_type* data, index_type pos );
+ NS_COM void NS_FASTCALL Insert( const char_type* data, index_type pos, size_type length );
+ NS_COM void NS_FASTCALL Insert( char_type c, index_type pos );
+
+
+ /**
+ * |Cut| is used to remove a range of characters from this string.
+ */
+
+ NS_COM void NS_FASTCALL Cut( index_type cutStart, size_type cutLength );
+
+
+ /**
+ * |Replace| is used overwrite a range of characters from this string.
+ */
+
+ NS_COM void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, const self_type& readable );
+ NS_COM void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, const substring_tuple_type& readable );
+
+
+ /**
+ * this is public to support automatic conversion of tuple to abstract
+ * string, which is necessary to support our API.
+ */
+ nsTAString_CharT(const substring_tuple_type& tuple)
+ : mVTable(obsolete_string_type::sCanonicalVTable)
+ , mData(nsnull)
+ , mLength(0)
+ , mFlags(0)
+ {
+ Assign(tuple);
+ }
+
+ protected:
+
+ friend class nsTSubstringTuple_CharT;
+
+ // GCC 3.2 erroneously needs these (even though they are subclasses!)
+ friend class nsTSubstring_CharT;
+ friend class nsTDependentSubstring_CharT;
+ friend class nsTPromiseFlatString_CharT;
+
+ /**
+ * the address of our virtual function table. required for backwards
+ * compatibility with Mozilla 1.0 frozen nsAC?String interface.
+ */
+ const void* mVTable;
+
+ /**
+ * these fields are "here" only when mVTable == sCanonicalVTable.
+ *
+ * they exist to support automatic construction of a nsTAString
+ * from a nsTSubstringTuple.
+ */
+ char_type* mData;
+ size_type mLength;
+ PRUint32 mFlags;
+
+ /**
+ * nsTAString must be subclassed before it can be instantiated.
+ */
+ nsTAString_CharT(char_type* data, size_type length, PRUint32 flags)
+ : mVTable(obsolete_string_type::sCanonicalVTable)
+ , mData(data)
+ , mLength(length)
+ , mFlags(flags)
+ {}
+
+ /**
+ * optional ctor for use by subclasses.
+ *
+ * NOTE: mData and mLength are intentionally left uninitialized.
+ */
+ explicit
+ nsTAString_CharT(PRUint32 flags)
+ : mVTable(obsolete_string_type::sCanonicalVTable)
+ , mFlags(flags)
+ {}
+
+ /**
+ * get pointer to internal string buffer (may not be null terminated).
+ * return length of buffer.
+ */
+ NS_COM size_type NS_FASTCALL GetReadableBuffer( const char_type **data ) const;
+ NS_COM size_type NS_FASTCALL GetWritableBuffer( char_type **data );
+
+ /**
+ * returns true if this tuple is dependent on (i.e., overlapping with)
+ * the given char sequence.
+ */
+ PRBool NS_FASTCALL IsDependentOn(const char_type *start, const char_type *end) const;
+
+ /**
+ * we can be converted to a const nsTSubstring (dependent on this)
+ */
+ const substring_type NS_FASTCALL ToSubstring() const;
+
+ /**
+ * type cast helpers
+ */
+
+ const obsolete_string_type* AsObsoleteString() const
+ {
+ return NS_REINTERPRET_CAST(const obsolete_string_type*, this);
+ }
+
+ obsolete_string_type* AsObsoleteString()
+ {
+ return NS_REINTERPRET_CAST(obsolete_string_type*, this);
+ }
+
+ const substring_type* AsSubstring() const
+ {
+ return NS_REINTERPRET_CAST(const substring_type*, this);
+ }
+
+ substring_type* AsSubstring()
+ {
+ return NS_REINTERPRET_CAST(substring_type*, this);
+ }
+
+ private:
+
+ // GCC 2.95.3, EGCS-2.91.66, Sun Workshop/Forte, and IBM VisualAge C++
+ // require a public copy-constructor in order to support automatic
+ // construction of a nsTAString from a nsTSubstringTuple. I believe
+ // enabling the default copy-constructor is harmless, but I do not want
+ // it to be enabled by default because that might tempt people into
+ // using it (where it would be invalid).
+#if !defined(__SUNPRO_CC) && \
+ !(defined(_AIX) && defined(__IBMCPP__)) && \
+ (!defined(__GNUC__) || __GNUC__ > 2 || __GNUC_MINOR__ > 95)
+
+ // NOT TO BE IMPLEMENTED
+ nsTAString_CharT( const self_type& );
+
+#endif
+
+ // NOT TO BE IMPLEMENTED
+ void operator= ( incompatible_char_type );
+ void Assign ( incompatible_char_type );
+ void operator+= ( incompatible_char_type );
+ void Append ( incompatible_char_type );
+ void Insert ( incompatible_char_type, index_type );
+ };
+
+
+NS_COM
+int NS_FASTCALL Compare( const nsTAString_CharT& lhs, const nsTAString_CharT& rhs, const nsTStringComparator_CharT& = nsTDefaultStringComparator_CharT() );
+
+
+inline
+PRBool operator!=( const nsTAString_CharT& lhs, const nsTAString_CharT& rhs )
+ {
+ return !lhs.Equals(rhs);
+ }
+
+inline
+PRBool operator< ( const nsTAString_CharT& lhs, const nsTAString_CharT& rhs )
+ {
+ return Compare(lhs, rhs)< 0;
+ }
+
+inline
+PRBool operator<=( const nsTAString_CharT& lhs, const nsTAString_CharT& rhs )
+ {
+ return Compare(lhs, rhs)<=0;
+ }
+
+inline
+PRBool operator==( const nsTAString_CharT& lhs, const nsTAString_CharT& rhs )
+ {
+ return lhs.Equals(rhs);
+ }
+
+inline
+PRBool operator>=( const nsTAString_CharT& lhs, const nsTAString_CharT& rhs )
+ {
+ return Compare(lhs, rhs)>=0;
+ }
+
+inline
+PRBool operator> ( const nsTAString_CharT& lhs, const nsTAString_CharT& rhs )
+ {
+ return Compare(lhs, rhs)> 0;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsTDependentString.h b/src/libs/xpcom18a4/xpcom/string/public/nsTDependentString.h
new file mode 100644
index 00000000..91a2b53e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsTDependentString.h
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@mozilla.org> (original author)
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+ /**
+ * nsTDependentString_CharT
+ *
+ * Stores a null-terminated, immutable sequence of characters.
+ *
+ * Subclass of nsTString that restricts string value to an immutable
+ * character sequence. This class does not own its data, so the creator
+ * of objects of this type must take care to ensure that a
+ * nsTDependentString continues to reference valid memory for the
+ * duration of its use.
+ */
+class nsTDependentString_CharT : public nsTString_CharT
+ {
+ public:
+
+ typedef nsTDependentString_CharT self_type;
+
+ public:
+
+ /**
+ * verify restrictions
+ */
+ void AssertValid()
+ {
+ NS_ASSERTION(mData, "nsTDependentString must wrap a non-NULL buffer");
+ NS_ASSERTION(mLength != size_type(-1), "nsTDependentString has bogus length");
+ NS_ASSERTION(mData[mLength] == 0, "nsTDependentString must wrap only null-terminated strings");
+ }
+
+
+ /**
+ * constructors
+ */
+
+ nsTDependentString_CharT( const char_type* start, const char_type* end )
+ : string_type(NS_CONST_CAST(char_type*, start), end - start, F_TERMINATED)
+ {
+ AssertValid();
+ }
+
+ nsTDependentString_CharT( const char_type* data, PRUint32 length )
+ : string_type(NS_CONST_CAST(char_type*, data), length, F_TERMINATED)
+ {
+ AssertValid();
+ }
+
+ explicit
+ nsTDependentString_CharT( const char_type* data )
+ : string_type(NS_CONST_CAST(char_type*, data), char_traits::length(data), F_TERMINATED)
+ {
+ AssertValid();
+ }
+
+ explicit
+ nsTDependentString_CharT( const substring_type& str )
+ : string_type(NS_CONST_CAST(char_type*, str.Data()), str.Length(), F_TERMINATED)
+ {
+ AssertValid();
+ }
+
+ // XXX are you sure??
+ // auto-generated copy-constructor OK
+ // auto-generated copy-assignment operator OK
+ // auto-generated destructor OK
+
+
+ /**
+ * allow this class to be bound to a different string...
+ */
+
+ void Rebind( const char_type* data )
+ {
+ mData = NS_CONST_CAST(char_type*, data);
+ mLength = char_traits::length(data);
+ SetDataFlags(F_TERMINATED);
+ AssertValid();
+ }
+
+ void Rebind( const char_type* data, size_type length )
+ {
+ mData = NS_CONST_CAST(char_type*, data);
+ mLength = length;
+ SetDataFlags(F_TERMINATED);
+ AssertValid();
+ }
+
+ void Rebind( const char_type* start, const char_type* end )
+ {
+ Rebind(start, end - start);
+ }
+
+ private:
+
+ // NOT USED
+ nsTDependentString_CharT( const substring_tuple_type& );
+ nsTDependentString_CharT( const abstract_string_type& );
+ };
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsTDependentSubstring.h b/src/libs/xpcom18a4/xpcom/string/public/nsTDependentSubstring.h
new file mode 100644
index 00000000..00e5f189
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsTDependentSubstring.h
@@ -0,0 +1,143 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@mozilla.org> (original author)
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+ /**
+ * nsTDependentSubstring_CharT
+ */
+class nsTDependentSubstring_CharT : public nsTSubstring_CharT
+ {
+ public:
+
+ typedef nsTDependentSubstring_CharT self_type;
+
+ public:
+
+ NS_COM void Rebind( const abstract_string_type&, PRUint32 startPos, PRUint32 length = size_type(-1) );
+ NS_COM void Rebind( const substring_type&, PRUint32 startPos, PRUint32 length = size_type(-1) );
+
+ void Rebind( const char_type* start, const char_type* end )
+ {
+ NS_ASSERTION(start && end, "nsTDependentSubstring must wrap a non-NULL buffer");
+ mData = NS_CONST_CAST(char_type*, start);
+ mLength = end - start;
+ SetDataFlags(F_NONE);
+ }
+
+ nsTDependentSubstring_CharT( const abstract_string_type& str, PRUint32 startPos, PRUint32 length = size_type(-1) )
+ : substring_type(F_NONE)
+ {
+ Rebind(str, startPos, length);
+ }
+
+ nsTDependentSubstring_CharT( const substring_type& str, PRUint32 startPos, PRUint32 length = size_type(-1) )
+ : substring_type(F_NONE)
+ {
+ Rebind(str, startPos, length);
+ }
+
+ nsTDependentSubstring_CharT( const char_type* start, const char_type* end )
+ : substring_type(NS_CONST_CAST(char_type*, start), end - start, F_NONE) {}
+
+ nsTDependentSubstring_CharT( const const_iterator& start, const const_iterator& end )
+ : substring_type(NS_CONST_CAST(char_type*, start.get()), end.get() - start.get(), F_NONE) {}
+
+ // auto-generated copy-constructor OK (XXX really?? what about base class copy-ctor?)
+
+ private:
+ // we're immutable, you can't assign into a substring
+ void operator=( const self_type& ) NS_DELETE;
+
+ };
+
+inline
+const nsTDependentSubstring_CharT
+Substring( const nsTAString_CharT& str, PRUint32 startPos, PRUint32 length = PRUint32(-1) )
+ {
+ return nsTDependentSubstring_CharT(str, startPos, length);
+ }
+
+inline
+const nsTDependentSubstring_CharT
+Substring( const nsTSubstring_CharT& str, PRUint32 startPos, PRUint32 length = PRUint32(-1) )
+ {
+ return nsTDependentSubstring_CharT(str, startPos, length);
+ }
+
+inline
+const nsTDependentSubstring_CharT
+Substring( const nsReadingIterator<CharT>& start, const nsReadingIterator<CharT>& end )
+ {
+ return nsTDependentSubstring_CharT(start.get(), end.get());
+ }
+
+inline
+const nsTDependentSubstring_CharT
+Substring( const CharT* start, const CharT* end )
+ {
+ return nsTDependentSubstring_CharT(start, end);
+ }
+
+inline
+const nsTDependentSubstring_CharT
+StringHead( const nsTAString_CharT& str, PRUint32 count )
+ {
+ return nsTDependentSubstring_CharT(str, 0, count);
+ }
+
+inline
+const nsTDependentSubstring_CharT
+StringHead( const nsTSubstring_CharT& str, PRUint32 count )
+ {
+ return nsTDependentSubstring_CharT(str, 0, count);
+ }
+
+inline
+const nsTDependentSubstring_CharT
+StringTail( const nsTAString_CharT& str, PRUint32 count )
+ {
+ return nsTDependentSubstring_CharT(str, str.Length() - count, count);
+ }
+
+inline
+const nsTDependentSubstring_CharT
+StringTail( const nsTSubstring_CharT& str, PRUint32 count )
+ {
+ return nsTDependentSubstring_CharT(str, str.Length() - count, count);
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsTObsoleteAString.h b/src/libs/xpcom18a4/xpcom/string/public/nsTObsoleteAString.h
new file mode 100644
index 00000000..82d5f56c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsTObsoleteAString.h
@@ -0,0 +1,165 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+ /**
+ * nsTObsoleteAString_CharT : binary compatible with old nsAC?String vtable
+ *
+ * @status FROZEN
+ */
+class nsTObsoleteAString_CharT
+ {
+ public:
+ /**
+ * This is holds the address of the vtable for the canonical string
+ * implementation (i.e., nsTString).
+ */
+ NS_COM static const void *sCanonicalVTable;
+
+ /**
+ * An |nsFragmentRequest| is used to tell |GetReadableFragment| and
+ * |GetWritableFragment| what to do.
+ *
+ * @see GetReadableFragment
+ */
+ enum nsFragmentRequest { kPrevFragment, kFirstFragment, kLastFragment, kNextFragment, kFragmentAt };
+
+ /**
+ * A |nsReadableFragment| provides |const| access to a contiguous hunk of
+ * string of homogenous units, e.g., bytes (|char|). This doesn't mean it
+ * represents a flat hunk. It could be a variable length encoding, for
+ * instance UTF-8. And the fragment itself need not be zero-terminated.
+ *
+ * An |nsReadableFragment| is the underlying machinery that lets
+ * |nsReadingIterator|s work.
+ *
+ * @see nsReadingIterator
+ * @status FROZEN
+ */
+ struct nsReadableFragment
+ {
+ const CharT* mStart;
+ const CharT* mEnd;
+ const void* mFragmentIdentifier;
+
+ nsReadableFragment() : mStart(0), mEnd(0), mFragmentIdentifier(0) {}
+ };
+
+
+ /**
+ * A |nsWritableFragment| provides non-|const| access to a contiguous hunk of
+ * string of homogenous units, e.g., bytes (|char|). This doesn't mean it
+ * represents a flat hunk. It could be a variable length encoding, for
+ * instance UTF-8. And the fragment itself need not be zero-terminated.
+ *
+ * An |nsWritableFragment| is the underlying machinery that lets
+ * |nsWritingIterator|s work.
+ *
+ * @see nsWritingIterator
+ * @status FROZEN
+ */
+ struct nsWritableFragment
+ {
+ CharT* mStart;
+ CharT* mEnd;
+ void* mFragmentIdentifier;
+
+ nsWritableFragment() : mStart(0), mEnd(0), mFragmentIdentifier(0) {}
+ };
+
+ protected:
+
+ typedef CharT char_type;
+
+ typedef void buffer_handle_type;
+ typedef void shared_buffer_handle_type;
+ typedef nsReadableFragment const_fragment_type;
+ typedef nsWritableFragment fragment_type;
+
+ typedef nsTAString_CharT abstract_string_type;
+
+ typedef PRUint32 size_type;
+ typedef PRUint32 index_type;
+
+ protected:
+
+ friend class nsTAString_CharT;
+ friend class nsTSubstring_CharT;
+
+ /** here's the old nsAC?String vtable **/
+
+ virtual ~nsTObsoleteAString_CharT() { }
+
+ virtual PRUint32 GetImplementationFlags() const = 0;
+ virtual const buffer_handle_type* GetFlatBufferHandle() const = 0;
+ virtual const buffer_handle_type* GetBufferHandle() const = 0;
+ virtual const shared_buffer_handle_type* GetSharedBufferHandle() const = 0;
+
+ virtual size_type Length() const = 0;
+
+ virtual PRBool IsVoid() const = 0;
+ virtual void SetIsVoid( PRBool ) = 0;
+
+ virtual void SetCapacity( size_type ) = 0;
+ virtual void SetLength( size_type ) = 0;
+
+ virtual void Cut( index_type cutStart, size_type cutLength ) = 0;
+
+ virtual void do_AssignFromReadable( const abstract_string_type& ) = 0;
+ virtual void do_AssignFromElementPtr( const char_type* ) = 0;
+ virtual void do_AssignFromElementPtrLength( const char_type*, size_type ) = 0;
+ virtual void do_AssignFromElement( char_type ) = 0;
+
+ virtual void do_AppendFromReadable( const abstract_string_type& ) = 0;
+ virtual void do_AppendFromElementPtr( const char_type* ) = 0;
+ virtual void do_AppendFromElementPtrLength( const char_type*, size_type ) = 0;
+ virtual void do_AppendFromElement( char_type ) = 0;
+
+ virtual void do_InsertFromReadable( const abstract_string_type&, index_type ) = 0;
+ virtual void do_InsertFromElementPtr( const char_type*, index_type ) = 0;
+ virtual void do_InsertFromElementPtrLength( const char_type*, index_type, size_type ) = 0;
+ virtual void do_InsertFromElement( char_type, index_type ) = 0;
+
+ virtual void do_ReplaceFromReadable( index_type, size_type, const abstract_string_type& ) = 0;
+
+ virtual const char_type* GetReadableFragment( const_fragment_type&, nsFragmentRequest, PRUint32 = 0 ) const = 0;
+ virtual char_type* GetWritableFragment( fragment_type&, nsFragmentRequest, PRUint32 = 0 ) = 0;
+ };
+
+ // forward declare implementation
+class nsTObsoleteAStringThunk_CharT;
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsTPromiseFlatString.h b/src/libs/xpcom18a4/xpcom/string/public/nsTPromiseFlatString.h
new file mode 100644
index 00000000..6899df7c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsTPromiseFlatString.h
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Scott Collins <scc@mozilla.org> (original author)
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+ /**
+ * NOTE:
+ *
+ * Try to avoid flat strings. |PromiseFlat[C]String| will help you as a last
+ * resort, and this may be necessary when dealing with legacy or OS calls,
+ * but in general, requiring a null-terminated array of characters kills many
+ * of the performance wins the string classes offer. Write your own code to
+ * use |nsA[C]String&|s for parameters. Write your string proccessing
+ * algorithms to exploit iterators. If you do this, you will benefit from
+ * being able to chain operations without copying or allocating and your code
+ * will be significantly more efficient. Remember, a function that takes an
+ * |const nsA[C]String&| can always be passed a raw character pointer by
+ * wrapping it (for free) in a |nsDependent[C]String|. But a function that
+ * takes a character pointer always has the potential to force allocation and
+ * copying.
+ *
+ *
+ * How to use it:
+ *
+ * A |nsPromiseFlat[C]String| doesn't necessarily own the characters it
+ * promises. You must never use it to promise characters out of a string
+ * with a shorter lifespan. The typical use will be something like this:
+ *
+ * SomeOSFunction( PromiseFlatCString(aCString).get() ); // GOOD
+ *
+ * Here's a BAD use:
+ *
+ * const char* buffer = PromiseFlatCString(aCString).get();
+ * SomeOSFunction(buffer); // BAD!! |buffer| is a dangling pointer
+ *
+ * The only way to make one is with the function |PromiseFlat[C]String|,
+ * which produce a |const| instance. ``What if I need to keep a promise
+ * around for a little while?'' you might ask. In that case, you can keep a
+ * reference, like so
+ *
+ * const nsPromiseFlatString& flat = PromiseFlatString(aString);
+ * // this reference holds the anonymous temporary alive, but remember,
+ * // it must _still_ have a lifetime shorter than that of |aString|
+ *
+ * SomeOSFunction(flat.get());
+ * SomeOtherOSFunction(flat.get());
+ *
+ *
+ * How does it work?
+ *
+ * A |nsPromiseFlat[C]String| is just a wrapper for another string. If you
+ * apply it to a string that happens to be flat, your promise is just a
+ * dependent reference to the string's data. If you apply it to a non-flat
+ * string, then a temporary flat string is created for you, by allocating and
+ * copying. In the event that you end up assigning the result into a sharing
+ * string (e.g., |nsTString|), the right thing happens.
+ */
+
+class nsTPromiseFlatString_CharT : public nsTString_CharT
+ {
+ public:
+
+ typedef nsTPromiseFlatString_CharT self_type;
+
+ private:
+
+ NS_COM void Init( const substring_type& );
+ NS_COM void Init( const abstract_string_type& );
+
+ // NOT TO BE IMPLEMENTED
+ void operator=( const self_type& ) NS_DELETE;
+
+ // NOT TO BE IMPLEMENTED
+ nsTPromiseFlatString_CharT() NS_DELETE;
+
+ public:
+
+ explicit
+ nsTPromiseFlatString_CharT( const substring_type& str )
+ : string_type()
+ {
+ Init(str);
+ }
+
+ explicit
+ nsTPromiseFlatString_CharT( const abstract_string_type& readable )
+ : string_type()
+ {
+ Init(readable);
+ }
+
+ explicit
+ nsTPromiseFlatString_CharT( const substring_tuple_type& tuple )
+ : string_type()
+ {
+ // nothing else to do here except assign the value of the tuple
+ // into ourselves.
+ Assign(tuple);
+ }
+ };
+
+inline
+const nsTPromiseFlatString_CharT
+TPromiseFlatString_CharT( const nsTAString_CharT& str )
+ {
+ return nsTPromiseFlatString_CharT(str);
+ }
+
+ // e.g., PromiseFlatCString(Substring(s))
+inline
+const nsTPromiseFlatString_CharT
+TPromiseFlatString_CharT( const nsTSubstring_CharT& frag )
+ {
+ return nsTPromiseFlatString_CharT(frag);
+ }
+
+ // e.g., PromiseFlatCString(a + b)
+inline
+const nsTPromiseFlatString_CharT
+TPromiseFlatString_CharT( const nsTSubstringTuple_CharT& tuple )
+ {
+ return nsTPromiseFlatString_CharT(tuple);
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsTString.h b/src/libs/xpcom18a4/xpcom/string/public/nsTString.h
new file mode 100644
index 00000000..2ef241b2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsTString.h
@@ -0,0 +1,721 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Rick Gessner <rickg@netscape.com> (original author)
+ * Scott Collins <scc@mozilla.org>
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+ /**
+ * This is the canonical null-terminated string class. All subclasses
+ * promise null-terminated storage. Instances of this class allocate
+ * strings on the heap.
+ *
+ * This class is also known as nsAFlat[C]String, where "flat" is used
+ * to denote a null-terminated string.
+ */
+class nsTString_CharT : public nsTSubstring_CharT
+ {
+ public:
+
+ typedef nsTString_CharT self_type;
+
+ public:
+
+ /**
+ * constructors
+ */
+
+ nsTString_CharT()
+ : substring_type() {}
+
+ explicit
+ nsTString_CharT( char_type c )
+ : substring_type()
+ {
+ Assign(c);
+ }
+
+ explicit
+ nsTString_CharT( const char_type* data, size_type length = size_type(-1) )
+ : substring_type()
+ {
+ Assign(data, length);
+ }
+
+ nsTString_CharT( const self_type& str )
+ : substring_type()
+ {
+ Assign(str);
+ }
+
+ nsTString_CharT( const substring_tuple_type& tuple )
+ : substring_type()
+ {
+ Assign(tuple);
+ }
+
+ explicit
+ nsTString_CharT( const abstract_string_type& readable )
+ : substring_type()
+ {
+ Assign(readable);
+ }
+
+
+ // |operator=| does not inherit, so we must define our own
+ self_type& operator=( char_type c ) { Assign(c); return *this; }
+ self_type& operator=( const char_type* data ) { Assign(data); return *this; }
+ self_type& operator=( const self_type& str ) { Assign(str); return *this; }
+ self_type& operator=( const substring_type& str ) { Assign(str); return *this; }
+ self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; }
+ self_type& operator=( const abstract_string_type& readable ) { Assign(readable); return *this; }
+
+
+ /**
+ * returns the null-terminated string
+ */
+
+ const char_type* get() const
+ {
+ return mData;
+ }
+
+
+ /**
+ * returns character at specified index.
+ *
+ * NOTE: unlike nsTSubstring::CharAt, this function allows you to index
+ * the null terminator character.
+ */
+
+ char_type CharAt( index_type i ) const
+ {
+ NS_ASSERTION(i <= mLength, "index exceeds allowable range");
+ return mData[i];
+ }
+
+ char_type operator[]( index_type i ) const
+ {
+ return CharAt(i);
+ }
+
+
+#if MOZ_STRING_WITH_OBSOLETE_API
+
+
+ /**
+ * Search for the given substring within this string.
+ *
+ * @param aString is substring to be sought in this
+ * @param aIgnoreCase selects case sensitivity
+ * @param aOffset tells us where in this string to start searching
+ * @param aCount tells us how far from the offset we are to search. Use
+ * -1 to search the whole string.
+ * @return offset in string, or kNotFound
+ */
+
+ NS_COM PRInt32 Find( const nsCString& aString, PRBool aIgnoreCase=PR_FALSE, PRInt32 aOffset=0, PRInt32 aCount=-1 ) const;
+ NS_COM PRInt32 Find( const char* aString, PRBool aIgnoreCase=PR_FALSE, PRInt32 aOffset=0, PRInt32 aCount=-1 ) const;
+
+#ifdef CharT_is_PRUnichar
+ NS_COM PRInt32 Find( const nsAFlatString& aString, PRInt32 aOffset=0, PRInt32 aCount=-1 ) const;
+ NS_COM PRInt32 Find( const PRUnichar* aString, PRInt32 aOffset=0, PRInt32 aCount=-1 ) const;
+#endif
+
+
+ /**
+ * This methods scans the string backwards, looking for the given string
+ *
+ * @param aString is substring to be sought in this
+ * @param aIgnoreCase tells us whether or not to do caseless compare
+ * @param aOffset tells us where in this string to start searching.
+ * Use -1 to search from the end of the string.
+ * @param aCount tells us how many iterations to make starting at the
+ * given offset.
+ * @return offset in string, or kNotFound
+ */
+
+ NS_COM PRInt32 RFind( const nsCString& aString, PRBool aIgnoreCase=PR_FALSE, PRInt32 aOffset=-1, PRInt32 aCount=-1 ) const;
+ NS_COM PRInt32 RFind( const char* aCString, PRBool aIgnoreCase=PR_FALSE, PRInt32 aOffset=-1, PRInt32 aCount=-1 ) const;
+
+#ifdef CharT_is_PRUnichar
+ NS_COM PRInt32 RFind( const nsAFlatString& aString, PRInt32 aOffset=-1, PRInt32 aCount=-1 ) const;
+ NS_COM PRInt32 RFind( const PRUnichar* aString, PRInt32 aOffset=-1, PRInt32 aCount=-1 ) const;
+#endif
+
+
+ /**
+ * Search for given char within this string
+ *
+ * @param aChar is the character to search for
+ * @param aOffset tells us where in this strig to start searching
+ * @param aCount tells us how far from the offset we are to search.
+ * Use -1 to search the whole string.
+ * @return offset in string, or kNotFound
+ */
+
+ // PRInt32 FindChar( PRUnichar aChar, PRInt32 aOffset=0, PRInt32 aCount=-1 ) const;
+ NS_COM PRInt32 RFindChar( PRUnichar aChar, PRInt32 aOffset=-1, PRInt32 aCount=-1 ) const;
+
+
+ /**
+ * This method searches this string for the first character found in
+ * the given string.
+ *
+ * @param aString contains set of chars to be found
+ * @param aOffset tells us where in this string to start searching
+ * (counting from left)
+ * @return offset in string, or kNotFound
+ */
+
+ NS_COM PRInt32 FindCharInSet( const char* aString, PRInt32 aOffset=0 ) const;
+ PRInt32 FindCharInSet( const self_type& aString, PRInt32 aOffset=0 ) const
+ {
+ return FindCharInSet(aString.get(), aOffset);
+ }
+
+#ifdef CharT_is_PRUnichar
+ NS_COM PRInt32 FindCharInSet( const PRUnichar* aString, PRInt32 aOffset=0 ) const;
+#endif
+
+
+ /**
+ * This method searches this string for the last character found in
+ * the given string.
+ *
+ * @param aString contains set of chars to be found
+ * @param aOffset tells us where in this string to start searching
+ * (counting from left)
+ * @return offset in string, or kNotFound
+ */
+
+ NS_COM PRInt32 RFindCharInSet( const char_type* aString, PRInt32 aOffset=-1 ) const;
+ PRInt32 RFindCharInSet( const self_type& aString, PRInt32 aOffset=-1 ) const
+ {
+ return RFindCharInSet(aString.get(), aOffset);
+ }
+
+
+ /**
+ * Compares a given string to this string.
+ *
+ * @param aString is the string to be compared
+ * @param aIgnoreCase tells us how to treat case
+ * @param aCount tells us how many chars to compare
+ * @return -1,0,1
+ */
+
+#ifdef CharT_is_char
+ NS_COM PRInt32 Compare( const char* aString, PRBool aIgnoreCase=PR_FALSE, PRInt32 aCount=-1 ) const;
+#endif
+
+
+ /**
+ * Equality check between given string and this string.
+ *
+ * @param aString is the string to check
+ * @param aIgnoreCase tells us how to treat case
+ * @param aCount tells us how many chars to compare
+ * @return boolean
+ */
+#ifdef CharT_is_char
+ PRBool EqualsIgnoreCase( const char* aString, PRInt32 aCount=-1 ) const {
+ return Compare(aString, PR_TRUE, aCount) == 0;
+ }
+#else
+ NS_COM PRBool EqualsIgnoreCase( const char* aString, PRInt32 aCount=-1 ) const;
+
+
+ /**
+ * Copies data from internal buffer onto given char* buffer
+ *
+ * NOTE: This only copies as many chars as will fit in given buffer (clips)
+ * @param aBuf is the buffer where data is stored
+ * @param aBuflength is the max # of chars to move to buffer
+ * @param aOffset is the offset to copy from
+ * @return ptr to given buffer
+ */
+
+ NS_COM char* ToCString( char* aBuf, PRUint32 aBufLength, PRUint32 aOffset=0 ) const;
+
+#endif // !CharT_is_PRUnichar
+
+ /**
+ * Perform string to float conversion.
+ *
+ * @param aErrorCode will contain error if one occurs
+ * @return float rep of string value
+ */
+ NS_COM float ToFloat( PRInt32* aErrorCode ) const;
+
+
+ /**
+ * Perform string to int conversion.
+ * @param aErrorCode will contain error if one occurs
+ * @param aRadix tells us which radix to assume; kAutoDetect tells us to determine the radix for you.
+ * @return int rep of string value, and possible (out) error code
+ */
+ NS_COM PRInt32 ToInteger( PRInt32* aErrorCode, PRUint32 aRadix=kRadix10 ) const;
+
+
+ /**
+ * |Left|, |Mid|, and |Right| are annoying signatures that seem better almost
+ * any _other_ way than they are now. Consider these alternatives
+ *
+ * aWritable = aReadable.Left(17); // ...a member function that returns a |Substring|
+ * aWritable = Left(aReadable, 17); // ...a global function that returns a |Substring|
+ * Left(aReadable, 17, aWritable); // ...a global function that does the assignment
+ *
+ * as opposed to the current signature
+ *
+ * aReadable.Left(aWritable, 17); // ...a member function that does the assignment
+ *
+ * or maybe just stamping them out in favor of |Substring|, they are just duplicate functionality
+ *
+ * aWritable = Substring(aReadable, 0, 17);
+ */
+
+ NS_COM size_type Mid( self_type& aResult, PRUint32 aStartPos, PRUint32 aCount ) const;
+
+ size_type Left( self_type& aResult, size_type aCount ) const
+ {
+ return Mid(aResult, 0, aCount);
+ }
+
+ size_type Right( self_type& aResult, size_type aCount ) const
+ {
+ aCount = NS_MIN(mLength, aCount);
+ return Mid(aResult, mLength - aCount, aCount);
+ }
+
+
+ /**
+ * Set a char inside this string at given index
+ *
+ * @param aChar is the char you want to write into this string
+ * @param anIndex is the ofs where you want to write the given char
+ * @return TRUE if successful
+ */
+
+ NS_COM PRBool SetCharAt( PRUnichar aChar, PRUint32 aIndex );
+
+
+ /**
+ * These methods are used to remove all occurances of the
+ * characters found in aSet from this string.
+ *
+ * @param aSet -- characters to be cut from this
+ */
+ NS_COM void StripChars( const char* aSet );
+
+
+ /**
+ * This method is used to remove all occurances of aChar from this
+ * string.
+ *
+ * @param aChar -- char to be stripped
+ * @param aOffset -- where in this string to start stripping chars
+ */
+
+ NS_COM void StripChar( char_type aChar, PRInt32 aOffset=0 );
+
+
+ /**
+ * This method strips whitespace throughout the string.
+ */
+ NS_COM void StripWhitespace();
+
+
+ /**
+ * swaps occurence of 1 string for another
+ */
+
+ NS_COM void ReplaceChar( char_type aOldChar, char_type aNewChar );
+ NS_COM void ReplaceChar( const char* aSet, char_type aNewChar );
+ NS_COM void ReplaceSubstring( const self_type& aTarget, const self_type& aNewValue);
+ NS_COM void ReplaceSubstring( const char_type* aTarget, const char_type* aNewValue);
+
+
+ /**
+ * This method trims characters found in aTrimSet from
+ * either end of the underlying string.
+ *
+ * @param aSet -- contains chars to be trimmed from both ends
+ * @param aEliminateLeading
+ * @param aEliminateTrailing
+ * @param aIgnoreQuotes -- if true, causes surrounding quotes to be ignored
+ * @return this
+ */
+ NS_COM void Trim( const char* aSet, PRBool aEliminateLeading=PR_TRUE, PRBool aEliminateTrailing=PR_TRUE, PRBool aIgnoreQuotes=PR_FALSE );
+
+ /**
+ * This method strips whitespace from string.
+ * You can control whether whitespace is yanked from start and end of
+ * string as well.
+ *
+ * @param aEliminateLeading controls stripping of leading ws
+ * @param aEliminateTrailing controls stripping of trailing ws
+ */
+ NS_COM void CompressWhitespace( PRBool aEliminateLeading=PR_TRUE, PRBool aEliminateTrailing=PR_TRUE );
+
+
+ /**
+ * assign/append/insert with _LOSSY_ conversion
+ */
+
+ NS_COM void AssignWithConversion( const nsTAString_IncompatibleCharT& aString );
+ NS_COM void AssignWithConversion( const incompatible_char_type* aData, PRInt32 aLength=-1 );
+
+ NS_COM void AppendWithConversion( const nsTAString_IncompatibleCharT& aString );
+ NS_COM void AppendWithConversion( const incompatible_char_type* aData, PRInt32 aLength=-1 );
+
+ /**
+ * Append the given integer to this string
+ */
+ NS_COM void AppendInt( PRInt32 aInteger, PRInt32 aRadix=kRadix10 ); //radix=8,10 or 16
+
+ /**
+ * Append the given unsigned integer to this string
+ */
+ inline void AppendInt( PRUint32 aInteger, PRInt32 aRadix = kRadix10 )
+ {
+ AppendInt(PRInt32(aInteger), aRadix);
+ }
+
+ /**
+ * Append the given 64-bit integer to this string.
+ * @param aInteger The integer to append
+ * @param aRadix The radix to use; can be 8, 10 or 16.
+ */
+ NS_COM void AppendInt( PRInt64 aInteger, PRInt32 aRadix=kRadix10 );
+
+ /**
+ * Append the given float to this string
+ */
+
+ NS_COM void AppendFloat( double aFloat );
+
+#endif // !MOZ_STRING_WITH_OBSOLETE_API
+
+
+ protected:
+
+ explicit
+ nsTString_CharT( PRUint32 flags )
+ : substring_type(flags) {}
+
+ // allow subclasses to initialize fields directly
+ nsTString_CharT( char_type* data, size_type length, PRUint32 flags )
+ : substring_type(data, length, flags) {}
+ };
+
+
+class nsTFixedString_CharT : public nsTString_CharT
+ {
+ public:
+
+ typedef nsTFixedString_CharT self_type;
+ typedef nsTFixedString_CharT fixed_string_type;
+
+ public:
+
+ /**
+ * @param data
+ * fixed-size buffer to be used by the string (the contents of
+ * this buffer may be modified by the string)
+ * @param storageSize
+ * the size of the fixed buffer
+ * @param length (optional)
+ * the length of the string already contained in the buffer
+ */
+
+ nsTFixedString_CharT( char_type* data, size_type storageSize )
+ : string_type(data, char_traits::length(data), F_TERMINATED | F_FIXED | F_CLASS_FIXED)
+ , mFixedCapacity(storageSize - 1)
+ , mFixedBuf(data)
+ {}
+
+ nsTFixedString_CharT( char_type* data, size_type storageSize, size_type length )
+ : string_type(data, length, F_TERMINATED | F_FIXED | F_CLASS_FIXED)
+ , mFixedCapacity(storageSize - 1)
+ , mFixedBuf(data)
+ {
+ // null-terminate
+ mFixedBuf[length] = char_type(0);
+ }
+
+ // |operator=| does not inherit, so we must define our own
+ self_type& operator=( char_type c ) { Assign(c); return *this; }
+ self_type& operator=( const char_type* data ) { Assign(data); return *this; }
+ self_type& operator=( const substring_type& str ) { Assign(str); return *this; }
+ self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; }
+ self_type& operator=( const abstract_string_type& readable ) { Assign(readable); return *this; }
+
+ protected:
+
+ friend class nsTSubstring_CharT;
+
+ size_type mFixedCapacity;
+ char_type *mFixedBuf;
+ };
+
+
+ /**
+ * nsTAutoString_CharT
+ *
+ * Subclass of nsTString_CharT that adds support for stack-based string
+ * allocation. Do not allocate this class on the heap! ;-)
+ */
+class nsTAutoString_CharT : public nsTFixedString_CharT
+ {
+ public:
+
+ typedef nsTAutoString_CharT self_type;
+
+ public:
+
+ /**
+ * constructors
+ */
+
+ nsTAutoString_CharT()
+ : fixed_string_type(mStorage, kDefaultStorageSize, 0)
+ {}
+
+ explicit
+ nsTAutoString_CharT( char_type c )
+ : fixed_string_type(mStorage, kDefaultStorageSize, 0)
+ {
+ Assign(c);
+ }
+
+ explicit
+ nsTAutoString_CharT( const char_type* data, size_type length = size_type(-1) )
+ : fixed_string_type(mStorage, kDefaultStorageSize, 0)
+ {
+ Assign(data, length);
+ }
+
+ nsTAutoString_CharT( const self_type& str )
+ : fixed_string_type(mStorage, kDefaultStorageSize, 0)
+ {
+ Assign(str);
+ }
+
+ explicit
+ nsTAutoString_CharT( const substring_type& str )
+ : fixed_string_type(mStorage, kDefaultStorageSize, 0)
+ {
+ Assign(str);
+ }
+
+ nsTAutoString_CharT( const substring_tuple_type& tuple )
+ : fixed_string_type(mStorage, kDefaultStorageSize, 0)
+ {
+ Assign(tuple);
+ }
+
+ explicit
+ nsTAutoString_CharT( const abstract_string_type& readable )
+ : fixed_string_type(mStorage, kDefaultStorageSize, 0)
+ {
+ Assign(readable);
+ }
+
+ // |operator=| does not inherit, so we must define our own
+ self_type& operator=( char_type c ) { Assign(c); return *this; }
+ self_type& operator=( const char_type* data ) { Assign(data); return *this; }
+ self_type& operator=( const self_type& str ) { Assign(str); return *this; }
+ self_type& operator=( const substring_type& str ) { Assign(str); return *this; }
+ self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; }
+ self_type& operator=( const abstract_string_type& readable ) { Assign(readable); return *this; }
+
+ enum { kDefaultStorageSize = 64 };
+
+ private:
+
+ char_type mStorage[kDefaultStorageSize];
+ };
+
+
+ /**
+ * nsTXPIDLString extends nsTString such that:
+ *
+ * (1) mData can be null
+ * (2) objects of this type can be automatically cast to |const CharT*|
+ * (3) getter_Copies method is supported to adopt data
+ */
+class nsTXPIDLString_CharT : public nsTString_CharT
+ {
+ public:
+
+ typedef nsTXPIDLString_CharT self_type;
+
+ public:
+
+ nsTXPIDLString_CharT()
+ : string_type(NS_CONST_CAST(char_type*, char_traits::sEmptyBuffer), 0, F_TERMINATED | F_VOIDED) {}
+
+ // copy-constructor required to avoid default
+ nsTXPIDLString_CharT( const self_type& str )
+ : string_type(NS_CONST_CAST(char_type*, char_traits::sEmptyBuffer), 0, F_TERMINATED | F_VOIDED)
+ {
+ Assign(str);
+ }
+
+ // return nsnull if we are voided
+ const char_type* get() const
+ {
+ return (mFlags & F_VOIDED) ? nsnull : mData;
+ }
+
+ // this case operator is the reason why this class cannot just be a
+ // typedef for nsTString
+ operator const char_type*() const
+ {
+ return get();
+ }
+
+ // need this to diambiguous operator[int]
+ char_type operator[]( PRInt32 i ) const
+ {
+ return CharAt(index_type(i));
+ }
+
+ // |operator=| does not inherit, so we must define our own
+ self_type& operator=( char_type c ) { Assign(c); return *this; }
+ self_type& operator=( const char_type* data ) { Assign(data); return *this; }
+ self_type& operator=( const self_type& str ) { Assign(str); return *this; }
+ self_type& operator=( const substring_type& str ) { Assign(str); return *this; }
+ self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; }
+ self_type& operator=( const abstract_string_type& readable ) { Assign(readable); return *this; }
+ };
+
+
+ /**
+ * getter_Copies support for use with raw string out params:
+ *
+ * NS_IMETHOD GetBlah(char**);
+ *
+ * void some_function()
+ * {
+ * nsXPIDLCString blah;
+ * GetBlah(getter_Copies(blah));
+ * // ...
+ * }
+ */
+class nsTGetterCopies_CharT
+ {
+ public:
+ typedef CharT char_type;
+
+ nsTGetterCopies_CharT(nsTXPIDLString_CharT& str)
+ : mString(str), mData(nsnull) {}
+
+ ~nsTGetterCopies_CharT()
+ {
+ mString.Adopt(mData); // OK if mData is null
+ }
+
+ operator char_type**()
+ {
+ return &mData;
+ }
+
+ private:
+ nsTXPIDLString_CharT& mString;
+ char_type* mData;
+ };
+
+inline
+nsTGetterCopies_CharT
+getter_Copies( nsTXPIDLString_CharT& aString )
+ {
+ return nsTGetterCopies_CharT(aString);
+ }
+
+
+ /**
+ * nsTAdoptingString extends nsTXPIDLString such that:
+ *
+ * (1) Adopt given string on construction or assignment, i.e. take
+ * the value of what's given, and make what's given forget its
+ * value. Note that this class violates constness in a few
+ * places. Be careful!
+ */
+class nsTAdoptingString_CharT : public nsTXPIDLString_CharT
+ {
+ public:
+
+ typedef nsTAdoptingString_CharT self_type;
+
+ public:
+
+ explicit nsTAdoptingString_CharT() {}
+ explicit nsTAdoptingString_CharT(char_type* str, size_type length = size_type(-1))
+ {
+ Adopt(str, length);
+ }
+
+ // copy-constructor required to adopt on copy. Note that this
+ // will violate the constness of |str| in the operator=()
+ // call. |str| will be truncated as a side-effect of this
+ // constructor.
+ nsTAdoptingString_CharT( const self_type& str )
+#ifdef VBOX /* bird: shut up annoying warnings */
+ : nsTXPIDLString_CharT()
+#endif
+ {
+ *this = str;
+ }
+
+ // |operator=| does not inherit, so we must define our own
+ self_type& operator=( const substring_type& str ) { Assign(str); return *this; }
+ self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; }
+ self_type& operator=( const abstract_string_type& readable ) { Assign(readable); return *this; }
+
+ // Adopt(), if possible, when assigning to a self_type&. Note
+ // that this violates the constness of str, str is always
+ // truncated when this operator is called.
+ NS_COM self_type& operator=( const self_type& str );
+
+ private:
+ // NOT TO BE IMPLEMENTED.
+ self_type& operator=( const char_type* data );
+ self_type& operator=( char_type* data );
+ };
+
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsTSubstring.h b/src/libs/xpcom18a4/xpcom/string/public/nsTSubstring.h
new file mode 100644
index 00000000..aaaf5a64
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsTSubstring.h
@@ -0,0 +1,575 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+ /**
+ * nsTSubstring
+ *
+ * The base string type. This type is not instantiated directly. A sub-
+ * class is instantiated instead. For example, see nsTString.
+ *
+ * This type works like nsTAString except that it does not have the ABI
+ * requirements of that interface. Like nsTAString, nsTSubstring
+ * represents a single contiguous array of characters that may or may not
+ * be null-terminated.
+ *
+ * Many of the accessors on nsTSubstring are inlined as an optimization.
+ *
+ * This class is also known as "nsASingleFragmentC?String".
+ */
+class nsTSubstring_CharT : public nsTAString_CharT
+ {
+ public:
+
+ typedef nsTSubstring_CharT self_type;
+ typedef nsTString_CharT string_type;
+
+ typedef char_type* char_iterator;
+ typedef const char_type* const_char_iterator;
+
+ public:
+
+ /**
+ * reading iterators
+ */
+
+ const_char_iterator BeginReading() const { return mData; }
+ const_char_iterator EndReading() const { return mData + mLength; }
+
+ /**
+ * deprecated reading iterators
+ */
+
+ const_iterator& BeginReading( const_iterator& iter ) const
+ {
+ iter.mStart = mData;
+ iter.mEnd = mData + mLength;
+ iter.mPosition = iter.mStart;
+ return iter;
+ }
+
+ const_iterator& EndReading( const_iterator& iter ) const
+ {
+ iter.mStart = mData;
+ iter.mEnd = mData + mLength;
+ iter.mPosition = iter.mEnd;
+ return iter;
+ }
+
+ const_char_iterator& BeginReading( const_char_iterator& iter ) const
+ {
+ return iter = mData;
+ }
+
+ const_char_iterator& EndReading( const_char_iterator& iter ) const
+ {
+ return iter = mData + mLength;
+ }
+
+
+ /**
+ * writing iterators
+ */
+
+ char_iterator BeginWriting() { EnsureMutable(); return mData; }
+ char_iterator EndWriting() { EnsureMutable(); return mData + mLength; }
+
+ /**
+ * deprecated writing iterators
+ */
+
+ iterator& BeginWriting( iterator& iter )
+ {
+ EnsureMutable();
+ iter.mStart = mData;
+ iter.mEnd = mData + mLength;
+ iter.mPosition = iter.mStart;
+ return iter;
+ }
+
+ iterator& EndWriting( iterator& iter )
+ {
+ EnsureMutable();
+ iter.mStart = mData;
+ iter.mEnd = mData + mLength;
+ iter.mPosition = iter.mEnd;
+ return iter;
+ }
+
+ char_iterator& BeginWriting( char_iterator& iter )
+ {
+ EnsureMutable();
+ return iter = mData;
+ }
+
+ char_iterator& EndWriting( char_iterator& iter )
+ {
+ EnsureMutable();
+ return iter = mData + mLength;
+ }
+
+
+ /**
+ * accessors
+ */
+
+ // returns pointer to string data (not necessarily null-terminated)
+ const char_type *Data() const
+ {
+ return mData;
+ }
+
+ size_type Length() const
+ {
+ return mLength;
+ }
+
+ PRBool IsEmpty() const
+ {
+ return mLength == 0;
+ }
+
+ PRBool IsVoid() const
+ {
+ return mFlags & F_VOIDED;
+ }
+
+ PRBool IsTerminated() const
+ {
+ return mFlags & F_TERMINATED;
+ }
+
+ char_type CharAt( index_type i ) const
+ {
+ NS_ASSERTION(i < mLength, "index exceeds allowable range");
+ return mData[i];
+ }
+
+ char_type operator[]( index_type i ) const
+ {
+ return CharAt(i);
+ }
+
+ char_type First() const
+ {
+ NS_ASSERTION(mLength > 0, "|First()| called on an empty string");
+ return mData[0];
+ }
+
+ inline
+ char_type Last() const
+ {
+ NS_ASSERTION(mLength > 0, "|Last()| called on an empty string");
+ return mData[mLength - 1];
+ }
+
+ NS_COM size_type NS_FASTCALL CountChar( char_type ) const;
+ NS_COM PRInt32 NS_FASTCALL FindChar( char_type, index_type offset = 0 ) const;
+
+
+ /**
+ * equality
+ */
+
+ NS_COM PRBool NS_FASTCALL Equals( const self_type& ) const;
+ NS_COM PRBool NS_FASTCALL Equals( const self_type&, const comparator_type& ) const;
+
+ NS_COM PRBool NS_FASTCALL Equals( const abstract_string_type& readable ) const;
+ NS_COM PRBool NS_FASTCALL Equals( const abstract_string_type& readable, const comparator_type& comp ) const;
+
+ NS_COM PRBool NS_FASTCALL Equals( const char_type* data ) const;
+ NS_COM PRBool NS_FASTCALL Equals( const char_type* data, const comparator_type& comp ) const;
+
+ /**
+ * An efficient comparison with ASCII that can be used even
+ * for wide strings. Call this version when you know the
+ * length of 'data'.
+ */
+ NS_COM PRBool NS_FASTCALL EqualsASCII( const char* data, size_type len ) const;
+ /**
+ * An efficient comparison with ASCII that can be used even
+ * for wide strings. Call this version when 'data' is
+ * null-terminated.
+ */
+ NS_COM PRBool NS_FASTCALL EqualsASCII( const char* data ) const;
+
+ // EqualsLiteral must ONLY be applied to an actual literal string.
+ // Do not attempt to use it with a regular char* pointer, or with a char
+ // array variable.
+ // The template trick to acquire the array length at compile time without
+ // using a macro is due to Corey Kosak, with much thanks.
+#ifdef NS_DISABLE_LITERAL_TEMPLATE
+ inline PRBool EqualsLiteral( const char* str ) const
+ {
+ return EqualsASCII(str);
+ }
+#else
+ template<int N>
+ inline PRBool EqualsLiteral( const char (&str)[N] ) const
+ {
+ return EqualsASCII(str, N-1);
+ }
+ template<int N>
+ inline PRBool EqualsLiteral( char (&str)[N] ) const
+ {
+ const char* s = str;
+ return EqualsASCII(s, N-1);
+ }
+#endif
+
+ // The LowerCaseEquals methods compare the lower case version of
+ // this string to some ASCII/Literal string. The ASCII string is
+ // *not* lowercased for you. If you compare to an ASCII or literal
+ // string that contains an uppercase character, it is guaranteed to
+ // return false. We will throw assertions too.
+ NS_COM PRBool NS_FASTCALL LowerCaseEqualsASCII( const char* data, size_type len ) const;
+ NS_COM PRBool NS_FASTCALL LowerCaseEqualsASCII( const char* data ) const;
+
+ // LowerCaseEqualsLiteral must ONLY be applied to an actual
+ // literal string. Do not attempt to use it with a regular char*
+ // pointer, or with a char array variable. Use
+ // LowerCaseEqualsASCII for them.
+#ifdef NS_DISABLE_LITERAL_TEMPLATE
+ inline PRBool LowerCaseEqualsLiteral( const char* str ) const
+ {
+ return LowerCaseEqualsASCII(str);
+ }
+#else
+ template<int N>
+ inline PRBool LowerCaseEqualsLiteral( const char (&str)[N] ) const
+ {
+ return LowerCaseEqualsASCII(str, N-1);
+ }
+ template<int N>
+ inline PRBool LowerCaseEqualsLiteral( char (&str)[N] ) const
+ {
+ const char* s = str;
+ return LowerCaseEqualsASCII(s, N-1);
+ }
+#endif
+
+ /**
+ * assignment
+ */
+
+ void Assign( char_type c ) { Assign(&c, 1); }
+ NS_COM void NS_FASTCALL Assign( const char_type* data, size_type length = size_type(-1) );
+ NS_COM void NS_FASTCALL Assign( const self_type& );
+ NS_COM void NS_FASTCALL Assign( const substring_tuple_type& );
+ NS_COM void NS_FASTCALL Assign( const abstract_string_type& );
+
+ NS_COM void NS_FASTCALL AssignASCII( const char* data, size_type length );
+ NS_COM void NS_FASTCALL AssignASCII( const char* data );
+
+ // AssignLiteral must ONLY be applied to an actual literal string.
+ // Do not attempt to use it with a regular char* pointer, or with a char
+ // array variable. Use AssignASCII for those.
+#ifdef NS_DISABLE_LITERAL_TEMPLATE
+ void AssignLiteral( const char* str )
+ { AssignASCII(str); }
+#else
+ template<int N>
+ void AssignLiteral( const char (&str)[N] )
+ { AssignASCII(str, N-1); }
+ template<int N>
+ void AssignLiteral( char (&str)[N] )
+ { AssignASCII(str, N-1); }
+#endif
+
+ self_type& operator=( char_type c ) { Assign(c); return *this; }
+ self_type& operator=( const char_type* data ) { Assign(data); return *this; }
+ self_type& operator=( const self_type& str ) { Assign(str); return *this; }
+ self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; }
+ self_type& operator=( const abstract_string_type& readable ) { Assign(readable); return *this; }
+
+ NS_COM void NS_FASTCALL Adopt( char_type* data, size_type length = size_type(-1) );
+
+
+ /**
+ * buffer manipulation
+ */
+
+ void Replace( index_type cutStart, size_type cutLength, char_type c ) { Replace(cutStart, cutLength, &c, 1); }
+ NS_COM void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, const char_type* data, size_type length = size_type(-1) );
+ void Replace( index_type cutStart, size_type cutLength, const self_type& str ) { Replace(cutStart, cutLength, str.Data(), str.Length()); }
+ NS_COM void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, const substring_tuple_type& tuple );
+ NS_COM void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, const abstract_string_type& readable );
+
+ NS_COM void NS_FASTCALL ReplaceASCII( index_type cutStart, size_type cutLength, const char* data, size_type length = size_type(-1) );
+
+ void Append( char_type c ) { Replace(mLength, 0, c); }
+ void Append( const char_type* data, size_type length = size_type(-1) ) { Replace(mLength, 0, data, length); }
+ void Append( const self_type& str ) { Replace(mLength, 0, str); }
+ void Append( const substring_tuple_type& tuple ) { Replace(mLength, 0, tuple); }
+ void Append( const abstract_string_type& readable ) { Replace(mLength, 0, readable); }
+
+ void AppendASCII( const char* data, size_type length = size_type(-1) ) { ReplaceASCII(mLength, 0, data, length); }
+
+ // AppendLiteral must ONLY be applied to an actual literal string.
+ // Do not attempt to use it with a regular char* pointer, or with a char
+ // array variable. Use AppendASCII for those.
+#ifdef NS_DISABLE_LITERAL_TEMPLATE
+ void AppendLiteral( const char* str )
+ { AppendASCII(str); }
+#else
+ template<int N>
+ void AppendLiteral( const char (&str)[N] )
+ { AppendASCII(str, N-1); }
+ template<int N>
+ void AppendLiteral( char (&str)[N] )
+ { AppendASCII(str, N-1); }
+#endif
+
+ self_type& operator+=( char_type c ) { Append(c); return *this; }
+ self_type& operator+=( const char_type* data ) { Append(data); return *this; }
+ self_type& operator+=( const self_type& str ) { Append(str); return *this; }
+ self_type& operator+=( const substring_tuple_type& tuple ) { Append(tuple); return *this; }
+ self_type& operator+=( const abstract_string_type& readable ) { Append(readable); return *this; }
+
+ void Insert( char_type c, index_type pos ) { Replace(pos, 0, c); }
+ void Insert( const char_type* data, index_type pos, size_type length = size_type(-1) ) { Replace(pos, 0, data, length); }
+ void Insert( const self_type& str, index_type pos ) { Replace(pos, 0, str); }
+ void Insert( const substring_tuple_type& tuple, index_type pos ) { Replace(pos, 0, tuple); }
+ void Insert( const abstract_string_type& readable, index_type pos ) { Replace(pos, 0, readable); }
+
+ void Cut( index_type cutStart, size_type cutLength ) { Replace(cutStart, cutLength, char_traits::sEmptyBuffer, 0); }
+
+
+ /**
+ * buffer sizing
+ */
+
+ NS_COM void NS_FASTCALL SetCapacity( size_type capacity );
+
+ NS_COM void NS_FASTCALL SetLength( size_type );
+
+ void Truncate( size_type newLength = 0 )
+ {
+ NS_ASSERTION(newLength <= mLength, "Truncate cannot make string longer");
+ SetLength(newLength);
+ }
+
+
+ /**
+ * string data is never null, but can be marked void. if true, the
+ * string will be truncated. @see nsTSubstring::IsVoid
+ */
+
+ NS_COM void NS_FASTCALL SetIsVoid( PRBool );
+
+
+ public:
+
+ /**
+ * this is public to support automatic conversion of tuple to string
+ * base type, which helps avoid converting to nsTAString.
+ */
+ nsTSubstring_CharT(const substring_tuple_type& tuple)
+ : abstract_string_type(nsnull, 0, F_NONE)
+ {
+ Assign(tuple);
+ }
+
+ protected:
+
+ friend class nsTObsoleteAStringThunk_CharT;
+ friend class nsTAString_CharT;
+ friend class nsTSubstringTuple_CharT;
+
+ // XXX GCC 3.4 needs this :-(
+ friend class nsTPromiseFlatString_CharT;
+
+ // default initialization
+ nsTSubstring_CharT()
+ : abstract_string_type(
+ NS_CONST_CAST(char_type*, char_traits::sEmptyBuffer), 0, F_TERMINATED) {}
+
+ // allow subclasses to initialize fields directly
+ nsTSubstring_CharT( char_type *data, size_type length, PRUint32 flags )
+ : abstract_string_type(data, length, flags) {}
+
+ // version of constructor that leaves mData and mLength uninitialized
+ explicit
+ nsTSubstring_CharT( PRUint32 flags )
+ : abstract_string_type(flags) {}
+
+ // copy-constructor, constructs as dependent on given object
+ // (NOTE: this is for internal use only)
+ nsTSubstring_CharT( const self_type& str )
+ : abstract_string_type(
+ str.mData, str.mLength, str.mFlags & (F_TERMINATED | F_VOIDED)) {}
+
+ /**
+ * this function releases mData and does not change the value of
+ * any of its member variables. inotherwords, this function acts
+ * like a destructor.
+ */
+ void NS_FASTCALL Finalize();
+
+ /**
+ * this function prepares mData to be mutated.
+ *
+ * @param capacity specifies the required capacity of mData
+ * @param old_data returns null or the old value of mData
+ * @param old_flags returns 0 or the old value of mFlags
+ *
+ * if mData is already mutable and of sufficient capacity, then this
+ * function will return immediately. otherwise, it will either resize
+ * mData or allocate a new shared buffer. if it needs to allocate a
+ * new buffer, then it will return the old buffer and the corresponding
+ * flags. this allows the caller to decide when to free the old data.
+ *
+ * XXX we should expose a way for subclasses to free old_data.
+ */
+ PRBool NS_FASTCALL MutatePrep( size_type capacity, char_type** old_data, PRUint32* old_flags );
+
+ /**
+ * this function prepares a section of mData to be modified. if
+ * necessary, this function will reallocate mData and possibly move
+ * existing data to open up the specified section.
+ *
+ * @param cutStart specifies the starting offset of the section
+ * @param cutLength specifies the length of the section to be replaced
+ * @param newLength specifies the length of the new section
+ *
+ * for example, suppose mData contains the string "abcdef" then
+ *
+ * ReplacePrep(2, 3, 4);
+ *
+ * would cause mData to look like "ab____f" where the characters
+ * indicated by '_' have an unspecified value and can be freely
+ * modified. this function will null-terminate mData upon return.
+ */
+ void NS_FASTCALL ReplacePrep( index_type cutStart, size_type cutLength, size_type newLength );
+
+ /**
+ * returns the number of writable storage units starting at mData.
+ * the value does not include space for the null-terminator character.
+ *
+ * NOTE: this function returns size_type(-1) if mData is immutable.
+ */
+ size_type NS_FASTCALL Capacity() const;
+
+ /**
+ * this helper function can be called prior to directly manipulating
+ * the contents of mData. see, for example, BeginWriting.
+ */
+ NS_COM void NS_FASTCALL EnsureMutable();
+
+ /**
+ * returns true if this string overlaps with the given string fragment.
+ */
+ PRBool IsDependentOn( const char_type *start, const char_type *end ) const
+ {
+ /**
+ * if it _isn't_ the case that one fragment starts after the other ends,
+ * or ends before the other starts, then, they conflict:
+ *
+ * !(f2.begin >= f1.end || f2.end <= f1.begin)
+ *
+ * Simplified, that gives us:
+ */
+ return ( start < (mData + mLength) && end > mData );
+ }
+
+ /**
+ * this helper function stores the specified dataFlags in mFlags
+ */
+ void SetDataFlags(PRUint32 dataFlags)
+ {
+ NS_ASSERTION((dataFlags & 0xFFFF0000) == 0, "bad flags");
+ mFlags = dataFlags | (mFlags & 0xFFFF0000);
+ }
+
+ public:
+
+ // mFlags is a bitwise combination of the following flags. the meaning
+ // and interpretation of these flags is an implementation detail.
+ //
+ // NOTE: these flags are declared public _only_ for convenience inside
+ // the string implementation.
+
+ enum
+ {
+ F_NONE = 0, // no flags
+
+ // data flags are in the lower 16-bits
+ F_TERMINATED = 1 << 0, // IsTerminated returns true
+ F_VOIDED = 1 << 1, // IsVoid returns true
+ F_SHARED = 1 << 2, // mData points to a heap-allocated, shared buffer
+ F_OWNED = 1 << 3, // mData points to a heap-allocated, raw buffer
+ F_FIXED = 1 << 4, // mData points to a fixed-size writable, dependent buffer
+
+ // class flags are in the upper 16-bits
+ F_CLASS_FIXED = 1 << 16 // indicates that |this| is of type nsTFixedString
+ };
+
+ //
+ // Some terminology:
+ //
+ // "dependent buffer" A dependent buffer is one that the string class
+ // does not own. The string class relies on some
+ // external code to ensure the lifetime of the
+ // dependent buffer.
+ //
+ // "shared buffer" A shared buffer is one that the string class
+ // allocates. When it allocates a shared string
+ // buffer, it allocates some additional space at
+ // the beginning of the buffer for additional
+ // fields, including a reference count and a
+ // buffer length. See nsStringHeader.
+ //
+ // "adopted buffer" An adopted buffer is a raw string buffer
+ // allocated on the heap (using nsMemory::Alloc)
+ // of which the string class subsumes ownership.
+ //
+ // Some comments about the string flags:
+ //
+ // F_SHARED, F_OWNED, and F_FIXED are all mutually exlusive. They
+ // indicate the allocation type of mData. If none of these flags
+ // are set, then the string buffer is dependent.
+ //
+ // F_SHARED, F_OWNED, or F_FIXED imply F_TERMINATED. This is because
+ // the string classes always allocate null-terminated buffers, and
+ // non-terminated substrings are always dependent.
+ //
+ // F_VOIDED implies F_TERMINATED, and moreover it implies that mData
+ // points to char_traits::sEmptyBuffer. Therefore, F_VOIDED is
+ // mutually exclusive with F_SHARED, F_OWNED, and F_FIXED.
+ //
+ };
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsTSubstringTuple.h b/src/libs/xpcom18a4/xpcom/string/public/nsTSubstringTuple.h
new file mode 100644
index 00000000..2ded17d5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsTSubstringTuple.h
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+ /**
+ * nsTSubstringTuple_CharT
+ *
+ * Represents a tuple of string fragments. Built as a recursive binary tree.
+ * It is used to implement the concatenation of two or more string objects.
+ *
+ * NOTE: This class is a private implementation detail and should never be
+ * referenced outside the string code.
+ */
+class nsTSubstringTuple_CharT
+ {
+ public:
+
+ typedef CharT char_type;
+ typedef nsCharTraits<char_type> char_traits;
+
+ typedef nsTSubstringTuple_CharT self_type;
+ typedef nsTSubstring_CharT substring_type;
+ typedef nsTString_CharT string_type;
+ typedef nsTAString_CharT abstract_string_type;
+ typedef nsTObsoleteAString_CharT obsolete_string_type;
+
+ typedef PRUint32 size_type;
+
+ public:
+
+ nsTSubstringTuple_CharT(const abstract_string_type* a, const abstract_string_type* b)
+ : mHead(nsnull)
+ , mFragA(a)
+ , mFragB(b) {}
+
+ nsTSubstringTuple_CharT(const self_type& head, const abstract_string_type* b)
+ : mHead(&head)
+ , mFragA(nsnull) // this fragment is ignored when head != nsnull
+ , mFragB(b) {}
+
+ /**
+ * computes the aggregate string length
+ */
+ NS_COM size_type Length() const;
+
+ /**
+ * writes the aggregate string to the given buffer. bufLen is assumed
+ * to be equal to or greater than the value returned by the Length()
+ * method. the string written to |buf| is not null-terminated.
+ */
+ NS_COM void WriteTo(char_type *buf, PRUint32 bufLen) const;
+
+ /**
+ * returns true if this tuple is dependent on (i.e., overlapping with)
+ * the given char sequence.
+ */
+ NS_COM PRBool IsDependentOn(const char_type *start, const char_type *end) const;
+
+ private:
+
+ const self_type* mHead;
+ const abstract_string_type* mFragA;
+ const abstract_string_type* mFragB;
+ };
+
+inline
+const nsTSubstringTuple_CharT
+operator+(const nsTAString_CharT& a, const nsTAString_CharT& b)
+ {
+ return nsTSubstringTuple_CharT(&a, &b);
+ }
+
+inline
+const nsTSubstringTuple_CharT
+operator+(const nsTSubstringTuple_CharT& head, const nsTAString_CharT& b)
+ {
+ return nsTSubstringTuple_CharT(head, &b);
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsUTF8Utils.h b/src/libs/xpcom18a4/xpcom/string/public/nsUTF8Utils.h
new file mode 100644
index 00000000..c91079c2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsUTF8Utils.h
@@ -0,0 +1,462 @@
+/* -*- 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) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Peter Annema <jaggernaut@netscape.com> (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 nsUTF8Utils_h_
+#define nsUTF8Utils_h_
+
+class UTF8traits
+ {
+ public:
+ static PRBool isASCII(char c) { return (c & 0x80) == 0x00; }
+ static PRBool isInSeq(char c) { return (c & 0xC0) == 0x80; }
+ static PRBool is2byte(char c) { return (c & 0xE0) == 0xC0; }
+ static PRBool is3byte(char c) { return (c & 0xF0) == 0xE0; }
+ static PRBool is4byte(char c) { return (c & 0xF8) == 0xF0; }
+ static PRBool is5byte(char c) { return (c & 0xFC) == 0xF8; }
+ static PRBool is6byte(char c) { return (c & 0xFE) == 0xFC; }
+ };
+
+#define PLANE1_BASE 0x00010000
+#define UCS2_REPLACEMENT_CHAR 0xfffd
+
+#ifdef __GNUC__
+#define NS_ALWAYS_INLINE __attribute__((always_inline))
+#else
+#define NS_ALWAYS_INLINE
+#endif
+
+/**
+ * A character sink (see |copy_string| in nsAlgorithm.h) for converting
+ * UTF-8 to UTF-16
+ */
+class ConvertUTF8toUTF16
+ {
+ public:
+ typedef nsACString::char_type value_type;
+ typedef nsAString::char_type buffer_type;
+
+ ConvertUTF8toUTF16( buffer_type* aBuffer )
+ : mStart(aBuffer), mBuffer(aBuffer), mErrorEncountered(PR_FALSE) {}
+
+ size_t Length() const { return mBuffer - mStart; }
+
+ PRUint32 NS_ALWAYS_INLINE write( const value_type* start, PRUint32 N )
+ {
+ if ( mErrorEncountered )
+ return N;
+
+ // algorithm assumes utf8 units won't
+ // be spread across fragments
+ const value_type* p = start;
+ const value_type* end = start + N;
+ buffer_type* out = mBuffer;
+ for ( ; p != end /* && *p */; )
+ {
+ char c = *p++;
+
+ if ( UTF8traits::isASCII(c) )
+ {
+ *out++ = buffer_type(c);
+ continue;
+ }
+
+ PRUint32 ucs4;
+ PRUint32 minUcs4;
+ PRInt32 state = 0;
+
+ if ( UTF8traits::is2byte(c) )
+ {
+ ucs4 = (PRUint32(c) << 6) & 0x000007C0L;
+ state = 1;
+ minUcs4 = 0x00000080;
+ }
+ else if ( UTF8traits::is3byte(c) )
+ {
+ ucs4 = (PRUint32(c) << 12) & 0x0000F000L;
+ state = 2;
+ minUcs4 = 0x00000800;
+ }
+ else if ( UTF8traits::is4byte(c) )
+ {
+ ucs4 = (PRUint32(c) << 18) & 0x001F0000L;
+ state = 3;
+ minUcs4 = 0x00010000;
+ }
+ else if ( UTF8traits::is5byte(c) )
+ {
+ ucs4 = (PRUint32(c) << 24) & 0x03000000L;
+ state = 4;
+ minUcs4 = 0x00200000;
+ }
+ else if ( UTF8traits::is6byte(c) )
+ {
+ ucs4 = (PRUint32(c) << 30) & 0x40000000L;
+ state = 5;
+ minUcs4 = 0x04000000;
+ }
+ else
+ {
+ NS_ERROR("Not a UTF-8 string. This code should only be used for converting from known UTF-8 strings.");
+ mErrorEncountered = PR_TRUE;
+ mBuffer = out;
+ return N;
+ }
+
+ while ( state-- )
+ {
+ c = *p++;
+
+ if ( UTF8traits::isInSeq(c) )
+ {
+ PRInt32 shift = state * 6;
+ ucs4 |= (PRUint32(c) & 0x3F) << shift;
+ }
+ else
+ {
+ NS_ERROR("not a UTF8 string");
+ mErrorEncountered = PR_TRUE;
+ mBuffer = out;
+ return N;
+ }
+ }
+
+ if ( ucs4 < minUcs4 )
+ {
+ // Overlong sequence
+ *out++ = UCS2_REPLACEMENT_CHAR;
+ }
+ else if ( ucs4 <= 0xD7FF )
+ {
+ *out++ = ucs4;
+ }
+ else if ( /* ucs4 >= 0xD800 && */ ucs4 <= 0xDFFF )
+ {
+ // Surrogates
+ *out++ = UCS2_REPLACEMENT_CHAR;
+ }
+ else if ( ucs4 == 0xFFFE || ucs4 == 0xFFFF )
+ {
+ // Prohibited characters
+ *out++ = UCS2_REPLACEMENT_CHAR;
+ }
+ else if ( ucs4 >= PLANE1_BASE )
+ {
+ if ( ucs4 >= 0x00110000 )
+ *out++ = UCS2_REPLACEMENT_CHAR;
+ else {
+ // surrogate, see unicode specification 3.7 for following math.
+ ucs4 -= PLANE1_BASE;
+ *out++ = (PRUnichar)(ucs4 >> 10) | 0xd800u;
+ *out++ = (PRUnichar)(ucs4 & 0x3ff) | 0xdc00u;
+ }
+ }
+ else
+ {
+ *out++ = ucs4;
+ }
+ }
+ mBuffer = out;
+ return p - start;
+ }
+
+ void write_terminator()
+ {
+ *mBuffer = buffer_type(0);
+ }
+
+ private:
+ buffer_type* const mStart;
+ buffer_type* mBuffer;
+ PRBool mErrorEncountered;
+ };
+
+/**
+ * A character sink (see |copy_string| in nsAlgorithm.h) for computing
+ * the length of the UTF-16 string equivalent to a UTF-8 string.
+ */
+class CalculateUTF8Length
+ {
+ public:
+ typedef nsACString::char_type value_type;
+
+ CalculateUTF8Length() : mLength(0), mErrorEncountered(PR_FALSE) { }
+
+ size_t Length() const { return mLength; }
+
+ PRUint32 NS_ALWAYS_INLINE write( const value_type* start, PRUint32 N )
+ {
+ // ignore any further requests
+ if ( mErrorEncountered )
+ return N;
+
+ // algorithm assumes utf8 units won't
+ // be spread across fragments
+ const value_type* p = start;
+ const value_type* end = start + N;
+ for ( ; p < end /* && *p */; ++mLength )
+ {
+ if ( UTF8traits::isASCII(*p) )
+ p += 1;
+ else if ( UTF8traits::is2byte(*p) )
+ p += 2;
+ else if ( UTF8traits::is3byte(*p) )
+ p += 3;
+ else if ( UTF8traits::is4byte(*p) ) {
+ p += 4;
+ // Because a UTF-8 sequence of 4 bytes represents a codepoint
+ // greater than 0xFFFF, it will become a surrogate pair in the
+ // UTF-16 string, so add 1 more to mLength.
+ // This doesn't happen with is5byte and is6byte because they
+ // are illegal UTF-8 sequences (greater than 0x10FFFF) so get
+ // converted to a single replacement character.
+ //
+ // XXX: if the 4-byte sequence is an illegal non-shortest form,
+ // it also gets converted to a replacement character, so
+ // mLength will be off by one in this case.
+ ++mLength;
+ }
+ else if ( UTF8traits::is5byte(*p) )
+ p += 5;
+ else if ( UTF8traits::is6byte(*p) )
+ p += 6;
+ else
+ {
+ break;
+ }
+ }
+ if ( p != end )
+ {
+ NS_ERROR("Not a UTF-8 string. This code should only be used for converting from known UTF-8 strings.");
+ mErrorEncountered = PR_TRUE;
+ mLength = 0;
+ return N;
+ }
+ return p - start;
+ }
+
+ private:
+ size_t mLength;
+ PRBool mErrorEncountered;
+ };
+
+/**
+ * A character sink (see |copy_string| in nsAlgorithm.h) for converting
+ * UTF-16 to UTF-8.
+ */
+class ConvertUTF16toUTF8
+ {
+ public:
+ typedef nsAString::char_type value_type;
+ typedef nsACString::char_type buffer_type;
+
+ // The error handling here is more lenient than that in
+ // |ConvertUTF8toUTF16|, but it's that way for backwards
+ // compatibility.
+
+ ConvertUTF16toUTF8( buffer_type* aBuffer )
+ : mStart(aBuffer), mBuffer(aBuffer) {}
+
+ size_t Size() const { return mBuffer - mStart; }
+
+ PRUint32 NS_ALWAYS_INLINE write( const value_type* start, PRUint32 N )
+ {
+ buffer_type *out = mBuffer; // gcc isn't smart enough to do this!
+
+ for (const value_type *p = start, *end = start + N; p < end; ++p )
+ {
+ value_type c = *p;
+ if (! (c & 0xFF80)) // U+0000 - U+007F
+ {
+ *out++ = (char)c;
+ }
+ else if (! (c & 0xF800)) // U+0100 - U+07FF
+ {
+ *out++ = 0xC0 | (char)(c >> 6);
+ *out++ = 0x80 | (char)(0x003F & c);
+ }
+ else if (0xD800 != (0xF800 & c)) // U+0800 - U+D7FF,U+E000 - U+FFFF
+ {
+ *out++ = 0xE0 | (char)(c >> 12);
+ *out++ = 0x80 | (char)(0x003F & (c >> 6));
+ *out++ = 0x80 | (char)(0x003F & c );
+ }
+ else if (0xD800 == (0xFC00 & c)) // U+D800 - U+DBFF
+ {
+ // D800- DBFF - High Surrogate
+ // N = (H- D800) *400 + 10000 + ...
+ PRUint32 ucs4 = 0x10000 + ((0x03FF & c) << 10);
+
+ ++p;
+ if (p == end)
+ {
+ NS_ERROR("Surrogate pair split between fragments");
+ mBuffer = out;
+ return N;
+ }
+ c = *p;
+
+ if (0xDC00 == (0xFC00 & c))
+ {
+ // DC00- DFFF - Low Surrogate
+ // N += ( L - DC00 )
+ ucs4 |= (0x03FF & c);
+
+ // 0001 0000-001F FFFF
+ *out++ = 0xF0 | (char)(ucs4 >> 18);
+ *out++ = 0x80 | (char)(0x003F & (ucs4 >> 12));
+ *out++ = 0x80 | (char)(0x003F & (ucs4 >> 6));
+ *out++ = 0x80 | (char)(0x003F & ucs4);
+ }
+ else
+ {
+ NS_ERROR("got a High Surrogate but no low surrogate");
+ // output nothing.
+ }
+ }
+ else // U+DC00 - U+DFFF
+ {
+ // DC00- DFFF - Low Surrogate
+ NS_ERROR("got a low Surrogate but no high surrogate");
+ // output nothing.
+ }
+ }
+
+ mBuffer = out;
+ return N;
+ }
+
+ void write_terminator()
+ {
+ *mBuffer = buffer_type(0);
+ }
+
+ private:
+ buffer_type* const mStart;
+ buffer_type* mBuffer;
+ };
+
+/**
+ * A character sink (see |copy_string| in nsAlgorithm.h) for computing
+ * the number of bytes a UTF-16 would occupy in UTF-8.
+ */
+class CalculateUTF8Size
+ {
+ public:
+ typedef nsAString::char_type value_type;
+
+ CalculateUTF8Size()
+ : mSize(0) { }
+
+ size_t Size() const { return mSize; }
+
+ PRUint32 NS_ALWAYS_INLINE write( const value_type* start, PRUint32 N )
+ {
+ // Assume UCS2 surrogate pairs won't be spread across fragments.
+ for (const value_type *p = start, *end = start + N; p < end; ++p )
+ {
+ value_type c = *p;
+ if (! (c & 0xFF80)) // U+0000 - U+007F
+ mSize += 1;
+ else if (! (c & 0xF800)) // U+0100 - U+07FF
+ mSize += 2;
+ else if (0xD800 != (0xF800 & c)) // U+0800 - U+D7FF,U+E000 - U+FFFF
+ mSize += 3;
+ else if (0xD800 == (0xFC00 & c)) // U+D800 - U+DBFF
+ {
+ ++p;
+ if (p == end)
+ {
+ NS_ERROR("Surrogate pair split between fragments");
+ return N;
+ }
+ c = *p;
+
+ if (0xDC00 == (0xFC00 & c))
+ mSize += 4;
+ else
+ NS_ERROR("got a high Surrogate but no low surrogate");
+ }
+ else // U+DC00 - U+DFFF
+ NS_ERROR("got a low Surrogate but no high surrogate");
+ }
+
+ return N;
+ }
+
+ private:
+ size_t mSize;
+ };
+
+/**
+ * A character sink that performs a |reinterpret_cast| style conversion
+ * between character types.
+ */
+template <class FromCharT, class ToCharT>
+class LossyConvertEncoding
+ {
+ public:
+ typedef FromCharT value_type;
+
+ typedef FromCharT input_type;
+ typedef ToCharT output_type;
+
+ typedef typename nsCharTraits<FromCharT>::unsigned_char_type unsigned_input_type;
+
+ public:
+ LossyConvertEncoding( output_type* aDestination ) : mDestination(aDestination) { }
+
+ PRUint32
+ write( const input_type* aSource, PRUint32 aSourceLength )
+ {
+ const input_type* done_writing = aSource + aSourceLength;
+ while ( aSource < done_writing )
+ *mDestination++ = (output_type)(unsigned_input_type)(*aSource++); // use old-style cast to mimic old |ns[C]String| behavior
+ return aSourceLength;
+ }
+
+ void
+ write_terminator()
+ {
+ *mDestination = output_type(0);
+ }
+
+ private:
+ output_type* mDestination;
+ };
+
+#endif /* !defined(nsUTF8Utils_h_) */
diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsXPIDLString.h b/src/libs/xpcom18a4/xpcom/string/public/nsXPIDLString.h
new file mode 100644
index 00000000..c66a2d7a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/nsXPIDLString.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 nsXPIDLString_h___
+#define nsXPIDLString_h___
+
+#ifndef nsString_h___
+#include "nsString.h"
+#endif
+
+#endif /* !defined(nsXPIDLString_h___) */
diff --git a/src/libs/xpcom18a4/xpcom/string/public/string-template-def-char.h b/src/libs/xpcom18a4/xpcom/string/public/string-template-def-char.h
new file mode 100644
index 00000000..d0f3a907
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/string-template-def-char.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+#define CharT char
+#define CharT_is_char 1
+#define nsTObsoleteAString_CharT nsObsoleteACString
+#define nsTObsoleteAStringThunk_CharT nsObsoleteACStringThunk
+#define nsTAString_CharT nsACString
+#define nsTAString_IncompatibleCharT nsAString
+#define nsTString_CharT nsCString
+#define nsTFixedString_CharT nsFixedCString
+#define nsTAutoString_CharT nsCAutoString
+#define nsTSubstring_CharT nsCSubstring
+#define nsTSubstringTuple_CharT nsCSubstringTuple
+#define nsTStringComparator_CharT nsCStringComparator
+#define nsTDefaultStringComparator_CharT nsDefaultCStringComparator
+#define nsTDependentString_CharT nsDependentCString
+#define nsTDependentSubstring_CharT nsDependentCSubstring
+#define nsTXPIDLString_CharT nsXPIDLCString
+#define nsTGetterCopies_CharT nsCGetterCopies
+#define nsTAdoptingString_CharT nsAdoptingCString
+#define nsTPromiseFlatString_CharT nsPromiseFlatCString
+#define TPromiseFlatString_CharT PromiseFlatCString
diff --git a/src/libs/xpcom18a4/xpcom/string/public/string-template-def-unichar.h b/src/libs/xpcom18a4/xpcom/string/public/string-template-def-unichar.h
new file mode 100644
index 00000000..c966dfbe
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/string-template-def-unichar.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+#define CharT PRUnichar
+#define CharT_is_PRUnichar 1
+#define nsTObsoleteAString_CharT nsObsoleteAString
+#define nsTObsoleteAStringThunk_CharT nsObsoleteAStringThunk
+#define nsTAString_CharT nsAString
+#define nsTAString_IncompatibleCharT nsACString
+#define nsTString_CharT nsString
+#define nsTFixedString_CharT nsFixedString
+#define nsTAutoString_CharT nsAutoString
+#define nsTSubstring_CharT nsSubstring
+#define nsTSubstringTuple_CharT nsSubstringTuple
+#define nsTStringComparator_CharT nsStringComparator
+#define nsTDefaultStringComparator_CharT nsDefaultStringComparator
+#define nsTDependentString_CharT nsDependentString
+#define nsTDependentSubstring_CharT nsDependentSubstring
+#define nsTXPIDLString_CharT nsXPIDLString
+#define nsTGetterCopies_CharT nsGetterCopies
+#define nsTAdoptingString_CharT nsAdoptingString
+#define nsTPromiseFlatString_CharT nsPromiseFlatString
+#define TPromiseFlatString_CharT PromiseFlatString
diff --git a/src/libs/xpcom18a4/xpcom/string/public/string-template-undef.h b/src/libs/xpcom18a4/xpcom/string/public/string-template-undef.h
new file mode 100644
index 00000000..45344370
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/public/string-template-undef.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+#undef CharT
+#undef CharT_is_PRUnichar
+#undef CharT_is_char
+#undef nsTObsoleteAString_CharT
+#undef nsTObsoleteAStringThunk_CharT
+#undef nsTAString_CharT
+#undef nsTAString_IncompatibleCharT
+#undef nsTString_CharT
+#undef nsTFixedString_CharT
+#undef nsTAutoString_CharT
+#undef nsTSubstring_CharT
+#undef nsTSubstringTuple_CharT
+#undef nsTStringComparator_CharT
+#undef nsTDefaultStringComparator_CharT
+#undef nsTDependentString_CharT
+#undef nsTDependentSubstring_CharT
+#undef nsTXPIDLString_CharT
+#undef nsTGetterCopies_CharT
+#undef nsTAdoptingString_CharT
+#undef nsTPromiseFlatString_CharT
+#undef TPromiseFlatString_CharT
diff --git a/src/libs/xpcom18a4/xpcom/string/src/.cvsignore b/src/libs/xpcom18a4/xpcom/string/src/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/string/src/Makefile.in b/src/libs/xpcom18a4/xpcom/string/src/Makefile.in
new file mode 100644
index 00000000..81033c6c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/Makefile.in
@@ -0,0 +1,77 @@
+# vim:set ts=8 sw=8 sts=8 noet:
+#
+# ***** 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.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications.
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Johnny Stenback <jst@netscape.com> (original author)
+# Scott Collins <scc@mozilla.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 *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = string
+LIBRARY_NAME = string_s
+
+REQUIRES = xpcom \
+ $(NULL)
+
+CPPSRCS = \
+ nsAString.cpp \
+ nsDependentSubstring.cpp \
+ nsObsoleteAStringThunk.cpp \
+ nsPrintfCString.cpp \
+ nsPromiseFlatString.cpp \
+ nsReadableUtils.cpp \
+ nsSubstring.cpp \
+ nsSubstringTuple.cpp \
+ nsString.cpp \
+ nsStringComparator.cpp \
+ nsStringObsolete.cpp \
+ $(NULL)
+
+# 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/string/src/nsAString.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsAString.cpp
new file mode 100644
index 00000000..5b481662
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsAString.cpp
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "nsAString.h"
+#include "nsObsoleteAString.h"
+#include "nsString.h"
+
+ // define nsAString
+#include "string-template-def-unichar.h"
+#include "nsTAString.cpp"
+#include "string-template-undef.h"
+
+ // define nsACString
+#include "string-template-def-char.h"
+#include "nsTAString.cpp"
+#include "string-template-undef.h"
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsDependentSubstring.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsDependentSubstring.cpp
new file mode 100644
index 00000000..971defc8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsDependentSubstring.cpp
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "nsDependentSubstring.h"
+#include "nsAlgorithm.h"
+
+ // define nsDependentSubstring
+#include "string-template-def-unichar.h"
+#include "nsTDependentSubstring.cpp"
+#include "string-template-undef.h"
+
+ // define nsDependentCSubstring
+#include "string-template-def-char.h"
+#include "nsTDependentSubstring.cpp"
+#include "string-template-undef.h"
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsObsoleteAStringThunk.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsObsoleteAStringThunk.cpp
new file mode 100644
index 00000000..8b511d1e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsObsoleteAStringThunk.cpp
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "nsObsoleteAString.h"
+#include "nsString.h"
+
+
+ // define nsObsoleteAStringThunk
+#include "string-template-def-unichar.h"
+#include "nsTObsoleteAStringThunk.cpp"
+#include "string-template-undef.h"
+
+
+ // define nsObsoleteACStringThunk
+#include "string-template-def-char.h"
+#include "nsTObsoleteAStringThunk.cpp"
+#include "string-template-undef.h"
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsPrintfCString.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsPrintfCString.cpp
new file mode 100644
index 00000000..8bb06da6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsPrintfCString.cpp
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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) 1994-2000
+ * 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 "nsPrintfCString.h"
+#include <stdarg.h>
+#include "prprf.h"
+
+
+// though these classes define a fixed buffer, they do not set the F_FIXED
+// flag. this is because they are not intended to be modified after they have
+// been constructed. we could change this but it would require adding a new
+// class to the hierarchy, one that both this class and nsCAutoString would
+// inherit from. for now, we populate the fixed buffer, and then let the
+// nsCString code treat the buffer as if it were a dependent buffer.
+
+nsPrintfCString::nsPrintfCString( const char_type* format, ... )
+ : string_type(mLocalBuffer, 0, F_TERMINATED)
+ {
+ va_list ap;
+
+ size_type logical_capacity = kLocalBufferSize;
+ size_type physical_capacity = logical_capacity + 1;
+
+ va_start(ap, format);
+ mLength = PR_vsnprintf(mData, physical_capacity, format, ap);
+ va_end(ap);
+ }
+
+nsPrintfCString::nsPrintfCString( size_type n, const char_type* format, ... )
+ : string_type(mLocalBuffer, 0, F_TERMINATED)
+ {
+ va_list ap;
+
+ // make sure there's at least |n| space
+ size_type logical_capacity = kLocalBufferSize;
+ if ( n > logical_capacity )
+ {
+ SetCapacity(n);
+ if (Capacity() < n)
+ return; // out of memory !!
+ logical_capacity = n;
+ }
+ size_type physical_capacity = logical_capacity + 1;
+
+ va_start(ap, format);
+ mLength = PR_vsnprintf(mData, physical_capacity, format, ap);
+ va_end(ap);
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsPromiseFlatString.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsPromiseFlatString.cpp
new file mode 100644
index 00000000..aab4f209
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsPromiseFlatString.cpp
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "nsPromiseFlatString.h"
+
+ // define nsPromiseFlatString
+#include "string-template-def-unichar.h"
+#include "nsTPromiseFlatString.cpp"
+#include "string-template-undef.h"
+
+ // define nsPromiseFlatCString
+#include "string-template-def-char.h"
+#include "nsTPromiseFlatString.cpp"
+#include "string-template-undef.h"
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsReadableUtils.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsReadableUtils.cpp
new file mode 100644
index 00000000..24305b6a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsReadableUtils.cpp
@@ -0,0 +1,1122 @@
+/* -*- 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@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 "nsReadableUtils.h"
+#include "nsMemory.h"
+#include "nsString.h"
+#include "nsUTF8Utils.h"
+
+NS_COM
+void
+LossyCopyUTF16toASCII( const nsAString& aSource, nsACString& aDest )
+ {
+ aDest.Truncate();
+ LossyAppendUTF16toASCII(aSource, aDest);
+ }
+
+NS_COM
+void
+CopyASCIItoUTF16( const nsACString& aSource, nsAString& aDest )
+ {
+ aDest.Truncate();
+ AppendASCIItoUTF16(aSource, aDest);
+ }
+
+NS_COM
+void
+LossyCopyUTF16toASCII( const PRUnichar* aSource, nsACString& aDest )
+ {
+ aDest.Truncate();
+ if (aSource) {
+ LossyAppendUTF16toASCII(nsDependentString(aSource), aDest);
+ }
+ }
+
+NS_COM
+void
+CopyASCIItoUTF16( const char* aSource, nsAString& aDest )
+ {
+ aDest.Truncate();
+ if (aSource) {
+ AppendASCIItoUTF16(nsDependentCString(aSource), aDest);
+ }
+ }
+
+NS_COM
+void
+CopyUTF16toUTF8( const nsAString& aSource, nsACString& aDest )
+ {
+ aDest.Truncate();
+ AppendUTF16toUTF8(aSource, aDest);
+ }
+
+NS_COM
+void
+CopyUTF8toUTF16( const nsACString& aSource, nsAString& aDest )
+ {
+ aDest.Truncate();
+ AppendUTF8toUTF16(aSource, aDest);
+ }
+
+NS_COM
+void
+CopyUTF16toUTF8( const PRUnichar* aSource, nsACString& aDest )
+ {
+ aDest.Truncate();
+ AppendUTF16toUTF8(aSource, aDest);
+ }
+
+NS_COM
+void
+CopyUTF8toUTF16( const char* aSource, nsAString& aDest )
+ {
+ aDest.Truncate();
+ AppendUTF8toUTF16(aSource, aDest);
+ }
+
+NS_COM
+void
+LossyAppendUTF16toASCII( const nsAString& aSource, nsACString& aDest )
+ {
+ PRUint32 old_dest_length = aDest.Length();
+ aDest.SetLength(old_dest_length + aSource.Length());
+
+ nsAString::const_iterator fromBegin, fromEnd;
+
+ nsACString::iterator dest;
+ aDest.BeginWriting(dest);
+
+ dest.advance(old_dest_length);
+
+ // right now, this won't work on multi-fragment destinations
+ LossyConvertEncoding<PRUnichar, char> converter(dest.get());
+
+ copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter);
+ }
+
+NS_COM
+void
+AppendASCIItoUTF16( const nsACString& aSource, nsAString& aDest )
+ {
+ PRUint32 old_dest_length = aDest.Length();
+ aDest.SetLength(old_dest_length + aSource.Length());
+
+ nsACString::const_iterator fromBegin, fromEnd;
+
+ nsAString::iterator dest;
+ aDest.BeginWriting(dest);
+
+ dest.advance(old_dest_length);
+
+ // right now, this won't work on multi-fragment destinations
+ LossyConvertEncoding<char, PRUnichar> converter(dest.get());
+
+ copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter);
+ }
+
+NS_COM
+void
+LossyAppendUTF16toASCII( const PRUnichar* aSource, nsACString& aDest )
+ {
+ if (aSource) {
+ LossyAppendUTF16toASCII(nsDependentString(aSource), aDest);
+ }
+ }
+
+NS_COM
+void
+AppendASCIItoUTF16( const char* aSource, nsAString& aDest )
+ {
+ if (aSource) {
+ AppendASCIItoUTF16(nsDependentCString(aSource), aDest);
+ }
+ }
+
+NS_COM
+void
+AppendUTF16toUTF8( const nsAString& aSource, nsACString& aDest )
+ {
+ nsAString::const_iterator source_start, source_end;
+ CalculateUTF8Size calculator;
+ copy_string(aSource.BeginReading(source_start),
+ aSource.EndReading(source_end), calculator);
+
+ PRUint32 count = calculator.Size();
+
+ if (count)
+ {
+ PRUint32 old_dest_length = aDest.Length();
+
+ // Grow the buffer if we need to.
+ aDest.SetLength(old_dest_length + count);
+
+ nsACString::iterator dest;
+ aDest.BeginWriting(dest);
+
+ dest.advance(old_dest_length);
+
+ if (count <= (PRUint32)dest.size_forward())
+ {
+ // aDest has enough room in the fragment just past the end
+ // of its old data that it can hold what we're about to
+ // append. Append using copy_string().
+
+ // All ready? Time to convert
+
+ ConvertUTF16toUTF8 converter(dest.get());
+ copy_string(aSource.BeginReading(source_start),
+ aSource.EndReading(source_end), converter);
+
+ if (converter.Size() != count)
+ {
+ NS_ERROR("Input invalid or incorrect length was calculated");
+
+ aDest.SetLength(old_dest_length);
+ }
+ }
+ else
+ {
+ // This isn't the fastest way to do this, but it gets
+ // complicated to convert UTF16 into a fragmented UTF8
+ // string, so we'll take the easy way out here in this
+ // rare situation.
+
+ aDest.Replace(old_dest_length, count,
+ NS_ConvertUTF16toUTF8(aSource));
+ }
+ }
+ }
+
+NS_COM
+void
+AppendUTF8toUTF16( const nsACString& aSource, nsAString& aDest )
+ {
+ nsACString::const_iterator source_start, source_end;
+ CalculateUTF8Length calculator;
+ copy_string(aSource.BeginReading(source_start),
+ aSource.EndReading(source_end), calculator);
+
+ PRUint32 count = calculator.Length();
+
+ if (count)
+ {
+ PRUint32 old_dest_length = aDest.Length();
+
+ // Grow the buffer if we need to.
+ aDest.SetLength(old_dest_length + count);
+
+ nsAString::iterator dest;
+ aDest.BeginWriting(dest);
+
+ dest.advance(old_dest_length);
+
+ if (count <= (PRUint32)dest.size_forward())
+ {
+ // aDest has enough room in the fragment just past the end
+ // of its old data that it can hold what we're about to
+ // append. Append using copy_string().
+
+ // All ready? Time to convert
+
+ ConvertUTF8toUTF16 converter(dest.get());
+ copy_string(aSource.BeginReading(source_start),
+ aSource.EndReading(source_end), converter);
+
+ if (converter.Length() != count)
+ {
+ NS_ERROR("Input wasn't UTF8 or incorrect length was calculated");
+ aDest.SetLength(old_dest_length);
+ }
+ }
+ else
+ {
+ // This isn't the fastest way to do this, but it gets
+ // complicated to convert parts of a UTF8 string into a
+ // UTF16 string, so we'll take the easy way out here in
+ // this rare situation.
+
+ aDest.Replace(old_dest_length, count,
+ NS_ConvertUTF8toUTF16(aSource));
+ }
+ }
+ }
+
+NS_COM
+void
+AppendUTF16toUTF8( const PRUnichar* aSource, nsACString& aDest )
+ {
+ if (aSource) {
+ AppendUTF16toUTF8(nsDependentString(aSource), aDest);
+ }
+ }
+
+NS_COM
+void
+AppendUTF8toUTF16( const char* aSource, nsAString& aDest )
+ {
+ if (aSource) {
+ AppendUTF8toUTF16(nsDependentCString(aSource), aDest);
+ }
+ }
+
+
+ /**
+ * A helper function that allocates a buffer of the desired character type big enough to hold a copy of the supplied string (plus a zero terminator).
+ *
+ * @param aSource an string you will eventually be making a copy of
+ * @return a new buffer (of the type specified by the second parameter) which you must free with |nsMemory::Free|.
+ *
+ */
+template <class FromStringT, class ToCharT>
+inline
+ToCharT*
+AllocateStringCopy( const FromStringT& aSource, ToCharT* )
+ {
+ return NS_STATIC_CAST(ToCharT*, nsMemory::Alloc((aSource.Length()+1) * sizeof(ToCharT)));
+ }
+
+
+NS_COM
+char*
+ToNewCString( const nsAString& aSource )
+ {
+ char* result = AllocateStringCopy(aSource, (char*)0);
+
+ nsAString::const_iterator fromBegin, fromEnd;
+ LossyConvertEncoding<PRUnichar, char> converter(result);
+ copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter).write_terminator();
+ return result;
+ }
+
+NS_COM
+char*
+ToNewUTF8String( const nsAString& aSource, PRUint32 *aUTF8Count )
+ {
+ nsAString::const_iterator start, end;
+ CalculateUTF8Size calculator;
+ copy_string(aSource.BeginReading(start), aSource.EndReading(end),
+ calculator);
+
+ if (aUTF8Count)
+ *aUTF8Count = calculator.Size();
+
+ char *result = NS_STATIC_CAST(char*,
+ nsMemory::Alloc(calculator.Size() + 1));
+
+ ConvertUTF16toUTF8 converter(result);
+ copy_string(aSource.BeginReading(start), aSource.EndReading(end),
+ converter).write_terminator();
+ NS_ASSERTION(calculator.Size() == converter.Size(), "length mismatch");
+
+ return result;
+ }
+
+NS_COM
+char*
+ToNewCString( const nsACString& aSource )
+ {
+ // no conversion needed, just allocate a buffer of the correct length and copy into it
+
+ char* result = AllocateStringCopy(aSource, (char*)0);
+
+ nsACString::const_iterator fromBegin, fromEnd;
+ char* toBegin = result;
+ *copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), toBegin) = char(0);
+ return result;
+ }
+
+NS_COM
+PRUnichar*
+ToNewUnicode( const nsAString& aSource )
+ {
+ // no conversion needed, just allocate a buffer of the correct length and copy into it
+
+ PRUnichar* result = AllocateStringCopy(aSource, (PRUnichar*)0);
+
+ nsAString::const_iterator fromBegin, fromEnd;
+ PRUnichar* toBegin = result;
+ *copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), toBegin) = PRUnichar(0);
+ return result;
+ }
+
+NS_COM
+PRUnichar*
+ToNewUnicode( const nsACString& aSource )
+ {
+ PRUnichar* result = AllocateStringCopy(aSource, (PRUnichar*)0);
+
+ nsACString::const_iterator fromBegin, fromEnd;
+ LossyConvertEncoding<char, PRUnichar> converter(result);
+ copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter).write_terminator();
+ return result;
+ }
+
+NS_COM
+PRUnichar*
+UTF8ToNewUnicode( const nsACString& aSource, PRUint32 *aUTF16Count )
+ {
+ nsACString::const_iterator start, end;
+ CalculateUTF8Length calculator;
+ copy_string(aSource.BeginReading(start), aSource.EndReading(end),
+ calculator);
+
+ if (aUTF16Count)
+ *aUTF16Count = calculator.Length();
+
+ PRUnichar *result = NS_STATIC_CAST(PRUnichar*,
+ nsMemory::Alloc(sizeof(PRUnichar) * (calculator.Length() + 1)));
+
+ ConvertUTF8toUTF16 converter(result);
+ copy_string(aSource.BeginReading(start), aSource.EndReading(end),
+ converter).write_terminator();
+ NS_ASSERTION(calculator.Length() == converter.Length(), "length mismatch");
+
+ return result;
+ }
+
+NS_COM
+PRUnichar*
+CopyUnicodeTo( const nsAString& aSource, PRUint32 aSrcOffset, PRUnichar* aDest, PRUint32 aLength )
+ {
+ nsAString::const_iterator fromBegin, fromEnd;
+ PRUnichar* toBegin = aDest;
+ copy_string(aSource.BeginReading(fromBegin).advance( PRInt32(aSrcOffset) ), aSource.BeginReading(fromEnd).advance( PRInt32(aSrcOffset+aLength) ), toBegin);
+ return aDest;
+ }
+
+NS_COM
+void
+CopyUnicodeTo( const nsAString::const_iterator& aSrcStart,
+ const nsAString::const_iterator& aSrcEnd,
+ nsAString& aDest )
+ {
+ nsAString::iterator writer;
+ aDest.SetLength(Distance(aSrcStart, aSrcEnd));
+ aDest.BeginWriting(writer);
+ nsAString::const_iterator fromBegin(aSrcStart);
+
+ copy_string(fromBegin, aSrcEnd, writer);
+ }
+
+NS_COM
+void
+AppendUnicodeTo( const nsAString::const_iterator& aSrcStart,
+ const nsAString::const_iterator& aSrcEnd,
+ nsAString& aDest )
+ {
+ nsAString::iterator writer;
+ PRUint32 oldLength = aDest.Length();
+ aDest.SetLength(oldLength + Distance(aSrcStart, aSrcEnd));
+ aDest.BeginWriting(writer).advance(oldLength);
+ nsAString::const_iterator fromBegin(aSrcStart);
+
+ copy_string(fromBegin, aSrcEnd, writer);
+ }
+
+NS_COM
+PRBool
+IsASCII( const nsAString& aString )
+ {
+ static const PRUnichar NOT_ASCII = PRUnichar(~0x007F);
+
+
+ // Don't want to use |copy_string| for this task, since we can stop at the first non-ASCII character
+
+ nsAString::const_iterator done_reading;
+ aString.EndReading(done_reading);
+
+ // for each chunk of |aString|...
+ PRUint32 fragmentLength = 0;
+ nsAString::const_iterator iter;
+ for ( aString.BeginReading(iter); iter != done_reading; iter.advance( PRInt32(fragmentLength) ) )
+ {
+ fragmentLength = PRUint32(iter.size_forward());
+ const PRUnichar* c = iter.get();
+ const PRUnichar* fragmentEnd = c + fragmentLength;
+
+ // for each character in this chunk...
+ while ( c < fragmentEnd )
+ if ( *c++ & NOT_ASCII )
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+ }
+
+NS_COM
+PRBool
+IsASCII( const nsACString& aString )
+ {
+ static const char NOT_ASCII = char(~0x7F);
+
+
+ // Don't want to use |copy_string| for this task, since we can stop at the first non-ASCII character
+
+ nsACString::const_iterator done_reading;
+ aString.EndReading(done_reading);
+
+ // for each chunk of |aString|...
+ PRUint32 fragmentLength = 0;
+ nsACString::const_iterator iter;
+ for ( aString.BeginReading(iter); iter != done_reading; iter.advance( PRInt32(fragmentLength) ) )
+ {
+ fragmentLength = PRUint32(iter.size_forward());
+ const char* c = iter.get();
+ const char* fragmentEnd = c + fragmentLength;
+
+ // for each character in this chunk...
+ while ( c < fragmentEnd )
+ if ( *c++ & NOT_ASCII )
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+ }
+
+NS_COM
+PRBool
+IsUTF8( const nsACString& aString )
+ {
+ nsReadingIterator<char> done_reading;
+ aString.EndReading(done_reading);
+
+ PRInt32 state = 0;
+ PRBool overlong = PR_FALSE;
+ PRBool surrogate = PR_FALSE;
+ PRBool nonchar = PR_FALSE;
+ PRUint16 olupper = 0; // overlong byte upper bound.
+ PRUint16 slower = 0; // surrogate byte lower bound.
+
+ // for each chunk of |aString|...
+ PRUint32 fragmentLength = 0;
+ nsReadingIterator<char> iter;
+
+ for ( aString.BeginReading(iter); iter != done_reading; iter.advance( PRInt32(fragmentLength) ) )
+ {
+ fragmentLength = PRUint32(iter.size_forward());
+ const char* ptr = iter.get();
+ const char* fragmentEnd = ptr + fragmentLength;
+
+ // for each character in this chunk...
+ while ( ptr < fragmentEnd )
+ {
+ PRUint8 c;
+
+ if (0 == state)
+ {
+ c = *ptr++;
+
+ if ( UTF8traits::isASCII(c) )
+ continue;
+
+ if ( c <= 0xC1 ) // [80-BF] where not expected, [C0-C1] for overlong.
+ return PR_FALSE;
+ else if ( UTF8traits::is2byte(c) )
+ state = 1;
+ else if ( UTF8traits::is3byte(c) )
+ {
+ state = 2;
+ if ( c == 0xE0 ) // to exclude E0[80-9F][80-BF]
+ {
+ overlong = PR_TRUE;
+ olupper = 0x9F;
+ }
+ else if ( c == 0xED ) // ED[A0-BF][80-BF] : surrogate codepoint
+ {
+ surrogate = PR_TRUE;
+ slower = 0xA0;
+ }
+ else if ( c == 0xEF ) // EF BF [BE-BF] : non-character
+ nonchar = PR_TRUE;
+ }
+ else if ( c <= 0xF4 ) // XXX replace /w UTF8traits::is4byte when it's updated to exclude [F5-F7].(bug 199090)
+ {
+ state = 3;
+ nonchar = PR_TRUE;
+ if ( c == 0xF0 ) // to exclude F0[80-8F][80-BF]{2}
+ {
+ overlong = PR_TRUE;
+ olupper = 0x8F;
+ }
+ else if ( c == 0xF4 ) // to exclude F4[90-BF][80-BF]
+ {
+ // actually not surrogates but codepoints beyond 0x10FFFF
+ surrogate = PR_TRUE;
+ slower = 0x90;
+ }
+ }
+ else
+ return PR_FALSE; // Not UTF-8 string
+ }
+
+ while (ptr < fragmentEnd && state)
+ {
+ c = *ptr++;
+ --state;
+
+ // non-character : EF BF [BE-BF] or F[0-7] [89AB]F BF [BE-BF]
+ if ( nonchar && ( (!state && c < 0xBE) ||
+ (state == 1 && c != 0xBF) ||
+ (state == 2 && 0x0F != (0x0F & c)) ))
+ nonchar = PR_FALSE;
+
+ if ( !UTF8traits::isInSeq(c) || (overlong && c <= olupper) ||
+ (surrogate && slower <= c) || (nonchar && !state) )
+ return PR_FALSE; // Not UTF-8 string
+ overlong = surrogate = PR_FALSE;
+ }
+ }
+ }
+ return !state; // state != 0 at the end indicates an invalid UTF-8 seq.
+ }
+
+ /**
+ * A character sink for in-place case conversion.
+ */
+class ConvertToUpperCase
+ {
+ public:
+ typedef char value_type;
+
+ PRUint32
+ write( const char* aSource, PRUint32 aSourceLength )
+ {
+ char* cp = NS_CONST_CAST(char*,aSource);
+ const char* end = aSource + aSourceLength;
+ while (cp != end) {
+ char ch = *cp;
+ if ((ch >= 'a') && (ch <= 'z'))
+ *cp = ch - ('a' - 'A');
+ ++cp;
+ }
+ return aSourceLength;
+ }
+ };
+
+NS_COM
+void
+ToUpperCase( nsACString& aCString )
+ {
+ nsACString::iterator fromBegin, fromEnd;
+ ConvertToUpperCase converter;
+ copy_string(aCString.BeginWriting(fromBegin), aCString.EndWriting(fromEnd), converter);
+ }
+
+NS_COM
+void
+ToUpperCase( nsCSubstring& aCString )
+ {
+ ConvertToUpperCase converter;
+ char* start;
+ converter.write(aCString.BeginWriting(start), aCString.Length());
+ }
+
+ /**
+ * A character sink for copying with case conversion.
+ */
+class CopyToUpperCase
+ {
+ public:
+ typedef char value_type;
+
+ CopyToUpperCase( nsACString::iterator& aDestIter )
+ : mIter(aDestIter)
+ {
+ }
+
+ PRUint32
+ write( const char* aSource, PRUint32 aSourceLength )
+ {
+ PRUint32 len = PR_MIN(PRUint32(mIter.size_forward()), aSourceLength);
+ char* cp = mIter.get();
+ const char* end = aSource + len;
+ while (aSource != end) {
+ char ch = *aSource;
+ if ((ch >= 'a') && (ch <= 'z'))
+ *cp = ch - ('a' - 'A');
+ else
+ *cp = ch;
+ ++aSource;
+ ++cp;
+ }
+ mIter.advance(len);
+ return len;
+ }
+
+ protected:
+ nsACString::iterator& mIter;
+ };
+
+NS_COM
+void
+ToUpperCase( const nsACString& aSource, nsACString& aDest )
+ {
+ nsACString::const_iterator fromBegin, fromEnd;
+ nsACString::iterator toBegin;
+ aDest.SetLength(aSource.Length());
+ CopyToUpperCase converter(aDest.BeginWriting(toBegin));
+ copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter);
+ }
+
+ /**
+ * A character sink for case conversion.
+ */
+class ConvertToLowerCase
+ {
+ public:
+ typedef char value_type;
+
+ PRUint32
+ write( const char* aSource, PRUint32 aSourceLength )
+ {
+ char* cp = NS_CONST_CAST(char*,aSource);
+ const char* end = aSource + aSourceLength;
+ while (cp != end) {
+ char ch = *cp;
+ if ((ch >= 'A') && (ch <= 'Z'))
+ *cp = ch + ('a' - 'A');
+ ++cp;
+ }
+ return aSourceLength;
+ }
+ };
+
+NS_COM
+void
+ToLowerCase( nsACString& aCString )
+ {
+ nsACString::iterator fromBegin, fromEnd;
+ ConvertToLowerCase converter;
+ copy_string(aCString.BeginWriting(fromBegin), aCString.EndWriting(fromEnd), converter);
+ }
+
+NS_COM
+void
+ToLowerCase( nsCSubstring& aCString )
+ {
+ ConvertToLowerCase converter;
+ char* start;
+ converter.write(aCString.BeginWriting(start), aCString.Length());
+ }
+
+ /**
+ * A character sink for copying with case conversion.
+ */
+class CopyToLowerCase
+ {
+ public:
+ typedef char value_type;
+
+ CopyToLowerCase( nsACString::iterator& aDestIter )
+ : mIter(aDestIter)
+ {
+ }
+
+ PRUint32
+ write( const char* aSource, PRUint32 aSourceLength )
+ {
+ PRUint32 len = PR_MIN(PRUint32(mIter.size_forward()), aSourceLength);
+ char* cp = mIter.get();
+ const char* end = aSource + len;
+ while (aSource != end) {
+ char ch = *aSource;
+ if ((ch >= 'A') && (ch <= 'Z'))
+ *cp = ch + ('a' - 'A');
+ else
+ *cp = ch;
+ ++aSource;
+ ++cp;
+ }
+ mIter.advance(len);
+ return len;
+ }
+
+ protected:
+ nsACString::iterator& mIter;
+ };
+
+NS_COM
+void
+ToLowerCase( const nsACString& aSource, nsACString& aDest )
+ {
+ nsACString::const_iterator fromBegin, fromEnd;
+ nsACString::iterator toBegin;
+ aDest.SetLength(aSource.Length());
+ CopyToLowerCase converter(aDest.BeginWriting(toBegin));
+ copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter);
+ }
+
+template <class StringT, class IteratorT, class Comparator>
+PRBool
+FindInReadable_Impl( const StringT& aPattern, IteratorT& aSearchStart, IteratorT& aSearchEnd, const Comparator& compare )
+ {
+ PRBool found_it = PR_FALSE;
+
+ // only bother searching at all if we're given a non-empty range to search
+ if ( aSearchStart != aSearchEnd )
+ {
+ IteratorT aPatternStart, aPatternEnd;
+ aPattern.BeginReading(aPatternStart);
+ aPattern.EndReading(aPatternEnd);
+
+ // outer loop keeps searching till we find it or run out of string to search
+ while ( !found_it )
+ {
+ // fast inner loop (that's what it's called, not what it is) looks for a potential match
+ while ( aSearchStart != aSearchEnd &&
+ compare(*aPatternStart, *aSearchStart) )
+ ++aSearchStart;
+
+ // if we broke out of the `fast' loop because we're out of string ... we're done: no match
+ if ( aSearchStart == aSearchEnd )
+ break;
+
+ // otherwise, we're at a potential match, let's see if we really hit one
+ IteratorT testPattern(aPatternStart);
+ IteratorT testSearch(aSearchStart);
+
+ // slow inner loop verifies the potential match (found by the `fast' loop) at the current position
+ for(;;)
+ {
+ // we already compared the first character in the outer loop,
+ // so we'll advance before the next comparison
+ ++testPattern;
+ ++testSearch;
+
+ // if we verified all the way to the end of the pattern, then we found it!
+ if ( testPattern == aPatternEnd )
+ {
+ found_it = PR_TRUE;
+ aSearchEnd = testSearch; // return the exact found range through the parameters
+ break;
+ }
+
+ // if we got to end of the string we're searching before we hit the end of the
+ // pattern, we'll never find what we're looking for
+ if ( testSearch == aSearchEnd )
+ {
+ aSearchStart = aSearchEnd;
+ break;
+ }
+
+ // else if we mismatched ... it's time to advance to the next search position
+ // and get back into the `fast' loop
+ if ( compare(*testPattern, *testSearch) )
+ {
+ ++aSearchStart;
+ break;
+ }
+ }
+ }
+ }
+
+ return found_it;
+ }
+
+
+NS_COM
+PRBool
+FindInReadable( const nsAString& aPattern, nsAString::const_iterator& aSearchStart, nsAString::const_iterator& aSearchEnd, const nsStringComparator& aComparator )
+ {
+ return FindInReadable_Impl(aPattern, aSearchStart, aSearchEnd, aComparator);
+ }
+
+NS_COM
+PRBool
+FindInReadable( const nsACString& aPattern, nsACString::const_iterator& aSearchStart, nsACString::const_iterator& aSearchEnd, const nsCStringComparator& aComparator)
+ {
+ return FindInReadable_Impl(aPattern, aSearchStart, aSearchEnd, aComparator);
+ }
+
+NS_COM
+PRBool
+CaseInsensitiveFindInReadable( const nsACString& aPattern, nsACString::const_iterator& aSearchStart, nsACString::const_iterator& aSearchEnd )
+ {
+ return FindInReadable_Impl(aPattern, aSearchStart, aSearchEnd, nsCaseInsensitiveCStringComparator());
+ }
+
+ /**
+ * This implementation is simple, but does too much work.
+ * It searches the entire string from left to right, and returns the last match found, if any.
+ * This implementation will be replaced when I get |reverse_iterator|s working.
+ */
+NS_COM
+PRBool
+RFindInReadable( const nsAString& aPattern, nsAString::const_iterator& aSearchStart, nsAString::const_iterator& aSearchEnd, const nsStringComparator& aComparator)
+ {
+ PRBool found_it = PR_FALSE;
+
+ nsAString::const_iterator savedSearchEnd(aSearchEnd);
+ nsAString::const_iterator searchStart(aSearchStart), searchEnd(aSearchEnd);
+
+ while ( searchStart != searchEnd )
+ {
+ if ( FindInReadable(aPattern, searchStart, searchEnd, aComparator) )
+ {
+ found_it = PR_TRUE;
+
+ // this is the best match so far, so remember it
+ aSearchStart = searchStart;
+ aSearchEnd = searchEnd;
+
+ // ...and get ready to search some more
+ // (it's tempting to set |searchStart=searchEnd| ... but that misses overlapping patterns)
+ ++searchStart;
+ searchEnd = savedSearchEnd;
+ }
+ }
+
+ // if we never found it, return an empty range
+ if ( !found_it )
+ aSearchStart = aSearchEnd;
+
+ return found_it;
+ }
+
+NS_COM
+PRBool
+RFindInReadable( const nsACString& aPattern, nsACString::const_iterator& aSearchStart, nsACString::const_iterator& aSearchEnd, const nsCStringComparator& aComparator)
+ {
+ PRBool found_it = PR_FALSE;
+
+ nsACString::const_iterator savedSearchEnd(aSearchEnd);
+ nsACString::const_iterator searchStart(aSearchStart), searchEnd(aSearchEnd);
+
+ while ( searchStart != searchEnd )
+ {
+ if ( FindInReadable(aPattern, searchStart, searchEnd, aComparator) )
+ {
+ found_it = PR_TRUE;
+
+ // this is the best match so far, so remember it
+ aSearchStart = searchStart;
+ aSearchEnd = searchEnd;
+
+ // ...and get ready to search some more
+ // (it's tempting to set |searchStart=searchEnd| ... but that misses overlapping patterns)
+ ++searchStart;
+ searchEnd = savedSearchEnd;
+ }
+ }
+
+ // if we never found it, return an empty range
+ if ( !found_it )
+ aSearchStart = aSearchEnd;
+
+ return found_it;
+ }
+
+NS_COM
+PRBool
+FindCharInReadable( PRUnichar aChar, nsAString::const_iterator& aSearchStart, const nsAString::const_iterator& aSearchEnd )
+ {
+ PRInt32 fragmentLength = aSearchEnd.get() - aSearchStart.get();
+
+ const PRUnichar* charFoundAt = nsCharTraits<PRUnichar>::find(aSearchStart.get(), fragmentLength, aChar);
+ if ( charFoundAt ) {
+ aSearchStart.advance( charFoundAt - aSearchStart.get() );
+ return PR_TRUE;
+ }
+
+ aSearchStart.advance(fragmentLength);
+ return PR_FALSE;
+ }
+
+NS_COM
+PRBool
+FindCharInReadable( char aChar, nsACString::const_iterator& aSearchStart, const nsACString::const_iterator& aSearchEnd )
+ {
+ PRInt32 fragmentLength = aSearchEnd.get() - aSearchStart.get();
+
+ const char* charFoundAt = nsCharTraits<char>::find(aSearchStart.get(), fragmentLength, aChar);
+ if ( charFoundAt ) {
+ aSearchStart.advance( charFoundAt - aSearchStart.get() );
+ return PR_TRUE;
+ }
+
+ aSearchStart.advance(fragmentLength);
+ return PR_FALSE;
+ }
+
+NS_COM
+PRUint32
+CountCharInReadable( const nsAString& aStr,
+ PRUnichar aChar )
+{
+ PRUint32 count = 0;
+ nsAString::const_iterator begin, end;
+
+ aStr.BeginReading(begin);
+ aStr.EndReading(end);
+
+ while (begin != end) {
+ if (*begin == aChar) {
+ ++count;
+ }
+ ++begin;
+ }
+
+ return count;
+}
+
+NS_COM
+PRUint32
+CountCharInReadable( const nsACString& aStr,
+ char aChar )
+{
+ PRUint32 count = 0;
+ nsACString::const_iterator begin, end;
+
+ aStr.BeginReading(begin);
+ aStr.EndReading(end);
+
+ while (begin != end) {
+ if (*begin == aChar) {
+ ++count;
+ }
+ ++begin;
+ }
+
+ return count;
+}
+
+NS_COM PRBool
+StringBeginsWith( const nsAString& aSource, const nsAString& aSubstring,
+ const nsStringComparator& aComparator )
+ {
+ nsAString::size_type src_len = aSource.Length(),
+ sub_len = aSubstring.Length();
+ if (sub_len > src_len)
+ return PR_FALSE;
+ return Substring(aSource, 0, sub_len).Equals(aSubstring, aComparator);
+ }
+
+NS_COM PRBool
+StringBeginsWith( const nsACString& aSource, const nsACString& aSubstring,
+ const nsCStringComparator& aComparator )
+ {
+ nsACString::size_type src_len = aSource.Length(),
+ sub_len = aSubstring.Length();
+ if (sub_len > src_len)
+ return PR_FALSE;
+ return Substring(aSource, 0, sub_len).Equals(aSubstring, aComparator);
+ }
+
+NS_COM PRBool
+StringEndsWith( const nsAString& aSource, const nsAString& aSubstring,
+ const nsStringComparator& aComparator )
+ {
+ nsAString::size_type src_len = aSource.Length(),
+ sub_len = aSubstring.Length();
+ if (sub_len > src_len)
+ return PR_FALSE;
+ return Substring(aSource, src_len - sub_len, sub_len).Equals(aSubstring,
+ aComparator);
+ }
+
+NS_COM PRBool
+StringEndsWith( const nsACString& aSource, const nsACString& aSubstring,
+ const nsCStringComparator& aComparator )
+ {
+ nsACString::size_type src_len = aSource.Length(),
+ sub_len = aSubstring.Length();
+ if (sub_len > src_len)
+ return PR_FALSE;
+ return Substring(aSource, src_len - sub_len, sub_len).Equals(aSubstring,
+ aComparator);
+ }
+
+
+
+template <class CharT>
+class CalculateHashCode
+ {
+ public:
+ typedef CharT char_type;
+ typedef PRUint32 hashcode_type;
+ typedef CharT value_type;
+
+ CalculateHashCode() : mHashCode(0) { }
+ hashcode_type GetHashCode() const { return mHashCode; }
+
+ PRUint32 write( const CharT* chars, PRUint32 N )
+ {
+ for ( const CharT *end = chars + N; chars < end; ++chars)
+ mHashCode = (mHashCode>>28) ^ (mHashCode<<4) ^ PRUint32(*chars);
+ return N;
+ }
+
+ private:
+ hashcode_type mHashCode;
+ };
+
+NS_COM PRUint32 HashString( const nsAString& aStr )
+ {
+ CalculateHashCode<nsAString::char_type> sink;
+ nsAString::const_iterator begin, end;
+ aStr.BeginReading(begin);
+ aStr.EndReading(end);
+ copy_string(begin, end, sink);
+ return sink.GetHashCode();
+ }
+
+NS_COM PRUint32 HashString( const nsACString& aStr )
+ {
+ CalculateHashCode<nsACString::char_type> sink;
+ nsACString::const_iterator begin, end;
+ aStr.BeginReading(begin);
+ aStr.EndReading(end);
+ copy_string(begin, end, sink);
+ return sink.GetHashCode();
+ }
+
+static const PRUnichar empty_buffer[1] = { '\0' };
+
+NS_COM const nsAFlatString& EmptyString()
+ {
+ static const nsDependentString sEmpty(empty_buffer);
+
+ return sEmpty;
+ }
+
+NS_COM const nsAFlatCString& EmptyCString()
+ {
+ static const nsDependentCString sEmpty((const char *)empty_buffer);
+
+ return sEmpty;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsString.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsString.cpp
new file mode 100644
index 00000000..aedf3295
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsString.cpp
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "nsString.h"
+
+ // define nsString
+#include "string-template-def-unichar.h"
+#include "nsTString.cpp"
+#include "string-template-undef.h"
+
+ // define nsCString
+#include "string-template-def-char.h"
+#include "nsTString.cpp"
+#include "string-template-undef.h"
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsStringComparator.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsStringComparator.cpp
new file mode 100644
index 00000000..ced75c73
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsStringComparator.cpp
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 <ctype.h>
+#include "nsAString.h"
+#include "plstr.h"
+
+
+ // define nsStringComparator
+#include "string-template-def-unichar.h"
+#include "nsTStringComparator.cpp"
+#include "string-template-undef.h"
+
+ // define nsCStringComparator
+#include "string-template-def-char.h"
+#include "nsTStringComparator.cpp"
+#include "string-template-undef.h"
+
+
+int
+nsCaseInsensitiveCStringComparator::operator()( const char_type* lhs, const char_type* rhs, PRUint32 aLength ) const
+ {
+ PRInt32 result=PRInt32(PL_strncasecmp(lhs, rhs, aLength));
+ //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;
+ }
+
+int
+nsCaseInsensitiveCStringComparator::operator()( char lhs, char rhs ) const
+ {
+ if (lhs == rhs) return 0;
+
+ lhs = tolower(lhs);
+ rhs = tolower(rhs);
+
+ return lhs - rhs;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsStringObsolete.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsStringObsolete.cpp
new file mode 100644
index 00000000..76106a27
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsStringObsolete.cpp
@@ -0,0 +1,1327 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "nsString.h"
+
+
+ /**
+ * nsTString obsolete API support
+ */
+
+#if MOZ_STRING_WITH_OBSOLETE_API
+
+#include "nsDependentString.h"
+#include "nsDependentSubstring.h"
+#include "nsReadableUtils.h"
+#include "nsCRT.h"
+#include "nsUTF8Utils.h"
+#include "prdtoa.h"
+#include "prprf.h"
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+# include <iprt/mem.h>
+#endif
+
+/* ***** BEGIN RICKG BLOCK *****
+ *
+ * NOTE: This section of code was extracted from rickg's bufferRoutines.h file.
+ * For the most part it remains unmodified. We want to eliminate (or at
+ * least clean up) this code at some point. If you find the formatting
+ * in this section somewhat inconsistent, don't blame me! ;-)
+ */
+
+// XXXdarin what is wrong with STDC's tolower?
+inline char
+ascii_tolower(char aChar)
+{
+ if (aChar >= 'A' && aChar <= 'Z')
+ return aChar + ('a' - 'A');
+ return aChar;
+}
+
+//-----------------------------------------------------------------------------
+//
+// This set of methods is used to search a buffer looking for a char.
+//
+
+
+/**
+ * This methods cans the given buffer for the given char
+ *
+ * @update gess 02/17/00
+ * @param aDest is the buffer to be searched
+ * @param aDestLength is the size (in char-units, not bytes) of the buffer
+ * @param anOffset is the start pos to begin searching
+ * @param aChar is the target character we're looking for
+ * @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
+ * @return index of pos if found, else -1 (kNotFound)
+ */
+static PRInt32
+FindChar1(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRInt32 aCount) {
+
+ if(anOffset < 0)
+ anOffset=0;
+
+ if(aCount < 0)
+ aCount = (PRInt32)aDestLength;
+
+ if((aChar < 256) && (0 < aDestLength) && ((PRUint32)anOffset < aDestLength)) {
+
+ //We'll only search if the given aChar is within the normal ascii a range,
+ //(Since this string is definitely within the ascii range).
+
+ if(0<aCount) {
+
+ const char* left= aDest+anOffset;
+ const char* last= left+aCount;
+ const char* max = aDest+aDestLength;
+ const char* end = (last<max) ? last : max;
+
+ PRInt32 theMax = end-left;
+ if(0<theMax) {
+
+ unsigned char theChar = (unsigned char) aChar;
+ const char* result=(const char*)memchr(left, (int)theChar, theMax);
+
+ if(result)
+ return result-aDest;
+
+ }
+ }
+ }
+
+ return kNotFound;
+}
+
+
+/**
+ * This methods cans the given buffer for the given char
+ *
+ * @update gess 3/25/98
+ * @param aDest is the buffer to be searched
+ * @param aDestLength is the size (in char-units, not bytes) of the buffer
+ * @param anOffset is the start pos to begin searching
+ * @param aChar is the target character we're looking for
+ * @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
+ * @return index of pos if found, else -1 (kNotFound)
+ */
+static PRInt32
+FindChar2(const PRUnichar* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRInt32 aCount) {
+
+ if(anOffset < 0)
+ anOffset=0;
+
+ if(aCount < 0)
+ aCount = (PRInt32)aDestLength;
+
+ if((0<aDestLength) && ((PRUint32)anOffset < aDestLength)) {
+
+ if(0<aCount) {
+
+ const PRUnichar* root = aDest;
+ const PRUnichar* left = root+anOffset;
+ const PRUnichar* last = left+aCount;
+ const PRUnichar* max = root+aDestLength;
+ const PRUnichar* end = (last<max) ? last : max;
+
+ while(left<end){
+
+ if(*left==aChar)
+ return (left-root);
+
+ ++left;
+ }
+ }
+ }
+
+ return kNotFound;
+}
+
+
+/**
+ * This methods cans the given buffer (in reverse) for the given char
+ *
+ * @update gess 02/17/00
+ * @param aDest is the buffer to be searched
+ * @param aDestLength is the size (in char-units, not bytes) of the buffer
+ * @param anOffset is the start pos to begin searching
+ * @param aChar is the target character we're looking for
+ * @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
+ * @return index of pos if found, else -1 (kNotFound)
+ */
+
+static PRInt32
+RFindChar1(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRInt32 aCount) {
+
+ if(anOffset < 0)
+ anOffset=(PRInt32)aDestLength-1;
+
+ if(aCount < 0)
+ aCount = PRInt32(aDestLength);
+
+ if((aChar<256) && (0 < aDestLength) && ((PRUint32)anOffset < aDestLength)) {
+
+ //We'll only search if the given aChar is within the normal ascii a range,
+ //(Since this string is definitely within the ascii range).
+
+ if(0 < aCount) {
+
+ const char* rightmost = aDest + anOffset;
+ const char* min = rightmost - aCount + 1;
+ const char* leftmost = (min<aDest) ? aDest: min;
+
+ char theChar=(char)aChar;
+ while(leftmost <= rightmost){
+
+ if((*rightmost) == theChar)
+ return rightmost - aDest;
+
+ --rightmost;
+ }
+ }
+ }
+
+ return kNotFound;
+}
+
+
+/**
+ * This methods cans the given buffer for the given char
+ *
+ * @update gess 3/25/98
+ * @param aDest is the buffer to be searched
+ * @param aDestLength is the size (in char-units, not bytes) of the buffer
+ * @param anOffset is the start pos to begin searching
+ * @param aChar is the target character we're looking for
+ * @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
+ * @return index of pos if found, else -1 (kNotFound)
+ */
+static PRInt32
+RFindChar2(const PRUnichar* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRInt32 aCount) {
+
+ if(anOffset < 0)
+ anOffset=(PRInt32)aDestLength-1;
+
+ if(aCount < 0)
+ aCount = PRInt32(aDestLength);
+
+ if((0 < aDestLength) && ((PRUint32)anOffset < aDestLength)) {
+
+ if(0 < aCount) {
+
+ const PRUnichar* root = aDest;
+ const PRUnichar* rightmost = root + anOffset;
+ const PRUnichar* min = rightmost - aCount + 1;
+ const PRUnichar* leftmost = (min<root) ? root: min;
+
+ while(leftmost <= rightmost){
+
+ if((*rightmost) == aChar)
+ return rightmost - root;
+
+ --rightmost;
+ }
+ }
+ }
+
+ return kNotFound;
+}
+
+//-----------------------------------------------------------------------------
+//
+// This set of methods is used to compare one buffer onto another. The
+// functions are differentiated by the size of source and dest character
+// sizes. WARNING: Your destination buffer MUST be big enough to hold all the
+// source bytes. We don't validate these ranges here (this should be done in
+// higher level routines).
+//
+
+
+/**
+ * This method compares the data in one buffer with another
+ * @update gess 01/04/99
+ * @param aStr1 is the first buffer to be compared
+ * @param aStr2 is the 2nd buffer to be compared
+ * @param aCount is the number of chars to compare
+ * @param aIgnoreCase tells us whether to use a case-sensitive comparison
+ * @return -1,0,1 depending on <,==,>
+ */
+static
+#ifdef __SUNPRO_CC
+inline
+#endif /* __SUNPRO_CC */
+PRInt32
+Compare1To1(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){
+ PRInt32 result=0;
+ if(aIgnoreCase)
+ result=PRInt32(PL_strncasecmp(aStr1, aStr2, aCount));
+ else
+ result=nsCharTraits<char>::compare(aStr1,aStr2,aCount);
+
+ // alien comparisons may return out-of-bound answers
+ // instead of the -1, 0, 1 expected by most clients
+ if ( result < -1 )
+ result = -1;
+ else if ( result > 1 )
+ result = 1;
+ return result;
+}
+
+/**
+ * This method compares the data in one buffer with another
+ * @update gess 01/04/99
+ * @param aStr1 is the first buffer to be compared
+ * @param aStr2 is the 2nd buffer to be compared
+ * @param aCount is the number of chars to compare
+ * @param aIgnoreCase tells us whether to use a case-sensitive comparison
+ * @return -1,0,1 depending on <,==,>
+ */
+static
+#ifdef __SUNPRO_CC
+inline
+#endif /* __SUNPRO_CC */
+PRInt32
+Compare2To2(const PRUnichar* aStr1,const PRUnichar* aStr2,PRUint32 aCount){
+ PRInt32 result;
+
+ if ( aStr1 && aStr2 )
+ result = nsCharTraits<PRUnichar>::compare(aStr1, aStr2, aCount);
+
+ // The following cases are rare and survivable caller errors.
+ // Two null pointers are equal, but any string, even 0 length
+ // is greater than a null pointer. It might not really matter,
+ // but we pick something reasonable anyway.
+ else if ( !aStr1 && !aStr2 )
+ result = 0;
+ else if ( aStr1 )
+ result = 1;
+ else
+ result = -1;
+
+ // alien comparisons may give answers outside the -1, 0, 1 expected by callers
+ if ( result < -1 )
+ result = -1;
+ else if ( result > 1 )
+ result = 1;
+ return result;
+}
+
+
+/**
+ * This method compares the data in one buffer with another
+ * @update gess 01/04/99
+ * @param aStr1 is the first buffer to be compared
+ * @param aStr2 is the 2nd buffer to be compared
+ * @param aCount is the number of chars to compare
+ * @param aIgnoreCase tells us whether to use a case-sensitive comparison
+ * @return -1,0,1 depending on <,==,>
+ */
+static
+#ifdef __SUNPRO_CC
+inline
+#endif /* __SUNPRO_CC */
+PRInt32
+Compare2To1(const PRUnichar* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){
+ const PRUnichar* s1 = aStr1;
+ const char *s2 = aStr2;
+
+ if (aStr1 && aStr2) {
+ if (aCount != 0) {
+ do {
+
+ PRUnichar c1 = *s1++;
+ PRUnichar c2 = PRUnichar((unsigned char)*s2++);
+
+ if (c1 != c2) {
+#ifdef NS_DEBUG
+ // we won't warn on c1>=128 (the 2-byte value) because often
+ // it is just fine to compare an constant, ascii value (i.e. "body")
+ // against some non-ascii value (i.e. a unicode string that
+ // was downloaded from a web page)
+ if (aIgnoreCase && c2>=128)
+ NS_WARNING("got a non-ASCII string, but we can't do an accurate case conversion!");
+#endif
+
+ // can't do case conversion on characters out of our range
+ if (aIgnoreCase && c1<128 && c2<128) {
+
+ c1 = ascii_tolower(char(c1));
+ c2 = ascii_tolower(char(c2));
+
+ if (c1 == c2) continue;
+ }
+
+ if (c1 < c2) return -1;
+ return 1;
+ }
+ } while (--aCount);
+ }
+ }
+ return 0;
+}
+
+
+/**
+ * This method compares the data in one buffer with another
+ * @update gess 01/04/99
+ * @param aStr1 is the first buffer to be compared
+ * @param aStr2 is the 2nd buffer to be compared
+ * @param aCount is the number of chars to compare
+ * @param aIgnoreCase tells us whether to use a case-sensitive comparison
+ * @return -1,0,1 depending on <,==,>
+ */
+inline PRInt32
+Compare1To2(const char* aStr1,const PRUnichar* aStr2,PRUint32 aCount,PRBool aIgnoreCase){
+ return Compare2To1(aStr2, aStr1, aCount, aIgnoreCase) * -1;
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// This set of methods is used compress char sequences in a buffer...
+//
+
+
+/**
+ * This method compresses duplicate runs of a given char from the given buffer
+ *
+ * @update rickg 03.23.2000
+ * @param aString is the buffer to be manipulated
+ * @param aLength is the length of the buffer
+ * @param aSet tells us which chars to compress from given buffer
+ * @param aEliminateLeading tells us whether to strip chars from the start of the buffer
+ * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
+ * @return the new length of the given buffer
+ */
+static PRInt32
+CompressChars1(char* aString,PRUint32 aLength,const char* aSet){
+
+ char* from = aString;
+ char* end = aString + aLength;
+ char* to = from;
+
+ //this code converts /n, /t, /r into normal space ' ';
+ //it also compresses runs of whitespace down to a single char...
+ if(aSet && aString && (0 < aLength)){
+ PRUint32 aSetLen=strlen(aSet);
+
+ while (from < end) {
+ char theChar = *from++;
+
+ *to++=theChar; //always copy this char...
+
+ if((kNotFound!=FindChar1(aSet,aSetLen,0,theChar,aSetLen))){
+ while (from < end) {
+ theChar = *from++;
+ if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen)){
+ *to++ = theChar;
+ break;
+ }
+ } //while
+ } //if
+ } //if
+ *to = 0;
+ }
+ return to - aString;
+}
+
+
+
+/**
+ * This method compresses duplicate runs of a given char from the given buffer
+ *
+ * @update rickg 03.23.2000
+ * @param aString is the buffer to be manipulated
+ * @param aLength is the length of the buffer
+ * @param aSet tells us which chars to compress from given buffer
+ * @param aEliminateLeading tells us whether to strip chars from the start of the buffer
+ * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
+ * @return the new length of the given buffer
+ */
+static PRInt32
+CompressChars2(PRUnichar* aString,PRUint32 aLength,const char* aSet){
+
+ PRUnichar* from = aString;
+ PRUnichar* end = from + aLength;
+ PRUnichar* to = from;
+
+ //this code converts /n, /t, /r into normal space ' ';
+ //it also compresses runs of whitespace down to a single char...
+ if(aSet && aString && (0 < aLength)){
+ PRUint32 aSetLen=strlen(aSet);
+
+ while (from < end) {
+ PRUnichar theChar = *from++;
+
+ *to++=theChar; //always copy this char...
+
+ if((theChar<256) && (kNotFound!=FindChar1(aSet,aSetLen,0,theChar,aSetLen))){
+ while (from < end) {
+ theChar = *from++;
+ if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen)){
+ *to++ = theChar;
+ break;
+ }
+ } //while
+ } //if
+ } //if
+ *to = 0;
+ }
+ return to - (PRUnichar*)aString;
+}
+
+/**
+ * This method strips chars in a given set from the given buffer
+ *
+ * @update gess 01/04/99
+ * @param aString is the buffer to be manipulated
+ * @param aLength is the length of the buffer
+ * @param aSet tells us which chars to compress from given buffer
+ * @param aEliminateLeading tells us whether to strip chars from the start of the buffer
+ * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
+ * @return the new length of the given buffer
+ */
+static PRInt32
+StripChars1(char* aString,PRUint32 aLength,const char* aSet){
+
+ // XXXdarin this code should defer writing until necessary.
+
+ char* to = aString;
+ char* from = aString-1;
+ char* end = aString + aLength;
+
+ if(aSet && aString && (0 < aLength)){
+ PRUint32 aSetLen=strlen(aSet);
+ while (++from < end) {
+ char theChar = *from;
+ if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen)){
+ *to++ = theChar;
+ }
+ }
+ *to = 0;
+ }
+ return to - (char*)aString;
+}
+
+
+/**
+ * This method strips chars in a given set from the given buffer
+ *
+ * @update gess 01/04/99
+ * @param aString is the buffer to be manipulated
+ * @param aLength is the length of the buffer
+ * @param aSet tells us which chars to compress from given buffer
+ * @param aEliminateLeading tells us whether to strip chars from the start of the buffer
+ * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
+ * @return the new length of the given buffer
+ */
+static PRInt32
+StripChars2(PRUnichar* aString,PRUint32 aLength,const char* aSet){
+
+ // XXXdarin this code should defer writing until necessary.
+
+ PRUnichar* to = aString;
+ PRUnichar* from = aString-1;
+ PRUnichar* end = to + aLength;
+
+ if(aSet && aString && (0 < aLength)){
+ PRUint32 aSetLen=strlen(aSet);
+ while (++from < end) {
+ PRUnichar theChar = *from;
+ //Note the test for ascii range below. If you have a real unicode char,
+ //and you're searching for chars in the (given) ascii string, there's no
+ //point in doing the real search since it's out of the ascii range.
+ if((255<theChar) || (kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen))){
+ *to++ = theChar;
+ }
+ }
+ *to = 0;
+ }
+ return to - (PRUnichar*)aString;
+}
+
+/* ***** END RICKG BLOCK ***** */
+
+static const char* kWhitespace="\b\t\r\n ";
+
+// This function is used to implement FindCharInSet and friends
+template <class CharT>
+#ifndef __SUNPRO_CC
+static
+#endif /* !__SUNPRO_CC */
+CharT
+GetFindInSetFilter( const CharT* set)
+ {
+ CharT filter = ~CharT(0); // All bits set
+ while (*set) {
+ filter &= ~(*set);
+ ++set;
+ }
+ return filter;
+ }
+
+// This template class is used by our code to access rickg's buffer routines.
+template <class CharT> struct nsBufferRoutines {};
+
+NS_SPECIALIZE_TEMPLATE
+struct nsBufferRoutines<char>
+ {
+ static
+ PRInt32 compare( const char* a, const char* b, PRUint32 max, PRBool ic )
+ {
+ return Compare1To1(a, b, max, ic);
+ }
+
+ static
+ PRInt32 compare( const char* a, const PRUnichar* b, PRUint32 max, PRBool ic )
+ {
+ return Compare1To2(a, b, max, ic);
+ }
+
+ static
+ PRInt32 find_char( const char* s, PRUint32 max, PRInt32 offset, const PRUnichar c, PRInt32 count )
+ {
+ return FindChar1(s, max, offset, c, count);
+ }
+
+ static
+ PRInt32 rfind_char( const char* s, PRUint32 max, PRInt32 offset, const PRUnichar c, PRInt32 count )
+ {
+ return RFindChar1(s, max, offset, c, count);
+ }
+
+ static
+ char get_find_in_set_filter( const char* set )
+ {
+ return GetFindInSetFilter(set);
+ }
+
+ static
+ PRInt32 strip_chars( char* s, PRUint32 len, const char* set )
+ {
+ return StripChars1(s, len, set);
+ }
+
+ static
+ PRInt32 compress_chars( char* s, PRUint32 len, const char* set )
+ {
+ return CompressChars1(s, len, set);
+ }
+ };
+
+NS_SPECIALIZE_TEMPLATE
+struct nsBufferRoutines<PRUnichar>
+ {
+ static
+ PRInt32 compare( const PRUnichar* a, const PRUnichar* b, PRUint32 max, PRBool ic )
+ {
+ NS_ASSERTION(!ic, "no case-insensitive compare here");
+ return Compare2To2(a, b, max);
+ }
+
+ static
+ PRInt32 compare( const PRUnichar* a, const char* b, PRUint32 max, PRBool ic )
+ {
+ return Compare2To1(a, b, max, ic);
+ }
+
+ static
+ PRInt32 find_char( const PRUnichar* s, PRUint32 max, PRInt32 offset, const PRUnichar c, PRInt32 count )
+ {
+ return FindChar2(s, max, offset, c, count);
+ }
+
+ static
+ PRInt32 rfind_char( const PRUnichar* s, PRUint32 max, PRInt32 offset, const PRUnichar c, PRInt32 count )
+ {
+ return RFindChar2(s, max, offset, c, count);
+ }
+
+ static
+ PRUnichar get_find_in_set_filter( const PRUnichar* set )
+ {
+ return GetFindInSetFilter(set);
+ }
+
+ static
+ PRUnichar get_find_in_set_filter( const char* set )
+ {
+ return (~PRUnichar(0)^~char(0)) | GetFindInSetFilter(set);
+ }
+
+ static
+ PRInt32 strip_chars( PRUnichar* s, PRUint32 max, const char* set )
+ {
+ return StripChars2(s, max, set);
+ }
+
+ static
+ PRInt32 compress_chars( PRUnichar* s, PRUint32 len, const char* set )
+ {
+ return CompressChars2(s, len, set);
+ }
+ };
+
+//-----------------------------------------------------------------------------
+
+template <class L, class R>
+#ifndef __SUNPRO_CC
+static
+#endif /* !__SUNPRO_CC */
+PRInt32
+FindSubstring( const L* big, PRUint32 bigLen,
+ const R* little, PRUint32 littleLen,
+ PRBool ignoreCase )
+ {
+ if (littleLen > bigLen)
+ return kNotFound;
+
+ PRInt32 i, max = PRInt32(bigLen - littleLen);
+ for (i=0; i<=max; ++i, ++big)
+ {
+ if (nsBufferRoutines<L>::compare(big, little, littleLen, ignoreCase) == 0)
+ return i;
+ }
+
+ return kNotFound;
+ }
+
+template <class L, class R>
+#ifndef __SUNPRO_CC
+static
+#endif /* !__SUNPRO_CC */
+PRInt32
+RFindSubstring( const L* big, PRUint32 bigLen,
+ const R* little, PRUint32 littleLen,
+ PRBool ignoreCase )
+ {
+ if (littleLen > bigLen)
+ return kNotFound;
+
+ PRInt32 i, max = PRInt32(bigLen - littleLen);
+
+ const L* iter = big + max;
+ for (i=max; iter >= big; --i, --iter)
+ {
+ if (nsBufferRoutines<L>::compare(iter, little, littleLen, ignoreCase) == 0)
+ return i;
+ }
+
+ return kNotFound;
+ }
+
+template <class CharT, class SetCharT>
+#ifndef __SUNPRO_CC
+static
+#endif /* !__SUNPRO_CC */
+PRInt32
+FindCharInSet( const CharT* data, PRUint32 dataLen, const SetCharT* set )
+ {
+ CharT filter = nsBufferRoutines<CharT>::get_find_in_set_filter(set);
+
+ const CharT* end = data + dataLen;
+ for (const CharT* iter = data; iter < end; ++iter)
+ {
+ CharT currentChar = *iter;
+ if (currentChar & filter)
+ continue; // char is not in filter set; go on with next char.
+
+ // test all chars
+ const SetCharT* charInSet = set;
+ CharT setChar = CharT(*charInSet);
+ while (setChar)
+ {
+ if (setChar == currentChar)
+ return iter - data; // found it! return index of the found char.
+
+ setChar = CharT(*(++charInSet));
+ }
+ }
+ return kNotFound;
+ }
+
+template <class CharT, class SetCharT>
+#ifndef __SUNPRO_CC
+static
+#endif /* !__SUNPRO_CC */
+PRInt32
+RFindCharInSet( const CharT* data, PRUint32 dataLen, const SetCharT* set )
+ {
+ CharT filter = nsBufferRoutines<CharT>::get_find_in_set_filter(set);
+
+ for (const CharT* iter = data + dataLen - 1; iter >= data; --iter)
+ {
+ CharT currentChar = *iter;
+ if (currentChar & filter)
+ continue; // char is not in filter set; go on with next char.
+
+ // test all chars
+ const CharT* charInSet = set;
+ CharT setChar = *charInSet;
+ while (setChar)
+ {
+ if (setChar == currentChar)
+ return iter - data; // found it! return index of the found char.
+
+ setChar = *(++charInSet);
+ }
+ }
+ return kNotFound;
+ }
+
+/**
+ * This is a copy of |PR_cnvtf| with a bug fixed. (The second argument
+ * of PR_dtoa is 2 rather than 1.)
+ *
+ * XXXdarin if this is the right thing, then why wasn't it fixed in NSPR?!?
+ */
+void
+Modified_cnvtf(char *buf, int bufsz, int prcsn, double fval)
+{
+ PRIntn decpt, sign, numdigits;
+ char *num, *nump;
+ char *bufp = buf;
+ char *endnum;
+
+ /* If anything fails, we store an empty string in 'buf' */
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ num = (char*)RTMemAlloc(bufsz);
+#else
+ num = (char*)malloc(bufsz);
+#endif
+ if (num == NULL) {
+ buf[0] = '\0';
+ return;
+ }
+ if (PR_dtoa(fval, 2, prcsn, &decpt, &sign, &endnum, num, bufsz)
+ == PR_FAILURE) {
+ buf[0] = '\0';
+ goto done;
+ }
+ numdigits = endnum - num;
+ nump = num;
+
+ /*
+ * The NSPR code had a fancy way of checking that we weren't dealing
+ * with -0.0 or -NaN, but I'll just use < instead.
+ * XXX Should we check !isnan(fval) as well? Is it portable? We
+ * probably don't need to bother since NAN isn't portable.
+ */
+ if (sign && fval < 0.0f) {
+ *bufp++ = '-';
+ }
+
+ if (decpt == 9999) {
+ while ((*bufp++ = *nump++) != 0) {} /* nothing to execute */
+ goto done;
+ }
+
+ if (decpt > (prcsn+1) || decpt < -(prcsn-1) || decpt < -5) {
+ *bufp++ = *nump++;
+ if (numdigits != 1) {
+ *bufp++ = '.';
+ }
+
+ while (*nump != '\0') {
+ *bufp++ = *nump++;
+ }
+ *bufp++ = 'e';
+ PR_snprintf(bufp, bufsz - (bufp - buf), "%+d", decpt-1);
+ }
+ else if (decpt >= 0) {
+ if (decpt == 0) {
+ *bufp++ = '0';
+ }
+ else {
+ while (decpt--) {
+ if (*nump != '\0') {
+ *bufp++ = *nump++;
+ }
+ else {
+ *bufp++ = '0';
+ }
+ }
+ }
+ if (*nump != '\0') {
+ *bufp++ = '.';
+ while (*nump != '\0') {
+ *bufp++ = *nump++;
+ }
+ }
+ *bufp++ = '\0';
+ }
+ else if (decpt < 0) {
+ *bufp++ = '0';
+ *bufp++ = '.';
+ while (decpt++) {
+ *bufp++ = '0';
+ }
+
+ while (*nump != '\0') {
+ *bufp++ = *nump++;
+ }
+ *bufp++ = '\0';
+ }
+done:
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(num);
+#else
+ free(num);
+#endif
+}
+
+ /**
+ * this method changes the meaning of |offset| and |count|:
+ *
+ * upon return,
+ * |offset| specifies start of search range
+ * |count| specifies length of search range
+ */
+static void
+Find_ComputeSearchRange( PRUint32 bigLen, PRUint32 littleLen, PRInt32& offset, PRInt32& count )
+ {
+ // |count| specifies how many iterations to make from |offset|
+
+ if (offset < 0)
+ {
+ offset = 0;
+ }
+ else if (PRUint32(offset) > bigLen)
+ {
+ count = 0;
+ return;
+ }
+
+ PRInt32 maxCount = bigLen - offset;
+ if (count < 0 || count > maxCount)
+ {
+ count = maxCount;
+ }
+ else
+ {
+ count += littleLen;
+ if (count > maxCount)
+ count = maxCount;
+ }
+ }
+
+ /**
+ * this method changes the meaning of |offset| and |count|:
+ *
+ * upon entry,
+ * |offset| specifies the end point from which to search backwards
+ * |count| specifies the number of iterations from |offset|
+ *
+ * upon return,
+ * |offset| specifies start of search range
+ * |count| specifies length of search range
+ *
+ *
+ * EXAMPLE
+ *
+ * + -- littleLen=4 -- +
+ * : :
+ * |____|____|____|____|____|____|____|____|____|____|____|____|
+ * : :
+ * offset=5 bigLen=12
+ *
+ * if count = 4, then we expect this function to return offset = 2 and
+ * count = 7.
+ *
+ */
+static void
+RFind_ComputeSearchRange( PRUint32 bigLen, PRUint32 littleLen, PRInt32& offset, PRInt32& count )
+ {
+ if (littleLen > bigLen)
+ {
+ offset = 0;
+ count = 0;
+ return;
+ }
+
+ if (offset < 0)
+ offset = bigLen - littleLen;
+ if (count < 0)
+ count = offset + 1;
+
+ PRInt32 start = offset - count + 1;
+ if (start < 0)
+ start = 0;
+
+ count = offset + littleLen - start;
+ offset = start;
+ }
+
+//-----------------------------------------------------------------------------
+
+ // define nsString obsolete methods
+#include "string-template-def-unichar.h"
+#include "nsTStringObsolete.cpp"
+#include "string-template-undef.h"
+
+ // define nsCString obsolete methods
+#include "string-template-def-char.h"
+#include "nsTStringObsolete.cpp"
+#include "string-template-undef.h"
+
+//-----------------------------------------------------------------------------
+
+// specialized methods:
+
+PRInt32
+nsString::Find( const nsAFlatString& aString, PRInt32 aOffset, PRInt32 aCount ) const
+ {
+ // this method changes the meaning of aOffset and aCount:
+ Find_ComputeSearchRange(mLength, aString.Length(), aOffset, aCount);
+
+ PRInt32 result = FindSubstring(mData + aOffset, aCount, aString.get(), aString.Length(), PR_FALSE);
+ if (result != kNotFound)
+ result += aOffset;
+ return result;
+ }
+
+PRInt32
+nsString::Find( const PRUnichar* aString, PRInt32 aOffset, PRInt32 aCount ) const
+ {
+ return Find(nsDependentString(aString), aOffset, aCount);
+ }
+
+PRInt32
+nsString::RFind( const nsAFlatString& aString, PRInt32 aOffset, PRInt32 aCount ) const
+ {
+ // this method changes the meaning of aOffset and aCount:
+ RFind_ComputeSearchRange(mLength, aString.Length(), aOffset, aCount);
+
+ PRInt32 result = RFindSubstring(mData + aOffset, aCount, aString.get(), aString.Length(), PR_FALSE);
+ if (result != kNotFound)
+ result += aOffset;
+ return result;
+ }
+
+PRInt32
+nsString::RFind( const PRUnichar* aString, PRInt32 aOffset, PRInt32 aCount ) const
+ {
+ return RFind(nsDependentString(aString), aOffset, aCount);
+ }
+
+PRInt32
+nsString::FindCharInSet( const PRUnichar* aSet, PRInt32 aOffset ) const
+ {
+ if (aOffset < 0)
+ aOffset = 0;
+ else if (aOffset >= PRInt32(mLength))
+ return kNotFound;
+
+ PRInt32 result = ::FindCharInSet(mData + aOffset, mLength - aOffset, aSet);
+ if (result != kNotFound)
+ result += aOffset;
+ return result;
+ }
+
+
+ /**
+ * nsTString::Compare,CompareWithConversion,etc.
+ */
+
+PRInt32
+nsCString::Compare( const char* aString, PRBool aIgnoreCase, PRInt32 aCount ) const
+ {
+ PRUint32 strLen = char_traits::length(aString);
+
+ PRInt32 maxCount = PRInt32(NS_MIN(mLength, strLen));
+
+ PRInt32 compareCount;
+ if (aCount < 0 || aCount > maxCount)
+ compareCount = maxCount;
+ else
+ compareCount = aCount;
+
+ PRInt32 result =
+ nsBufferRoutines<char>::compare(mData, aString, compareCount, aIgnoreCase);
+
+ if (result == 0 &&
+ (aCount < 0 || strLen < PRUint32(aCount) || mLength < PRUint32(aCount)))
+ {
+ // Since the caller didn't give us a length to test, or strings shorter
+ // than aCount, and compareCount characters matched, we have to assume
+ // that the longer string is greater.
+
+ if (mLength != strLen)
+ result = (mLength < strLen) ? -1 : 1;
+ }
+ return result;
+ }
+
+PRBool
+nsString::EqualsIgnoreCase( const char* aString, PRInt32 aCount ) const
+ {
+ PRUint32 strLen = nsCharTraits<char>::length(aString);
+
+ PRInt32 maxCount = PRInt32(NS_MIN(mLength, strLen));
+
+ PRInt32 compareCount;
+ if (aCount < 0 || aCount > maxCount)
+ compareCount = maxCount;
+ else
+ compareCount = aCount;
+
+ PRInt32 result =
+ nsBufferRoutines<PRUnichar>::compare(mData, aString, compareCount, PR_TRUE);
+
+ if (result == 0 &&
+ (aCount < 0 || strLen < PRUint32(aCount) || mLength < PRUint32(aCount)))
+ {
+ // Since the caller didn't give us a length to test, or strings shorter
+ // than aCount, and compareCount characters matched, we have to assume
+ // that the longer string is greater.
+
+ if (mLength != strLen)
+ result = 1; // Arbitrarily using any number != 0
+ }
+ return result == 0;
+ }
+
+ /**
+ * ToCString, ToFloat, ToInteger
+ */
+
+char*
+nsString::ToCString( char* aBuf, PRUint32 aBufLength, PRUint32 aOffset ) const
+ {
+ // because the old implementation checked aBuf
+ if (!(aBuf && aBufLength > 0 && aOffset <= mLength))
+ return nsnull;
+
+ PRUint32 maxCount = NS_MIN(aBufLength-1, mLength - aOffset);
+
+ LossyConvertEncoding<PRUnichar, char> converter(aBuf);
+ converter.write(mData + aOffset, maxCount);
+ converter.write_terminator();
+ return aBuf;
+ }
+
+float
+nsCString::ToFloat(PRInt32* aErrorCode) const
+ {
+ float res = 0.0f;
+ if (mLength > 0)
+ {
+ char *conv_stopped;
+ const char *str = mData;
+ // Use PR_strtod, not strtod, since we don't want locale involved.
+ res = (float)PR_strtod(str, &conv_stopped);
+ if (conv_stopped == str+mLength)
+ *aErrorCode = (PRInt32) NS_OK;
+ else // Not all the string was scanned
+ *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE;
+ }
+ else
+ {
+ // The string was too short (0 characters)
+ *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE;
+ }
+ return res;
+ }
+
+float
+nsString::ToFloat(PRInt32* aErrorCode) const
+ {
+ float res = 0.0f;
+ char buf[100];
+ if (mLength > 0 && mLength < sizeof(buf))
+ {
+ char *conv_stopped;
+ const char *str = ToCString(buf, sizeof(buf));
+ // Use PR_strtod, not strtod, since we don't want locale involved.
+ res = (float)PR_strtod(str, &conv_stopped);
+ if (conv_stopped == str+mLength)
+ *aErrorCode = (PRInt32) NS_OK;
+ else // Not all the string was scanned
+ *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE;
+ }
+ else
+ {
+ // The string was too short (0 characters) or too long (sizeof(buf))
+ *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE;
+ }
+ return res;
+ }
+
+
+ /**
+ * nsTString::AssignWithConversion
+ */
+
+void
+nsCString::AssignWithConversion( const nsAString& aData )
+ {
+ LossyCopyUTF16toASCII(aData, *this);
+ }
+
+void
+nsString::AssignWithConversion( const nsACString& aData )
+ {
+ CopyASCIItoUTF16(aData, *this);
+ }
+
+
+ /**
+ * nsTString::AppendWithConversion
+ */
+
+void
+nsCString::AppendWithConversion( const nsAString& aData )
+ {
+ LossyAppendUTF16toASCII(aData, *this);
+ }
+
+void
+nsString::AppendWithConversion( const nsACString& aData )
+ {
+ AppendASCIItoUTF16(aData, *this);
+ }
+
+
+ /**
+ * nsTString::AppendInt
+ */
+
+void
+nsCString::AppendInt( PRInt32 aInteger, PRInt32 aRadix )
+ {
+ char buf[20];
+ const char* fmt;
+ switch (aRadix) {
+ case 8:
+ fmt = "%o";
+ break;
+ case 10:
+ fmt = "%d";
+ break;
+ default:
+ NS_ASSERTION(aRadix == 16, "Invalid radix!");
+ fmt = "%x";
+ }
+ PR_snprintf(buf, sizeof(buf), fmt, aInteger);
+ Append(buf);
+ }
+
+void
+nsString::AppendInt( PRInt32 aInteger, PRInt32 aRadix )
+ {
+ char buf[20];
+ const char* fmt;
+ switch (aRadix) {
+ case 8:
+ fmt = "%o";
+ break;
+ case 10:
+ fmt = "%d";
+ break;
+ default:
+ NS_ASSERTION(aRadix == 16, "Invalid radix!");
+ fmt = "%x";
+ }
+ PR_snprintf(buf, sizeof(buf), fmt, aInteger);
+ AppendASCIItoUTF16(buf, *this);
+ }
+
+void
+nsCString::AppendInt( PRInt64 aInteger, PRInt32 aRadix )
+ {
+ char buf[30];
+ const char* fmt;
+ switch (aRadix) {
+ case 8:
+ fmt = "%llo";
+ break;
+ case 10:
+ fmt = "%lld";
+ break;
+ default:
+ NS_ASSERTION(aRadix == 16, "Invalid radix!");
+ fmt = "%llx";
+ }
+ PR_snprintf(buf, sizeof(buf), fmt, aInteger);
+ Append(buf);
+ }
+
+void
+nsString::AppendInt( PRInt64 aInteger, PRInt32 aRadix )
+ {
+ char buf[30];
+ const char* fmt;
+ switch (aRadix) {
+ case 8:
+ fmt = "%llo";
+ break;
+ case 10:
+ fmt = "%lld";
+ break;
+ default:
+ NS_ASSERTION(aRadix == 16, "Invalid radix!");
+ fmt = "%llx";
+ }
+ PR_snprintf(buf, sizeof(buf), fmt, aInteger);
+ AppendASCIItoUTF16(buf, *this);
+ }
+
+ /**
+ * nsTString::AppendFloat
+ */
+
+void
+nsCString::AppendFloat( double aFloat )
+ {
+ char buf[40];
+ // Use Modified_cnvtf, which is locale-insensitive, instead of the
+ // locale-sensitive PR_snprintf or sprintf(3)
+ Modified_cnvtf(buf, sizeof(buf), 6, aFloat);
+ Append(buf);
+ }
+
+void
+nsString::AppendFloat( double aFloat )
+ {
+ char buf[40];
+ // Use Modified_cnvtf, which is locale-insensitive, instead of the
+ // locale-sensitive PR_snprintf or sprintf(3)
+ Modified_cnvtf(buf, sizeof(buf), 6, aFloat);
+ AppendWithConversion(buf);
+ }
+
+#endif // !MOZ_STRING_WITH_OBSOLETE_API
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsSubstring.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsSubstring.cpp
new file mode 100644
index 00000000..6ed0c5c8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsSubstring.cpp
@@ -0,0 +1,250 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+#ifdef DEBUG
+#define ENABLE_STRING_STATS
+#endif
+
+#ifdef ENABLE_STRING_STATS
+#include <stdio.h>
+#endif
+
+#include <stdlib.h>
+#include "nsSubstring.h"
+#include "nsString.h"
+#include "nsDependentString.h"
+#include "nsMemory.h"
+#include "pratom.h"
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+# include <iprt/mem.h>
+#endif
+
+// ---------------------------------------------------------------------------
+
+static const PRUnichar gNullChar = 0;
+
+const char* nsCharTraits<char> ::sEmptyBuffer = (const char*) &gNullChar;
+const PRUnichar* nsCharTraits<PRUnichar>::sEmptyBuffer = &gNullChar;
+
+// ---------------------------------------------------------------------------
+
+#ifdef ENABLE_STRING_STATS
+class nsStringStats
+ {
+ public:
+ nsStringStats()
+ : mAllocCount(0), mReallocCount(0), mFreeCount(0), mShareCount(0) {}
+
+ ~nsStringStats()
+ {
+ // this is a hack to suppress duplicate string stats printing
+ // in seamonkey as a result of the string code being linked
+ // into seamonkey and libxpcom! :-(
+ if (!mAllocCount && !mAdoptCount)
+ return;
+
+#ifndef VBOX
+ printf("nsStringStats\n");
+ printf(" => mAllocCount: % 10d\n", mAllocCount);
+ printf(" => mReallocCount: % 10d\n", mReallocCount);
+ printf(" => mFreeCount: % 10d", mFreeCount);
+ if (mAllocCount > mFreeCount)
+ printf(" -- LEAKED %d !!!\n", mAllocCount - mFreeCount);
+ else
+ printf("\n");
+ printf(" => mShareCount: % 10d\n", mShareCount);
+ printf(" => mAdoptCount: % 10d\n", mAdoptCount);
+ printf(" => mAdoptFreeCount: % 10d", mAdoptFreeCount);
+ if (mAdoptCount > mAdoptFreeCount)
+ printf(" -- LEAKED %d !!!\n", mAdoptCount - mAdoptFreeCount);
+ else
+ printf("\n");
+#endif
+ }
+
+ PRInt32 mAllocCount;
+ PRInt32 mReallocCount;
+ PRInt32 mFreeCount;
+ PRInt32 mShareCount;
+ PRInt32 mAdoptCount;
+ PRInt32 mAdoptFreeCount;
+ };
+static nsStringStats gStringStats;
+#define STRING_STAT_INCREMENT(_s) PR_AtomicIncrement(&gStringStats.m ## _s ## Count)
+#else
+#define STRING_STAT_INCREMENT(_s)
+#endif
+
+// ---------------------------------------------------------------------------
+
+ /**
+ * This structure precedes the string buffers "we" allocate. It may be the
+ * case that nsTSubstring::mData does not point to one of these special
+ * buffers. The mFlags member variable distinguishes the buffer type.
+ *
+ * When this header is in use, it enables reference counting, and capacity
+ * tracking. NOTE: A string buffer can be modified only if its reference
+ * count is 1.
+ */
+class nsStringHeader
+ {
+ private:
+
+ PRInt32 mRefCount;
+ PRUint32 mStorageSize;
+
+ public:
+
+ void AddRef()
+ {
+ PR_AtomicIncrement(&mRefCount);
+ STRING_STAT_INCREMENT(Share);
+ }
+
+ void Release()
+ {
+ if (PR_AtomicDecrement(&mRefCount) == 0)
+ {
+ STRING_STAT_INCREMENT(Free);
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(this); // we were allocated with |malloc|
+#else
+ free(this); // we were allocated with |malloc|
+#endif
+ }
+ }
+
+ /**
+ * Alloc returns a pointer to a new string header with set capacity.
+ */
+ static nsStringHeader* Alloc(size_t size)
+ {
+ STRING_STAT_INCREMENT(Alloc);
+
+ NS_ASSERTION(size != 0, "zero capacity allocation not allowed");
+
+ nsStringHeader *hdr =
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ (nsStringHeader *) RTMemAlloc(sizeof(nsStringHeader) + size);
+#else
+ (nsStringHeader *) malloc(sizeof(nsStringHeader) + size);
+#endif
+ if (hdr)
+ {
+ hdr->mRefCount = 1;
+ hdr->mStorageSize = size;
+ }
+ return hdr;
+ }
+
+ static nsStringHeader* Realloc(nsStringHeader* hdr, size_t size)
+ {
+ STRING_STAT_INCREMENT(Realloc);
+
+ NS_ASSERTION(size != 0, "zero capacity allocation not allowed");
+
+ // no point in trying to save ourselves if we hit this assertion
+ NS_ASSERTION(!hdr->IsReadonly(), "|Realloc| attempted on readonly string");
+
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ hdr = (nsStringHeader*) RTMemRealloc(hdr, sizeof(nsStringHeader) + size);
+#else
+ hdr = (nsStringHeader*) realloc(hdr, sizeof(nsStringHeader) + size);
+#endif
+ if (hdr)
+ hdr->mStorageSize = size;
+
+ return hdr;
+ }
+
+ static nsStringHeader* FromData(void* data)
+ {
+ return (nsStringHeader*) ( ((char*) data) - sizeof(nsStringHeader) );
+ }
+
+ void* Data() const
+ {
+ return (void*) ( ((char*) this) + sizeof(nsStringHeader) );
+ }
+
+ PRUint32 StorageSize() const
+ {
+ return mStorageSize;
+ }
+
+ /**
+ * Because nsTSubstring allows only single threaded access, if this
+ * method returns FALSE, then the caller can be sure that it has
+ * exclusive access to the nsStringHeader and associated data.
+ * However, if this function returns TRUE, then other strings may
+ * rely on the data in this buffer being constant and other threads
+ * may access this buffer simultaneously.
+ */
+ PRBool IsReadonly() const
+ {
+ return mRefCount > 1;
+ }
+ };
+
+// ---------------------------------------------------------------------------
+
+inline void
+ReleaseData( void* data, PRUint32 flags )
+ {
+ if (flags & nsSubstring::F_SHARED)
+ {
+ nsStringHeader::FromData(data)->Release();
+ }
+ else if (flags & nsSubstring::F_OWNED)
+ {
+ nsMemory::Free(data);
+ STRING_STAT_INCREMENT(AdoptFree);
+ }
+ // otherwise, nothing to do.
+ }
+
+
+ // define nsSubstring
+#include "string-template-def-unichar.h"
+#include "nsTSubstring.cpp"
+#include "string-template-undef.h"
+
+ // define nsCSubstring
+#include "string-template-def-char.h"
+#include "nsTSubstring.cpp"
+#include "string-template-undef.h"
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsSubstringTuple.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsSubstringTuple.cpp
new file mode 100644
index 00000000..a5445d7a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsSubstringTuple.cpp
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "nsSubstringTuple.h"
+
+#if 0
+ // convert fragment to |const string_base_type&|
+#define TO_SUBSTRING(_v) \
+ ( (ptrdiff_t(_v) & 0x1) \
+ ? NS_REINTERPRET_CAST(const abstract_string_type*, \
+ ((unsigned long)_v & ~0x1))->ToSubstring() \
+ : *NS_REINTERPRET_CAST(const substring_type*, (_v)) )
+#endif
+
+ // convert fragment to |const substring_type&|
+#define TO_SUBSTRING(_v) \
+ ( (_v)->mVTable == obsolete_string_type::sCanonicalVTable \
+ ? *(_v)->AsSubstring() \
+ : (_v)->ToSubstring() )
+
+ // define nsSubstringTuple
+#include "string-template-def-unichar.h"
+#include "nsTSubstringTuple.cpp"
+#include "string-template-undef.h"
+
+ // define nsCSubstringTuple
+#include "string-template-def-char.h"
+#include "nsTSubstringTuple.cpp"
+#include "string-template-undef.h"
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTAString.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTAString.cpp
new file mode 100644
index 00000000..ffd75fe8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsTAString.cpp
@@ -0,0 +1,509 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+ /**
+ * Some comments on this implementation...
+ *
+ * This class is a bridge between the old string implementation and the new
+ * string implementation. If mVTable points to the canonical vtable for the
+ * new string implementation, then we can cast directly to the new string
+ * classes (helped by the AsSubstring() methods). However, if mVTable is not
+ * ours, then we need to call through the vtable to satisfy the nsTAString
+ * methods.
+ *
+ * In most cases we will avoid the vtable.
+ */
+
+
+nsTAString_CharT::~nsTAString_CharT()
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Finalize();
+ else
+ AsObsoleteString()->~nsTObsoleteAString_CharT();
+ }
+
+
+nsTAString_CharT::size_type
+nsTAString_CharT::Length() const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->Length();
+
+ return AsObsoleteString()->Length();
+ }
+
+PRBool
+nsTAString_CharT::Equals( const self_type& readable ) const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->Equals(readable);
+
+ return ToSubstring().Equals(readable);
+ }
+
+PRBool
+nsTAString_CharT::Equals( const self_type& readable, const comparator_type& comparator ) const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->Equals(readable, comparator);
+
+ return ToSubstring().Equals(readable, comparator);
+ }
+
+PRBool
+nsTAString_CharT::Equals( const char_type* data ) const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->Equals(data);
+
+ return ToSubstring().Equals(data);
+ }
+
+PRBool
+nsTAString_CharT::Equals( const char_type* data, const comparator_type& comparator ) const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->Equals(data, comparator);
+
+ return ToSubstring().Equals(data, comparator);
+ }
+
+PRBool
+nsTAString_CharT::EqualsASCII( const char* data, size_type len ) const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->EqualsASCII(data, len);
+
+ return ToSubstring().EqualsASCII(data, len);
+ }
+
+PRBool
+nsTAString_CharT::EqualsASCII( const char* data ) const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->EqualsASCII(data);
+
+ return ToSubstring().EqualsASCII(data);
+ }
+
+PRBool
+nsTAString_CharT::LowerCaseEqualsASCII( const char* data, size_type len ) const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->LowerCaseEqualsASCII(data, len);
+
+ return ToSubstring().LowerCaseEqualsASCII(data, len);
+ }
+
+PRBool
+nsTAString_CharT::LowerCaseEqualsASCII( const char* data ) const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->LowerCaseEqualsASCII(data);
+
+ return ToSubstring().LowerCaseEqualsASCII(data);
+ }
+
+PRBool
+nsTAString_CharT::IsVoid() const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->IsVoid();
+
+ return AsObsoleteString()->IsVoid();
+ }
+
+void
+nsTAString_CharT::SetIsVoid( PRBool val )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->SetIsVoid(val);
+ else
+ AsObsoleteString()->SetIsVoid(val);
+ }
+
+PRBool
+nsTAString_CharT::IsTerminated() const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->IsTerminated();
+
+ return AsObsoleteString()->GetFlatBufferHandle() != nsnull;
+ }
+
+CharT
+nsTAString_CharT::First() const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->First();
+
+ return ToSubstring().First();
+ }
+
+CharT
+nsTAString_CharT::Last() const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->Last();
+
+ return ToSubstring().Last();
+ }
+
+nsTAString_CharT::size_type
+nsTAString_CharT::CountChar( char_type c ) const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->CountChar(c);
+
+ return ToSubstring().CountChar(c);
+ }
+
+PRInt32
+nsTAString_CharT::FindChar( char_type c, index_type offset ) const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->FindChar(c, offset);
+
+ return ToSubstring().FindChar(c, offset);
+ }
+
+void
+nsTAString_CharT::SetCapacity( size_type size )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->SetCapacity(size);
+ else
+ AsObsoleteString()->SetCapacity(size);
+ }
+
+void
+nsTAString_CharT::SetLength( size_type size )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->SetLength(size);
+ else
+ AsObsoleteString()->SetLength(size);
+ }
+
+void
+nsTAString_CharT::Assign( const self_type& readable )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Assign(readable);
+ else
+ AsObsoleteString()->do_AssignFromReadable(readable);
+ }
+
+void
+nsTAString_CharT::Assign( const substring_tuple_type& tuple )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Assign(tuple);
+ else
+ AsObsoleteString()->do_AssignFromReadable(nsTAutoString_CharT(tuple));
+ }
+
+void
+nsTAString_CharT::Assign( const char_type* data )
+ {
+ // null check and SetLength(0) cases needed for backwards compat
+
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Assign(data);
+ else if (data)
+ AsObsoleteString()->do_AssignFromElementPtr(data);
+ else
+ AsObsoleteString()->SetLength(0);
+ }
+
+void
+nsTAString_CharT::Assign( const char_type* data, size_type length )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Assign(data, length);
+ else
+ AsObsoleteString()->do_AssignFromElementPtrLength(data, length);
+ }
+
+void
+nsTAString_CharT::AssignASCII( const char* data )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->AssignASCII(data);
+ else
+ {
+#ifdef CharT_is_char
+ AsObsoleteString()->do_AssignFromElementPtr(data);
+#else
+ nsTAutoString_CharT temp;
+ temp.AssignASCII(data);
+ AsObsoleteString()->do_AssignFromReadable(temp);
+#endif
+ }
+ }
+
+void
+nsTAString_CharT::AssignASCII( const char* data, size_type length )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->AssignASCII(data, length);
+ else
+ {
+#ifdef CharT_is_char
+ AsObsoleteString()->do_AssignFromElementPtrLength(data, length);
+#else
+ nsTAutoString_CharT temp;
+ temp.AssignASCII(data, length);
+ AsObsoleteString()->do_AssignFromReadable(temp);
+#endif
+ }
+ }
+
+void
+nsTAString_CharT::Assign( char_type c )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Assign(c);
+ else
+ AsObsoleteString()->do_AssignFromElement(c);
+ }
+
+void
+nsTAString_CharT::Append( const self_type& readable )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Append(readable);
+ else
+ AsObsoleteString()->do_AppendFromReadable(readable);
+ }
+
+void
+nsTAString_CharT::Append( const substring_tuple_type& tuple )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Append(tuple);
+ else
+ AsObsoleteString()->do_AppendFromReadable(nsTAutoString_CharT(tuple));
+ }
+
+void
+nsTAString_CharT::Append( const char_type* data )
+ {
+ // null check case needed for backwards compat
+
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Append(data);
+ else if (data)
+ AsObsoleteString()->do_AppendFromElementPtr(data);
+ }
+
+void
+nsTAString_CharT::Append( const char_type* data, size_type length )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Append(data, length);
+ else
+ AsObsoleteString()->do_AppendFromElementPtrLength(data, length);
+ }
+
+void
+nsTAString_CharT::AppendASCII( const char* data )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->AppendASCII(data);
+ else
+ {
+#ifdef CharT_is_char
+ AsObsoleteString()->do_AppendFromElementPtr(data);
+#else
+ nsTAutoString_CharT temp;
+ temp.AssignASCII(data);
+ AsObsoleteString()->do_AppendFromReadable(temp);
+#endif
+ }
+ }
+
+void
+nsTAString_CharT::AppendASCII( const char* data, size_type length )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->AppendASCII(data, length);
+ else
+ {
+#ifdef CharT_is_char
+ AsObsoleteString()->do_AppendFromElementPtrLength(data, length);
+#else
+ nsTAutoString_CharT temp;
+ temp.AssignASCII(data, length);
+ AsObsoleteString()->do_AppendFromReadable(temp);
+#endif
+ }
+ }
+
+void
+nsTAString_CharT::Append( char_type c )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Append(c);
+ else
+ AsObsoleteString()->do_AppendFromElement(c);
+ }
+
+void
+nsTAString_CharT::Insert( const self_type& readable, index_type pos )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Insert(readable, pos);
+ else
+ AsObsoleteString()->do_InsertFromReadable(readable, pos);
+ }
+
+void
+nsTAString_CharT::Insert( const substring_tuple_type& tuple, index_type pos )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Insert(tuple, pos);
+ else
+ AsObsoleteString()->do_InsertFromReadable(nsTAutoString_CharT(tuple), pos);
+ }
+
+void
+nsTAString_CharT::Insert( const char_type* data, index_type pos )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Insert(data, pos);
+ else
+ AsObsoleteString()->do_InsertFromElementPtr(data, pos);
+ }
+
+void
+nsTAString_CharT::Insert( const char_type* data, index_type pos, size_type length )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Insert(data, pos, length);
+ else
+ AsObsoleteString()->do_InsertFromElementPtrLength(data, pos, length);
+ }
+
+void
+nsTAString_CharT::Insert( char_type c, index_type pos )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Insert(c, pos);
+ else
+ AsObsoleteString()->do_InsertFromElement(c, pos);
+ }
+
+void
+nsTAString_CharT::Cut( index_type cutStart, size_type cutLength )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Cut(cutStart, cutLength);
+ else
+ AsObsoleteString()->Cut(cutStart, cutLength);
+ }
+
+void
+nsTAString_CharT::Replace( index_type cutStart, size_type cutLength, const self_type& readable )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Replace(cutStart, cutLength, readable);
+ else
+ AsObsoleteString()->do_ReplaceFromReadable(cutStart, cutLength, readable);
+ }
+
+void
+nsTAString_CharT::Replace( index_type cutStart, size_type cutLength, const substring_tuple_type& tuple )
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ AsSubstring()->Replace(cutStart, cutLength, tuple);
+ else
+ AsObsoleteString()->do_ReplaceFromReadable(cutStart, cutLength, nsTAutoString_CharT(tuple));
+ }
+
+nsTAString_CharT::size_type
+nsTAString_CharT::GetReadableBuffer( const char_type **data ) const
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ {
+ const substring_type* str = AsSubstring();
+ *data = str->mData;
+ return str->mLength;
+ }
+
+ obsolete_string_type::const_fragment_type frag;
+ AsObsoleteString()->GetReadableFragment(frag, obsolete_string_type::kFirstFragment, 0);
+ *data = frag.mStart;
+ return (frag.mEnd - frag.mStart);
+ }
+
+nsTAString_CharT::size_type
+nsTAString_CharT::GetWritableBuffer(char_type **data)
+ {
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ {
+ substring_type* str = AsSubstring();
+ str->BeginWriting(*data);
+ return str->Length();
+ }
+
+ obsolete_string_type::fragment_type frag;
+ AsObsoleteString()->GetWritableFragment(frag, obsolete_string_type::kFirstFragment, 0);
+ *data = frag.mStart;
+ return (frag.mEnd - frag.mStart);
+ }
+
+PRBool
+nsTAString_CharT::IsDependentOn(const char_type* start, const char_type *end) const
+ {
+ // this is an optimization...
+ if (mVTable == obsolete_string_type::sCanonicalVTable)
+ return AsSubstring()->IsDependentOn(start, end);
+
+ return ToSubstring().IsDependentOn(start, end);
+ }
+
+const nsTAString_CharT::substring_type
+nsTAString_CharT::ToSubstring() const
+ {
+ const char_type* data;
+ size_type length = GetReadableBuffer(&data);
+ return substring_type(NS_CONST_CAST(char_type*, data), length, 0);
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTDependentSubstring.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTDependentSubstring.cpp
new file mode 100644
index 00000000..8421ecc0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsTDependentSubstring.cpp
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+void
+nsTDependentSubstring_CharT::Rebind( const abstract_string_type& readable, PRUint32 startPos, PRUint32 length )
+ {
+ size_type strLength = readable.GetReadableBuffer((const char_type**) &mData);
+
+ if (startPos > strLength)
+ startPos = strLength;
+
+ mData += startPos;
+ mLength = NS_MIN(length, strLength - startPos);
+
+ SetDataFlags(F_NONE);
+ }
+
+void
+nsTDependentSubstring_CharT::Rebind( const substring_type& str, PRUint32 startPos, PRUint32 length )
+ {
+ size_type strLength = str.Length();
+
+ if (startPos > strLength)
+ startPos = strLength;
+
+ mData = NS_CONST_CAST(char_type*, str.Data()) + startPos;
+ mLength = NS_MIN(length, strLength - startPos);
+
+ SetDataFlags(F_NONE);
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTObsoleteAStringThunk.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTObsoleteAStringThunk.cpp
new file mode 100644
index 00000000..3d1590a8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsTObsoleteAStringThunk.cpp
@@ -0,0 +1,235 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+class nsTObsoleteAStringThunk_CharT : public nsTObsoleteAString_CharT
+ {
+ public:
+ typedef nsTObsoleteAStringThunk_CharT self_type;
+ typedef nsTSubstring_CharT substring_type;
+
+ public:
+
+ nsTObsoleteAStringThunk_CharT() {}
+
+
+ static const void* get_vptr()
+ {
+ const void* result;
+ new (&result) self_type();
+ return result;
+ }
+
+
+ /**
+ * we are a nsTSubstring in disguise!
+ */
+
+ substring_type* concrete_self() { return NS_REINTERPRET_CAST( substring_type*, this); }
+ const substring_type* concrete_self() const { return NS_REINTERPRET_CAST(const substring_type*, this); }
+
+
+ /**
+ * all virtual methods need to be redirected to appropriate nsString methods
+ */
+
+ virtual ~nsTObsoleteAStringThunk_CharT()
+ {
+ concrete_self()->Finalize();
+ }
+
+ virtual PRUint32 GetImplementationFlags() const
+ {
+ return 0;
+ }
+
+ virtual const buffer_handle_type* GetFlatBufferHandle() const
+ {
+ return (const buffer_handle_type*) (concrete_self()->IsTerminated() != PR_FALSE);
+ }
+
+ virtual const buffer_handle_type* GetBufferHandle() const
+ {
+ return 0;
+ }
+
+ virtual const shared_buffer_handle_type* GetSharedBufferHandle() const
+ {
+ return 0;
+ }
+
+ virtual size_type Length() const
+ {
+ return concrete_self()->Length();
+ }
+
+ virtual PRBool IsVoid() const
+ {
+ return concrete_self()->IsVoid();
+ }
+
+ virtual void SetIsVoid(PRBool val)
+ {
+ concrete_self()->SetIsVoid(val);
+ }
+
+ virtual void SetCapacity(size_type size)
+ {
+ concrete_self()->SetCapacity(size);
+ }
+
+ virtual void SetLength(size_type size)
+ {
+ concrete_self()->SetLength(size);
+ }
+
+ virtual void Cut(index_type cutStart, size_type cutLength)
+ {
+ concrete_self()->Cut(cutStart, cutLength);
+ }
+
+ virtual void do_AssignFromReadable(const abstract_string_type &s)
+ {
+ concrete_self()->Assign(s);
+ }
+
+ virtual void do_AssignFromElementPtr(const char_type *data)
+ {
+ concrete_self()->Assign(data);
+ }
+
+ virtual void do_AssignFromElementPtrLength(const char_type *data, size_type length)
+ {
+ concrete_self()->Assign(data, length);
+ }
+
+ virtual void do_AssignFromElement(char_type c)
+ {
+ concrete_self()->Assign(c);
+ }
+
+ virtual void do_AppendFromReadable(const abstract_string_type &s)
+ {
+ concrete_self()->Append(s);
+ }
+
+ virtual void do_AppendFromElementPtr(const char_type *data)
+ {
+ concrete_self()->Append(data);
+ }
+
+ virtual void do_AppendFromElementPtrLength(const char_type *data, size_type length)
+ {
+ concrete_self()->Append(data, length);
+ }
+
+ virtual void do_AppendFromElement(char_type c)
+ {
+ concrete_self()->Append(c);
+ }
+
+ virtual void do_InsertFromReadable(const abstract_string_type &s, index_type pos)
+ {
+ concrete_self()->Insert(s, pos);
+ }
+
+ virtual void do_InsertFromElementPtr(const char_type *data, index_type pos)
+ {
+ concrete_self()->Insert(data, pos);
+ }
+
+ virtual void do_InsertFromElementPtrLength(const char_type *data, index_type pos, size_type length)
+ {
+ concrete_self()->Insert(data, pos, length);
+ }
+
+ virtual void do_InsertFromElement(char_type c, index_type pos)
+ {
+ concrete_self()->Insert(c, pos);
+ }
+
+ virtual void do_ReplaceFromReadable(index_type cutStart, size_type cutLength, const abstract_string_type &s)
+ {
+ concrete_self()->Replace(cutStart, cutLength, s);
+ }
+
+ virtual const char_type *GetReadableFragment(const_fragment_type& frag, nsFragmentRequest which, PRUint32 offset) const
+ {
+ const substring_type* s = concrete_self();
+ switch (which)
+ {
+ case kFirstFragment:
+ case kLastFragment:
+ case kFragmentAt:
+ frag.mStart = s->Data();
+ frag.mEnd = frag.mStart + s->Length();
+ return frag.mStart + offset;
+ case kPrevFragment:
+ case kNextFragment:
+ default:
+ return 0;
+ }
+ }
+
+ virtual char_type *GetWritableFragment(fragment_type& frag, nsFragmentRequest which, PRUint32 offset)
+ {
+ substring_type* s = concrete_self();
+ switch (which)
+ {
+ case kFirstFragment:
+ case kLastFragment:
+ case kFragmentAt:
+ char_type* start;
+ s->BeginWriting(start);
+ frag.mStart = start;
+ frag.mEnd = start + s->Length();
+ return frag.mStart + offset;
+ case kPrevFragment:
+ case kNextFragment:
+ default:
+ return 0;
+ }
+ }
+ };
+
+
+ /**
+ * initialize the pointer to the canonical vtable...
+ */
+
+const void *nsTObsoleteAString_CharT::sCanonicalVTable = nsTObsoleteAStringThunk_CharT::get_vptr();
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTPromiseFlatString.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTPromiseFlatString.cpp
new file mode 100644
index 00000000..bf0bfc32
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsTPromiseFlatString.cpp
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+void
+nsTPromiseFlatString_CharT::Init(const substring_type& str)
+ {
+ // we have to manually set this here since we are being called on an
+ // unitialized object.
+ mVTable = nsTObsoleteAString_CharT::sCanonicalVTable;
+
+ if (str.IsTerminated())
+ {
+ mData = NS_CONST_CAST(char_type*, str.Data());
+ mLength = str.Length();
+ mFlags = F_TERMINATED; // does not promote F_VOIDED
+ }
+ else
+ {
+ Assign(str);
+ }
+ }
+
+ // this function is non-inline to minimize codesize
+void
+nsTPromiseFlatString_CharT::Init(const abstract_string_type& readable)
+ {
+ if (readable.mVTable == nsTObsoleteAString_CharT::sCanonicalVTable)
+ Init(*readable.AsSubstring());
+ else
+ Init(readable.ToSubstring());
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTString.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTString.cpp
new file mode 100644
index 00000000..84911f5f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsTString.cpp
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ * Johnny Stenback <jst@mozilla.jstenback.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 ***** */
+
+NS_COM nsTAdoptingString_CharT&
+nsTAdoptingString_CharT::operator=( const self_type& str )
+ {
+ // This'll violate the constness of this argument, that's just
+ // the nature of this class...
+ self_type* mutable_str = NS_CONST_CAST(self_type*, &str);
+
+ if (str.mFlags & F_OWNED)
+ {
+ Adopt(str.mData, str.mLength);
+
+ // Make str forget the buffer we just took ownership of.
+ new (mutable_str) self_type();
+ }
+ else
+ {
+ Assign(str);
+
+ mutable_str->Truncate();
+ }
+
+ return *this;
+ }
+
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTStringComparator.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTStringComparator.cpp
new file mode 100644
index 00000000..6d2645a1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsTStringComparator.cpp
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+NS_COM int
+Compare( const nsTAString_CharT& lhs, const nsTAString_CharT& rhs, const nsTStringComparator_CharT& comp )
+ {
+ typedef nsTAString_CharT::size_type size_type;
+
+ if ( &lhs == &rhs )
+ return 0;
+
+ nsTAString_CharT::const_iterator leftIter, rightIter;
+ lhs.BeginReading(leftIter);
+ rhs.BeginReading(rightIter);
+
+ size_type lLength = leftIter.size_forward();
+ size_type rLength = rightIter.size_forward();
+ size_type lengthToCompare = NS_MIN(lLength, rLength);
+
+ int result;
+ if ( (result = comp(leftIter.get(), rightIter.get(), lengthToCompare)) == 0 )
+ {
+ if ( lLength < rLength )
+ result = -1;
+ else if ( rLength < lLength )
+ result = 1;
+ else
+ result = 0;
+ }
+
+ return result;
+ }
+
+int
+nsTDefaultStringComparator_CharT::operator()( const char_type* lhs, const char_type* rhs, PRUint32 aLength ) const
+ {
+ return nsCharTraits<CharT>::compare(lhs, rhs, aLength);
+ }
+
+int
+nsTDefaultStringComparator_CharT::operator()( char_type lhs, char_type rhs) const
+ {
+ return lhs - rhs;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTStringObsolete.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTStringObsolete.cpp
new file mode 100644
index 00000000..5ed065ad
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsTStringObsolete.cpp
@@ -0,0 +1,518 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+
+ /**
+ * nsTString::Find
+ *
+ * aOffset specifies starting index
+ * aCount specifies number of string compares (iterations)
+ */
+
+PRInt32
+nsTString_CharT::Find( const nsCString& aString, PRBool aIgnoreCase, PRInt32 aOffset, PRInt32 aCount) const
+ {
+ // this method changes the meaning of aOffset and aCount:
+ Find_ComputeSearchRange(mLength, aString.Length(), aOffset, aCount);
+
+ PRInt32 result = FindSubstring(mData + aOffset, aCount, aString.get(), aString.Length(), aIgnoreCase);
+ if (result != kNotFound)
+ result += aOffset;
+ return result;
+ }
+
+PRInt32
+nsTString_CharT::Find( const char* aString, PRBool aIgnoreCase, PRInt32 aOffset, PRInt32 aCount) const
+ {
+ return Find(nsDependentCString(aString), aIgnoreCase, aOffset, aCount);
+ }
+
+
+ /**
+ * nsTString::RFind
+ *
+ * aOffset specifies starting index
+ * aCount specifies number of string compares (iterations)
+ */
+
+PRInt32
+nsTString_CharT::RFind( const nsCString& aString, PRBool aIgnoreCase, PRInt32 aOffset, PRInt32 aCount) const
+ {
+ // this method changes the meaning of aOffset and aCount:
+ RFind_ComputeSearchRange(mLength, aString.Length(), aOffset, aCount);
+
+ PRInt32 result = RFindSubstring(mData + aOffset, aCount, aString.get(), aString.Length(), aIgnoreCase);
+ if (result != kNotFound)
+ result += aOffset;
+ return result;
+ }
+
+PRInt32
+nsTString_CharT::RFind( const char* aString, PRBool aIgnoreCase, PRInt32 aOffset, PRInt32 aCount) const
+ {
+ return RFind(nsDependentCString(aString), aIgnoreCase, aOffset, aCount);
+ }
+
+
+ /**
+ * nsTString::RFindChar
+ */
+
+PRInt32
+nsTString_CharT::RFindChar( PRUnichar aChar, PRInt32 aOffset, PRInt32 aCount) const
+ {
+ return nsBufferRoutines<CharT>::rfind_char(mData, mLength, aOffset, aChar, aCount);
+ }
+
+
+ /**
+ * nsTString::FindCharInSet
+ */
+
+PRInt32
+nsTString_CharT::FindCharInSet( const char* aSet, PRInt32 aOffset ) const
+ {
+ if (aOffset < 0)
+ aOffset = 0;
+ else if (aOffset >= PRInt32(mLength))
+ return kNotFound;
+
+ PRInt32 result = ::FindCharInSet(mData + aOffset, mLength - aOffset, aSet);
+ if (result != kNotFound)
+ result += aOffset;
+ return result;
+ }
+
+
+ /**
+ * nsTString::RFindCharInSet
+ */
+
+PRInt32
+nsTString_CharT::RFindCharInSet( const CharT* aSet, PRInt32 aOffset ) const
+ {
+ // We want to pass a "data length" to ::RFindCharInSet
+ if (aOffset < 0 || aOffset > PRInt32(mLength))
+ aOffset = mLength;
+ else
+ ++aOffset;
+
+ return ::RFindCharInSet(mData, aOffset, aSet);
+ }
+
+
+ // it's a shame to replicate this code. it was done this way in the past
+ // to help performance. this function also gets to keep the rickg style
+ // indentation :-/
+PRInt32
+nsTString_CharT::ToInteger( PRInt32* aErrorCode, PRUint32 aRadix ) const
+{
+ CharT* cp=mData;
+ PRInt32 theRadix=10; // base 10 unless base 16 detected, or overriden (aRadix != kAutoDetect)
+ PRInt32 result=0;
+ PRBool negate=PR_FALSE;
+ CharT theChar=0;
+
+ //initial value, override if we find an integer
+ *aErrorCode=NS_ERROR_ILLEGAL_VALUE;
+
+ if(cp) {
+
+ //begin by skipping over leading chars that shouldn't be part of the number...
+
+ CharT* endcp=cp+mLength;
+ PRBool done=PR_FALSE;
+
+ while((cp<endcp) && (!done)){
+ switch(*cp++) {
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ theRadix=16;
+ done=PR_TRUE;
+ break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ done=PR_TRUE;
+ break;
+ case '-':
+ negate=PR_TRUE; //fall through...
+ break;
+ case 'X': case 'x':
+ theRadix=16;
+ break;
+ default:
+ break;
+ } //switch
+ }
+
+ if (done) {
+
+ //integer found
+ *aErrorCode = NS_OK;
+
+ if (aRadix!=kAutoDetect) theRadix = aRadix; // override
+
+ //now iterate the numeric chars and build our result
+ CharT* first=--cp; //in case we have to back up.
+ PRBool haveValue = PR_FALSE;
+
+ while(cp<endcp){
+ theChar=*cp++;
+ if(('0'<=theChar) && (theChar<='9')){
+ result = (theRadix * result) + (theChar-'0');
+ haveValue = PR_TRUE;
+ }
+ else if((theChar>='A') && (theChar<='F')) {
+ if(10==theRadix) {
+ if(kAutoDetect==aRadix){
+ theRadix=16;
+ cp=first; //backup
+ result=0;
+ haveValue = PR_FALSE;
+ }
+ else {
+ *aErrorCode=NS_ERROR_ILLEGAL_VALUE;
+ result=0;
+ break;
+ }
+ }
+ else {
+ result = (theRadix * result) + ((theChar-'A')+10);
+ haveValue = PR_TRUE;
+ }
+ }
+ else if((theChar>='a') && (theChar<='f')) {
+ if(10==theRadix) {
+ if(kAutoDetect==aRadix){
+ theRadix=16;
+ cp=first; //backup
+ result=0;
+ haveValue = PR_FALSE;
+ }
+ else {
+ *aErrorCode=NS_ERROR_ILLEGAL_VALUE;
+ result=0;
+ break;
+ }
+ }
+ else {
+ result = (theRadix * result) + ((theChar-'a')+10);
+ haveValue = PR_TRUE;
+ }
+ }
+ else if((('X'==theChar) || ('x'==theChar)) && (!haveValue || result == 0)) {
+ continue;
+ }
+ else if((('#'==theChar) || ('+'==theChar)) && !haveValue) {
+ continue;
+ }
+ else {
+ //we've encountered a char that's not a legal number or sign
+ break;
+ }
+ } //while
+ if(negate)
+ result=-result;
+ } //if
+ }
+ return result;
+}
+
+
+ /**
+ * nsTString::Mid
+ */
+
+PRUint32
+nsTString_CharT::Mid( self_type& aResult, index_type aStartPos, size_type aLengthToCopy ) const
+ {
+ if (aStartPos == 0 && aLengthToCopy >= mLength)
+ aResult = *this;
+ else
+ aResult = Substring(*this, aStartPos, aLengthToCopy);
+
+ return aResult.mLength;
+ }
+
+
+ /**
+ * nsTString::SetCharAt
+ */
+
+PRBool
+nsTString_CharT::SetCharAt( PRUnichar aChar, PRUint32 aIndex )
+ {
+ if (aIndex >= mLength)
+ return PR_FALSE;
+
+ EnsureMutable();
+
+ mData[aIndex] = CharT(aChar);
+ return PR_TRUE;
+ }
+
+
+ /**
+ * nsTString::StripChars,StripChar,StripWhitespace
+ */
+
+void
+nsTString_CharT::StripChars( const char* aSet )
+ {
+ EnsureMutable();
+ mLength = nsBufferRoutines<CharT>::strip_chars(mData, mLength, aSet);
+ }
+
+void
+nsTString_CharT::StripChar( char_type aChar, PRInt32 aOffset )
+ {
+ if (mLength == 0 || aOffset >= PRInt32(mLength))
+ return;
+
+ EnsureMutable(); // XXX do this lazily?
+
+ // XXXdarin this code should defer writing until necessary.
+
+ char_type* to = mData + aOffset;
+ char_type* from = mData + aOffset;
+ char_type* end = mData + mLength;
+
+ while (from < end)
+ {
+ char_type theChar = *from++;
+ if (aChar != theChar)
+ *to++ = theChar;
+ }
+ *to = char_type(0); // add the null
+ mLength = to - mData;
+ }
+
+void
+nsTString_CharT::StripWhitespace()
+ {
+ StripChars(kWhitespace);
+ }
+
+
+ /**
+ * nsTString::ReplaceChar,ReplaceSubstring
+ */
+
+void
+nsTString_CharT::ReplaceChar( char_type aOldChar, char_type aNewChar )
+ {
+ EnsureMutable(); // XXX do this lazily?
+
+ for (PRUint32 i=0; i<mLength; ++i)
+ {
+ if (mData[i] == aOldChar)
+ mData[i] = aNewChar;
+ }
+ }
+
+void
+nsTString_CharT::ReplaceChar( const char* aSet, char_type aNewChar )
+ {
+ EnsureMutable(); // XXX do this lazily?
+
+ char_type* data = mData;
+ PRUint32 lenRemaining = mLength;
+
+ while (lenRemaining)
+ {
+ PRInt32 i = ::FindCharInSet(data, lenRemaining, aSet);
+ if (i == kNotFound)
+ break;
+
+ data[i++] = aNewChar;
+ data += i;
+ lenRemaining -= i;
+ }
+ }
+
+void
+nsTString_CharT::ReplaceSubstring( const char_type* aTarget, const char_type* aNewValue )
+ {
+ ReplaceSubstring(nsTDependentString_CharT(aTarget),
+ nsTDependentString_CharT(aNewValue));
+ }
+
+void
+nsTString_CharT::ReplaceSubstring( const self_type& aTarget, const self_type& aNewValue )
+ {
+ if (aTarget.Length() == 0)
+ return;
+
+ PRUint32 i = 0;
+ while (i < mLength)
+ {
+ PRInt32 r = FindSubstring(mData + i, mLength - i, aTarget.Data(), aTarget.Length(), PR_FALSE);
+ if (r == kNotFound)
+ break;
+
+ Replace(i + r, aTarget.Length(), aNewValue);
+ i += r + aNewValue.Length();
+ }
+ }
+
+
+ /**
+ * nsTString::Trim
+ */
+
+void
+nsTString_CharT::Trim( const char* aSet, PRBool aTrimLeading, PRBool aTrimTrailing, PRBool aIgnoreQuotes )
+ {
+ // the old implementation worried about aSet being null :-/
+ if (!aSet)
+ return;
+
+ char_type* start = mData;
+ char_type* end = mData + mLength;
+
+ // skip over quotes if requested
+ if (aIgnoreQuotes && mLength > 2 && mData[0] == mData[mLength - 1] &&
+ (mData[0] == '\'' || mData[0] == '"'))
+ {
+ ++start;
+ --end;
+ }
+
+ PRUint32 setLen = nsCharTraits<char>::length(aSet);
+
+ if (aTrimLeading)
+ {
+ PRUint32 cutStart = start - mData;
+ PRUint32 cutLength = 0;
+
+ // walk forward from start to end
+ for (; start != end; ++start, ++cutLength)
+ {
+ PRInt32 pos = FindChar1(aSet, setLen, 0, *start, setLen);
+ if (pos == kNotFound)
+ break;
+ }
+
+ if (cutLength)
+ {
+ Cut(cutStart, cutLength);
+
+ // reset iterators
+ start = mData + cutStart;
+ end = mData + mLength - cutStart;
+ }
+ }
+
+ if (aTrimTrailing)
+ {
+ PRUint32 cutEnd = end - mData;
+ PRUint32 cutLength = 0;
+
+ // walk backward from end to start
+ --end;
+ for (; end >= start; --end, ++cutLength)
+ {
+ PRInt32 pos = FindChar1(aSet, setLen, 0, *end, setLen);
+ if (pos == kNotFound)
+ break;
+ }
+
+ if (cutLength)
+ Cut(cutEnd - cutLength, cutLength);
+ }
+ }
+
+
+ /**
+ * nsTString::CompressWhitespace
+ */
+
+void
+nsTString_CharT::CompressWhitespace( PRBool aTrimLeading, PRBool aTrimTrailing )
+ {
+ const char* set = kWhitespace;
+
+ ReplaceChar(set, ' ');
+ Trim(set, aTrimLeading, aTrimTrailing);
+
+ // this one does some questionable fu... just copying the old code!
+ mLength = nsBufferRoutines<char_type>::compress_chars(mData, mLength, set);
+ }
+
+
+ /**
+ * nsTString::AssignWithConversion
+ */
+
+void
+nsTString_CharT::AssignWithConversion( const incompatible_char_type* aData, PRInt32 aLength )
+ {
+ // for compatibility with the old string implementation, we need to allow
+ // for a NULL input buffer :-(
+ if (!aData)
+ {
+ Truncate();
+ }
+ else
+ {
+ if (aLength < 0)
+ aLength = nsCharTraits<incompatible_char_type>::length(aData);
+
+ AssignWithConversion(Substring(aData, aData + aLength));
+ }
+ }
+
+
+ /**
+ * nsTString::AppendWithConversion
+ */
+
+void
+nsTString_CharT::AppendWithConversion( const incompatible_char_type* aData, PRInt32 aLength )
+ {
+ // for compatibility with the old string implementation, we need to allow
+ // for a NULL input buffer :-(
+ if (aData)
+ {
+ if (aLength < 0)
+ aLength = nsCharTraits<incompatible_char_type>::length(aData);
+
+ AppendWithConversion(Substring(aData, aData + aLength));
+ }
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTSubstring.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTSubstring.cpp
new file mode 100644
index 00000000..e36b1863
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsTSubstring.cpp
@@ -0,0 +1,656 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+ /**
+ * helper function for down-casting a nsTSubstring to a nsTFixedString.
+ */
+inline const nsTFixedString_CharT*
+AsFixedString( const nsTSubstring_CharT* s )
+ {
+ return NS_STATIC_CAST(const nsTFixedString_CharT*, s);
+ }
+
+
+ /**
+ * this function is called to prepare mData for writing. the given capacity
+ * indicates the required minimum storage size for mData, in sizeof(char_type)
+ * increments. this function returns true if the operation succeeds. it also
+ * returns the old data and old flags members if mData is newly allocated.
+ * the old data must be released by the caller.
+ */
+PRBool
+nsTSubstring_CharT::MutatePrep( size_type capacity, char_type** oldData, PRUint32* oldFlags )
+ {
+ // initialize to no old data
+ *oldData = nsnull;
+ *oldFlags = 0;
+
+ size_type curCapacity = Capacity();
+
+ // |curCapacity == size_type(-1)| means that the buffer is immutable, so we
+ // need to allocate a new buffer. we cannot use the existing buffer even
+ // though it might be large enough.
+
+ if (curCapacity != size_type(-1))
+ {
+ if (capacity <= curCapacity)
+ return PR_TRUE;
+
+ if (curCapacity > 0)
+ {
+ // use doubling algorithm when forced to increase available capacity,
+ // but always start out with exactly the requested amount.
+ PRUint32 temp = curCapacity;
+ while (temp < capacity)
+ temp <<= 1;
+ capacity = temp;
+ }
+ }
+
+ //
+ // several cases:
+ //
+ // (1) we have a shared buffer (mFlags & F_SHARED)
+ // (2) we have an owned buffer (mFlags & F_OWNED)
+ // (3) we have a fixed buffer (mFlags & F_FIXED)
+ // (4) we have a readonly buffer
+ //
+ // requiring that we in some cases preserve the data before creating
+ // a new buffer complicates things just a bit ;-)
+ //
+
+ size_type storageSize = (capacity + 1) * sizeof(char_type);
+
+ // case #1
+ if (mFlags & F_SHARED)
+ {
+ nsStringHeader* hdr = nsStringHeader::FromData(mData);
+ if (!hdr->IsReadonly())
+ {
+ nsStringHeader *newHdr = nsStringHeader::Realloc(hdr, storageSize);
+ if (newHdr)
+ {
+ hdr = newHdr;
+ mData = (char_type*) hdr->Data();
+ return PR_TRUE;
+ }
+ hdr->Release();
+ // out of memory!! put us in a consistent state at least.
+ mData = NS_CONST_CAST(char_type*, char_traits::sEmptyBuffer);
+ mLength = 0;
+ SetDataFlags(F_TERMINATED);
+ return PR_FALSE;
+ }
+ }
+
+ char_type* newData;
+ PRUint32 newDataFlags;
+
+ // if we have a fixed buffer of sufficient size, then use it. this helps
+ // avoid heap allocations.
+ if ((mFlags & F_CLASS_FIXED) && (capacity < AsFixedString(this)->mFixedCapacity))
+ {
+ newData = AsFixedString(this)->mFixedBuf;
+ newDataFlags = F_TERMINATED | F_FIXED;
+ }
+ else
+ {
+ // if we reach here then, we must allocate a new buffer. we cannot
+ // make use of our F_OWNED or F_FIXED buffers because they are not
+ // large enough.
+
+ nsStringHeader* newHdr = nsStringHeader::Alloc(storageSize);
+ if (!newHdr)
+ return PR_FALSE; // we are still in a consistent state
+
+ newData = (char_type*) newHdr->Data();
+ newDataFlags = F_TERMINATED | F_SHARED;
+ }
+
+ // save old data and flags
+ *oldData = mData;
+ *oldFlags = mFlags;
+
+ mData = newData;
+ SetDataFlags(newDataFlags);
+
+ // mLength does not change
+
+ // though we are not necessarily terminated at the moment, now is probably
+ // still the best time to set F_TERMINATED.
+
+ return PR_TRUE;
+ }
+
+void
+nsTSubstring_CharT::Finalize()
+ {
+ ::ReleaseData(mData, mFlags);
+ // mData, mLength, and mFlags are purposefully left dangling
+ }
+
+void
+nsTSubstring_CharT::ReplacePrep( index_type cutStart, size_type cutLen, size_type fragLen )
+ {
+ // bound cut length
+ cutLen = NS_MIN(cutLen, mLength - cutStart);
+
+ PRUint32 newLen = mLength - cutLen + fragLen;
+
+ char_type* oldData;
+ PRUint32 oldFlags;
+ if (!MutatePrep(newLen, &oldData, &oldFlags))
+ return; // XXX out-of-memory error occured!
+
+ if (oldData)
+ {
+ // determine whether or not we need to copy part of the old string
+ // over to the new string.
+
+ if (cutStart > 0)
+ {
+ // copy prefix from old string
+ char_traits::copy(mData, oldData, cutStart);
+ }
+
+ if (cutStart + cutLen < mLength)
+ {
+ // copy suffix from old string to new offset
+ size_type from = cutStart + cutLen;
+ size_type fromLen = mLength - from;
+ PRUint32 to = cutStart + fragLen;
+ char_traits::copy(mData + to, oldData + from, fromLen);
+ }
+
+ ::ReleaseData(oldData, oldFlags);
+ }
+ else
+ {
+ // original data remains intact
+
+ // determine whether or not we need to move part of the existing string
+ // to make room for the requested hole.
+ if (fragLen != cutLen && cutStart + cutLen < mLength)
+ {
+ PRUint32 from = cutStart + cutLen;
+ PRUint32 fromLen = mLength - from;
+ PRUint32 to = cutStart + fragLen;
+ char_traits::move(mData + to, mData + from, fromLen);
+ }
+ }
+
+ // add null terminator (mutable mData always has room for the null-
+ // terminator).
+ mData[newLen] = char_type(0);
+ mLength = newLen;
+ }
+
+nsTSubstring_CharT::size_type
+nsTSubstring_CharT::Capacity() const
+ {
+ // return size_type(-1) to indicate an immutable buffer
+
+ size_type capacity;
+ if (mFlags & F_SHARED)
+ {
+ // if the string is readonly, then we pretend that it has no capacity.
+ nsStringHeader* hdr = nsStringHeader::FromData(mData);
+ if (hdr->IsReadonly())
+ capacity = size_type(-1);
+ else
+ capacity = (hdr->StorageSize() / sizeof(char_type)) - 1;
+ }
+ else if (mFlags & F_FIXED)
+ {
+ capacity = AsFixedString(this)->mFixedCapacity;
+ }
+ else if (mFlags & F_OWNED)
+ {
+ // we don't store the capacity of an adopted buffer because that would
+ // require an additional member field. the best we can do is base the
+ // capacity on our length. remains to be seen if this is the right
+ // trade-off.
+ capacity = mLength;
+ }
+ else
+ {
+ capacity = size_type(-1);
+ }
+
+ return capacity;
+ }
+
+void
+nsTSubstring_CharT::EnsureMutable()
+ {
+ if (mFlags & (F_FIXED | F_OWNED))
+ return;
+ if ((mFlags & F_SHARED) && !nsStringHeader::FromData(mData)->IsReadonly())
+ return;
+
+ // promote to a shared string buffer
+ Assign(string_type(mData, mLength));
+ }
+
+// ---------------------------------------------------------------------------
+
+void
+nsTSubstring_CharT::Assign( const char_type* data, size_type length )
+ {
+ // unfortunately, some callers pass null :-(
+ if (!data)
+ {
+ Truncate();
+ return;
+ }
+
+ if (length == size_type(-1))
+ length = char_traits::length(data);
+
+ if (IsDependentOn(data, data + length))
+ {
+ // take advantage of sharing here...
+ Assign(string_type(data, length));
+ return;
+ }
+
+ ReplacePrep(0, mLength, length);
+ char_traits::copy(mData, data, length);
+ }
+
+void
+nsTSubstring_CharT::AssignASCII( const char* data, size_type length )
+ {
+ // A Unicode string can't depend on an ASCII string buffer,
+ // so this dependence check only applies to CStrings.
+#ifdef CharT_is_char
+ if (IsDependentOn(data, data + length))
+ {
+ // take advantage of sharing here...
+ Assign(string_type(data, length));
+ return;
+ }
+#endif
+
+ ReplacePrep(0, mLength, length);
+ char_traits::copyASCII(mData, data, length);
+ }
+
+void
+nsTSubstring_CharT::AssignASCII( const char* data )
+ {
+ AssignASCII(data, strlen(data));
+ }
+
+void
+nsTSubstring_CharT::Assign( const self_type& str )
+ {
+ // |str| could be sharable. we need to check its flags to know how to
+ // deal with it.
+
+ if (&str == this)
+ return;
+
+ if (str.mFlags & F_SHARED)
+ {
+ // nice! we can avoid a string copy :-)
+
+ // |str| should be null-terminated
+ NS_ASSERTION(str.mFlags & F_TERMINATED, "shared, but not terminated");
+
+ ::ReleaseData(mData, mFlags);
+
+ mData = str.mData;
+ mLength = str.mLength;
+ SetDataFlags(F_TERMINATED | F_SHARED);
+
+ // get an owning reference to the mData
+ nsStringHeader::FromData(mData)->AddRef();
+ }
+ else if (str.mFlags & F_VOIDED)
+ {
+ // inherit the F_VOIDED attribute
+ SetIsVoid(PR_TRUE);
+ }
+ else
+ {
+ // else, treat this like an ordinary assignment.
+ Assign(str.Data(), str.Length());
+ }
+ }
+
+void
+nsTSubstring_CharT::Assign( const substring_tuple_type& tuple )
+ {
+ if (tuple.IsDependentOn(mData, mData + mLength))
+ {
+ // take advantage of sharing here...
+ Assign(string_type(tuple));
+ return;
+ }
+
+ size_type length = tuple.Length();
+
+ ReplacePrep(0, mLength, length);
+ if (length)
+ tuple.WriteTo(mData, length);
+ }
+
+ // this is non-inline to reduce codesize at the callsite
+void
+nsTSubstring_CharT::Assign( const abstract_string_type& readable )
+ {
+ // promote to string if possible to take advantage of sharing
+ if (readable.mVTable == nsTObsoleteAString_CharT::sCanonicalVTable)
+ Assign(*readable.AsSubstring());
+ else
+ Assign(readable.ToSubstring());
+ }
+
+
+void
+nsTSubstring_CharT::Adopt( char_type* data, size_type length )
+ {
+ if (data)
+ {
+ ::ReleaseData(mData, mFlags);
+
+ if (length == size_type(-1))
+ length = char_traits::length(data);
+
+ mData = data;
+ mLength = length;
+ SetDataFlags(F_TERMINATED | F_OWNED);
+
+ STRING_STAT_INCREMENT(Adopt);
+ }
+ else
+ {
+ SetIsVoid(PR_TRUE);
+ }
+ }
+
+
+void
+nsTSubstring_CharT::Replace( index_type cutStart, size_type cutLength, const char_type* data, size_type length )
+ {
+ // unfortunately, some callers pass null :-(
+ if (!data)
+ {
+ length = 0;
+ }
+ else
+ {
+ if (length == size_type(-1))
+ length = char_traits::length(data);
+
+ if (IsDependentOn(data, data + length))
+ {
+ nsTAutoString_CharT temp(data, length);
+ Replace(cutStart, cutLength, temp);
+ return;
+ }
+ }
+
+ cutStart = PR_MIN(cutStart, Length());
+
+ ReplacePrep(cutStart, cutLength, length);
+
+ if (length > 0)
+ char_traits::copy(mData + cutStart, data, length);
+ }
+
+void
+nsTSubstring_CharT::ReplaceASCII( index_type cutStart, size_type cutLength, const char* data, size_type length )
+ {
+ if (length == size_type(-1))
+ length = strlen(data);
+
+ // A Unicode string can't depend on an ASCII string buffer,
+ // so this dependence check only applies to CStrings.
+#ifdef CharT_is_char
+ if (IsDependentOn(data, data + length))
+ {
+ nsTAutoString_CharT temp(data, length);
+ Replace(cutStart, cutLength, temp);
+ return;
+ }
+#endif
+
+ cutStart = PR_MIN(cutStart, Length());
+
+ ReplacePrep(cutStart, cutLength, length);
+
+ if (length > 0)
+ char_traits::copyASCII(mData + cutStart, data, length);
+ }
+
+void
+nsTSubstring_CharT::Replace( index_type cutStart, size_type cutLength, const substring_tuple_type& tuple )
+ {
+ if (tuple.IsDependentOn(mData, mData + mLength))
+ {
+ nsTAutoString_CharT temp(tuple);
+ Replace(cutStart, cutLength, temp);
+ return;
+ }
+
+ size_type length = tuple.Length();
+
+ cutStart = PR_MIN(cutStart, Length());
+
+ ReplacePrep(cutStart, cutLength, length);
+
+ if (length > 0)
+ tuple.WriteTo(mData + cutStart, length);
+ }
+
+void
+nsTSubstring_CharT::Replace( index_type cutStart, size_type cutLength, const abstract_string_type& readable )
+ {
+ Replace(cutStart, cutLength, readable.ToSubstring());
+ }
+
+void
+nsTSubstring_CharT::SetCapacity( size_type capacity )
+ {
+ // capacity does not include room for the terminating null char
+
+ // if our capacity is reduced to zero, then free our buffer.
+ if (capacity == 0)
+ {
+ ::ReleaseData(mData, mFlags);
+ mData = NS_CONST_CAST(char_type*, char_traits::sEmptyBuffer);
+ mLength = 0;
+ SetDataFlags(F_TERMINATED);
+ }
+ else
+ {
+ char_type* oldData;
+ PRUint32 oldFlags;
+ if (!MutatePrep(capacity, &oldData, &oldFlags))
+ return; // XXX out-of-memory error occured!
+
+ // compute new string length
+ size_type newLen = NS_MIN(mLength, capacity);
+
+ if (oldData)
+ {
+ // preserve old data
+ if (mLength > 0)
+ char_traits::copy(mData, oldData, newLen);
+
+ ::ReleaseData(oldData, oldFlags);
+ }
+
+ // adjust mLength if our buffer shrunk down in size
+ if (newLen < mLength)
+ mLength = newLen;
+
+ // always null-terminate here, even if the buffer got longer. this is
+ // for backwards compat with the old string implementation.
+ mData[capacity] = char_type(0);
+ }
+ }
+
+void
+nsTSubstring_CharT::SetLength( size_type length )
+ {
+ SetCapacity(length);
+ mLength = length;
+ }
+
+void
+nsTSubstring_CharT::SetIsVoid( PRBool val )
+ {
+ if (val)
+ {
+ Truncate();
+ mFlags |= F_VOIDED;
+ }
+ else
+ {
+ mFlags &= ~F_VOIDED;
+ }
+ }
+
+PRBool
+nsTSubstring_CharT::Equals( const self_type& str ) const
+ {
+ return mLength == str.mLength && char_traits::compare(mData, str.mData, mLength) == 0;
+ }
+
+PRBool
+nsTSubstring_CharT::Equals( const self_type& str, const comparator_type& comp ) const
+ {
+ return mLength == str.mLength && comp(mData, str.mData, mLength) == 0;
+ }
+
+PRBool
+nsTSubstring_CharT::Equals( const abstract_string_type& readable ) const
+ {
+ const char_type* data;
+ size_type length = readable.GetReadableBuffer(&data);
+
+ return mLength == length && char_traits::compare(mData, data, mLength) == 0;
+ }
+
+PRBool
+nsTSubstring_CharT::Equals( const abstract_string_type& readable, const comparator_type& comp ) const
+ {
+ const char_type* data;
+ size_type length = readable.GetReadableBuffer(&data);
+
+ return mLength == length && comp(mData, data, mLength) == 0;
+ }
+
+PRBool
+nsTSubstring_CharT::Equals( const char_type* data ) const
+ {
+ // unfortunately, some callers pass null :-(
+ if (!data)
+ {
+ NS_NOTREACHED("null data pointer");
+ return mLength == 0;
+ }
+
+ // XXX avoid length calculation?
+ size_type length = char_traits::length(data);
+ return mLength == length && char_traits::compare(mData, data, mLength) == 0;
+ }
+
+PRBool
+nsTSubstring_CharT::Equals( const char_type* data, const comparator_type& comp ) const
+ {
+ // unfortunately, some callers pass null :-(
+ if (!data)
+ {
+ NS_NOTREACHED("null data pointer");
+ return mLength == 0;
+ }
+
+ // XXX avoid length calculation?
+ size_type length = char_traits::length(data);
+ return mLength == length && comp(mData, data, mLength) == 0;
+ }
+
+PRBool
+nsTSubstring_CharT::EqualsASCII( const char* data, size_type len ) const
+ {
+ return mLength == len && char_traits::compareASCII(mData, data, len) == 0;
+ }
+
+PRBool
+nsTSubstring_CharT::EqualsASCII( const char* data ) const
+ {
+ return char_traits::compareASCIINullTerminated(mData, mLength, data) == 0;
+ }
+
+PRBool
+nsTSubstring_CharT::LowerCaseEqualsASCII( const char* data, size_type len ) const
+ {
+ return mLength == len && char_traits::compareLowerCaseToASCII(mData, data, len) == 0;
+ }
+
+PRBool
+nsTSubstring_CharT::LowerCaseEqualsASCII( const char* data ) const
+ {
+ return char_traits::compareLowerCaseToASCIINullTerminated(mData, mLength, data) == 0;
+ }
+
+nsTSubstring_CharT::size_type
+nsTSubstring_CharT::CountChar( char_type c ) const
+ {
+ const char_type *start = mData;
+ const char_type *end = mData + mLength;
+
+ return NS_COUNT(start, end, c);
+ }
+
+PRInt32
+nsTSubstring_CharT::FindChar( char_type c, index_type offset ) const
+ {
+ if (offset < mLength)
+ {
+ const char_type* result = char_traits::find(mData + offset, mLength - offset, c);
+ if (result)
+ return result - mData;
+ }
+ return -1;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTSubstringTuple.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTSubstringTuple.cpp
new file mode 100644
index 00000000..7fff5175
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/string/src/nsTSubstringTuple.cpp
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 ***** */
+
+
+ /**
+ * computes the aggregate string length
+ */
+
+nsTSubstringTuple_CharT::size_type
+nsTSubstringTuple_CharT::Length() const
+ {
+ PRUint32 len;
+ if (mHead)
+ len = mHead->Length();
+ else
+ len = TO_SUBSTRING(mFragA).Length();
+
+ return len + TO_SUBSTRING(mFragB).Length();
+ }
+
+
+ /**
+ * writes the aggregate string to the given buffer. bufLen is assumed
+ * to be equal to or greater than the value returned by the Length()
+ * method. the string written to |buf| is not null-terminated.
+ */
+
+void
+nsTSubstringTuple_CharT::WriteTo( char_type *buf, PRUint32 bufLen ) const
+ {
+ const substring_type& b = TO_SUBSTRING(mFragB);
+
+ NS_ASSERTION(bufLen >= b.Length(), "buffer too small");
+ PRUint32 headLen = bufLen - b.Length();
+ if (mHead)
+ {
+ mHead->WriteTo(buf, headLen);
+ }
+ else
+ {
+ const substring_type& a = TO_SUBSTRING(mFragA);
+
+ NS_ASSERTION(a.Length() == headLen, "buffer incorrectly sized");
+ char_traits::copy(buf, a.Data(), a.Length());
+ }
+
+ char_traits::copy(buf + headLen, b.Data(), b.Length());
+
+#if 0
+ // we need to write out data into |buf|, ending at |buf+bufLen|. so our
+ // data needs to precede |buf+bufLen| exactly. we trust that the buffer
+ // was properly sized!
+
+ const substring_type& b = TO_SUBSTRING(mFragB);
+
+ NS_ASSERTION(bufLen >= b.Length(), "buffer is too small");
+ char_traits::copy(buf + bufLen - b.Length(), b.Data(), b.Length());
+
+ bufLen -= b.Length();
+
+ if (mHead)
+ {
+ mHead->WriteTo(buf, bufLen);
+ }
+ else
+ {
+ const substring_type& a = TO_SUBSTRING(mFragA);
+ NS_ASSERTION(bufLen == a.Length(), "buffer is too small");
+ char_traits::copy(buf, a.Data(), a.Length());
+ }
+#endif
+ }
+
+
+ /**
+ * returns true if this tuple is dependent on (i.e., overlapping with)
+ * the given char sequence.
+ */
+
+PRBool
+nsTSubstringTuple_CharT::IsDependentOn( const char_type *start, const char_type *end ) const
+ {
+ // we start with the right-most fragment since it is faster to check.
+
+ if (TO_SUBSTRING(mFragB).IsDependentOn(start, end))
+ return PR_TRUE;
+
+ if (mHead)
+ return mHead->IsDependentOn(start, end);
+
+ return TO_SUBSTRING(mFragA).IsDependentOn(start, end);
+ }
diff --git a/src/libs/xpcom18a4/xpcom/stub/nsStringAPI.cpp b/src/libs/xpcom18a4/xpcom/stub/nsStringAPI.cpp
new file mode 100644
index 00000000..ca9a76e4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/stub/nsStringAPI.cpp
@@ -0,0 +1,261 @@
+/* vim:set ts=2 sw=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 "nsString.h"
+#include "nsCharTraits.h"
+
+#define NS_STRINGAPI_IMPL
+#include "nsStringAPI.h"
+#include "nsNativeCharsetUtils.h"
+
+/* ------------------------------------------------------------------------- */
+
+NS_STRINGAPI(nsresult)
+NS_StringContainerInit(nsStringContainer &aContainer)
+{
+ NS_ASSERTION(sizeof(nsStringContainer) >= sizeof(nsString),
+ "nsStringContainer is not large enough");
+
+ // use placement new to avoid heap allocating nsString object
+ new (&aContainer) nsString();
+
+ return NS_OK;
+}
+
+NS_STRINGAPI(void)
+NS_StringContainerFinish(nsStringContainer &aContainer)
+{
+ // call the nsString dtor
+ NS_REINTERPRET_CAST(nsString *, &aContainer)->~nsString();
+}
+
+/* ------------------------------------------------------------------------- */
+
+NS_STRINGAPI(PRUint32)
+NS_StringGetData(const nsAString &aStr, const PRUnichar **aData,
+ PRBool *aTerminated)
+{
+ if (aTerminated)
+ *aTerminated = aStr.IsTerminated();
+
+ nsAString::const_iterator begin;
+ aStr.BeginReading(begin);
+ *aData = begin.get();
+ return begin.size_forward();
+}
+
+NS_STRINGAPI(PRUnichar *)
+NS_StringCloneData(const nsAString &aStr)
+{
+ return ToNewUnicode(aStr);
+}
+
+NS_STRINGAPI(nsresult)
+NS_StringSetData(nsAString &aStr, const PRUnichar *aData, PRUint32 aDataLength)
+{
+ aStr.Assign(aData, aDataLength);
+ return NS_OK; // XXX report errors
+}
+
+NS_STRINGAPI(nsresult)
+NS_StringSetDataRange(nsAString &aStr,
+ PRUint32 aCutOffset, PRUint32 aCutLength,
+ const PRUnichar *aData, PRUint32 aDataLength)
+{
+ if (aCutOffset == PR_UINT32_MAX)
+ {
+ // append case
+ if (aData)
+ aStr.Append(aData, aDataLength);
+ return NS_OK; // XXX report errors
+ }
+
+ if (aCutLength == PR_UINT32_MAX)
+ aCutLength = aStr.Length() - aCutOffset;
+
+ if (aData)
+ {
+ if (aDataLength == PR_UINT32_MAX)
+ aStr.Replace(aCutOffset, aCutLength, nsDependentString(aData));
+ else
+ aStr.Replace(aCutOffset, aCutLength, Substring(aData, aData + aDataLength));
+ }
+ else
+ aStr.Cut(aCutOffset, aCutLength);
+
+ return NS_OK; // XXX report errors
+}
+
+NS_STRINGAPI(nsresult)
+NS_StringCopy(nsAString &aDest, const nsAString &aSrc)
+{
+ aDest.Assign(aSrc);
+ return NS_OK; // XXX report errors
+}
+
+/* ------------------------------------------------------------------------- */
+
+NS_STRINGAPI(nsresult)
+NS_CStringContainerInit(nsCStringContainer &aContainer)
+{
+ NS_ASSERTION(sizeof(nsCStringContainer) >= sizeof(nsCString),
+ "nsCStringContainer is not large enough");
+
+ // use placement new to avoid heap allocating nsCString object
+ new (&aContainer) nsCString();
+
+ return NS_OK;
+}
+
+NS_STRINGAPI(void)
+NS_CStringContainerFinish(nsCStringContainer &aContainer)
+{
+ // call the nsCString dtor
+ NS_REINTERPRET_CAST(nsCString *, &aContainer)->~nsCString();
+}
+
+/* ------------------------------------------------------------------------- */
+
+NS_STRINGAPI(PRUint32)
+NS_CStringGetData(const nsACString &aStr, const char **aData,
+ PRBool *aTerminated)
+{
+ if (aTerminated)
+ *aTerminated = aStr.IsTerminated();
+
+ nsACString::const_iterator begin;
+ aStr.BeginReading(begin);
+ *aData = begin.get();
+ return begin.size_forward();
+}
+
+NS_STRINGAPI(char *)
+NS_CStringCloneData(const nsACString &aStr)
+{
+ return ToNewCString(aStr);
+}
+
+NS_STRINGAPI(nsresult)
+NS_CStringSetData(nsACString &aStr, const char *aData, PRUint32 aDataLength)
+{
+ aStr.Assign(aData, aDataLength);
+ return NS_OK; // XXX report errors
+}
+
+NS_STRINGAPI(nsresult)
+NS_CStringSetDataRange(nsACString &aStr,
+ PRUint32 aCutOffset, PRUint32 aCutLength,
+ const char *aData, PRUint32 aDataLength)
+{
+ if (aCutOffset == PR_UINT32_MAX)
+ {
+ // append case
+ if (aData)
+ aStr.Append(aData, aDataLength);
+ return NS_OK; // XXX report errors
+ }
+
+ if (aCutLength == PR_UINT32_MAX)
+ aCutLength = aStr.Length() - aCutOffset;
+
+ if (aData)
+ {
+ if (aDataLength == PR_UINT32_MAX)
+ aStr.Replace(aCutOffset, aCutLength, nsDependentCString(aData));
+ else
+ aStr.Replace(aCutOffset, aCutLength, Substring(aData, aData + aDataLength));
+ }
+ else
+ aStr.Cut(aCutOffset, aCutLength);
+
+ return NS_OK; // XXX report errors
+}
+
+NS_STRINGAPI(nsresult)
+NS_CStringCopy(nsACString &aDest, const nsACString &aSrc)
+{
+ aDest.Assign(aSrc);
+ return NS_OK; // XXX report errors
+}
+
+/* ------------------------------------------------------------------------- */
+
+NS_STRINGAPI(nsresult)
+NS_CStringToUTF16(const nsACString &aSrc,
+ nsCStringEncoding aSrcEncoding,
+ nsAString &aDest)
+{
+ switch (aSrcEncoding)
+ {
+ case NS_CSTRING_ENCODING_ASCII:
+ CopyASCIItoUTF16(aSrc, aDest);
+ break;
+ case NS_CSTRING_ENCODING_UTF8:
+ CopyUTF8toUTF16(aSrc, aDest);
+ break;
+ case NS_CSTRING_ENCODING_NATIVE_FILESYSTEM:
+ NS_CopyNativeToUnicode(aSrc, aDest);
+ break;
+ default:
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ return NS_OK; // XXX report errors
+}
+
+NS_STRINGAPI(nsresult)
+NS_UTF16ToCString(const nsAString &aSrc,
+ nsCStringEncoding aDestEncoding,
+ nsACString &aDest)
+{
+ switch (aDestEncoding)
+ {
+ case NS_CSTRING_ENCODING_ASCII:
+ LossyCopyUTF16toASCII(aSrc, aDest);
+ break;
+ case NS_CSTRING_ENCODING_UTF8:
+ CopyUTF16toUTF8(aSrc, aDest);
+ break;
+ case NS_CSTRING_ENCODING_NATIVE_FILESYSTEM:
+ NS_CopyUnicodeToNative(aSrc, aDest);
+ break;
+ default:
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ return NS_OK; // XXX report errors
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/.cvsignore b/src/libs/xpcom18a4/xpcom/tests/.cvsignore
new file mode 100644
index 00000000..d01075e3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/.cvsignore
@@ -0,0 +1,31 @@
+CvtURL
+FilesTest
+Makefile
+PropertiesTest
+RegFactory
+SizeTest01
+SizeTest02
+SizeTest03
+SizeTest04
+SizeTest05
+SizeTest06
+TestAtoms
+TestAutoLock
+TestBuffers
+TestCOMPtr
+TestCOMPtrEq
+TestArray
+TestCRT
+TestFactory
+TestID
+TestObserverService
+TestPermanentAtoms
+TestPipes
+TestThreads
+TestVoidBTree
+TestXPIDLString
+TestServMgr
+nsIFileEnumerator
+nsIFileTest
+TestCallTemplates
+TestDeque
diff --git a/src/libs/xpcom18a4/xpcom/tests/CvtURL.cpp b/src/libs/xpcom18a4/xpcom/tests/CvtURL.cpp
new file mode 100644
index 00000000..4dd052ac
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/CvtURL.cpp
@@ -0,0 +1,126 @@
+/* -*- 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 <stdio.h>
+#include "nscore.h"
+#include "nsIConverterInputStream.h"
+#include "nsIURL.h"
+#include "nsNetUtil.h"
+#include "nsCRT.h"
+#include "nsString.h"
+#include "prprf.h"
+#include "prtime.h"
+
+static nsString* ConvertCharacterSetName(const char* aName)
+{
+ return new nsString(NS_ConvertASCIItoUCS2(aName));
+}
+
+int main(int argc, char** argv)
+{
+ if (3 != argc) {
+ printf("usage: CvtURL url utf8\n");
+ return -1;
+ }
+
+ char* characterSetName = argv[2];
+ nsString* cset = ConvertCharacterSetName(characterSetName);
+ if (NS_PTR_TO_INT32(cset) < 0) {
+ printf("illegal character set name: '%s'\n", characterSetName);
+ return -1;
+ }
+
+ // Create url object
+ char* urlName = argv[1];
+ nsIURI* url;
+ nsresult rv;
+ rv = NS_NewURI(&url, urlName);
+ if (NS_OK != rv) {
+ printf("invalid URL: '%s'\n", urlName);
+ return -1;
+ }
+
+ // Get an input stream from the url
+ nsresult ec;
+ nsIInputStream* in;
+ ec = NS_OpenURI(&in, url);
+ if (nsnull == in) {
+ printf("open of url('%s') failed: error=%x\n", urlName, ec);
+ return -1;
+ }
+
+ // Translate the input using the argument character set id into
+ // unicode
+ nsCOMPtr<nsIConverterInputStream> uin =
+ do_CreateInstance("@mozilla.org/intl/converter-input-stream;1", &rv);
+ if (NS_SUCCEEDED(rv))
+ uin->Init(in, cset->get(), nsnull, PR_TRUE);
+ if (NS_OK != rv) {
+ printf("can't create converter input stream: %d\n", rv);
+ return -1;
+ }
+
+ // Read the input and write some output
+ PRTime start = PR_Now();
+ PRInt32 count = 0;
+ for (;;) {
+ PRUnichar buf[1000];
+ PRUint32 nb;
+ ec = uin->Read(buf, 0, 1000, &nb);
+ if (NS_FAILED(ec)) {
+ printf("i/o error: %d\n", ec);
+ break;
+ }
+ if (nb == 0) break; // EOF
+ count += nb;
+ }
+ PRTime end = PR_Now();
+ PRTime conversion, ustoms;
+ LL_I2L(ustoms, 1000);
+ LL_SUB(conversion, end, start);
+ LL_DIV(conversion, conversion, ustoms);
+ char buf[500];
+ PR_snprintf(buf, sizeof(buf),
+ "converting and discarding %d bytes took %lldms",
+ count, conversion);
+ puts(buf);
+
+ // Release the objects
+ in->Release();
+ url->Release();
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/Makefile.in b/src/libs/xpcom18a4/xpcom/tests/Makefile.in
new file mode 100644
index 00000000..2bd730e9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/Makefile.in
@@ -0,0 +1,116 @@
+#
+# ***** 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
+DIRS = dynamic services
+ifeq ($(OS_ARCH),WINNT)
+DIRS += windows
+endif
+
+REQUIRES = \
+ string \
+ $(NULL)
+
+CPPSRCS = \
+ nsIFileEnumerator.cpp \
+ nsIFileTest.cpp \
+ TestArray.cpp \
+ TestAtoms.cpp \
+ TestAutoLock.cpp \
+ TestCallTemplates.cpp \
+ TestCOMPtr.cpp \
+ TestCOMPtrEq.cpp \
+ TestCRT.cpp \
+ TestFactory.cpp \
+ TestHashtables.cpp \
+ TestID.cpp \
+ TestObserverService.cpp \
+ TestPermanentAtoms.cpp \
+ TestPipes.cpp \
+ TestServMgr.cpp \
+ TestThreads.cpp \
+ TestXPIDLString.cpp \
+ TestDeque.cpp \
+ TestAutoPtr.cpp \
+ TestMinStringAPI.cpp \
+ TestStrings.cpp \
+ $(NULL)
+
+#CPPSRCS += TimerTest.cpp
+
+SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))
+
+include $(topsrcdir)/config/config.mk
+
+LIBS += \
+ $(XPCOM_LIBS) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+# Needed to resolve __yylex (?)
+ifeq ($(OS_ARCH)$(OS_RELEASE),FreeBSD2)
+LIBS += -lpcap
+endif
+
+include $(topsrcdir)/config/rules.mk
+
+LOCAL_INCLUDES = \
+ -I$(srcdir)/../ds \
+ -I$(srcdir)/services \
+ $(NULL)
+
+ifeq ($(OS_ARCH),WINNT)
+ifdef GNU_CXX
+CXXFLAGS += -fexceptions
+else
+CXXFLAGS += -GX
+endif
+endif
+
+libs::
+ $(INSTALL) $(srcdir)/test.properties $(DIST)/bin/res
+
+install::
+ $(SYSINSTALL) $(IFLAGS1) $(srcdir)/test.properties $(DESTDIR)$(mozappdir)/res
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/RegFactory.cpp b/src/libs/xpcom18a4/xpcom/tests/RegFactory.cpp
new file mode 100644
index 00000000..79e53394
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/RegFactory.cpp
@@ -0,0 +1,162 @@
+/* -*- 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 <iostream.h>
+#include "plstr.h"
+#include "prlink.h"
+#include "nsIComponentRegistrar.h"
+#include "nsIComponentManager.h"
+#include "nsIServiceManager.h"
+#include "nsILocalFile.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+
+static PRBool gUnreg = PR_FALSE;
+
+void print_err(nsresult err)
+{
+ switch (err) {
+ case NS_ERROR_FACTORY_NOT_LOADED:
+ cerr << "Factory not loaded";
+ break;
+ case NS_NOINTERFACE:
+ cerr << "No Interface";
+ break;
+ case NS_ERROR_NULL_POINTER:
+ cerr << "Null pointer";
+ break;
+ case NS_ERROR_OUT_OF_MEMORY:
+ cerr << "Out of memory";
+ break;
+ default:
+ cerr << hex << err << dec;
+ }
+}
+
+nsresult Register(nsIComponentRegistrar* registrar, const char *path)
+{
+ nsCOMPtr<nsILocalFile> file;
+ nsresult rv =
+ NS_NewLocalFile(
+ NS_ConvertUTF8toUCS2(path),
+ PR_TRUE,
+ getter_AddRefs(file));
+ if (NS_FAILED(rv)) return rv;
+ rv = registrar->AutoRegister(file);
+ return rv;
+}
+
+nsresult Unregister(const char *path)
+{
+ /* NEEDS IMPLEMENTATION */
+#if 0
+ nsresult res = nsComponentManager::AutoUnregisterComponent(path);
+ return res;
+#else
+ return NS_ERROR_FAILURE;
+#endif
+}
+
+int ProcessArgs(nsIComponentRegistrar* registrar, int argc, char *argv[])
+{
+ int i = 1;
+ nsresult res;
+
+ while (i < argc) {
+ if (argv[i][0] == '-') {
+ int j;
+ for (j = 1; argv[i][j] != '\0'; j++) {
+ switch (argv[i][j]) {
+ case 'u':
+ gUnreg = PR_TRUE;
+ break;
+ default:
+ cerr << "Unknown option '" << argv[i][j] << "'\n";
+ }
+ }
+ i++;
+ } else {
+ if (gUnreg == PR_TRUE) {
+ res = Unregister(argv[i]);
+ if (NS_SUCCEEDED(res)) {
+ cout << "Successfully unregistered: " << argv[i] << "\n";
+ } else {
+ cerr << "Unregister failed (";
+ print_err(res);
+ cerr << "): " << argv[i] << "\n";
+ }
+ } else {
+ res = Register(registrar, argv[i]);
+ if (NS_SUCCEEDED(res)) {
+ cout << "Successfully registered: " << argv[i] << "\n";
+ } else {
+ cerr << "Register failed (";
+ print_err(res);
+ cerr << "): " << argv[i] << "\n";
+ }
+ }
+ i++;
+ }
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int ret = 0;
+ nsresult rv;
+ {
+ nsCOMPtr<nsIServiceManager> servMan;
+ rv = NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull);
+ if (NS_FAILED(rv)) return -1;
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan);
+ NS_ASSERTION(registrar, "Null nsIComponentRegistrar");
+
+ /* With no arguments, RegFactory will autoregister */
+ if (argc <= 1)
+ {
+ rv = registrar->AutoRegister(nsnull);
+ ret = (NS_FAILED(rv)) ? -1 : 0;
+ }
+ else
+ ret = ProcessArgs(registrar, argc, argv);
+ } // this scopes the nsCOMPtrs
+ // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
+ rv = NS_ShutdownXPCOM( NULL );
+ NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
+ return ret;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/SizeTest01.cpp b/src/libs/xpcom18a4/xpcom/tests/SizeTest01.cpp
new file mode 100644
index 00000000..2d552a36
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/SizeTest01.cpp
@@ -0,0 +1,107 @@
+// Test01.cpp
+
+#include "nsIDOMNode.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+
+NS_DEF_PTR(nsIDOMNode);
+
+ /*
+ This test file compares the generated code size of similar functions between raw
+ COM interface pointers (|AddRef|ing and |Release|ing by hand) and |nsCOMPtr|s.
+
+ Function size results were determined by examining dissassembly of the generated code.
+ mXXX is the size of the generated code on the Macintosh. wXXX is the size on Windows.
+ For these tests, all reasonable optimizations were enabled and exceptions were
+ disabled (just as we build for release).
+
+ The tests in this file explore only the simplest functionality: assigning a pointer
+ to be reference counted into a [raw, nsCOMPtr] object; ensuring that it is
+ |AddRef|ed and |Release|d appropriately; calling through the pointer to a function
+ supplied by the underlying COM interface.
+
+ Windows:
+ raw_optimized 31 bytes
+ raw, nsCOMPtr* 34
+ nsCOMPtr_optimized* 38
+ nsCOMPtr_optimized 42
+ nsCOMPtr 46
+
+ Macintosh:
+ raw_optimized, nsCOMPtr_optimized 112 bytes (1.0000)
+ nsCOMPtr 120 (1.0714) i.e., 7.14% bigger than raw_optimized et al
+ raw 140 (1.2500)
+
+ The overall difference in size between Windows and Macintosh is caused by the
+ the PowerPC RISC architecture where every instruction is 4 bytes.
+
+ On Macintosh, nsCOMPtr generates out-of-line destructors which are
+ not referenced, and which can be stripped by the linker.
+ */
+
+void
+Test01_raw( nsIDOMNode* aDOMNode, nsString* aResult )
+ // m140, w34
+ {
+ /*
+ This test is designed to be more like a typical large function where,
+ because you are working with several resources, you don't just return when
+ one of them is |NULL|. Similarly: |Test01_nsCOMPtr00|, and |Test01_nsIPtr00|.
+ */
+
+ nsIDOMNode* node = aDOMNode;
+ NS_IF_ADDREF(node);
+
+ if ( node )
+ node->GetNodeName(*aResult);
+
+ NS_IF_RELEASE(node);
+ }
+
+void
+Test01_raw_optimized( nsIDOMNode* aDOMNode, nsString* aResult )
+ // m112, w31
+ {
+ /*
+ This test simulates smaller functions where you _do_ just return
+ |NULL| at the first sign of trouble. Similarly: |Test01_nsCOMPtr01|,
+ and |Test01_nsIPtr01|.
+ */
+
+ /*
+ This test produces smaller code that |Test01_raw| because it avoids
+ the three tests: |NS_IF_...|, and |if ( node )|.
+ */
+
+// -- the following code is assumed, but is commented out so we compare only
+// the relevent generated code
+
+// if ( !aDOMNode )
+// return;
+
+ nsIDOMNode* node = aDOMNode;
+ NS_ADDREF(node);
+ node->GetNodeName(*aResult);
+ NS_RELEASE(node);
+ }
+
+void
+Test01_nsCOMPtr( nsIDOMNode* aDOMNode, nsString* aResult )
+ // m120, w46/34
+ {
+ nsCOMPtr<nsIDOMNode> node = aDOMNode;
+
+ if ( node )
+ node->GetNodeName(*aResult);
+ }
+
+void
+Test01_nsCOMPtr_optimized( nsIDOMNode* aDOMNode, nsString* aResult )
+ // m112, w42/38
+ {
+// if ( !aDOMNode )
+// return;
+
+ nsCOMPtr<nsIDOMNode> node = aDOMNode;
+ node->GetNodeName(*aResult);
+ }
diff --git a/src/libs/xpcom18a4/xpcom/tests/SizeTest02.cpp b/src/libs/xpcom18a4/xpcom/tests/SizeTest02.cpp
new file mode 100644
index 00000000..8515fcb1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/SizeTest02.cpp
@@ -0,0 +1,93 @@
+// Test02.cpp
+
+#include "nsIDOMNode.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+
+#ifdef __MWERKS__
+ #pragma exceptions off
+#endif
+
+NS_DEF_PTR(nsIDOMNode);
+
+ /*
+ This test file compares the generated code size of similar functions between raw
+ COM interface pointers (|AddRef|ing and |Release|ing by hand) and |nsCOMPtr|s.
+
+ Function size results were determined by examining dissassembly of the generated code.
+ mXXX is the size of the generated code on the Macintosh. wXXX is the size on Windows.
+ For these tests, all reasonable optimizations were enabled and exceptions were
+ disabled (just as we build for release).
+
+ The tests in this file explore more complicated functionality: assigning a pointer
+ to be reference counted into a [raw, nsCOMPtr] object using |QueryInterface|;
+ ensuring that it is |AddRef|ed and |Release|d appropriately; calling through the pointer
+ to a function supplied by the underlying COM interface. The tests in this file expand
+ on the tests in "Test01.cpp" by adding |QueryInterface|.
+
+ Windows:
+ raw01 52
+ nsCOMPtr 63
+ raw 66
+ nsCOMPtr* 68
+
+ Macintosh:
+ nsCOMPtr 120 (1.0000)
+ Raw01 128 (1.1429) i.e., 14.29% bigger than nsCOMPtr
+ Raw00 144 (1.2000)
+ */
+
+
+void // nsresult
+Test02_Raw00( nsISupports* aDOMNode, nsString* aResult )
+ // m144, w66
+ {
+// -- the following code is assumed, but is commented out so we compare only
+// the relevent generated code
+
+// if ( !aDOMNode )
+// return NS_ERROR_NULL_POINTER;
+
+ nsIDOMNode* node = 0;
+ nsresult status = aDOMNode->QueryInterface(NS_GET_IID(nsIDOMNode), (void**)&node);
+ if ( NS_SUCCEEDED(status) )
+ {
+ node->GetNodeName(*aResult);
+ }
+
+ NS_IF_RELEASE(node);
+
+// return status;
+ }
+
+void // nsresult
+Test02_Raw01( nsISupports* aDOMNode, nsString* aResult )
+ // m128, w52
+ {
+// if ( !aDOMNode )
+// return NS_ERROR_NULL_POINTER;
+
+ nsIDOMNode* node;
+ nsresult status = aDOMNode->QueryInterface(NS_GET_IID(nsIDOMNode), (void**)&node);
+ if ( NS_SUCCEEDED(status) )
+ {
+ node->GetNodeName(*aResult);
+ NS_RELEASE(node);
+ }
+
+// return status;
+ }
+
+void // nsresult
+Test02_nsCOMPtr( nsISupports* aDOMNode, nsString* aResult )
+ // m120, w63/68
+ {
+ nsresult status;
+ nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aDOMNode, &status);
+
+ if ( node )
+ node->GetNodeName(*aResult);
+
+// return status;
+ }
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/SizeTest03.cpp b/src/libs/xpcom18a4/xpcom/tests/SizeTest03.cpp
new file mode 100644
index 00000000..9ca71c72
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/SizeTest03.cpp
@@ -0,0 +1,101 @@
+// Test03.cpp
+
+#include "nsIDOMNode.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+
+#ifdef __MWERKS__
+ #pragma exceptions off
+#endif
+
+NS_DEF_PTR(nsIDOMNode);
+
+ /*
+ Windows:
+ nsCOMPtr_optimized* 45
+ raw_optimized 48
+ nsCOMPtr_optimized 50
+ nsCOMPtr 54
+ nsCOMPtr* 59
+ raw 62
+
+ Macintosh:
+ nsCOMPtr_optimized 112 (1.0000)
+ raw_optimized 124 bytes (1.1071) i.e., 10.71% bigger than nsCOMPtr_optimized
+ nsCOMPtr 144 (1.2857)
+ */
+
+void // nsresult
+Test03_raw( nsIDOMNode* aDOMNode, nsString* aResult )
+ // m140, w62
+ {
+// -- the following code is assumed, but is commented out so we compare only
+// the relevent generated code
+
+// if ( !aDOMNode || !aResult )
+// return NS_ERROR_NULL_POINTER;
+
+ nsIDOMNode* parent = 0;
+ nsresult status = aDOMNode->GetParentNode(&parent);
+
+ if ( NS_SUCCEEDED(status) )
+ {
+ parent->GetNodeName(*aResult);
+ }
+
+ NS_IF_RELEASE(parent);
+
+// return status;
+ }
+
+
+void // nsresult
+Test03_raw_optimized( nsIDOMNode* aDOMNode, nsString* aResult )
+ // m124, w48
+ {
+// if ( !aDOMNode || !aResult )
+// return NS_ERROR_NULL_POINTER;
+
+ nsIDOMNode* parent;
+ nsresult status = aDOMNode->GetParentNode(&parent);
+
+ if ( NS_SUCCEEDED(status) )
+ {
+ parent->GetNodeName(*aResult);
+ NS_RELEASE(parent);
+ }
+
+// return status;
+ }
+
+
+void // nsresult
+Test03_nsCOMPtr( nsIDOMNode* aDOMNode, nsString* aResult )
+ // m144, w54/59
+ {
+// if ( !aDOMNode || !aResult )
+// return NS_ERROR_NULL_POINTER;
+
+ nsCOMPtr<nsIDOMNode> parent;
+ nsresult status = aDOMNode->GetParentNode( getter_AddRefs(parent) );
+ if ( parent )
+ parent->GetNodeName(*aResult);
+
+// return status;
+ }
+
+void // nsresult
+Test03_nsCOMPtr_optimized( nsIDOMNode* aDOMNode, nsString* aResult )
+ // m112, w50/45
+ {
+// if ( !aDOMNode || !aResult )
+// return NS_ERROR_NULL_POINTER;
+
+ nsIDOMNode* temp;
+ nsresult status = aDOMNode->GetParentNode(&temp);
+ nsCOMPtr<nsIDOMNode> parent( dont_AddRef(temp) );
+ if ( parent )
+ parent->GetNodeName(*aResult);
+
+// return status;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/tests/SizeTest04.cpp b/src/libs/xpcom18a4/xpcom/tests/SizeTest04.cpp
new file mode 100644
index 00000000..aad4ee68
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/SizeTest04.cpp
@@ -0,0 +1,72 @@
+// Test04.cpp
+
+#include "nsIDOMNode.h"
+#include "nsCOMPtr.h"
+
+#ifdef __MWERKS__
+ #pragma exceptions off
+#endif
+
+NS_DEF_PTR(nsIDOMNode);
+
+ /*
+ Windows:
+ nsCOMPtr 13
+ raw 36
+
+ Macintosh:
+ nsCOMPtr 36 bytes (1.0000)
+ raw 120 (3.3333) i.e., 333.33% bigger than nsCOMPtr
+ */
+
+class Test04_Raw
+ {
+ public:
+ Test04_Raw();
+ ~Test04_Raw();
+
+ void /*nsresult*/ SetNode( nsIDOMNode* newNode );
+
+ private:
+ nsIDOMNode* mNode;
+ };
+
+Test04_Raw::Test04_Raw()
+ : mNode(0)
+ {
+ // nothing else to do here
+ }
+
+Test04_Raw::~Test04_Raw()
+ {
+ NS_IF_RELEASE(mNode);
+ }
+
+void // nsresult
+Test04_Raw::SetNode( nsIDOMNode* newNode )
+ // m120, w36
+ {
+ NS_IF_ADDREF(newNode);
+ NS_IF_RELEASE(mNode);
+ mNode = newNode;
+
+// return NS_OK;
+ }
+
+
+
+class Test04_nsCOMPtr
+ {
+ public:
+ void /*nsresult*/ SetNode( nsIDOMNode* newNode );
+
+ private:
+ nsCOMPtr<nsIDOMNode> mNode;
+ };
+
+void // nsresult
+Test04_nsCOMPtr::SetNode( nsIDOMNode* newNode )
+ // m36, w13/13
+ {
+ mNode = newNode;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/tests/SizeTest05.cpp b/src/libs/xpcom18a4/xpcom/tests/SizeTest05.cpp
new file mode 100644
index 00000000..0211610e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/SizeTest05.cpp
@@ -0,0 +1,78 @@
+// Test05.cpp
+
+#include "nsIDOMNode.h"
+#include "nsCOMPtr.h"
+
+#ifdef __MWERKS__
+ #pragma exceptions off
+#endif
+
+NS_DEF_PTR(nsIDOMNode);
+
+ /*
+ Windows:
+ raw, nsCOMPtr 21 bytes
+
+ Macintosh:
+ Raw, nsCOMPtr 64 bytes
+ */
+
+class Test05_Raw
+ {
+ public:
+ Test05_Raw();
+ ~Test05_Raw();
+
+ void /*nsresult*/ GetNode( nsIDOMNode** aNode );
+
+ private:
+ nsIDOMNode* mNode;
+ };
+
+Test05_Raw::Test05_Raw()
+ : mNode(0)
+ {
+ // nothing else to do here
+ }
+
+Test05_Raw::~Test05_Raw()
+ {
+ NS_IF_RELEASE(mNode);
+ }
+
+void // nsresult
+Test05_Raw::GetNode( nsIDOMNode** aNode )
+ // m64, w21
+ {
+// if ( !aNode )
+// return NS_ERROR_NULL_POINTER;
+
+ *aNode = mNode;
+ NS_IF_ADDREF(*aNode);
+
+// return NS_OK;
+ }
+
+
+
+class Test05_nsCOMPtr
+ {
+ public:
+ void /*nsresult*/ GetNode( nsIDOMNode** aNode );
+
+ private:
+ nsCOMPtr<nsIDOMNode> mNode;
+ };
+
+void // nsresult
+Test05_nsCOMPtr::GetNode( nsIDOMNode** aNode )
+ // m64, w21
+ {
+// if ( !aNode )
+// return NS_ERROR_NULL_POINTER;
+
+ *aNode = mNode;
+ NS_IF_ADDREF(*aNode);
+
+// return NS_OK;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/tests/SizeTest06.cpp b/src/libs/xpcom18a4/xpcom/tests/SizeTest06.cpp
new file mode 100644
index 00000000..2c28e7f3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/SizeTest06.cpp
@@ -0,0 +1,231 @@
+// Test06.cpp
+
+#include "nsIDOMWindowInternal.h"
+#include "nsIScriptGlobalObject.h"
+#include "nsIWebShell.h"
+#include "nsIDocShell.h"
+#include "nsIWebShellWindow.h"
+#include "nsCOMPtr.h"
+
+NS_DEF_PTR(nsIScriptGlobalObject);
+NS_DEF_PTR(nsIWebShell);
+NS_DEF_PTR(nsIWebShellContainer);
+NS_DEF_PTR(nsIWebShellWindow);
+
+ /*
+ Windows:
+ nsCOMPtr_optimized 176
+ nsCOMPtr_as_found 181
+ nsCOMPtr_optimized* 182
+ nsCOMPtr02* 184
+ nsCOMPtr02 187
+ nsCOMPtr02* 188
+ nsCOMPtr03 189
+ raw_optimized, nsCOMPtr00 191
+ nsCOMPtr00* 199
+ nsCOMPtr_as_found* 201
+ raw 214
+
+ Macintosh:
+ nsCOMPtr_optimized 300 (1.0000)
+ nsCOMPtr02 320 (1.0667) i.e., 6.67% bigger than nsCOMPtr_optimized
+ nsCOMPtr00 328 (1.0933)
+ raw_optimized, nsCOMPtr03 332 (1.1067)
+ nsCOMPtr_as_found 344 (1.1467)
+ raw 388 (1.2933)
+
+ */
+
+
+void // nsresult
+Test06_raw(nsIDOMWindowInternal* aDOMWindow, nsIWebShellWindow** aWebShellWindow)
+ // m388, w214
+{
+// if (!aDOMWindow)
+// return NS_ERROR_NULL_POINTER;
+ nsIScriptGlobalObject* scriptGlobalObject = 0;
+ nsresult status = aDOMWindow->QueryInterface(NS_GET_IID(nsIScriptGlobalObject), (void**)&scriptGlobalObject);
+ nsIDocShell* docShell = 0;
+ if (scriptGlobalObject)
+ scriptGlobalObject->GetDocShell(&docShell);
+ nsIWebShell* webShell = 0;
+ if (docShell)
+ status=docShell->QueryInterface(NS_GET_IID(nsIWebShell), (void**)&webShell);
+ nsIWebShell* rootWebShell = 0;
+ if (webShell)
+ //status = webShell->GetRootWebShellEvenIfChrome(rootWebShell);
+ {}
+ nsIWebShellContainer* webShellContainer = 0;
+ if (rootWebShell)
+ status = rootWebShell->GetContainer(webShellContainer);
+ if (webShellContainer)
+ status = webShellContainer->QueryInterface(NS_GET_IID(nsIWebShellWindow), (void**)aWebShellWindow);
+ else
+ (*aWebShellWindow) = 0;
+ NS_IF_RELEASE(webShellContainer);
+ NS_IF_RELEASE(rootWebShell);
+ NS_IF_RELEASE(webShell);
+ NS_IF_RELEASE(docShell);
+ NS_IF_RELEASE(scriptGlobalObject);
+// return status;
+}
+
+void // nsresult
+Test06_raw_optimized(nsIDOMWindowInternal* aDOMWindow, nsIWebShellWindow** aWebShellWindow)
+ // m332, w191
+{
+// if (!aDOMWindow)
+// return NS_ERROR_NULL_POINTER;
+ (*aWebShellWindow) = 0;
+ nsIScriptGlobalObject* scriptGlobalObject;
+ nsresult status = aDOMWindow->QueryInterface(NS_GET_IID(nsIScriptGlobalObject), (void**)&scriptGlobalObject);
+ if (NS_SUCCEEDED(status)) {
+ nsIDocShell* docShell = 0;
+ scriptGlobalObject->GetDocShell(&docShell);
+ if (docShell) {
+ nsIWebShell* webShell = 0;
+ docShell->QueryInterface(NS_GET_IID(nsIWebShell), (void**)webShell);
+ if (webShell) {
+ nsIWebShell* rootWebShell;
+ // status = webShell->GetRootWebShellEvenIfChrome(rootWebShell);
+ if (NS_SUCCEEDED(status)) {
+ nsIWebShellContainer* webShellContainer;
+ status = rootWebShell->GetContainer(webShellContainer);
+ if (NS_SUCCEEDED(status)) {
+ status = webShellContainer->QueryInterface(NS_GET_IID(nsIWebShellWindow), (void**)aWebShellWindow);
+ NS_RELEASE(webShellContainer);
+ }
+ NS_RELEASE(rootWebShell);
+ }
+ NS_RELEASE(webShell);
+ }
+ NS_RELEASE(docShell);
+ }
+ NS_RELEASE(scriptGlobalObject);
+ }
+// return status;
+}
+
+void
+Test06_nsCOMPtr_as_found(nsIDOMWindowInternal* aDOMWindow, nsCOMPtr<nsIWebShellWindow>* aWebShellWindow)
+ // m344, w181/201
+{
+// if (!aDOMWindow)
+// return;
+ nsCOMPtr<nsIScriptGlobalObject> scriptGlobalObject = do_QueryInterface(aDOMWindow);
+ nsCOMPtr<nsIDocShell> docShell;
+ if (scriptGlobalObject)
+ scriptGlobalObject->GetDocShell(getter_AddRefs(docShell));
+ nsCOMPtr<nsIWebShell> webShell;
+ if (docShell)
+ webShell = do_QueryInterface(docShell);
+ nsCOMPtr<nsIWebShell> rootWebShell;
+ if (webShell)
+ //webShell->GetRootWebShellEvenIfChrome(*getter_AddRefs(rootWebShell));
+ {}
+ nsCOMPtr<nsIWebShellContainer> webShellContainer;
+ if (rootWebShell)
+ rootWebShell->GetContainer(*getter_AddRefs(webShellContainer));
+ (*aWebShellWindow) = do_QueryInterface(webShellContainer);
+}
+
+void // nsresult
+Test06_nsCOMPtr00(nsIDOMWindowInternal* aDOMWindow, nsIWebShellWindow** aWebShellWindow)
+ // m328, w191/199
+{
+// if (!aDOMWindow)
+// return NS_ERROR_NULL_POINTER;
+ nsresult status;
+ nsCOMPtr<nsIScriptGlobalObject> scriptGlobalObject = do_QueryInterface(aDOMWindow, &status);
+ nsIDocShell* temp0 = 0;
+ if (scriptGlobalObject)
+ scriptGlobalObject->GetDocShell(&temp0);
+ nsCOMPtr<nsIDocShell> docShell = dont_AddRef(temp0);
+ nsCOMPtr<nsIWebShell> webShell;
+ if (docShell)
+ webShell=do_QueryInterface(docShell, &status);
+ nsIWebShellContainer* temp2 = 0;
+ if (webShell)
+ status = webShell->GetContainer(temp2);
+ nsCOMPtr<nsIWebShellContainer> webShellContainer = dont_AddRef(temp2);
+ if (webShellContainer)
+ status = webShellContainer->QueryInterface(NS_GET_IID(nsIWebShellWindow), (void**)aWebShellWindow);
+ else
+ (*aWebShellWindow) = 0;
+// return status;
+}
+
+void // nsresult
+Test06_nsCOMPtr_optimized(nsIDOMWindowInternal* aDOMWindow, nsCOMPtr<nsIWebShellWindow>* aWebShellWindow)
+ // m300, w176/182
+{
+// if (!aDOMWindow)
+// return NS_ERROR_NULL_POINTER;
+ nsresult status;
+ nsCOMPtr<nsIScriptGlobalObject> scriptGlobalObject = do_QueryInterface(aDOMWindow, &status);
+ nsIDocShell* temp0 = 0;
+ if (scriptGlobalObject)
+ scriptGlobalObject->GetDocShell(&temp0);
+ nsCOMPtr<nsIWebShell> webShell = do_QueryInterface(temp0, &status);
+ nsIWebShell* temp2 = 0;
+ if (webShell)
+ // status = webShell->GetRootWebShellEvenIfChrome(temp2);
+ {}
+ nsCOMPtr<nsIWebShell> rootWebShell = dont_AddRef(temp2);
+ nsIWebShellContainer* temp3 = 0;
+ if (rootWebShell)
+ status = rootWebShell->GetContainer(temp3);
+ nsCOMPtr<nsIWebShellContainer> webShellContainer = dont_AddRef(temp3);
+ (*aWebShellWindow) = do_QueryInterface(webShellContainer, &status);
+// return status;
+}
+
+void // nsresult
+Test06_nsCOMPtr02(nsIDOMWindowInternal* aDOMWindow, nsIWebShellWindow** aWebShellWindow)
+ // m320, w187/184
+{
+// if (!aDOMWindow)
+// return NS_ERROR_NULL_POINTER;
+ (*aWebShellWindow) = 0;
+ nsresult status;
+ nsCOMPtr<nsIScriptGlobalObject> scriptGlobalObject = do_QueryInterface(aDOMWindow, &status);
+ if (scriptGlobalObject) {
+ nsIDocShell* temp0;
+ scriptGlobalObject->GetDocShell(&temp0);
+ nsCOMPtr<nsIWebShell> webShell = do_QueryInterface(temp0);
+ if (webShell) {
+ nsIWebShellContainer* temp2;
+ status = webShell->GetContainer(temp2);
+ nsCOMPtr<nsIWebShellContainer> webShellContainer = dont_AddRef(temp2);
+ if (webShellContainer)
+ status = webShellContainer->QueryInterface(NS_GET_IID(nsIWebShellWindow), (void**)aWebShellWindow);
+ }
+ }
+// return status;
+}
+
+void // nsresult
+Test06_nsCOMPtr03(nsIDOMWindowInternal* aDOMWindow, nsCOMPtr<nsIWebShellWindow>* aWebShellWindow)
+ // m332, w189/188
+{
+// if (!aDOMWindow)
+// return NS_ERROR_NULL_POINTER;
+ (*aWebShellWindow) = 0;
+ nsresult status;
+ nsCOMPtr<nsIScriptGlobalObject> scriptGlobalObject = do_QueryInterface(aDOMWindow, &status);
+ if (scriptGlobalObject) {
+ nsIDocShell* temp0;
+ scriptGlobalObject->GetDocShell(&temp0);
+ nsCOMPtr<nsIDocShell> docShell = dont_AddRef(temp0);
+ if (docShell) {
+ nsCOMPtr<nsIWebShell> webShell = do_QueryInterface(docShell, &status);
+ if (webShell) {
+ nsIWebShellContainer* temp2;
+ status = webShell->GetContainer(temp2);
+ nsCOMPtr<nsIWebShellContainer> webShellContainer = dont_AddRef(temp2);
+ (*aWebShellWindow) = do_QueryInterface(webShellContainer, &status);
+ }
+ }
+ }
+// return status;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/Makefile.in b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/Makefile.in
new file mode 100644
index 00000000..1ced5d3e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/Makefile.in
@@ -0,0 +1,76 @@
+#
+# ***** 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
+PROGRAM = profile_strings
+#PROGRAM = test_main
+
+CPPSRCS = \
+ $(topsrcdir)/xpcom/ds/nsString2.cpp \
+ $(topsrcdir)/xpcom/ds/nsStr.cpp \
+ $(topsrcdir)/xpcom/ds/nsString.cpp \
+ $(topsrcdir)/xpcom/ds/nsCRT.cpp \
+ $(topsrcdir)/xpcom/base/nsAllocator.cpp \
+ $(topsrcdir)/xpcom/ds/nsDeque.cpp \
+ profile_main.cpp \
+ $(NULL)
+# test_main.cpp \
+
+
+LIBS += \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -DNEW_STRING_APIS -DSTANDALONE_STRING_TESTS -UDEBUG -DNDEBUG
+#DEFINES += -DSTANDALONE_STRING_TESTS -UDEBUG -DNDEBUG
+INCLUDES += -I$(srcdir)/../public -I$(srcdir)/services
+
+libs::
+ $(INSTALL) $(srcdir)/test.properties $(DIST)/bin/res
+
+install::
+ $(SYSINSTALL) $(IFLAGS1) $(srcdir)/test.properties $(DESTDIR)$(mozappdir)/res
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTest.Prefix b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTest.Prefix
new file mode 100644
index 00000000..b9580e49
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTest.Prefix
@@ -0,0 +1,4 @@
+// StringTest.Prefix
+
+#define STANDALONE_STRING_TESTS
+#define HAVE_CPP_2BYTE_WCHAR_T
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTest.mcp b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTest.mcp
new file mode 100644
index 00000000..12b125ed
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTest.mcp
Binary files differ
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestDebug.Prefix b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestDebug.Prefix
new file mode 100644
index 00000000..3724af94
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestDebug.Prefix
@@ -0,0 +1,4 @@
+#include "StringTest.Prefix"
+
+#define DEBUG 1
+#undef NDEBUG
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestNo_wchar_t.Prefix b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestNo_wchar_t.Prefix
new file mode 100644
index 00000000..dddf8450
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestNo_wchar_t.Prefix
@@ -0,0 +1,5 @@
+// StringTestNo_wchar_t.Prefix
+
+#include "StringTest.Prefix"
+
+#undef HAVE_CPP_2BYTE_WCHAR_T
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileNew.Prefix b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileNew.Prefix
new file mode 100644
index 00000000..b6ca50d3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileNew.Prefix
@@ -0,0 +1,3 @@
+// StringTestProfileNew.Prefix
+
+#include "StringTest.Prefix"
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileOld.Prefix b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileOld.Prefix
new file mode 100644
index 00000000..d23e3ea9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileOld.Prefix
@@ -0,0 +1,6 @@
+// StringTestProfileOld.Prefix
+
+#include "StringTest.Prefix"
+
+#define OLD_STRING_APIS
+#undef HAVE_CPP_2BYTE_WCHAR_T \ No newline at end of file
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileStd.Prefix b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileStd.Prefix
new file mode 100644
index 00000000..eb8a7a85
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/StringTestProfileStd.Prefix
@@ -0,0 +1,7 @@
+// StringTestProfileOld.Prefix
+
+#include "StringTest.Prefix"
+
+#define OLD_STRING_APIS
+#define TEST_STD_STRING
+#undef HAVE_CPP_2BYTE_WCHAR_T \ No newline at end of file
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/ToDo.doc b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/ToDo.doc
new file mode 100644
index 00000000..da114471
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/ToDo.doc
@@ -0,0 +1,41 @@
+// To Do...
+
+ - Decide: do I really want to define |Equals| (i.e., so many extra signatures)
+
+ . Make |ns[C]String| rename its converting operations to, e.g., |EqualsWithConversion|,
+ |AssignWithConversion|, |CompareWithConversion|, |AppendWithConversion|, etc.
+
+ . Bring |Equals| and |Compare| into scope
+
+ . Implement chunky iterators
+
+ . Get "nsAReadableString.h" and "nsAWritableString.h" to added to the MANIFEST, etc.
+
+ - Get "nsAReadableString.h" and "nsAWritableString.h" to compile everywhere
+
+ - Add test for |Replace|...
+
+ - Add tests for Find and RFind
+
+ - Implement the Find and RFind signatures
+
+ . Fix Truncate / SetLength confusion (make SetLength the real function in |nsString|)
+
+ . Chop out conflicting |ns[C]String| operators
+
+ . Figure out how if we can make PRUnichar be wchar_t, so we get the cheap constructors,
+ ...and ensure the cheap constructors can be made to work everywhere
+
+ x Try the |static const unsigned long kLeftString = 1 - 1; /* because VC++ doesn't like =0 */| hack
+
+ . Add tests for |nsShared[C]String|
+
+ . Implement |nsShared[C]String|
+
+ - Add tests for the shared string smart pointer
+
+ . Implement the shared string smart pointer
+
+ . Figure out why StdStringWrapper isn't as good as raw std::string
+
+ - Implement a smart allocator for StdStringWrapper
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/nsStdStringWrapper.h b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/nsStdStringWrapper.h
new file mode 100644
index 00000000..6e43b528
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/nsStdStringWrapper.h
@@ -0,0 +1,234 @@
+/* -*- 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):
+ * Scott Collins <scc@mozilla.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 ***** */
+
+#ifndef nsStdStringWrapper_h___
+#define nsStdStringWrapper_h___
+
+#include <string>
+
+#ifndef nsAString_h___
+#include "nsAString.h"
+#endif
+
+
+template <class T>
+class nsStringAllocator
+ : public std::allocator<T> // temporarily
+ {
+ // ...
+ };
+
+
+template < class CharT, class TraitsT = nsCharTraits<CharT>, class AllocatorT = nsStringAllocator<CharT> >
+class basic_nsStdStringWrapper
+ : public basic_nsAString<CharT>
+ /*
+ ...
+ */
+ {
+ protected:
+ std::basic_string<CharT, TraitsT, AllocatorT> mRawString;
+
+ typedef std::basic_string<CharT, TraitsT, AllocatorT> basic_string_t;
+
+ using typename basic_string_t::traits_type;
+ using typename basic_string_t::value_type;
+ using typename basic_string_t::allocator_type;
+ using typename basic_string_t::size_type;
+ using typename basic_string_t::difference_type;
+ using typename basic_string_t::reference;
+ using typename basic_string_t::const_reference;
+ using typename basic_string_t::pointer;
+ using typename basic_string_t::const_pointer;
+ using typename basic_string_t::iterator;
+ using typename basic_string_t::const_iterator;
+ using typename basic_string_t::reverse_iterator;
+ using typename basic_string_t::const_reverse_iterator;
+
+ static const size_type npos = size_type(-1);
+
+ protected:
+ virtual const void* Implementation() const;
+
+ virtual const CharT* GetReadableFragment( nsReadableFragment<CharT>&, nsFragmentRequest, PRUint32 ) const;
+ virtual CharT* GetWritableFragment( nsWritableFragment<CharT>&, nsFragmentRequest, PRUint32 );
+
+ public:
+ basic_nsStdStringWrapper() { }
+
+#if 0
+ explicit
+ basic_nsStdStringWrapper( const AllocatorT& a = AllocatorT() )
+ : mRawString(a)
+ {
+ }
+#endif
+
+ explicit
+ basic_nsStdStringWrapper( const basic_nsAString<CharT>& str )
+ {
+ Assign(str);
+ }
+
+#if 0
+ explicit
+ basic_nsStdStringWrapper( const basic_string_t& str, size_type pos = 0, size_type n = npos )
+ : mRawString(str, pos, n)
+ {
+ }
+
+ basic_nsStdStringWrapper( const basic_string_t& str, size_type pos, size_type n, const AllocatorT& a )
+ : mRawString(str, pos, n, a)
+ {
+ }
+#endif
+
+ basic_nsStdStringWrapper( const CharT* s, size_type n, const AllocatorT& a = AllocatorT() )
+ : mRawString(s, n, a)
+ {
+ }
+
+ explicit
+ basic_nsStdStringWrapper( const CharT* s, const AllocatorT& a = AllocatorT() )
+ : mRawString(s, a)
+ {
+ }
+
+#if 0
+ basic_nsStdStringWrapper( size_type n, CharT c, const AllocatorT& a = AllocatorT() )
+ : mRawString(n, c, a)
+ {
+ }
+#endif
+
+ virtual
+ PRUint32
+ Length() const
+ {
+ return mRawString.length();
+ }
+
+ virtual
+ void
+ SetCapacity( PRUint32 aNewCapacity )
+ {
+ mRawString.reserve(aNewCapacity);
+ }
+
+ virtual
+ void
+ SetLength( PRUint32 aNewLength )
+ {
+ mRawString.resize(aNewLength);
+ }
+
+ protected:
+ virtual void do_AssignFromReadable( const basic_nsAString<CharT>& );
+
+ // ...
+ };
+
+NS_DEF_TEMPLATE_STRING_COMPARISON_OPERATORS(basic_nsStdStringWrapper<CharT>, CharT)
+
+
+
+template <class CharT, class TraitsT, class AllocatorT>
+const void*
+basic_nsStdStringWrapper<CharT, TraitsT, AllocatorT>::Implementation() const
+ {
+ static const char* implementation = "nsStdStringWrapper";
+ return implementation;
+ }
+
+
+template <class CharT, class TraitsT, class AllocatorT>
+const CharT*
+basic_nsStdStringWrapper<CharT, TraitsT, AllocatorT>::GetReadableFragment( nsReadableFragment<CharT>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const
+ {
+ switch ( aRequest )
+ {
+ case kFirstFragment:
+ case kLastFragment:
+ case kFragmentAt:
+ aFragment.mEnd = (aFragment.mStart = mRawString.data()) + mRawString.length();
+ return aFragment.mStart + aOffset;
+
+ case kPrevFragment:
+ case kNextFragment:
+ default:
+ return 0;
+ }
+ }
+
+template <class CharT, class TraitsT, class AllocatorT>
+CharT*
+basic_nsStdStringWrapper<CharT, TraitsT, AllocatorT>::GetWritableFragment( nsWritableFragment<CharT>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset )
+ {
+ switch ( aRequest )
+ {
+ case kFirstFragment:
+ case kLastFragment:
+ case kFragmentAt:
+ aFragment.mEnd = (aFragment.mStart = NS_CONST_CAST(CharT*, mRawString.data())) + mRawString.length();
+ return aFragment.mStart + aOffset;
+
+ case kPrevFragment:
+ case kNextFragment:
+ default:
+ return 0;
+ }
+ }
+
+template <class CharT, class TraitsT, class AllocatorT>
+void
+basic_nsStdStringWrapper<CharT, TraitsT, AllocatorT>::do_AssignFromReadable( const basic_nsAString<CharT>& rhs )
+ {
+ typedef basic_nsStdStringWrapper<CharT, TraitsT, AllocatorT> this_t;
+
+ if ( SameImplementation(*this, rhs) )
+ mRawString = NS_STATIC_CAST(this_t, rhs).mRawString;
+ else
+ basic_nsAString<CharT>::do_AssignFromReadable(rhs);
+ }
+
+
+typedef basic_nsStdStringWrapper<PRUnichar> nsStdString;
+typedef basic_nsStdStringWrapper<char> nsStdCString;
+
+
+#endif // !defined(nsStdStringWrapper_h___)
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/profile_main.cpp b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/profile_main.cpp
new file mode 100644
index 00000000..d7c14621
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/profile_main.cpp
@@ -0,0 +1,497 @@
+// profile_main.cpp
+
+#include "nscore.h"
+#include <iostream.h>
+#include <string>
+#include <iomanip>
+
+#include "nsInt64.h"
+
+#ifdef XP_MAC
+#include <Timer.h>
+#include "Profiler.h"
+#else
+#include "prtime.h"
+#endif
+
+#ifndef TEST_STD_STRING
+#include "nsString.h"
+#else
+#include "nsStdStringWrapper.h"
+typedef nsStdCString nsCString;
+#endif
+
+static const int kTestSucceeded = 0;
+static const int kTestFailed = 1;
+
+static const size_t N = 100000;
+
+
+template <class T>
+inline
+PRUint32
+TotalLength( const T& s )
+ {
+ return s.Length();
+ }
+
+NS_SPECIALIZE_TEMPLATE
+inline
+PRUint32
+TotalLength( const string& s )
+ {
+ return s.length();
+ }
+
+template <class T>
+inline
+PRUint32
+Find( const T& text, const T& pattern )
+ {
+ return text.Find(pattern);
+ }
+
+NS_SPECIALIZE_TEMPLATE
+inline
+PRUint32
+Find( const string& text, const string& pattern )
+ {
+ return text.find(pattern);
+ }
+
+inline
+nsInt64
+GetTime()
+ {
+#ifdef XP_MAC
+ UnsignedWide time;
+ Microseconds(&time);
+ return nsInt64( *reinterpret_cast<PRInt64*>(&time) );
+#else
+ return nsInt64( PR_Now() );
+#endif
+ }
+
+class TestTimer
+ {
+ public:
+ TestTimer() : mStartTime(GetTime()) { }
+
+ ~TestTimer()
+ {
+ nsInt64 stopTime = GetTime();
+ nsInt64 totalTime = stopTime - mStartTime;
+#ifdef HAVE_LONG_LONG
+ cout << setw(10) << NS_STATIC_CAST(PRInt64, totalTime) << " µs : ";
+#else
+ cout << setw(10) << NS_STATIC_CAST(PRInt32, totalTime) << "µs : ";
+#endif
+ }
+
+ private:
+ nsInt64 mStartTime;
+ };
+
+inline
+int
+foo( const nsCString& )
+ {
+ return 1;
+ }
+
+static
+int
+test_construction()
+ {
+ cout << endl;
+
+ {
+ nsCString someCString;
+ int total = 0;
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ {
+ total += foo( someCString );
+ }
+ }
+ cout << "null loop time for constructor" << endl;
+
+
+ {
+ int total = 0;
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ {
+ total += foo( nsCString() );
+ }
+ }
+ cout << "nsCString()" << endl;
+
+
+ {
+ int total = 0;
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ {
+ total += foo( nsCString("This is a reasonable length string with some text in it and it is good.") );
+ }
+ }
+ cout << "nsCString(\"abc\")" << endl;
+
+ return kTestSucceeded;
+ }
+
+static
+int
+test_concat()
+ {
+ cout << endl;
+
+ //---------|---------|---------|---------|---------|---------|---------|
+ nsCString s1("This is a reasonable length string with some text in it and it is good.");
+ nsCString s2("This is another string that I will use in the concatenation test.");
+ nsCString s3("This is yet a third string that I will use in the concatenation test.");
+
+ PRUint32 len = TotalLength( s1 + s2 + s3 + s1 + s2 + s3 );
+ if ( len != (71 + 65 + 69 + 71 + 65 + 69) )
+ {
+ cout << "|test_concat()| FAILED" << endl;
+ return kTestFailed;
+ }
+
+
+ {
+ nsCString anEmptyCString;
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ {
+ len += TotalLength( anEmptyCString );
+ }
+ }
+ cout << "null loop time for concat" << endl;
+
+
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ len += TotalLength( s1 + s2 + s3 + s1 + s2 + s3 );
+ }
+ cout << "TotalLength( s1 + s2 + s3 + s1 + s2 + s3 )" << endl;
+
+
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ len += TotalLength( s1 + s2 );
+ }
+ cout << "TotalLength( s1 + s2 )" << endl;
+
+ return kTestSucceeded;
+ }
+
+static
+int
+test_concat_and_assign()
+ {
+ //---------|---------|---------|---------|---------|---------|---------|
+ nsCString s1("This is a reasonable length string with some text in it and it is good.");
+ nsCString s2("This is another string that I will use in the concatenation test.");
+ nsCString s3("This is yet a third string that I will use in the concatenation test.");
+
+ nsCString s4( s1 + s2 + s3 + s1 + s2 + s3 );
+ if ( TotalLength(s4) != (71 + 65 + 69 + 71 + 65 + 69) )
+ {
+ cout << "|test_concat()| FAILED" << endl;
+ return kTestFailed;
+ }
+
+
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ s4 = s1 + s2 + s3 + s1 + s2 + s3;
+ }
+ cout << "s4 = s1 + s2 + s3 + s1 + s2 + s3" << endl;
+
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ s4 = s1 + s2;
+ }
+ cout << "s4 = s1 + s2" << endl;
+
+ return kTestSucceeded;
+ }
+
+static
+int
+test_compare()
+ {
+ nsCString s1("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxThis is a reasonable length string with some text in it and it is good.");
+ nsCString s2("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxThis is a reasonable length string with some text in it and it is bad.");
+
+ int count = 0;
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ if ( s1 > s2 )
+ ++count;
+ }
+ cout << "s1 > s2" << endl;
+
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ if ( s1 == s1 )
+ ++count;
+ }
+ cout << "s1 == s1" << endl;
+
+ return kTestSucceeded;
+ }
+
+static
+int
+test_countchar()
+ {
+ nsCString s1("This is a reasonable length string with some text in it and it is good.");
+
+ if ( s1.CountChar('e') != 5 )
+ {
+ cout << "|test_countchar()| FAILED: found a count of " << s1.CountChar('e') << endl;
+ return kTestFailed;
+ }
+
+ PRUint32 total = 0;
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ total += s1.CountChar('e');
+ }
+ cout << "s1.CountChar('e')" << endl;
+
+ return kTestSucceeded;
+ }
+
+static
+int
+test_append_string()
+ {
+ nsCString s1("This is a reasonable length string with some text in it and it is good.");
+ nsCString s2("This is another string that I will use in the concatenation test.");
+
+ PRUint32 len = 0;
+
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ {
+ nsCString s3;
+ s3.Append(s1);
+ s3.Append(s2);
+ len += TotalLength(s3);
+ }
+ }
+ cout << "s3.Append(s1); s3.Append(s2)" << endl;
+
+ return kTestSucceeded;
+ }
+
+static
+int
+test_repeated_append_string()
+ {
+ nsCString s1("This is a reasonable length string with some text in it and it is good.");
+ nsCString s2("This is another string that I will use in the concatenation test.");
+
+ PRUint32 len = 0;
+
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ {
+ nsCString s3;
+ for ( int j=0; j<100; ++j )
+ {
+ s3.Append(s1);
+ s3.Append(s2);
+ len += TotalLength(s3);
+ }
+ }
+ }
+ cout << "repeated s3.Append(s1); s3.Append(s2)" << endl;
+
+ return kTestSucceeded;
+ }
+
+static
+int
+test_append_char()
+ {
+ cout << endl;
+
+ PRUint32 len = 0;
+
+ nsCString s1("hello");
+ PRUint32 oldLength = s1.Length();
+
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ {
+ s1.SetLength(oldLength);
+ }
+ }
+ cout << "null loop time for append char" << endl;
+
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ {
+ s1.Append('e');
+ s1.SetLength(oldLength);
+ }
+ }
+ cout << "s1.Append('e')" << endl;
+
+ return kTestSucceeded;
+ }
+
+static
+int
+test_repeated_append_char()
+ {
+ PRUint32 len = 0;
+
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ {
+ nsCString s1;
+ for ( int j=0; j<1000; ++j )
+ {
+ s1.Append('e');
+ len += TotalLength(s1);
+ }
+ }
+ }
+ cout << "repeated s1.Append('e')" << endl;
+
+ return kTestSucceeded;
+ }
+
+static
+int
+test_insert_string()
+ {
+ nsCString s1("This is a reasonable length string with some text in it and it is good.");
+
+ PRUint32 len = 0;
+
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ {
+ nsCString s2("This is another string that I will use in the concatenation test.");
+ s2.Insert(s1, 3);
+ len += TotalLength(s2);
+ }
+ }
+ cout << "s2.Insert(s1, 3)" << endl;
+
+ return kTestSucceeded;
+ }
+
+#ifndef TEST_STD_STRING
+static
+int
+test_find_string()
+ {
+ nsCString text("aaaaaaaaaab");
+ nsCString pattern("aab");
+
+ PRUint32 position = 0;
+ {
+ TestTimer timer;
+ for ( int i=0; i<N; ++i )
+ position = Find(text, pattern);
+ }
+ cout << "text.Find(pattern)" << endl;
+
+ return kTestSucceeded;
+ }
+#endif
+
+class Profiler
+ {
+ public:
+ Profiler()
+ {
+#if 0
+ ProfilerInit(collectDetailed, bestTimeBase, 100, 32);
+#endif
+ }
+
+ void
+ Dump( const char* output_name )
+ {
+ }
+
+ void
+ Dump( const unsigned char* output_name )
+ {
+#if 0
+ ProfilerDump(output_name);
+#endif
+ }
+
+ ~Profiler()
+ {
+#if 0
+ ProfilerDump(mOutputName);
+ ProfilerTerm();
+#endif
+ }
+ };
+
+int
+main()
+ {
+
+ cout << "String performance profiling. Compiled " __DATE__ " " __TIME__ << endl;
+#ifdef TEST_STD_STRING
+ cout << "Testing std::string." << endl;
+#else
+ cout << "Testing factored nsString." << endl;
+#endif
+
+ int tests_failed = 0;
+
+ Profiler profiler;
+
+ tests_failed += test_construction();
+ tests_failed += test_concat();
+ tests_failed += test_concat_and_assign();
+ tests_failed += test_compare();
+ tests_failed += test_countchar();
+ tests_failed += test_append_string();
+ tests_failed += test_repeated_append_string();
+ tests_failed += test_append_char();
+ tests_failed += test_repeated_append_char();
+ tests_failed += test_insert_string();
+#ifndef TEST_STD_STRING
+ tests_failed += test_find_string();
+#endif
+
+#ifdef TEST_STD_STRING
+ profiler.Dump("\pStandard String.prof");
+#else
+ profiler.Dump("\pFactored String.prof");
+#endif
+
+ if ( tests_failed )
+ cout << "One or more tests FAILED. Measurements may be invalid." << endl;
+
+ cout << "End of string performance profiling." << endl;
+ return 0;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/test_main.cpp b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/test_main.cpp
new file mode 100644
index 00000000..b8365dac
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/StringFactoringTests/test_main.cpp
@@ -0,0 +1,651 @@
+#include <iostream.h>
+#include "nsStringIO.h"
+
+//#define TEST_STD_STRING
+
+
+#include "nsString.h"
+#include "nsFragmentedString.h"
+#include "nsReadableUtils.h"
+#include "nsSlidingString.h"
+
+#ifdef TEST_STD_STRING
+#include "nsStdStringWrapper.h"
+#else
+ typedef nsString nsStdString;
+ typedef nsCString nsStdCString;
+#endif
+
+template <class CharT>
+basic_nsLiteralString<CharT>
+literal_hello( CharT* )
+ {
+ }
+
+NS_SPECIALIZE_TEMPLATE
+basic_nsLiteralString<char>
+literal_hello( char* )
+ {
+ return basic_nsLiteralString<char>("Hello");
+ }
+
+NS_SPECIALIZE_TEMPLATE
+basic_nsLiteralString<PRUnichar>
+literal_hello( PRUnichar* )
+ {
+#ifdef HAVE_CPP_2BYTE_WCHAR_T
+ return basic_nsLiteralString<PRUnichar>(L"Hello");
+#else
+ static PRUnichar constant_unicode[] = { 'H', 'e', 'l', 'l', 'o', PRUnichar() };
+ return basic_nsLiteralString<PRUnichar>(constant_unicode);
+#endif
+ }
+
+template <class T>
+struct string_class_traits
+ {
+ };
+
+NS_SPECIALIZE_TEMPLATE
+struct string_class_traits<PRUnichar>
+ {
+ typedef PRUnichar* pointer;
+ typedef nsString implementation_t;
+
+ static basic_nsLiteralString<PRUnichar> literal_hello() { return ::literal_hello(pointer()); }
+ };
+
+NS_SPECIALIZE_TEMPLATE
+struct string_class_traits<char>
+ {
+ typedef char* pointer;
+ typedef nsCString implementation_t;
+
+ static basic_nsLiteralString<char> literal_hello() { return ::literal_hello(pointer()); }
+ };
+
+
+static
+void
+CallCMid( nsACString& aResult, const nsACString& aSource, PRUint32 aStartPos, PRUint32 aLengthToCopy )
+ {
+ aSource.Mid(aResult, aStartPos, aLengthToCopy);
+ }
+
+
+
+template <class CharT>
+int
+test_multifragment_iterators( const basic_nsAString<CharT>& aString )
+ /*
+ ...this tests a problem that was present in |nsPromiseConcatenation| where,
+ because it originally stored some iteration state in the object itself, rather than
+ in the fragment, the iterators could get confused if used out of sequence.
+
+ This test should be run on any multi-fragment implementation to verify that it
+ does not have the same bug. Make sure the first fragment is only one character long.
+ */
+ {
+ typedef typename basic_nsAString<CharT>::const_iterator ConstIterator;
+
+ int tests_failed = 0;
+
+ ConstIterator iter1 = aString.BeginReading();
+ ConstIterator iter2 = aString.BeginReading();
+ ++iter2; ++iter2;
+
+ ConstIterator iter3 = aString.EndReading();
+ --iter3;
+ ++iter1; ++iter1;
+ if ( iter1 != iter2 )
+ {
+ cout << "FAILED in |test_multifragment_iterators|" << endl;
+ ++tests_failed;
+ }
+
+ return tests_failed;
+ }
+
+template <class CharT>
+int
+test_Vidur_functions( const basic_nsAString<CharT>& aString )
+ {
+ char* char_copy = ToNewCString(aString);
+ PRUnichar* PRUnichar_copy = ToNewUnicode(aString);
+
+ nsMemory::Free(PRUnichar_copy);
+ nsMemory::Free(char_copy);
+
+ return 0;
+ }
+
+template <class CharT>
+int
+test_readable_hello( const basic_nsAString<CharT>& aReadable )
+ {
+ int tests_failed = 0;
+
+ if ( aReadable.Length() != 5 )
+ {
+ cout << "FAILED |test_readable_hello|: |Length()| --> " << aReadable.Length() << endl;
+ ++tests_failed;
+ }
+
+ if ( aReadable.First() != CharT('H') )
+ {
+ cout << "FAILED |test_readable_hello|: |First()| --> '" << aReadable.First() << "'" << endl;
+ ++tests_failed;
+ }
+
+ if ( aReadable.Last() != CharT('o') )
+ {
+ cout << "FAILED |test_readable_hello|: |Last()| --> '" << aReadable.Last() << "'" << endl;
+ ++tests_failed;
+ }
+
+ if ( aReadable[3] != CharT('l') )
+ {
+ cout << "FAILED |test_readable_hello|: |operator[]| --> '" << aReadable[3] << "'" << endl;
+ ++tests_failed;
+ }
+
+ if ( aReadable.CountChar( CharT('l') ) != 2 )
+ {
+ cout << "FAILED |test_readable_hello|: |CountChar('l')| --> " << aReadable.CountChar(CharT('l')) << endl;
+ ++tests_failed;
+ }
+
+ basic_nsAString<CharT>::const_iterator iter = aReadable.BeginReading();
+ if ( *iter != CharT('H') )
+ {
+ cout << "FAILED |test_readable_hello|: didn't start out pointing to the right thing, or else couldn't be dereferenced. --> '" << *iter << "'" << endl;
+ ++tests_failed;
+ }
+
+ ++iter;
+
+ if ( *iter != CharT('e') )
+ {
+ cout << "FAILED |test_readable_hello|: iterator couldn't be incremented, or else couldn't be dereferenced. --> '" << *iter << "'" << endl;
+ ++tests_failed;
+ }
+
+ iter = aReadable.EndReading();
+ --iter;
+ if ( *iter != CharT('o') )
+ {
+ cout << "FAILED |test_readable_hello|: iterator couldn't be set to |EndReading()|, or else couldn't be decremented, or else couldn't be dereferenced. --> '" << *iter << "'" << endl;
+ ++tests_failed;
+ }
+
+ basic_nsAString<CharT>::const_iterator iter1 = aReadable.BeginReading().advance(3);
+ if ( *iter1 != CharT('l') )
+ {
+ cout << "FAILED |test_readable_hello|: iterator couldn't be set to |BeginReading()+=n|, or else couldn't be dereferenced. --> '" << *iter1 << "'" << endl;
+ ++tests_failed;
+ }
+
+ basic_nsAString<CharT>::const_iterator iter2 = aReadable.EndReading().advance(-2);
+ if ( *iter2 != CharT('l') )
+ {
+ cout << "FAILED |test_readable_hello|: iterator couldn't be set to |EndReading()-=n|, or else couldn't be dereferenced. --> '" << *iter2 << "'" << endl;
+ ++tests_failed;
+ }
+
+ if ( iter1 != iter2 )
+ {
+ cout << "FAILED |test_readable_hello|: iterator comparison with !=." << endl;
+ ++tests_failed;
+ }
+
+ if ( !(iter1 == iter2) )
+ {
+ cout << "FAILED |test_readable_hello|: iterator comparison with ==." << endl;
+ ++tests_failed;
+ }
+
+ typedef CharT* CharT_ptr;
+ if ( aReadable != literal_hello(CharT_ptr()) )
+ {
+ cout << "FAILED |test_readable_hello|: comparison with \"Hello\"" << endl;
+ ++tests_failed;
+ }
+
+ tests_failed += test_multifragment_iterators(aReadable);
+ // tests_failed += test_deprecated_GetBufferGetUnicode(aReadable);
+
+ test_Vidur_functions(aReadable);
+
+ return tests_failed;
+ }
+
+
+template <class CharT>
+int
+test_SetLength( basic_nsAString<CharT>& aWritable )
+ {
+ int tests_failed = 0;
+
+ string_class_traits<CharT>::implementation_t oldValue(aWritable);
+
+
+ size_t oldLength = aWritable.Length();
+
+ if ( oldValue != Substring(aWritable, 0, oldLength) )
+ {
+ cout << "FAILED growing a string in |test_SetLength|, saving the value didn't work." << endl;
+ ++tests_failed;
+ }
+
+ size_t newLength = 2*(oldLength+1);
+
+ aWritable.SetLength(newLength);
+ if ( aWritable.Length() != newLength )
+ {
+ cout << "FAILED growing a string in |test_SetLength|, length is wrong." << endl;
+ ++tests_failed;
+ }
+
+ if ( oldValue != Substring(aWritable, 0, oldLength) )
+ {
+ cout << "FAILED growing a string in |test_SetLength|, contents damaged after growing." << endl;
+ ++tests_failed;
+ }
+
+ aWritable.SetLength(oldLength);
+ if ( aWritable.Length() != oldLength )
+ {
+ cout << "FAILED shrinking a string in |test_SetLength|." << endl;
+ ++tests_failed;
+ }
+
+ if ( oldValue != Substring(aWritable, 0, oldLength) )
+ {
+ cout << "FAILED growing a string in |test_SetLength|, contents damaged after shrinking." << endl;
+ ++tests_failed;
+ }
+
+ return tests_failed;
+ }
+
+
+template <class CharT>
+int
+test_insert( basic_nsAString<CharT>& aWritable )
+ {
+ int tests_failed = 0;
+
+ string_class_traits<CharT>::implementation_t oldValue(aWritable);
+
+ if ( oldValue != aWritable )
+ {
+ cout << "FAILED saving the old string value in |test_insert|." << endl;
+ ++tests_failed;
+ }
+
+ string_class_traits<CharT>::implementation_t insertable( string_class_traits<CharT>::literal_hello() );
+
+ insertable.SetLength(1);
+ aWritable.Insert(insertable, 0);
+
+ if ( aWritable != (insertable + oldValue) )
+ {
+ cout << "FAILED in |test_insert|." << endl;
+ ++tests_failed;
+ }
+
+ aWritable = oldValue;
+
+ return tests_failed;
+ }
+
+
+template <class CharT>
+int
+test_cut( basic_nsAString<CharT>& aWritable )
+ {
+ int tests_failed = 0;
+
+ aWritable.Cut(0, aWritable.Length()+5);
+
+ return tests_failed;
+ }
+
+template <class CharT>
+int
+test_self_assign( basic_nsAString<CharT>& aWritable )
+ {
+ int tests_failed = 0;
+ string_class_traits<CharT>::implementation_t oldValue(aWritable);
+
+ aWritable = aWritable;
+ if ( aWritable != oldValue )
+ {
+ cout << "FAILED self assignment." << endl;
+ ++tests_failed;
+ }
+
+ aWritable = oldValue;
+ return tests_failed;
+ }
+
+template <class CharT>
+int
+test_self_append( basic_nsAString<CharT>& aWritable )
+ {
+ int tests_failed = 0;
+ string_class_traits<CharT>::implementation_t oldValue(aWritable);
+
+ aWritable += aWritable;
+ if ( aWritable != oldValue + oldValue )
+ {
+ cout << "FAILED self append." << endl;
+ ++tests_failed;
+ }
+
+ aWritable = oldValue;
+ return tests_failed;
+ }
+
+template <class CharT>
+int
+test_self_insert( basic_nsAString<CharT>& aWritable )
+ {
+ int tests_failed = 0;
+ string_class_traits<CharT>::implementation_t oldValue(aWritable);
+
+ aWritable.Insert(aWritable, 0);
+ if ( aWritable != oldValue + oldValue )
+ {
+ cout << "FAILED self insert." << endl;
+ ++tests_failed;
+ }
+
+ aWritable = oldValue;
+ return tests_failed;
+ }
+
+template <class CharT>
+int
+test_self_replace( basic_nsAString<CharT>& aWritable )
+ {
+ int tests_failed = 0;
+ string_class_traits<CharT>::implementation_t oldValue(aWritable);
+
+ aWritable.Replace(0, 0, aWritable);
+ if ( aWritable != oldValue + oldValue )
+ {
+ cout << "FAILED self insert." << endl;
+ ++tests_failed;
+ }
+
+ aWritable = oldValue;
+ return tests_failed;
+ }
+
+
+
+template <class CharT>
+int
+test_writable( basic_nsAString<CharT>& aWritable )
+ {
+ int tests_failed = 0;
+ // ...
+
+
+ {
+ typedef CharT* CharT_ptr;
+ aWritable = literal_hello(CharT_ptr());
+
+ if ( aWritable != literal_hello(CharT_ptr()) )
+ {
+ cout << "FAILED assignment and/or comparison in |test_writable|." << endl;
+ ++tests_failed;
+ }
+
+ tests_failed += test_readable_hello(aWritable);
+ }
+
+ tests_failed += test_SetLength(aWritable);
+ tests_failed += test_insert(aWritable);
+ tests_failed += test_cut(aWritable);
+ tests_failed += test_self_assign(aWritable);
+ tests_failed += test_self_append(aWritable);
+ tests_failed += test_self_insert(aWritable);
+ tests_failed += test_self_replace(aWritable);
+
+ return tests_failed;
+ }
+
+
+
+typedef void* void_ptr;
+
+int
+main()
+ {
+ int tests_failed = 0;
+ cout << "String unit tests. Compiled " __DATE__ " " __TIME__ << endl;
+
+#if 0
+ {
+ nsFragmentedCString fs0;
+ fs0.Append("Hello");
+ tests_failed += test_readable_hello(fs0);
+ tests_failed += test_writable(fs0);
+ }
+#endif
+
+ {
+ NS_NAMED_LITERAL_STRING(literal, "Hello");
+ PRUnichar* buffer = ToNewUnicode(literal);
+
+ nsSlidingString ss0(buffer, buffer+5, buffer+6);
+// ss0.AppendBuffer(buffer, buffer+5, buffer+6);
+ nsReadingIterator<PRUnichar> ri0;
+ ss0.BeginReading(ri0);
+
+ tests_failed += test_readable_hello(ss0);
+
+ nsSlidingSubstring ss1(ss0);
+ tests_failed += test_readable_hello(ss1);
+
+ buffer = ToNewUnicode(literal);
+ ss0.AppendBuffer(buffer, buffer+5, buffer+6);
+
+ ri0.advance(5);
+ ss0.DiscardPrefix(ri0);
+
+ tests_failed += test_readable_hello(ss0);
+ tests_failed += test_readable_hello(ss1);
+
+ nsReadingIterator<PRUnichar> ri1;
+ ss0.EndReading(ri1);
+
+ nsSlidingSubstring ss2(ss0, ri0, ri1);
+ tests_failed += test_readable_hello(ss2);
+ }
+
+
+ {
+ nsLiteralCString s0("Patrick Beard made me write this: \"This is just a test\"\n");
+ print_string(s0);
+
+ const char* raw_string = "He also made me write this.\n";
+ nsFileCharSink<char> output(stdout);
+ copy_string(raw_string, raw_string+nsCharTraits<char>::length(raw_string), output);
+
+ nsLiteralCString s1("This ", 5), s2("is ", 3), s3("a ", 2), s4("test\n", 5);
+ print_string(s1+s2+s3+s4);
+
+ nsLiteralCString s5( "This is " "a " "test" );
+ print_string(s5+NS_LITERAL_CSTRING("\n"));
+
+ print_string(nsLiteralCString("The value of the string |x| is \"") + Substring(s0, 0, s0.Length()-1) + NS_LITERAL_CSTRING("\". Hope you liked it."));
+ }
+
+
+ {
+ tests_failed += test_readable_hello(NS_LITERAL_STRING("Hello"));
+
+ nsLiteralCString s1("Hello");
+ tests_failed += test_readable_hello(s1);
+ }
+
+ {
+
+ nsString s3( NS_LITERAL_STRING("Hello") );
+
+ tests_failed += test_readable_hello(s3);
+ tests_failed += test_writable(s3);
+
+ nsCString s4("Hello");
+ tests_failed += test_readable_hello(s4);
+ tests_failed += test_writable(s4);
+ }
+
+ {
+ nsStdString s5( NS_LITERAL_STRING("Hello") );
+
+ tests_failed += test_readable_hello(s5);
+ tests_failed += test_writable(s5);
+
+ nsStdCString s6("Hello");
+ tests_failed += test_readable_hello(s6);
+ tests_failed += test_writable(s6);
+ }
+
+ {
+ nsLiteralString s7(NS_LITERAL_STRING("He"));
+ nsString s8(NS_LITERAL_STRING("l"));
+ nsStdString s9(NS_LITERAL_STRING("lo"));
+
+ tests_failed += test_readable_hello(s7+s8+s9);
+
+ nsString s13( s7 + s8 + s9 );
+ tests_failed += test_readable_hello(s13);
+
+ nsStdString s14( s7 + s8 + s9 );
+ tests_failed += test_readable_hello(s14);
+
+ nsCString s10("He");
+ nsLiteralCString s11("l");
+ nsStdCString s12("lo");
+
+ tests_failed += test_readable_hello(s10+s11+s12);
+
+
+ }
+
+ {
+ const char *foo = "this is a really long string";
+ nsCString origString;
+ nsCString string2;
+ nsCString string3;
+
+ origString = foo;
+
+ string2 = Substring(origString, 0, 5);
+ string3 = Substring(origString, 6, origString.Length() - 6);
+ }
+
+ {
+ nsLiteralCString s13("He");
+ nsCAutoString s14("l");
+ nsLiteralCString s15("lo");
+
+ s14.Assign(s13 + s14 + s15);
+
+ if ( int failures = test_readable_hello(s14) )
+ {
+ tests_failed += failures;
+ cout << "FAILED to keep a promise." << endl;
+ }
+ }
+
+
+ {
+ nsLiteralCString str1("Hello");
+ nsStdCString str2("Hello");
+
+ nsLiteralCString str3("Hello there");
+
+ if ( str1 != str2 )
+ {
+ cout << "string comparison using != failed" << endl;
+ ++tests_failed;
+ }
+
+ if ( !(str3 > str2) )
+ {
+ cout << "string comparison using > failed" << endl;
+ ++tests_failed;
+ }
+
+ if ( !(str2 < str3) )
+ {
+ cout << "string comparison using < failed" << endl;
+ ++tests_failed;
+ }
+
+ if ( str1 != "Hello" )
+ {
+ cout << "string comparison using == failed" << endl;
+ ++tests_failed;
+ }
+ }
+
+#if 0
+ nsStdCString extracted_middle("XXXXXXXXXX");
+ CallCMid(extracted_middle, part1+part2a+part2b, 1, 3);
+
+ cout << "The result of mid was \"" << extracted_middle << "\"" << endl;
+
+ nsLiteralCString middle_answer("ell");
+ if ( middle_answer != extracted_middle )
+ {
+ cout << "mid FAILED on nsConcatString" << endl;
+ ++tests_failed;
+ }
+
+
+
+ //
+ // |nsStdStringWrapper|, i.e., |nsStdCString|
+ //
+
+ {
+ nsStdCString extracted_middle;
+ CallCMid(extracted_middle, part1+part2a+part2b, 1, 3);
+
+ cout << "The result of mid was \"" << extracted_middle << "\"" << endl;
+
+ nsLiteralCString middle_answer("ell");
+ if ( middle_answer != extracted_middle )
+ {
+ cout << "mid FAILED on nsStdCString" << endl;
+ ++tests_failed;
+ }
+ }
+
+
+
+ nsStdCString leftString;
+ source.Left(leftString, 9);
+ // cout << static_cast<const nsACString>(leftString) << endl;
+
+
+
+ tests_failed += test_multifragment_iterators(part1+part2a+part2b);
+#endif
+
+
+
+ cout << "End of string unit tests." << endl;
+ if ( !tests_failed )
+ cout << "OK, all tests passed." << endl;
+ else
+ cout << "FAILED one or more tests." << endl;
+
+ return tests_failed;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestArray.cpp b/src/libs/xpcom18a4/xpcom/tests/TestArray.cpp
new file mode 100644
index 00000000..852938fe
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestArray.cpp
@@ -0,0 +1,230 @@
+/* -*- 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):
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include "nsISupportsArray.h"
+
+// {9e70a320-be02-11d1-8031-006008159b5a}
+#define NS_IFOO_IID \
+ {0x9e70a320, 0xbe02, 0x11d1, \
+ {0x80, 0x31, 0x00, 0x60, 0x08, 0x15, 0x9b, 0x5a}}
+
+static const PRBool kExitOnError = PR_TRUE;
+
+class IFoo : public nsISupports {
+public:
+
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IFOO_IID)
+
+ NS_IMETHOD_(nsrefcnt) RefCnt() = 0;
+ NS_IMETHOD_(PRInt32) ID() = 0;
+};
+
+class Foo : public IFoo {
+public:
+
+ Foo(PRInt32 aID);
+
+ // nsISupports implementation
+ NS_DECL_ISUPPORTS
+
+ // IFoo implementation
+ NS_IMETHOD_(nsrefcnt) RefCnt() { return mRefCnt; }
+ NS_IMETHOD_(PRInt32) ID() { return mID; }
+
+ static PRInt32 gCount;
+
+ PRInt32 mID;
+
+private:
+ ~Foo();
+};
+
+PRInt32 Foo::gCount;
+
+Foo::Foo(PRInt32 aID)
+{
+ mID = aID;
+ ++gCount;
+ fprintf(stdout, "init: %d (%p), %d total)\n", mID, this, gCount);
+}
+
+Foo::~Foo()
+{
+ --gCount;
+ fprintf(stdout, "destruct: %d (%p), %d remain)\n", mID, this, gCount);
+}
+
+NS_IMPL_ISUPPORTS1(Foo, IFoo)
+
+const char* AssertEqual(PRInt32 aValue1, PRInt32 aValue2)
+{
+ if (aValue1 == aValue2) {
+ return "OK";
+ }
+ if (kExitOnError) {
+ exit(1);
+ }
+ return "ERROR";
+}
+
+void DumpArray(nsISupportsArray* aArray, PRInt32 aExpectedCount, PRInt32 aElementIDs[], PRInt32 aExpectedTotal)
+{
+ PRUint32 cnt = 0;
+ nsresult rv = aArray->Count(&cnt);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "Count failed");
+ PRInt32 count = cnt;
+ PRInt32 index;
+
+ fprintf(stdout, "object count %d = %d %s\n", Foo::gCount, aExpectedTotal,
+ AssertEqual(Foo::gCount, aExpectedTotal));
+ fprintf(stdout, "array count %d = %d %s\n", count, aExpectedCount,
+ AssertEqual(count, aExpectedCount));
+
+ for (index = 0; (index < count) && (index < aExpectedCount); index++) {
+ IFoo* foo = (IFoo*)(aArray->ElementAt(index));
+ fprintf(stdout, "%2d: %d=%d (%p) c: %d %s\n",
+ index, aElementIDs[index], foo->ID(), foo, foo->RefCnt() - 1,
+ AssertEqual(foo->ID(), aElementIDs[index]));
+ foo->Release();
+ }
+}
+
+void FillArray(nsISupportsArray* aArray, PRInt32 aCount)
+{
+ PRInt32 index;
+ for (index = 0; index < aCount; index++) {
+ nsCOMPtr<IFoo> foo = new Foo(index);
+ aArray->AppendElement(foo);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ nsISupportsArray* array;
+ nsresult rv;
+
+ if (NS_OK == (rv = NS_NewISupportsArray(&array))) {
+ FillArray(array, 10);
+ fprintf(stdout, "Array created:\n");
+ PRInt32 fillResult[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ DumpArray(array, 10, fillResult, 10);
+
+ // test insert
+ IFoo* foo = (IFoo*)array->ElementAt(3);
+ foo->Release(); // pre-release to fix ref count for dumps
+ array->InsertElementAt(foo, 5);
+ fprintf(stdout, "insert 3 at 5:\n");
+ PRInt32 insertResult[11] = {0, 1, 2, 3, 4, 3, 5, 6, 7, 8, 9};
+ DumpArray(array, 11, insertResult, 10);
+ fprintf(stdout, "insert 3 at 0:\n");
+ array->InsertElementAt(foo, 0);
+ PRInt32 insertResult2[12] = {3, 0, 1, 2, 3, 4, 3, 5, 6, 7, 8, 9};
+ DumpArray(array, 12, insertResult2, 10);
+ fprintf(stdout, "append 3:\n");
+ array->AppendElement(foo);
+ PRInt32 appendResult[13] = {3, 0, 1, 2, 3, 4, 3, 5, 6, 7, 8, 9, 3};
+ DumpArray(array, 13, appendResult, 10);
+
+
+ // test IndexOf && LastIndexOf
+ PRInt32 expectedIndex[5] = {0, 4, 6, 12, -1};
+ PRInt32 count = 0;
+ PRInt32 index = array->IndexOf(foo);
+ fprintf(stdout, "IndexOf(foo): %d=%d %s\n", index, expectedIndex[count],
+ AssertEqual(index, expectedIndex[count]));
+ while (-1 != index) {
+ count++;
+ index = array->IndexOfStartingAt(foo, index + 1);
+ if (-1 != index)
+ fprintf(stdout, "IndexOf(foo): %d=%d %s\n", index, expectedIndex[count],
+ AssertEqual(index, expectedIndex[count]));
+ }
+ index = array->LastIndexOf(foo);
+ count--;
+ fprintf(stdout, "LastIndexOf(foo): %d=%d %s\n", index, expectedIndex[count],
+ AssertEqual(index, expectedIndex[count]));
+
+ // test ReplaceElementAt
+ fprintf(stdout, "ReplaceElementAt(8):\n");
+ array->ReplaceElementAt(foo, 8);
+ PRInt32 replaceResult[13] = {3, 0, 1, 2, 3, 4, 3, 5, 3, 7, 8, 9, 3};
+ DumpArray(array, 13, replaceResult, 9);
+
+ // test RemoveElementAt, RemoveElement RemoveLastElement
+ fprintf(stdout, "RemoveElementAt(0):\n");
+ array->RemoveElementAt(0);
+ PRInt32 removeResult[12] = {0, 1, 2, 3, 4, 3, 5, 3, 7, 8, 9, 3};
+ DumpArray(array, 12, removeResult, 9);
+ fprintf(stdout, "RemoveElementAt(7):\n");
+ array->RemoveElementAt(7);
+ PRInt32 removeResult2[11] = {0, 1, 2, 3, 4, 3, 5, 7, 8, 9, 3};
+ DumpArray(array, 11, removeResult2, 9);
+ fprintf(stdout, "RemoveElement(foo):\n");
+ array->RemoveElement(foo);
+ PRInt32 removeResult3[10] = {0, 1, 2, 4, 3, 5, 7, 8, 9, 3};
+ DumpArray(array, 10, removeResult3, 9);
+ fprintf(stdout, "RemoveLastElement(foo):\n");
+ array->RemoveLastElement(foo);
+ PRInt32 removeResult4[9] = {0, 1, 2, 4, 3, 5, 7, 8, 9};
+ DumpArray(array, 9, removeResult4, 9);
+
+ // test clear
+ fprintf(stdout, "clear array:\n");
+ array->Clear();
+ DumpArray(array, 0, 0, 0);
+ fprintf(stdout, "add 4 new:\n");
+ FillArray(array, 4);
+ DumpArray(array, 4, fillResult, 4);
+
+ // test compact
+ fprintf(stdout, "compact array:\n");
+ array->Compact();
+ DumpArray(array, 4, fillResult, 4);
+
+ // test delete
+ fprintf(stdout, "release array:\n");
+ NS_RELEASE(array);
+ }
+ else {
+ fprintf(stdout, "error can't create array: %x\n", rv);
+ }
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestAtoms.cpp b/src/libs/xpcom18a4/xpcom/tests/TestAtoms.cpp
new file mode 100644
index 00000000..48b2f603
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestAtoms.cpp
@@ -0,0 +1,132 @@
+/* -*- 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 "nsIAtom.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+#include "prprf.h"
+#include "prtime.h"
+#include <stdio.h>
+
+extern "C" int _CrtSetDbgFlag(int);
+
+int main(int argc, char** argv)
+{
+ FILE* fp = fopen("words.txt", "r");
+ if (nsnull == fp) {
+ printf("can't open words.txt\n");
+ return -1;
+ }
+
+ PRInt32 count = 0;
+ PRUnichar** strings = new PRUnichar*[60000];
+ nsIAtom** ids = new nsIAtom*[60000];
+ nsAutoString s1, s2;
+ PRTime start = PR_Now();
+ PRInt32 i;
+ for (i = 0; i < 30000; i++) {
+ char buf[1000];
+ char* s = fgets(buf, sizeof(buf), fp);
+ if (nsnull == s) {
+ break;
+ }
+ nsCAutoString sb;
+ sb.Assign(buf);
+ strings[count++] = ToNewUnicode(sb);
+ ToUpperCase(sb);
+ strings[count++] = ToNewUnicode(sb);
+ }
+ PRTime end0 = PR_Now();
+
+ // Find and create idents
+ for (i = 0; i < count; i++) {
+ ids[i] = NS_NewAtom(strings[i]);
+ }
+ PRUnichar qqs[1]; qqs[0] = 0;
+ nsIAtom* qq = NS_NewAtom(qqs);
+ PRTime end1 = PR_Now();
+
+ // Now make sure we can find all the idents we just made
+ for (i = 0; i < count; i++) {
+ const char *utf8String;
+ ids[i]->GetUTF8String(&utf8String);
+ nsIAtom* id = NS_NewAtom(utf8String);
+ if (id != ids[i]) {
+ id->ToString(s1);
+ ids[i]->ToString(s2);
+ printf("find failed: id='%s' ids[%d]='%s'\n",
+ NS_LossyConvertUCS2toASCII(s1).get(), i, NS_LossyConvertUCS2toASCII(s2).get());
+ return -1;
+ }
+ NS_RELEASE(id);
+ }
+ PRTime end2 = PR_Now();
+
+ // Destroy all the atoms we just made
+ NS_RELEASE(qq);
+ for (i = 0; i < count; i++) {
+ NS_RELEASE(ids[i]);
+ }
+
+ // Print out timings
+ PRTime end3 = PR_Now();
+ PRTime creates, finds, lookups, dtor, ustoms;
+ LL_I2L(ustoms, 1000);
+ LL_SUB(creates, end0, start);
+ LL_DIV(creates, creates, ustoms);
+ LL_SUB(finds, end1, end0);
+ LL_DIV(finds, finds, ustoms);
+ LL_SUB(lookups, end2, end1);
+ LL_DIV(lookups, lookups, ustoms);
+ LL_SUB(dtor, end3, end2);
+ char buf[500];
+ PR_snprintf(buf, sizeof(buf), "making %d ident strings took %lldms",
+ count, creates);
+ puts(buf);
+ PR_snprintf(buf, sizeof(buf), "%d new idents took %lldms",
+ count, finds);
+ puts(buf);
+ PR_snprintf(buf, sizeof(buf), "%d ident lookups took %lldms",
+ count, lookups);
+ puts(buf);
+ PR_snprintf(buf, sizeof(buf), "dtor took %lldusec", dtor);
+ puts(buf);
+
+ printf("%d live atoms\n", NS_GetNumberOfAtoms());
+ NS_POSTCONDITION(0 == NS_GetNumberOfAtoms(), "dangling atoms");
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestAutoLock.cpp b/src/libs/xpcom18a4/xpcom/tests/TestAutoLock.cpp
new file mode 100644
index 00000000..4537044f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestAutoLock.cpp
@@ -0,0 +1,91 @@
+/* -*- 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 ***** */
+
+/*
+
+ Some tests for nsAutoLock.
+
+ */
+
+#include "nsAutoLock.h"
+#include "prthread.h"
+
+PRLock* gLock;
+int gCount;
+
+static void PR_CALLBACK run(void* arg)
+{
+ for (int i = 0; i < 1000000; ++i) {
+ nsAutoLock guard(gLock);
+ ++gCount;
+ PR_ASSERT(gCount == 1);
+ --gCount;
+ }
+}
+
+
+int main(int argc, char** argv)
+{
+ gLock = PR_NewLock();
+ gCount = 0;
+
+ // This shouldn't compile
+ //nsAutoLock* l1 = new nsAutoLock(theLock);
+ //delete l1;
+
+ // Create a block-scoped lock. This should compile.
+ {
+ nsAutoLock l2(gLock);
+ }
+
+ // Fork a thread to access the shared variable in a tight loop
+ PRThread* t1 =
+ PR_CreateThread(PR_SYSTEM_THREAD,
+ run,
+ nsnull,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ // ...and now do the same thing ourselves
+ run(nsnull);
+
+ // Wait for the background thread to finish, if necessary.
+ PR_JoinThread(t1);
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestAutoPtr.cpp b/src/libs/xpcom18a4/xpcom/tests/TestAutoPtr.cpp
new file mode 100644
index 00000000..c48134a4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestAutoPtr.cpp
@@ -0,0 +1,566 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+// vim:cindent:ts=4:et:sw=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 TestCOMPtrEq.cpp.
+ *
+ * The Initial Developer of the Original Code is
+ * L. David Baron.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * L. David Baron <dbaron@dbaron.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 "nsAutoPtr.h"
+#include <stdio.h>
+#include "nscore.h"
+
+class TestObjectBaseA {
+ public:
+ // Virtual dtor for deleting through base class pointer
+ virtual ~TestObjectBaseA() { };
+ int fooA;
+};
+
+class TestObjectBaseB {
+ public:
+ // Virtual dtor for deleting through base class pointer
+ virtual ~TestObjectBaseB() { };
+ int fooB;
+};
+
+class TestObject : public TestObjectBaseA, public TestObjectBaseB {
+ public:
+ TestObject()
+ {
+ printf(" Creating TestObject %p.\n",
+ NS_STATIC_CAST(void*, this));
+ }
+
+ // Virtual dtor for deleting through base class pointer
+ virtual ~TestObject()
+ {
+ printf(" Destroying TestObject %p.\n",
+ NS_STATIC_CAST(void*, this));
+ }
+};
+
+class TestRefObjectBaseA {
+ public:
+ int fooA;
+ // Must return |nsrefcnt| to keep |nsDerivedSafe| happy.
+ virtual nsrefcnt AddRef() = 0;
+ virtual nsrefcnt Release() = 0;
+};
+
+class TestRefObjectBaseB {
+ public:
+ int fooB;
+ virtual nsrefcnt AddRef() = 0;
+ virtual nsrefcnt Release() = 0;
+};
+
+class TestRefObject : public TestRefObjectBaseA, public TestRefObjectBaseB {
+ public:
+ TestRefObject()
+ : mRefCount(0)
+ {
+ printf(" Creating TestRefObject %p.\n",
+ NS_STATIC_CAST(void*, this));
+ }
+
+ ~TestRefObject()
+ {
+ printf(" Destroying TestRefObject %p.\n",
+ NS_STATIC_CAST(void*, this));
+ }
+
+ nsrefcnt AddRef()
+ {
+ ++mRefCount;
+ printf(" AddRef to %d on TestRefObject %p.\n",
+ mRefCount, NS_STATIC_CAST(void*, this));
+ return mRefCount;
+ }
+
+ nsrefcnt Release()
+ {
+ --mRefCount;
+ printf(" Release to %d on TestRefObject %p.\n",
+ mRefCount, NS_STATIC_CAST(void*, this));
+ if (mRefCount == 0) {
+ delete NS_CONST_CAST(TestRefObject*, this);
+ return 0;
+ }
+ return mRefCount;
+ }
+
+ protected:
+ PRUint32 mRefCount;
+
+};
+
+static void CreateTestObject(TestObject **aResult)
+{
+ *aResult = new TestObject();
+}
+
+static void CreateTestRefObject(TestRefObject **aResult)
+{
+ (*aResult = new TestRefObject())->AddRef();
+}
+
+static void DoSomethingWithTestObject(TestObject *aIn)
+{
+ printf(" Doing something with |TestObject| %p.\n",
+ NS_STATIC_CAST(void*, aIn));
+}
+
+static void DoSomethingWithConstTestObject(const TestObject *aIn)
+{
+ printf(" Doing something with |const TestObject| %p.\n",
+ NS_STATIC_CAST(const void*, aIn));
+}
+
+static void DoSomethingWithTestRefObject(TestRefObject *aIn)
+{
+ printf(" Doing something with |TestRefObject| %p.\n",
+ NS_STATIC_CAST(void*, aIn));
+}
+
+static void DoSomethingWithConstTestRefObject(const TestRefObject *aIn)
+{
+ printf(" Doing something with |const TestRefObject| %p.\n",
+ NS_STATIC_CAST(const void*, aIn));
+}
+
+static void DoSomethingWithTestObjectBaseB(TestObjectBaseB *aIn)
+{
+ printf(" Doing something with |TestObjectBaseB| %p.\n",
+ NS_STATIC_CAST(void*, aIn));
+}
+
+static void DoSomethingWithConstTestObjectBaseB(const TestObjectBaseB *aIn)
+{
+ printf(" Doing something with |const TestObjectBaseB| %p.\n",
+ NS_STATIC_CAST(const void*, aIn));
+}
+
+static void DoSomethingWithTestRefObjectBaseB(TestRefObjectBaseB *aIn)
+{
+ printf(" Doing something with |TestRefObjectBaseB| %p.\n",
+ NS_STATIC_CAST(void*, aIn));
+}
+
+static void DoSomethingWithConstTestRefObjectBaseB(const TestRefObjectBaseB *aIn)
+{
+ printf(" Doing something with |const TestRefObjectBaseB| %p.\n",
+ NS_STATIC_CAST(const void*, aIn));
+}
+
+int main()
+{
+ {
+ printf("Should create one |TestObject|:\n");
+ nsAutoPtr<TestObject> pobj( new TestObject() );
+ printf("Should destroy one |TestObject|:\n");
+ }
+
+ {
+ printf("Should create one |TestObject|:\n");
+ nsAutoPtr<TestObject> pobj( new TestObject() );
+ printf("Should create one |TestObject| and then destroy one:\n");
+ pobj = new TestObject();
+ printf("Should destroy one |TestObject|:\n");
+ }
+
+ {
+ printf("Should create 3 |TestObject|s:\n");
+ nsAutoArrayPtr<TestObject> pobj( new TestObject[3] );
+ printf("Should create 5 |TestObject|s and then destroy 3:\n");
+ pobj = new TestObject[5];
+ printf("Should destroy 5 |TestObject|s:\n");
+ }
+
+ {
+ printf("Should create and AddRef one |TestRefObject|:\n");
+ nsRefPtr<TestRefObject> pobj( new TestRefObject() );
+ printf("Should Release and destroy one |TestRefObject|:\n");
+ }
+
+ {
+ printf("Should create and AddRef one |TestRefObject|:\n");
+ nsRefPtr<TestRefObject> pobj( new TestRefObject() );
+ printf("Should create and AddRef one |TestRefObject| and then Release and destroy one:\n");
+ pobj = new TestRefObject();
+ printf("Should Release and destroy one |TestRefObject|:\n");
+ }
+
+ {
+ printf("Should create and AddRef one |TestRefObject|:\n");
+ nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ printf("Should AddRef one |TestRefObject|:\n");
+ nsRefPtr<TestRefObject> p2( p1 );
+ printf("Should Release twice and destroy one |TestRefObject|:\n");
+ }
+
+ printf("\nTesting equality (with all const-ness combinations):\n");
+
+ {
+ nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ nsRefPtr<TestRefObject> p2( p1 );
+ printf("equality %s.\n",
+ ((p1 == p2) && !(p1 != p2)) ? "OK" : "broken");
+ }
+
+ {
+ const nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ nsRefPtr<TestRefObject> p2( p1 );
+ printf("equality %s.\n",
+ ((p1 == p2) && !(p1 != p2)) ? "OK" : "broken");
+ }
+
+ {
+ nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ const nsRefPtr<TestRefObject> p2( p1 );
+ printf("equality %s.\n",
+ ((p1 == p2) && !(p1 != p2)) ? "OK" : "broken");
+ }
+
+ {
+ const nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ const nsRefPtr<TestRefObject> p2( p1 );
+ printf("equality %s.\n",
+ ((p1 == p2) && !(p1 != p2)) ? "OK" : "broken");
+ }
+
+ {
+ nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ TestRefObject * p2 = p1;
+ printf("equality %s.\n",
+ ((p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) ? "OK" : "broken");
+ }
+
+ {
+ const nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ TestRefObject * p2 = p1;
+ printf("equality %s.\n",
+ ((p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) ? "OK" : "broken");
+ }
+
+#if 0 /* MSVC++ 6.0 can't be coaxed to accept this */
+ {
+ nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ TestRefObject * const p2 = p1;
+ printf("equality %s.\n",
+ ((p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) ? "OK" : "broken");
+ }
+
+ {
+ const nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ TestRefObject * const p2 = p1;
+ printf("equality %s.\n",
+ ((p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) ? "OK" : "broken");
+ }
+#endif /* Things that MSVC++ 6.0 can't be coaxed to accept */
+
+ {
+ nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ const TestRefObject * p2 = p1;
+ printf("equality %s.\n",
+ ((p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) ? "OK" : "broken");
+ }
+
+ {
+ const nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ const TestRefObject * p2 = p1;
+ printf("equality %s.\n",
+ ((p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) ? "OK" : "broken");
+ }
+
+ {
+ nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ const TestRefObject * const p2 = p1;
+ printf("equality %s.\n",
+ ((p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) ? "OK" : "broken");
+ }
+
+ {
+ const nsRefPtr<TestRefObject> p1( new TestRefObject() );
+ const TestRefObject * const p2 = p1;
+ printf("equality %s.\n",
+ ((p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) ? "OK" : "broken");
+ }
+
+ printf("\nTesting getter_Transfers and getter_AddRefs.\n");
+
+ {
+ nsAutoPtr<TestObject> ptr;
+ printf("Should create one |TestObject|:\n");
+ CreateTestObject(getter_Transfers(ptr));
+ printf("Should destroy one |TestObject|:\n");
+ }
+
+ {
+ nsRefPtr<TestRefObject> ptr;
+ printf("Should create and AddRef one |TestRefObject|:\n");
+ CreateTestRefObject(getter_AddRefs(ptr));
+ printf("Should Release and destroy one |TestRefObject|:\n");
+ }
+
+ printf("\nTesting casts and equality tests.\n");
+
+ if ((void*)(TestObject*)0x1000 ==
+ (void*)(TestObjectBaseB*)(TestObject*)0x1000)
+ printf("\n\nAll these tests are meaningless!\n\n\n");
+
+ {
+ nsAutoPtr<TestObject> p1(new TestObject());
+ TestObjectBaseB *p2 = p1;
+ printf("equality %s.\n",
+ ((NS_STATIC_CAST(void*, p1) != NS_STATIC_CAST(void*, p2)) &&
+ (p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1))
+ ? "OK" : "broken");
+ }
+
+ {
+ TestObject *p1 = new TestObject();
+ nsAutoPtr<TestObjectBaseB> p2(p1);
+ printf("equality %s.\n",
+ ((NS_STATIC_CAST(void*, p1) != NS_STATIC_CAST(void*, p2)) &&
+ (p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1))
+ ? "OK" : "broken");
+ }
+
+ {
+ nsRefPtr<TestRefObject> p1 = new TestRefObject();
+ // nsCOMPtr requires a |get| for something like this as well
+ nsRefPtr<TestRefObjectBaseB> p2 = p1.get();
+ printf("equality %s.\n",
+ ((NS_STATIC_CAST(void*, p1) != NS_STATIC_CAST(void*, p2)) &&
+ (p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1))
+ ? "OK" : "broken");
+ }
+
+ {
+ nsRefPtr<TestRefObject> p1 = new TestRefObject();
+ TestRefObjectBaseB *p2 = p1;
+ printf("equality %s.\n",
+ ((NS_STATIC_CAST(void*, p1) != NS_STATIC_CAST(void*, p2)) &&
+ (p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1))
+ ? "OK" : "broken");
+ }
+
+ {
+ TestRefObject *p1 = new TestRefObject();
+ nsRefPtr<TestRefObjectBaseB> p2 = p1;
+ printf("equality %s.\n",
+ ((NS_STATIC_CAST(void*, p1) != NS_STATIC_CAST(void*, p2)) &&
+ (p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1))
+ ? "OK" : "broken");
+ }
+
+ printf("\nTesting |forget()|.\n");
+
+ {
+ printf("Should create one |TestObject|:\n");
+ nsAutoPtr<TestObject> pobj( new TestObject() );
+ printf("Should do nothing:\n");
+ nsAutoPtr<TestObject> pobj2( pobj.forget() );
+ printf("Should destroy one |TestObject|:\n");
+ }
+
+ {
+ printf("Should create 3 |TestObject|s:\n");
+ nsAutoArrayPtr<TestObject> pobj( new TestObject[3] );
+ printf("Should do nothing:\n");
+ nsAutoArrayPtr<TestObject> pobj2( pobj.forget() );
+ printf("Should destroy 3 |TestObject|s:\n");
+ }
+
+ printf("\nTesting construction.\n");
+
+ {
+ printf("Should create one |TestObject|:\n");
+ nsAutoPtr<TestObject> pobj(new TestObject());
+ printf("Should destroy one |TestObject|:\n");
+ }
+
+ {
+ printf("Should create 3 |TestObject|s:\n");
+ nsAutoArrayPtr<TestObject> pobj(new TestObject[3]);
+ printf("Should destroy 3 |TestObject|s:\n");
+ }
+
+ {
+ printf("Should create and AddRef one |TestRefObject|:\n");
+ nsRefPtr<TestRefObject> pobj = new TestRefObject();
+ printf("Should Release and destroy one |TestRefObject|:\n");
+ }
+
+ printf("\nTesting calling of functions (including array access and casts).\n");
+
+ {
+ printf("Should create one |TestObject|:\n");
+ nsAutoPtr<TestObject> pobj(new TestObject());
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithTestObject(pobj);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithConstTestObject(pobj);
+ printf("Should destroy one |TestObject|:\n");
+ }
+
+ {
+ printf("Should create 3 |TestObject|s:\n");
+ nsAutoArrayPtr<TestObject> pobj(new TestObject[3]);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithTestObject(&pobj[2]);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithConstTestObject(&pobj[1]);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithTestObject(pobj + 2);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithConstTestObject(pobj + 1);
+ printf("Should destroy 3 |TestObject|s:\n");
+ }
+
+ {
+ printf("Should create and AddRef one |TestRefObject|:\n");
+ nsRefPtr<TestRefObject> pobj = new TestRefObject();
+ printf("Should do something with one |TestRefObject|:\n");
+ DoSomethingWithTestRefObject(pobj);
+ printf("Should do something with one |TestRefObject|:\n");
+ DoSomethingWithConstTestRefObject(pobj);
+ printf("Should Release and destroy one |TestRefObject|:\n");
+ }
+
+ {
+ printf("Should create one |TestObject|:\n");
+ nsAutoPtr<TestObject> pobj(new TestObject());
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithTestObjectBaseB(pobj);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithConstTestObjectBaseB(pobj);
+ printf("Should destroy one |TestObject|:\n");
+ }
+
+ {
+ printf("Should create 3 |TestObject|s:\n");
+ nsAutoArrayPtr<TestObject> pobj(new TestObject[3]);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithTestObjectBaseB(&pobj[2]);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithConstTestObjectBaseB(&pobj[1]);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithTestObjectBaseB(pobj + 2);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithConstTestObjectBaseB(pobj + 1);
+ printf("Should destroy 3 |TestObject|s:\n");
+ }
+
+ {
+ printf("Should create and AddRef one |TestRefObject|:\n");
+ nsRefPtr<TestRefObject> pobj = new TestRefObject();
+ printf("Should do something with one |TestRefObject|:\n");
+ DoSomethingWithTestRefObjectBaseB(pobj);
+ printf("Should do something with one |TestRefObject|:\n");
+ DoSomethingWithConstTestRefObjectBaseB(pobj);
+ printf("Should Release and destroy one |TestRefObject|:\n");
+ }
+
+ {
+ printf("Should create one |TestObject|:\n");
+ const nsAutoPtr<TestObject> pobj(new TestObject());
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithTestObject(pobj);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithConstTestObject(pobj);
+ printf("Should destroy one |TestObject|:\n");
+ }
+
+ {
+ printf("Should create 3 |TestObject|s:\n");
+ const nsAutoArrayPtr<TestObject> pobj(new TestObject[3]);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithTestObject(&pobj[2]);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithConstTestObject(&pobj[1]);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithTestObject(pobj + 2);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithConstTestObject(pobj + 1);
+ printf("Should destroy 3 |TestObject|s:\n");
+ }
+
+ {
+ printf("Should create and AddRef one |TestRefObject|:\n");
+ const nsRefPtr<TestRefObject> pobj = new TestRefObject();
+ printf("Should do something with one |TestRefObject|:\n");
+ DoSomethingWithTestRefObject(pobj);
+ printf("Should do something with one |TestRefObject|:\n");
+ DoSomethingWithConstTestRefObject(pobj);
+ printf("Should Release and destroy one |TestRefObject|:\n");
+ }
+
+ {
+ printf("Should create one |TestObject|:\n");
+ const nsAutoPtr<TestObject> pobj(new TestObject());
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithTestObjectBaseB(pobj);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithConstTestObjectBaseB(pobj);
+ printf("Should destroy one |TestObject|:\n");
+ }
+
+ {
+ printf("Should create 3 |TestObject|s:\n");
+ const nsAutoArrayPtr<TestObject> pobj(new TestObject[3]);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithTestObjectBaseB(&pobj[2]);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithConstTestObjectBaseB(&pobj[1]);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithTestObjectBaseB(pobj + 2);
+ printf("Should do something with one |TestObject|:\n");
+ DoSomethingWithConstTestObjectBaseB(pobj + 1);
+ printf("Should destroy 3 |TestObject|s:\n");
+ }
+
+ {
+ printf("Should create and AddRef one |TestRefObject|:\n");
+ const nsRefPtr<TestRefObject> pobj = new TestRefObject();
+ printf("Should do something with one |TestRefObject|:\n");
+ DoSomethingWithTestRefObjectBaseB(pobj);
+ printf("Should do something with one |TestRefObject|:\n");
+ DoSomethingWithConstTestRefObjectBaseB(pobj);
+ printf("Should Release and destroy one |TestRefObject|:\n");
+ }
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestCOMPtr.cpp b/src/libs/xpcom18a4/xpcom/tests/TestCOMPtr.cpp
new file mode 100644
index 00000000..c48219e2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestCOMPtr.cpp
@@ -0,0 +1,651 @@
+/* -*- 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 <assert.h>
+#include <stdio.h>
+#include "nsCOMPtr.h"
+#include "nsISupports.h"
+
+#ifdef HAVE_CPP_NEW_CASTS
+ #define STATIC_CAST(T,x) static_cast<T>(x)
+ #define REINTERPRET_CAST(T,x) reinterpret_cast<T>(x)
+#else
+ #define STATIC_CAST(T,x) ((T)(x))
+ #define REINTERPRET_CAST(T,x) ((T)(x))
+#endif
+
+
+#define NS_IFOO_IID \
+{ 0x6f7652e0, 0xee43, 0x11d1, \
+ { 0x9c, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 } }
+
+class IFoo : public nsISupports
+ {
+ public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IFOO_IID)
+
+ public:
+ IFoo();
+ // virtual dtor because IBar uses our Release()
+ virtual ~IFoo();
+
+ NS_IMETHOD_(nsrefcnt) AddRef();
+ NS_IMETHOD_(nsrefcnt) Release();
+ NS_IMETHOD QueryInterface( const nsIID&, void** );
+
+ static void print_totals();
+
+ private:
+ unsigned int refcount_;
+
+ static unsigned int total_constructions_;
+ static unsigned int total_destructions_;
+ };
+
+class IBar;
+
+ // some types I'll need
+typedef unsigned long NS_RESULT;
+
+ // some functions I'll need (and define below)
+ nsresult CreateIFoo( void** );
+ nsresult CreateIBar( void** result );
+ void AnIFooPtrPtrContext( IFoo** );
+ void AnISupportsPtrPtrContext( nsISupports** );
+ void AVoidPtrPtrContext( void** );
+ void set_a_IFoo( nsCOMPtr<IFoo>* result );
+nsCOMPtr<IFoo> return_a_IFoo();
+
+
+
+
+unsigned int IFoo::total_constructions_;
+unsigned int IFoo::total_destructions_;
+
+class test_message
+ {
+ public:
+ test_message()
+ {
+ printf("BEGIN unit tests for |nsCOMPtr|, compiled " __DATE__ "\n");
+ }
+
+ ~test_message()
+ {
+ IFoo::print_totals();
+ printf("END unit tests for |nsCOMPtr|.\n");
+ }
+ };
+
+test_message gTestMessage;
+
+
+ /*
+ ...
+ */
+
+void
+IFoo::print_totals()
+ {
+ printf("total constructions/destructions --> %d/%d\n",
+ total_constructions_, total_destructions_);
+ }
+
+IFoo::IFoo()
+ : refcount_(0)
+ {
+ ++total_constructions_;
+ printf(" new IFoo@%p [#%d]\n",
+ STATIC_CAST(void*, this), total_constructions_);
+ }
+
+IFoo::~IFoo()
+ {
+ ++total_destructions_;
+ printf("IFoo@%p::~IFoo() [#%d]\n",
+ STATIC_CAST(void*, this), total_destructions_);
+ }
+
+nsrefcnt
+IFoo::AddRef()
+ {
+ ++refcount_;
+ printf("IFoo@%p::AddRef(), refcount --> %d\n",
+ STATIC_CAST(void*, this), refcount_);
+ return refcount_;
+ }
+
+nsrefcnt
+IFoo::Release()
+ {
+ int wrap_message = (refcount_ == 1);
+ if ( wrap_message )
+ printf(">>");
+
+ nsrefcnt const newcount = --refcount_;
+ printf("IFoo@%p::Release(), refcount --> %d\n",
+ STATIC_CAST(void*, this), newcount);
+
+ if ( !newcount )
+ {
+ printf(" delete IFoo@%p\n", STATIC_CAST(void*, this));
+ delete this;
+ }
+
+ if ( wrap_message )
+ printf("<<IFoo@%p::Release()\n", STATIC_CAST(void*, this));
+
+ return newcount;
+ }
+
+nsresult
+IFoo::QueryInterface( const nsIID& aIID, void** aResult )
+ {
+ printf("IFoo@%p::QueryInterface()\n", STATIC_CAST(void*, this));
+ nsISupports* rawPtr = 0;
+ nsresult status = NS_OK;
+
+ if ( aIID.Equals(GetIID()) )
+ rawPtr = this;
+ else
+ {
+ nsID iid_of_ISupports = NS_ISUPPORTS_IID;
+ if ( aIID.Equals(iid_of_ISupports) )
+ rawPtr = STATIC_CAST(nsISupports*, this);
+ else
+ status = NS_ERROR_NO_INTERFACE;
+ }
+
+ NS_IF_ADDREF(rawPtr);
+ *aResult = rawPtr;
+
+ return status;
+ }
+
+nsresult
+CreateIFoo( void** result )
+ // a typical factory function (that calls AddRef)
+ {
+ printf(">>CreateIFoo() --> ");
+ IFoo* foop = new IFoo;
+ printf("IFoo@%p\n", STATIC_CAST(void*, foop));
+
+ foop->AddRef();
+ *result = foop;
+
+ printf("<<CreateIFoo()\n");
+ return 0;
+ }
+
+void
+set_a_IFoo( nsCOMPtr<IFoo>* result )
+ {
+ printf(">>set_a_IFoo()\n");
+ assert(result);
+
+ nsCOMPtr<IFoo> foop( do_QueryInterface(new IFoo) );
+ *result = foop;
+ printf("<<set_a_IFoo()\n");
+ }
+
+nsCOMPtr<IFoo>
+return_a_IFoo()
+ {
+ printf(">>return_a_IFoo()\n");
+ nsCOMPtr<IFoo> foop( do_QueryInterface(new IFoo) );
+ printf("<<return_a_IFoo()\n");
+ return foop;
+ }
+
+
+
+
+#define NS_IBAR_IID \
+{ 0x6f7652e1, 0xee43, 0x11d1, \
+ { 0x9c, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 } }
+
+class IBar : public IFoo
+ {
+ public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IBAR_IID)
+
+ public:
+ IBar();
+ virtual ~IBar();
+
+ NS_IMETHOD QueryInterface( const nsIID&, void** );
+ };
+
+IBar::IBar()
+ {
+ printf(" new IBar@%p\n", STATIC_CAST(void*, this));
+ }
+
+IBar::~IBar()
+ {
+ printf("IBar@%p::~IBar()\n", STATIC_CAST(void*, this));
+ }
+
+nsresult
+IBar::QueryInterface( const nsID& aIID, void** aResult )
+ {
+ printf("IBar@%p::QueryInterface()\n", STATIC_CAST(void*, this));
+ nsISupports* rawPtr = 0;
+ nsresult status = NS_OK;
+
+ if ( aIID.Equals(GetIID()) )
+ rawPtr = this;
+ else if ( aIID.Equals(NS_GET_IID(IFoo)) )
+ rawPtr = STATIC_CAST(IFoo*, this);
+ else
+ {
+ nsID iid_of_ISupports = NS_ISUPPORTS_IID;
+ if ( aIID.Equals(iid_of_ISupports) )
+ rawPtr = STATIC_CAST(nsISupports*, this);
+ else
+ status = NS_ERROR_NO_INTERFACE;
+ }
+
+ NS_IF_ADDREF(rawPtr);
+ *aResult = rawPtr;
+
+ return status;
+ }
+
+
+
+nsresult
+CreateIBar( void** result )
+ // a typical factory function (that calls AddRef)
+ {
+ printf(">>CreateIBar() --> ");
+ IBar* barp = new IBar;
+ printf("IBar@%p\n", STATIC_CAST(void*, barp));
+
+ barp->AddRef();
+ *result = barp;
+
+ printf("<<CreateIBar()\n");
+ return 0;
+ }
+
+void
+AnIFooPtrPtrContext( IFoo** )
+ {
+ }
+
+void
+AVoidPtrPtrContext( void** )
+ {
+ }
+
+void
+AnISupportsPtrPtrContext( nsISupports** )
+ {
+ }
+
+
+// Optimism
+#define TEST_EXCEPTIONS 1
+
+// HAVE_CPP_EXCEPTIONS is defined automagically on unix
+#if defined(XP_UNIX) || defined(XP_BEOS) || defined(XP_OS2)
+#if !defined(HAVE_CPP_EXCEPTIONS)
+#undef TEST_EXCEPTIONS
+#endif
+#endif
+
+#ifdef TEST_EXCEPTIONS
+static
+nsresult
+TestBloat_Raw()
+ {
+ IBar* barP = 0;
+ nsresult result = CreateIBar(REINTERPRET_CAST(void**, &barP));
+
+ if ( barP )
+ {
+ try
+ {
+ IFoo* fooP = 0;
+ if ( NS_SUCCEEDED( result = barP->QueryInterface(NS_GET_IID(IFoo), REINTERPRET_CAST(void**, &fooP)) ) )
+ {
+ try
+ {
+ fooP->print_totals();
+ }
+ catch( ... )
+ {
+ NS_RELEASE(fooP);
+ throw;
+ }
+
+ NS_RELEASE(fooP);
+ }
+ }
+ catch( ... )
+ {
+ NS_RELEASE(barP);
+ throw;
+ }
+
+ NS_RELEASE(barP);
+ }
+
+ return result;
+ }
+#endif // TEST_EXCEPTIONS
+
+static
+nsresult
+TestBloat_Raw_Unsafe()
+ {
+ IBar* barP = 0;
+ nsresult result = CreateIBar(REINTERPRET_CAST(void**, &barP));
+
+ if ( barP )
+ {
+ IFoo* fooP = 0;
+ if ( NS_SUCCEEDED( result = barP->QueryInterface(NS_GET_IID(IFoo), REINTERPRET_CAST(void**, &fooP)) ) )
+ {
+ fooP->print_totals();
+ NS_RELEASE(fooP);
+ }
+
+ NS_RELEASE(barP);
+ }
+
+ return result;
+ }
+
+
+static
+nsresult
+TestBloat_Smart()
+ {
+ nsCOMPtr<IBar> barP;
+ nsresult result = CreateIBar( getter_AddRefs(barP) );
+
+ nsCOMPtr<IFoo> fooP( do_QueryInterface(barP, &result) );
+
+ if ( fooP )
+ fooP->print_totals();
+
+ return result;
+ }
+
+
+
+
+nsCOMPtr<IFoo> gFoop;
+
+int
+main()
+ {
+ printf(">>main()\n");
+
+ printf("sizeof(nsCOMPtr<IFoo>) --> %zd\n", sizeof(nsCOMPtr<IFoo>));
+
+#ifdef TEST_EXCEPTIONS
+ TestBloat_Raw();
+#endif // TEST_EXCEPTIONS
+ TestBloat_Raw_Unsafe();
+ TestBloat_Smart();
+
+
+ {
+ printf("\n### Test 1: will a |nsCOMPtr| call |AddRef| on a pointer assigned into it?\n");
+ nsCOMPtr<IFoo> foop( do_QueryInterface(new IFoo) );
+
+ printf("\n### Test 2: will a |nsCOMPtr| |Release| its old pointer when a new one is assigned in?\n");
+ foop = do_QueryInterface(new IFoo);
+
+ // [Shouldn't compile] Is it a compile time error to try to |AddRef| by hand?
+ //foop->AddRef();
+
+ // [Shouldn't compile] Is it a compile time error to try to |Release| be hand?
+ //foop->Release();
+
+ // [Shouldn't compile] Is it a compile time error to try to |delete| an |nsCOMPtr|?
+ //delete foop;
+
+ printf("\n### Test 3: can you |AddRef| if you must?\n");
+ STATIC_CAST(IFoo*, foop)->AddRef();
+
+ printf("\n### Test 4: can you |Release| if you must?\n");
+ STATIC_CAST(IFoo*, foop)->Release();
+
+ printf("\n### Test 5: will a |nsCOMPtr| |Release| when it goes out of scope?\n");
+ }
+
+ {
+ printf("\n### Test 6: will a |nsCOMPtr| call the correct destructor?\n");
+ nsCOMPtr<IFoo> foop( do_QueryInterface(new IBar) );
+ }
+
+ {
+ printf("\n### Test 7: can you compare one |nsCOMPtr| with another [!=]?\n");
+
+ nsCOMPtr<IFoo> foo1p( do_QueryInterface(new IFoo) );
+
+ // [Shouldn't compile] Is it a compile time error to omit |getter_[doesnt_]AddRef[s]|?
+ //AnIFooPtrPtrContext(&foo1p);
+
+ // [Shouldn't compile] Is it a compile time error to omit |getter_[doesnt_]AddRef[s]|?
+ //AVoidPtrPtrContext(&foo1p);
+
+ nsCOMPtr<IFoo> foo2p( do_QueryInterface(new IFoo) );
+
+ if ( foo1p != foo2p )
+ printf("foo1p != foo2p\n");
+ else
+ printf("foo1p == foo2p\n");
+
+ printf("\n### Test 7.5: can you compare a |nsCOMPtr| with NULL, 0, nsnull [!=]?\n");
+ if ( foo1p != 0 )
+ printf("foo1p != 0\n");
+ if ( 0 != foo1p )
+ printf("0 != foo1p\n");
+ if ( foo1p == 0 )
+ printf("foo1p == 0\n");
+ if ( 0 == foo1p )
+ printf("0 == foo1p\n");
+
+
+ IFoo* raw_foo2p = foo2p.get();
+
+ printf("\n### Test 8: can you compare a |nsCOMPtr| with a raw interface pointer [!=]?\n");
+ if ( foo1p.get() != raw_foo2p )
+ printf("foo1p != raw_foo2p\n");
+ else
+ printf("foo1p == raw_foo2p\n");
+
+
+ printf("\n### Test 9: can you assign one |nsCOMPtr| into another?\n");
+ foo1p = foo2p;
+
+ printf("\n### Test 10: can you compare one |nsCOMPtr| with another [==]?\n");
+ if ( foo1p == foo2p )
+ printf("foo1p == foo2p\n");
+ else
+ printf("foo1p != foo2p\n");
+
+ printf("\n### Test 11: can you compare a |nsCOMPtr| with a raw interface pointer [==]?\n");
+ if ( raw_foo2p == foo2p.get() )
+ printf("raw_foo2p == foo2p\n");
+ else
+ printf("raw_foo2p != foo2p\n");
+
+#if 1
+ printf("\n### Test 11.5: can you compare a |nsCOMPtr| with a raw interface pointer [==]?\n");
+ if ( nsCOMPtr<IFoo>( raw_foo2p ) == foo2p )
+ printf("raw_foo2p == foo2p\n");
+ else
+ printf("raw_foo2p != foo2p\n");
+#endif
+
+ printf("\n### Test 12: bare pointer test?\n");
+ if ( foo1p )
+ printf("foo1p is not NULL\n");
+ else
+ printf("foo1p is NULL\n");
+
+ printf("\n### Test 13: numeric pointer test?\n");
+ if ( foo1p == 0 )
+ printf("foo1p is NULL\n");
+ else
+ printf("foo1p is not NULL\n");
+
+#if 0
+ if ( foo1p == 1 )
+ printf("foo1p allowed compare with in\n");
+#endif
+
+ printf("\n### Test 14: how about when two |nsCOMPtr|s referring to the same object go out of scope?\n");
+ }
+
+ {
+ printf("\n### Test 15,16 ...setup...\n");
+ IFoo* raw_foo1p = new IFoo;
+ raw_foo1p->AddRef();
+
+ IFoo* raw_foo2p = new IFoo;
+ raw_foo2p->AddRef();
+
+ printf("\n### Test 15: what if I don't want to |AddRef| when I construct?\n");
+ nsCOMPtr<IFoo> foo1p( dont_AddRef(raw_foo1p) );
+ //nsCOMPtr<IFoo> foo1p = dont_AddRef(raw_foo1p);
+
+ printf("\n### Test 16: what if I don't want to |AddRef| when I assign in?\n");
+ nsCOMPtr<IFoo> foo2p;
+ foo2p = dont_AddRef(raw_foo2p);
+ }
+
+
+
+
+
+
+
+ {
+ printf("\n### setup for Test 17\n");
+ nsCOMPtr<IFoo> foop;
+ printf("### Test 17: basic parameter behavior?\n");
+ CreateIFoo( nsGetterAddRefs<IFoo>(foop) );
+ }
+ printf("### End Test 17\n");
+
+
+ {
+ printf("\n### setup for Test 18\n");
+ nsCOMPtr<IFoo> foop;
+ printf("### Test 18: basic parameter behavior, using the short form?\n");
+ CreateIFoo( getter_AddRefs(foop) );
+ }
+ printf("### End Test 18\n");
+
+
+ {
+ printf("\n### setup for Test 19, 20\n");
+ nsCOMPtr<IFoo> foop;
+ printf("### Test 19: reference parameter behavior?\n");
+ set_a_IFoo(address_of(foop));
+
+ printf("### Test 20: return value behavior?\n");
+ foop = return_a_IFoo();
+ }
+ printf("### End Test 19, 20\n");
+
+ {
+ printf("\n### setup for Test 21\n");
+ nsCOMPtr<IFoo> fooP;
+
+ printf("### Test 21: is |QueryInterface| called on assigning in a raw pointer?\n");
+ fooP = do_QueryInterface(new IFoo);
+ }
+ printf("### End Test 21\n");
+
+ {
+ printf("\n### setup for Test 22\n");
+ nsCOMPtr<IFoo> fooP;
+ fooP = do_QueryInterface(new IFoo);
+
+ nsCOMPtr<IFoo> foo2P;
+
+ printf("### Test 22: is |QueryInterface| _not_ called when assigning in a smart-pointer of the same type?\n");
+ foo2P = fooP;
+ }
+ printf("### End Test 22\n");
+
+ {
+ printf("\n### setup for Test 23\n");
+ nsCOMPtr<IBar> barP( do_QueryInterface(new IBar) );
+
+ printf("### Test 23: is |QueryInterface| called when assigning in a smart-pointer of a different type?\n");
+
+ nsCOMPtr<IFoo> fooP( do_QueryInterface(barP) );
+ if ( fooP )
+ printf("an IBar* is an IFoo*\n");
+ }
+ printf("### End Test 23\n");
+
+
+ {
+ nsCOMPtr<IFoo> fooP;
+
+ AnIFooPtrPtrContext( getter_AddRefs(fooP) );
+ AVoidPtrPtrContext( getter_AddRefs(fooP) );
+ AnISupportsPtrPtrContext( getter_AddRefs(fooP) );
+ }
+
+
+ {
+ nsCOMPtr<nsISupports> supportsP;
+
+ AVoidPtrPtrContext( getter_AddRefs(supportsP) );
+ AnISupportsPtrPtrContext( getter_AddRefs(supportsP) );
+ }
+
+
+ printf("\n### Test 24: will a static |nsCOMPtr| |Release| before program termination?\n");
+ gFoop = do_QueryInterface(new IFoo);
+
+ printf("<<main()\n");
+ return 0;
+ }
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestCOMPtrEq.cpp b/src/libs/xpcom18a4/xpcom/tests/TestCOMPtrEq.cpp
new file mode 100644
index 00000000..916a0775
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestCOMPtrEq.cpp
@@ -0,0 +1,200 @@
+/* -*- 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 TestCOMPtrEq.cpp.
+ *
+ * The Initial Developer of the Original Code is
+ * L. David Baron.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * L. David Baron <dbaron@dbaron.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 ***** */
+
+ /**
+ * This attempts to test all the possible variations of |operator==|
+ * used with |nsCOMPtr|s. Currently only the tests where pointers
+ * are to the same class are enabled. It's not clear whether we
+ * should be supporting other tests, and some of them won't work
+ * on at least some platforms. If we add separate comparisons
+ * for nsCOMPtr<nsISupports> we'll need to add more tests for
+ * those cases.
+ */
+
+#include "nsCOMPtr.h"
+
+ // Don't test these now, since some of them won't work and it's
+ // not clear whether they should (see above).
+#undef NSCAP_EQTEST_TEST_ACROSS_TYPES
+
+#define NS_ICOMPTREQTESTFOO_IID \
+ {0x8eb5bbef, 0xd1a3, 0x4659, \
+ {0x9c, 0xf6, 0xfd, 0xf3, 0xe4, 0xd2, 0x00, 0x0e}}
+
+class nsICOMPtrEqTestFoo : public nsISupports {
+ public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_ICOMPTREQTESTFOO_IID)
+};
+
+#ifdef NSCAP_EQTEST_TEST_ACROSS_TYPES
+
+#define NS_ICOMPTREQTESTFOO2_IID \
+ {0x6516387b, 0x36c5, 0x4036, \
+ {0x82, 0xc9, 0xa7, 0x4d, 0xd9, 0xe5, 0x92, 0x2f}}
+
+class nsICOMPtrEqTestFoo2 : public nsISupports {
+ public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_ICOMPTREQTESTFOO2_IID)
+};
+
+#endif
+
+int
+main()
+ {
+ nsCOMPtr<nsICOMPtrEqTestFoo> s;
+ nsICOMPtrEqTestFoo* r = 0;
+ const nsCOMPtr<nsICOMPtrEqTestFoo> sc;
+ const nsICOMPtrEqTestFoo* rc = 0;
+ nsICOMPtrEqTestFoo* const rk = 0;
+ const nsICOMPtrEqTestFoo* const rkc = 0;
+ nsDerivedSafe<nsICOMPtrEqTestFoo>* d = s.get();
+
+#ifdef NSCAP_EQTEST_TEST_ACROSS_TYPES
+ nsCOMPtr<nsICOMPtrEqTestFoo2> s2;
+ nsICOMPtrEqTestFoo2* r2 = 0;
+ const nsCOMPtr<nsICOMPtrEqTestFoo2> sc2;
+ const nsICOMPtrEqTestFoo2* rc2 = 0;
+ nsICOMPtrEqTestFoo2* const rk2 = 0;
+ const nsICOMPtrEqTestFoo2* const rkc2 = 0;
+ nsDerivedSafe<nsICOMPtrEqTestFoo2>* d2 = s2.get();
+#endif
+
+ return (!(PR_TRUE &&
+ (s == s) &&
+ (s == r) &&
+ (s == sc) &&
+ (s == rc) &&
+ (s == rk) &&
+ (s == rkc) &&
+ (s == d) &&
+ (r == s) &&
+ (r == r) &&
+ (r == sc) &&
+ (r == rc) &&
+ (r == rk) &&
+ (r == rkc) &&
+ (r == d) &&
+ (sc == s) &&
+ (sc == r) &&
+ (sc == sc) &&
+ (sc == rc) &&
+ (sc == rk) &&
+ (sc == rkc) &&
+ (sc == d) &&
+ (rc == s) &&
+ (rc == r) &&
+ (rc == sc) &&
+ (rc == rc) &&
+ (rc == rk) &&
+ (rc == rkc) &&
+ (rc == d) &&
+ (rk == s) &&
+ (rk == r) &&
+ (rk == sc) &&
+ (rk == rc) &&
+ (rk == rk) &&
+ (rk == rkc) &&
+ (rk == d) &&
+ (rkc == s) &&
+ (rkc == r) &&
+ (rkc == sc) &&
+ (rkc == rc) &&
+ (rkc == rk) &&
+ (rkc == rkc) &&
+ (rkc == d) &&
+ (d == s) &&
+ (d == r) &&
+ (d == sc) &&
+ (d == rc) &&
+ (d == rk) &&
+ (d == rkc) &&
+ (d == d) &&
+#ifdef NSCAP_EQTEST_TEST_ACROSS_TYPES
+ (s == s2) &&
+ (s == r2) &&
+ (s == sc2) &&
+ (s == rc2) &&
+ (s == rk2) &&
+ (s == rkc2) &&
+ (s == d2) &&
+ (r == s2) &&
+ (r == r2) &&
+ (r == sc2) &&
+ (r == rc2) &&
+ (r == rk2) &&
+ (r == rkc2) &&
+ (r == d2) &&
+ (sc == s2) &&
+ (sc == r2) &&
+ (sc == sc2) &&
+ (sc == rc2) &&
+ (sc == rk2) &&
+ (sc == rkc2) &&
+ (sc == d2) &&
+ (rc == s2) &&
+ (rc == r2) &&
+ (rc == sc2) &&
+ (rc == rc2) &&
+ (rc == rk2) &&
+ (rc == rkc2) &&
+ (rc == d2) &&
+ (rk == s2) &&
+ (rk == r2) &&
+ (rk == sc2) &&
+ (rk == rc2) &&
+ (rk == rk2) &&
+ (rk == rkc2) &&
+ (rk == d2) &&
+ (rkc == s2) &&
+ (rkc == r2) &&
+ (rkc == sc2) &&
+ (rkc == rc2) &&
+ (rkc == rk2) &&
+ (rkc == rkc2) &&
+ (rkc == d2) &&
+ (d == s2) &&
+ (d == r2) &&
+ (d == sc2) &&
+ (d == rc2) &&
+ (d == rk2) &&
+ (d == rkc2) &&
+ (d == d2) &&
+#endif
+ PR_TRUE));
+ }
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestCRT.cpp b/src/libs/xpcom18a4/xpcom/tests/TestCRT.cpp
new file mode 100644
index 00000000..11bdd512
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestCRT.cpp
@@ -0,0 +1,112 @@
+/* -*- 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 "nsCRT.h"
+#include "nsString.h"
+#include "plstr.h"
+#include <stdlib.h>
+
+// The return from strcmp etc is only defined to be postive, zero or
+// negative. The magnitude of a non-zero return is irrelevant.
+PRIntn sign(PRIntn val) {
+ if (val == 0)
+ return 0;
+ else {
+ if (val > 0)
+ return 1;
+ else
+ return -1;
+ }
+}
+
+
+// Verify that nsCRT versions of string comparison routines get the
+// same answers as the native non-unicode versions. We only pass in
+// iso-latin-1 strings, so the comparison must be valid.
+static void Check(const char* s1, const char* s2, PRIntn n)
+{
+ PRIntn clib = PL_strcmp(s1, s2);
+ PRIntn clib_n = PL_strncmp(s1, s2, n);
+ PRIntn clib_case = PL_strcasecmp(s1, s2);
+ PRIntn clib_case_n = PL_strncasecmp(s1, s2, n);
+
+ nsAutoString t1,t2;
+ t1.AssignWithConversion(s1);
+ t2.AssignWithConversion(s2);
+ const PRUnichar* us1 = t1.get();
+ const PRUnichar* us2 = t2.get();
+
+ PRIntn u2 = nsCRT::strcmp(us1, us2);
+ PRIntn u2_n = nsCRT::strncmp(us1, us2, n);
+
+ NS_ASSERTION(sign(clib) == sign(u2), "strcmp");
+ NS_ASSERTION(sign(clib_n) == sign(u2_n), "strncmp");
+}
+
+struct Test {
+ const char* s1;
+ const char* s2;
+ PRIntn n;
+};
+
+static Test tests[] = {
+ { "foo", "foo", 3 },
+ { "foo", "fo", 3 },
+
+ { "foo", "bar", 3 },
+ { "foo", "ba", 3 },
+
+ { "foo", "zap", 3 },
+ { "foo", "za", 3 },
+
+ { "bar", "foo", 3 },
+ { "bar", "fo", 3 },
+
+ { "bar", "foo", 3 },
+ { "bar", "fo", 3 },
+};
+#define NUM_TESTS int((sizeof(tests) / sizeof(tests[0])))
+
+int main()
+{
+ Test* tp = tests;
+ for (int i = 0; i < NUM_TESTS; i++, tp++) {
+ Check(tp->s1, tp->s2, tp->n);
+ }
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestCallTemplates.cpp b/src/libs/xpcom18a4/xpcom/tests/TestCallTemplates.cpp
new file mode 100644
index 00000000..3ec9c29a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestCallTemplates.cpp
@@ -0,0 +1,129 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim:cindent:ts=8:et:sw=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.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * L. David Baron <dbaron@dbaron.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 ***** */
+
+/*
+ * This test is NOT intended to be run. It's a test to make sure
+ * a group of functions BUILD correctly.
+ */
+
+#include "nsISupportsUtils.h"
+#include "nsIWeakReference.h"
+#include "nsIComponentManager.h"
+#include "nsIServiceManager.h"
+#include "nsWeakReference.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsIInterfaceRequestorUtils.h"
+
+#define NS_ITESTSERVICE_IID \
+ {0x127b5253, 0x37b1, 0x43c7, \
+ { 0x96, 0x2b, 0xab, 0xf1, 0x2d, 0x22, 0x56, 0xae }}
+
+class NS_NO_VTABLE nsITestService : public nsISupports {
+ public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_ITESTSERVICE_IID)
+};
+
+class nsTestService : public nsITestService, public nsSupportsWeakReference
+{
+ public:
+ NS_DECL_ISUPPORTS
+};
+
+NS_IMPL_ISUPPORTS2(nsTestService, nsITestService, nsISupportsWeakReference)
+
+#define NS_TEST_SERVICE_CONTRACTID "@mozilla.org/test/testservice;1"
+#define NS_TEST_SERVICE_CID \
+ {0xa00c1406, 0x283a, 0x45c9, \
+ {0xae, 0xd2, 0x1a, 0xb6, 0xdd, 0xba, 0xfe, 0x53}}
+static NS_DEFINE_CID(kTestServiceCID, NS_TEST_SERVICE_CID);
+
+int main()
+{
+ /*
+ * NOTE: This does NOT demonstrate how these functions are
+ * intended to be used. They are intended for filling in out
+ * parameters that need to be |AddRef|ed. I'm just too lazy
+ * to write lots of little getter functions for a test program
+ * when I don't need to.
+ */
+
+ NS_NOTREACHED("This test is not intended to run, only to compile!");
+
+ /* Test CallQueryInterface */
+
+ nsISupports *mySupportsPtr = NS_REINTERPRET_CAST(nsISupports*, 0x1000);
+
+ nsITestService *myITestService = nsnull;
+ CallQueryInterface(mySupportsPtr, &myITestService);
+
+ nsTestService *myTestService =
+ NS_REINTERPRET_CAST(nsTestService*, mySupportsPtr);
+ nsISupportsWeakReference *mySupportsWeakRef;
+ CallQueryInterface(myTestService, &mySupportsWeakRef);
+
+ /* Test CallQueryReferent */
+
+ nsIWeakReference *myWeakRef =
+ NS_STATIC_CAST(nsIWeakReference*, mySupportsPtr);
+ CallQueryReferent(myWeakRef, &myITestService);
+
+ /* Test CallCreateInstance */
+
+ CallCreateInstance(kTestServiceCID, mySupportsPtr, &myITestService);
+ CallCreateInstance(kTestServiceCID, &myITestService);
+ CallCreateInstance(NS_TEST_SERVICE_CONTRACTID, mySupportsPtr,
+ &myITestService);
+ CallCreateInstance(NS_TEST_SERVICE_CONTRACTID, &myITestService);
+
+ /* Test CallGetService */
+ nsIShutdownListener *myShutdownListener = nsnull;
+ CallGetService(kTestServiceCID, &myITestService);
+ CallGetService(kTestServiceCID, myShutdownListener, &myITestService);
+ CallGetService(NS_TEST_SERVICE_CONTRACTID, &myITestService);
+ CallGetService(NS_TEST_SERVICE_CONTRACTID, myShutdownListener,
+ &myITestService);
+
+ /* Test CallGetInterface */
+ nsIInterfaceRequestor *myInterfaceRequestor =
+ NS_STATIC_CAST(nsIInterfaceRequestor*, mySupportsPtr);
+ CallGetInterface(myInterfaceRequestor, &myITestService);
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestDeque.cpp b/src/libs/xpcom18a4/xpcom/tests/TestDeque.cpp
new file mode 100644
index 00000000..4b00c7fb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestDeque.cpp
@@ -0,0 +1,155 @@
+/* -*- 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"
+#include <stdio.h>
+
+/**************************************************************
+ Now define the token deallocator class...
+ **************************************************************/
+class _TestDeque {
+public:
+ _TestDeque() {
+ SelfTest();
+ }
+ int SelfTest();
+ nsresult OriginalTest();
+ nsresult OriginalFlaw();
+ nsresult AssignFlaw();
+};
+static _TestDeque sTestDeque;
+
+class _Dealloc: public nsDequeFunctor {
+ virtual void* operator()(void* aObject) {
+ return 0;
+ }
+};
+
+/**
+ * conduct automated self test for this class
+ *
+ * @param
+ * @return
+ */
+int _TestDeque::SelfTest() {
+ /* the old deque should have failed a bunch of these tests */
+ int results=0;
+ results+=OriginalTest();
+ results+=OriginalFlaw();
+ results+=AssignFlaw();
+ return results;
+}
+
+nsresult _TestDeque::OriginalTest() {
+ int ints[200];
+ int count=sizeof(ints)/sizeof(int);
+ int i=0;
+ int* temp;
+ nsDeque theDeque(new _Dealloc); //construct a simple one...
+
+ for (i=0;i<count;i++) { //initialize'em
+ ints[i]=10*(1+i);
+ }
+ for (i=0;i<70;i++) {
+ theDeque.Push(&ints[i]);
+ }
+ for (i=0;i<56;i++) {
+ temp=(int*)theDeque.Pop();
+ }
+ for (i=0;i<55;i++) {
+ theDeque.Push(&ints[i]);
+ }
+ for (i=0;i<35;i++) {
+ temp=(int*)theDeque.Pop();
+ }
+ for (i=0;i<35;i++) {
+ theDeque.Push(&ints[i]);
+ }
+ for (i=0;i<38;i++) {
+ temp=(int*)theDeque.Pop();
+ }
+ return NS_OK;
+}
+
+nsresult _TestDeque::OriginalFlaw() {
+ int ints[200];
+ int i=0;
+ int* temp;
+ nsDeque secondDeque(new _Dealloc);
+ /**
+ * Test 1. Origin near end, semi full, call Peek().
+ * you start, mCapacity is 8
+ */
+ printf("fill array\n");
+ for (i=32; i; --i)
+ ints[i]=i*3+10;
+ printf("push 6 times\n");
+ for (i=0; i<6; i++)
+ secondDeque.Push(&ints[i]);
+ printf("popfront 4 times:\n");
+ for (i=4; i; --i) {
+ temp=(int*)secondDeque.PopFront();
+ printf("%d\t",*temp);
+ }
+ printf("push 4 times\n");
+ for (int j=4; j; --j)
+ secondDeque.Push(&ints[++i]);
+ printf("origin should now be about 4\n");
+ printf("and size should be 6\n");
+ printf("origin+size>capacity\n");
+
+ /*<akk> Oh, I see ... it's a circular buffer */
+ printf("but the old code wasn't behaving accordingly.\n");
+
+ /*right*/
+ printf("we shouldn't crash or anything interesting, ");
+
+ temp=(int*)secondDeque.Peek();
+ printf("peek: %d\n",*temp);
+ return NS_OK;
+}
+
+nsresult _TestDeque::AssignFlaw() {
+ nsDeque src(new _Dealloc),dest(new _Dealloc);
+ return NS_OK;
+}
+
+int main (void) {
+ _TestDeque test;
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestFactory.cpp b/src/libs/xpcom18a4/xpcom/tests/TestFactory.cpp
new file mode 100644
index 00000000..f0d5f777
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestFactory.cpp
@@ -0,0 +1,160 @@
+/* -*- 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 <stdio.h>
+#include "TestFactory.h"
+#include "nsISupports.h"
+#include "nsIComponentManager.h"
+#include "nsIComponentRegistrar.h"
+#include "nsIServiceManager.h"
+
+NS_DEFINE_CID(kTestFactoryCID, NS_TESTFACTORY_CID);
+NS_DEFINE_CID(kTestLoadedFactoryCID, NS_TESTLOADEDFACTORY_CID);
+
+
+/**
+ * ITestClass implementation
+ */
+
+class TestClassImpl: public ITestClass {
+ NS_DECL_ISUPPORTS
+public:
+ TestClassImpl() {
+ }
+
+ void Test();
+};
+
+NS_IMPL_ISUPPORTS1(TestClassImpl, ITestClass)
+
+void TestClassImpl::Test() {
+ printf("hello, world!\n");
+}
+
+/**
+ * TestFactory implementation
+ */
+
+class TestFactory: public nsIFactory {
+ NS_DECL_ISUPPORTS
+
+public:
+ TestFactory() {
+ }
+
+ NS_IMETHOD CreateInstance(nsISupports *aDelegate,
+ const nsIID &aIID,
+ void **aResult);
+
+ NS_IMETHOD LockFactory(PRBool aLock) { return NS_OK; }
+};
+
+NS_IMPL_ISUPPORTS1(TestFactory, nsIFactory)
+
+nsresult TestFactory::CreateInstance(nsISupports *aDelegate,
+ const nsIID &aIID,
+ void **aResult) {
+ if (aDelegate != NULL) {
+ return NS_ERROR_NO_AGGREGATION;
+ }
+
+ TestClassImpl *t = new TestClassImpl();
+
+ if (t == NULL) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ nsresult res = t->QueryInterface(aIID, aResult);
+
+ if (NS_FAILED(res)) {
+ *aResult = NULL;
+ delete t;
+ }
+
+ return res;
+}
+
+
+int main(int argc, char **argv) {
+ nsresult rv;
+
+ {
+ nsCOMPtr<nsIServiceManager> servMan;
+ rv = NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull);
+ if (NS_FAILED(rv)) return -1;
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan);
+ NS_ASSERTION(registrar, "Null nsIComponentRegistrar");
+ if (registrar)
+ registrar->RegisterFactory(kTestFactoryCID,
+ nsnull,
+ nsnull,
+ new TestFactory());
+
+ ITestClass *t = NULL;
+ nsComponentManager::CreateInstance(kTestFactoryCID,
+ NULL,
+ NS_GET_IID(ITestClass),
+ (void **) &t);
+
+ if (t != NULL) {
+ t->Test();
+ t->Release();
+ } else {
+ printf("CreateInstance failed\n");
+ }
+
+ t = NULL;
+
+ nsComponentManager::CreateInstance(kTestLoadedFactoryCID,
+ NULL,
+ NS_GET_IID(ITestClass),
+ (void **) &t);
+
+ if (t != NULL) {
+ t->Test();
+ t->Release();
+ } else {
+ printf("Dynamic CreateInstance failed\n");
+ }
+ } // this scopes the nsCOMPtrs
+ // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
+ rv = NS_ShutdownXPCOM(nsnull);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
+ return 0;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestFactory.h b/src/libs/xpcom18a4/xpcom/tests/TestFactory.h
new file mode 100644
index 00000000..d81cefc7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestFactory.h
@@ -0,0 +1,69 @@
+/* -*- 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):
+ * 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 ***** */
+
+#ifndef __TestFactory_h
+#define __TestFactory_h
+
+#include "nsIFactory.h"
+
+// {8B330F20-A24A-11d1-A961-00805F8A7AC4}
+#define NS_TESTFACTORY_CID \
+{ 0x8b330f20, 0xa24a, 0x11d1, \
+ { 0xa9, 0x61, 0x0, 0x80, 0x5f, 0x8a, 0x7a, 0xc4 } }
+
+// {8B330F21-A24A-11d1-A961-00805F8A7AC4}
+#define NS_ITESTCLASS_IID \
+{ 0x8b330f21, 0xa24a, 0x11d1, \
+ { 0xa9, 0x61, 0x0, 0x80, 0x5f, 0x8a, 0x7a, 0xc4 } }
+
+// {8B330F22-A24A-11d1-A961-00805F8A7AC4}
+#define NS_TESTLOADEDFACTORY_CID \
+{ 0x8b330f22, 0xa24a, 0x11d1, \
+ { 0xa9, 0x61, 0x0, 0x80, 0x5f, 0x8a, 0x7a, 0xc4 } }
+
+#define NS_TESTLOADEDFACTORY_CONTRACTID "@mozilla.org/xpcom/dynamic-test;1"
+
+class ITestClass: public nsISupports {
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_ITESTCLASS_IID)
+ virtual void Test() = 0;
+};
+
+extern "C" void RegisterTestFactories();
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestHashtables.cpp b/src/libs/xpcom18a4/xpcom/tests/TestHashtables.cpp
new file mode 100644
index 00000000..1b2d3671
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestHashtables.cpp
@@ -0,0 +1,939 @@
+/* -*- 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 "nsBaseHashtable.h"
+#include "nsDataHashtable.h"
+#include "nsInterfaceHashtable.h"
+#include "nsClassHashtable.h"
+
+#include "nsCOMPtr.h"
+#include "nsISupports.h"
+#include "nsCRT.h"
+#include "nsCOMArray.h"
+
+class TestUniChar // for nsClassHashtable
+{
+public:
+ TestUniChar(PRUint32 aWord)
+ {
+ printf(" TestUniChar::TestUniChar() %u\n", aWord);
+ mWord = aWord;
+ }
+
+ ~TestUniChar()
+ {
+ printf(" TestUniChar::~TestUniChar() %u\n", mWord);
+ }
+
+ PRUint32 GetChar() const { return mWord; }
+
+private:
+ PRUint32 mWord;
+};
+
+struct EntityNode {
+ const char* mStr; // never owns buffer
+ PRUint32 mUnicode;
+};
+
+EntityNode gEntities[] = {
+ {"nbsp",160},
+ {"iexcl",161},
+ {"cent",162},
+ {"pound",163},
+ {"curren",164},
+ {"yen",165},
+ {"brvbar",166},
+ {"sect",167},
+ {"uml",168},
+ {"copy",169},
+ {"ordf",170},
+ {"laquo",171},
+ {"not",172},
+ {"shy",173},
+ {"reg",174},
+ {"macr",175}
+};
+
+#define ENTITY_COUNT (sizeof(gEntities)/sizeof(EntityNode))
+
+class EntityToUnicodeEntry : public PLDHashEntryHdr
+{
+public:
+ typedef const char* KeyType;
+ typedef const char* KeyTypePointer;
+
+ EntityToUnicodeEntry(const char* aKey) { mNode = nsnull; }
+ EntityToUnicodeEntry(const EntityToUnicodeEntry& aEntry) { mNode = aEntry.mNode; }
+ ~EntityToUnicodeEntry() { };
+
+ const char* GetKeyPointer() const { return mNode->mStr; }
+ PRBool KeyEquals(const char* aEntity) const { return !strcmp(mNode->mStr, aEntity); }
+ static const char* KeyToPointer(const char* aEntity) { return aEntity; }
+ static PLDHashNumber HashKey(const char* aEntity) { return nsCRT::HashCode(aEntity); }
+ enum { ALLOW_MEMMOVE = PR_TRUE };
+
+ const EntityNode* mNode;
+};
+
+PLDHashOperator
+nsTEnumGo(EntityToUnicodeEntry* aEntry, void* userArg) {
+ printf(" enumerated \"%s\" = %u\n",
+ aEntry->mNode->mStr, aEntry->mNode->mUnicode);
+
+ return PL_DHASH_NEXT;
+}
+
+PLDHashOperator
+nsTEnumStop(EntityToUnicodeEntry* aEntry, void* userArg) {
+ printf(" enumerated \"%s\" = %u\n",
+ aEntry->mNode->mStr, aEntry->mNode->mUnicode);
+
+ return PL_DHASH_REMOVE;
+}
+
+void
+testTHashtable(nsTHashtable<EntityToUnicodeEntry>& hash, PRUint32 numEntries) {
+ printf("Filling hash with %d entries.\n", numEntries);
+
+ PRUint32 i;
+ for (i = 0; i < numEntries; ++i) {
+ printf(" Putting entry \"%s\"...", gEntities[i].mStr);
+ EntityToUnicodeEntry* entry =
+ hash.PutEntry(gEntities[i].mStr);
+
+ if (!entry) {
+ printf("FAILED\n");
+ exit (2);
+ }
+ printf("OK...");
+
+ if (entry->mNode) {
+ printf("entry already exists!\n");
+ exit (3);
+ }
+ printf("\n");
+
+ entry->mNode = &gEntities[i];
+ }
+
+ printf("Testing Get:\n");
+
+ for (i = 0; i < numEntries; ++i) {
+ printf(" Getting entry \"%s\"...", gEntities[i].mStr);
+ EntityToUnicodeEntry* entry =
+ hash.GetEntry(gEntities[i].mStr);
+
+ if (!entry) {
+ printf("FAILED\n");
+ exit (4);
+ }
+
+ printf("Found %u\n", entry->mNode->mUnicode);
+ }
+
+ printf("Testing non-existent entries...");
+
+ EntityToUnicodeEntry* entry =
+ hash.GetEntry("xxxy");
+
+ if (entry) {
+ printf("FOUND! BAD!\n");
+ exit (5);
+ }
+
+ printf("not found; good.\n");
+
+ printf("Enumerating:\n");
+ PRUint32 count = hash.EnumerateEntries(nsTEnumGo, nsnull);
+ if (count != numEntries) {
+ printf(" Bad count!\n");
+ exit (6);
+ }
+}
+
+PLDHashOperator
+nsDEnumRead(const PRUint32& aKey, const char* aData, void* userArg) {
+ printf(" enumerated %u = \"%s\"\n", aKey, aData);
+ return PL_DHASH_NEXT;
+}
+
+PLDHashOperator
+nsDEnum(const PRUint32& aKey, const char*& aData, void* userArg) {
+ printf(" enumerated %u = \"%s\"\n", aKey, aData);
+ return PL_DHASH_NEXT;
+}
+
+PLDHashOperator
+nsCEnumRead(const nsACString& aKey, TestUniChar* aData, void* userArg) {
+ printf(" enumerated \"%s\" = %c\n",
+ PromiseFlatCString(aKey).get(), aData->GetChar());
+ return PL_DHASH_NEXT;
+}
+
+PLDHashOperator
+nsCEnum(const nsACString& aKey, nsAutoPtr<TestUniChar>& aData, void* userArg) {
+ printf(" enumerated \"%s\" = %c\n",
+ PromiseFlatCString(aKey).get(), aData->GetChar());
+ return PL_DHASH_NEXT;
+}
+
+//
+// all this nsIFoo stuff was copied wholesale from TestCOMPTr.cpp
+//
+
+#define NS_IFOO_IID \
+{ 0x6f7652e0, 0xee43, 0x11d1, \
+ { 0x9c, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 } }
+
+class IFoo : public nsISupports
+ {
+ public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IFOO_IID)
+
+ public:
+ IFoo();
+
+ NS_IMETHOD_(nsrefcnt) AddRef();
+ NS_IMETHOD_(nsrefcnt) Release();
+ NS_IMETHOD QueryInterface( const nsIID&, void** );
+
+ NS_IMETHOD SetString(const nsACString& /*in*/ aString);
+ NS_IMETHOD GetString(nsACString& /*out*/ aString);
+
+ static void print_totals();
+
+ private:
+ ~IFoo();
+
+ unsigned int refcount_;
+
+ static unsigned int total_constructions_;
+ static unsigned int total_destructions_;
+ nsCString mString;
+ };
+
+unsigned int IFoo::total_constructions_;
+unsigned int IFoo::total_destructions_;
+
+void
+IFoo::print_totals()
+ {
+ printf("total constructions/destructions --> %d/%d\n",
+ total_constructions_, total_destructions_);
+ }
+
+IFoo::IFoo()
+ : refcount_(0)
+ {
+ ++total_constructions_;
+ printf(" new IFoo@%p [#%d]\n",
+ NS_STATIC_CAST(void*, this), total_constructions_);
+ }
+
+IFoo::~IFoo()
+ {
+ ++total_destructions_;
+ printf("IFoo@%p::~IFoo() [#%d]\n",
+ NS_STATIC_CAST(void*, this), total_destructions_);
+ }
+
+nsrefcnt
+IFoo::AddRef()
+ {
+ ++refcount_;
+ printf("IFoo@%p::AddRef(), refcount --> %d\n",
+ NS_STATIC_CAST(void*, this), refcount_);
+ return refcount_;
+ }
+
+nsrefcnt
+IFoo::Release()
+ {
+ int wrap_message = (refcount_ == 1);
+ if ( wrap_message )
+ printf(">>");
+
+ nsrefcnt newrefcount = --refcount_;
+ printf("IFoo@%p::Release(), refcount --> %d\n",
+ NS_STATIC_CAST(void*, this), newrefcount);
+
+ if ( !newrefcount )
+ {
+ printf(" delete IFoo@%p\n", NS_STATIC_CAST(void*, this));
+ delete this;
+ }
+
+ if ( wrap_message )
+ printf(" delete IFoo@%p\n", NS_STATIC_CAST(void*, this));
+
+ return newrefcount;
+ }
+
+nsresult
+IFoo::QueryInterface( const nsIID& aIID, void** aResult )
+ {
+ printf("IFoo@%p::QueryInterface()\n", NS_STATIC_CAST(void*, this));
+ nsISupports* rawPtr = 0;
+ nsresult status = NS_OK;
+
+ if ( aIID.Equals(GetIID()) )
+ rawPtr = this;
+ else
+ {
+ nsID iid_of_ISupports = NS_ISUPPORTS_IID;
+ if ( aIID.Equals(iid_of_ISupports) )
+ rawPtr = NS_STATIC_CAST(nsISupports*, this);
+ else
+ status = NS_ERROR_NO_INTERFACE;
+ }
+
+ NS_IF_ADDREF(rawPtr);
+ *aResult = rawPtr;
+
+ return status;
+ }
+
+nsresult
+IFoo::SetString(const nsACString& aString)
+{
+ mString = aString;
+ return NS_OK;
+}
+
+nsresult
+IFoo::GetString(nsACString& aString)
+{
+ aString = mString;
+ return NS_OK;
+}
+
+nsresult
+CreateIFoo( IFoo** result )
+ // a typical factory function (that calls AddRef)
+ {
+ printf(" >>CreateIFoo() --> ");
+ IFoo* foop = new IFoo();
+ printf("IFoo@%p\n", NS_STATIC_CAST(void*, foop));
+
+ foop->AddRef();
+ *result = foop;
+
+ printf("<<CreateIFoo()\n");
+ return 0;
+ }
+
+PLDHashOperator
+nsIEnumRead(const PRUint32& aKey, IFoo* aFoo, void* userArg) {
+ nsCAutoString str;
+ aFoo->GetString(str);
+
+ printf(" enumerated %u = \"%s\"\n", aKey, str.get());
+ return PL_DHASH_NEXT;
+}
+
+PLDHashOperator
+nsIEnum(const PRUint32& aKey, nsCOMPtr<IFoo>& aData, void* userArg) {
+ nsCAutoString str;
+ aData->GetString(str);
+
+ printf(" enumerated %u = \"%s\"\n", aKey, str.get());
+ return PL_DHASH_NEXT;
+}
+
+PLDHashOperator
+nsIEnum2Read(nsISupports* aKey, PRUint32 aData, void* userArg) {
+ nsCAutoString str;
+ nsCOMPtr<IFoo> foo = do_QueryInterface(aKey);
+ foo->GetString(str);
+
+
+ printf(" enumerated \"%s\" = %u\n", str.get(), aData);
+ return PL_DHASH_NEXT;
+}
+
+PLDHashOperator
+nsIEnum2(nsISupports* aKey, PRUint32& aData, void* userArg) {
+ nsCAutoString str;
+ nsCOMPtr<IFoo> foo = do_QueryInterface(aKey);
+ foo->GetString(str);
+
+ printf(" enumerated \"%s\" = %u\n", str.get(), aData);
+ return PL_DHASH_NEXT;
+}
+
+int
+main(void) {
+ // check an nsTHashtable
+ nsTHashtable<EntityToUnicodeEntry> EntityToUnicode;
+
+ printf("Initializing nsTHashtable...");
+ if (!EntityToUnicode.Init(ENTITY_COUNT)) {
+ printf("FAILED\n");
+ exit (1);
+ }
+ printf("OK\n");
+
+ printf("Partially filling nsTHashtable:\n");
+ testTHashtable(EntityToUnicode, 5);
+
+ printf("Enumerate-removing...\n");
+ PRUint32 count = EntityToUnicode.EnumerateEntries(nsTEnumStop, nsnull);
+ if (count != 5) {
+ printf("wrong count\n");
+ exit (7);
+ }
+ printf("OK\n");
+
+ printf("Check enumeration...");
+ count = EntityToUnicode.EnumerateEntries(nsTEnumGo, nsnull);
+ if (count) {
+ printf("entries remain in table!\n");
+ exit (8);
+ }
+ printf("OK\n");
+
+ printf("Filling nsTHashtable:\n");
+ testTHashtable(EntityToUnicode, ENTITY_COUNT);
+
+ printf("Clearing...");
+ EntityToUnicode.Clear();
+ printf("OK\n");
+
+ printf("Check enumeration...");
+ count = EntityToUnicode.EnumerateEntries(nsTEnumGo, nsnull);
+ if (count) {
+ printf("entries remain in table!\n");
+ exit (9);
+ }
+ printf("OK\n");
+
+ //
+ // now check a data-hashtable
+ //
+
+ nsDataHashtable<nsUint32HashKey,const char*> UniToEntity;
+
+ printf("Initializing nsDataHashtable...");
+ if (!UniToEntity.Init(ENTITY_COUNT)) {
+ printf("FAILED\n");
+ exit (10);
+ }
+ printf("OK\n");
+
+ printf("Filling hash with %zd entries.\n", ENTITY_COUNT);
+
+ PRUint32 i;
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Putting entry %u...", gEntities[i].mUnicode);
+ if (!UniToEntity.Put(gEntities[i].mUnicode, gEntities[i].mStr)) {
+ printf("FAILED\n");
+ exit (11);
+ }
+ printf("OK...\n");
+ }
+
+ printf("Testing Get:\n");
+ const char* str;
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Getting entry %u...", gEntities[i].mUnicode);
+ if (!UniToEntity.Get(gEntities[i].mUnicode, &str)) {
+ printf("FAILED\n");
+ exit (12);
+ }
+
+ printf("Found %s\n", str);
+ }
+
+ printf("Testing non-existent entries...");
+ if (UniToEntity.Get(99446, &str)) {
+ printf("FOUND! BAD!\n");
+ exit (13);
+ }
+
+ printf("not found; good.\n");
+
+ printf("Enumerating:\n");
+
+ count = UniToEntity.EnumerateRead(nsDEnumRead, nsnull);
+ if (count != ENTITY_COUNT) {
+ printf(" Bad count!\n");
+ exit (14);
+ }
+
+ printf("Clearing...");
+ UniToEntity.Clear();
+ printf("OK\n");
+
+ printf("Checking count...");
+ count = UniToEntity.Enumerate(nsDEnum, nsnull);
+ if (count) {
+ printf(" Clear did not remove all entries.\n");
+ exit (15);
+ }
+
+ printf("OK\n");
+
+ //
+ // now check a thread-safe data-hashtable
+ //
+
+ nsDataHashtableMT<nsUint32HashKey,const char*> UniToEntityL;
+
+ printf("Initializing nsDataHashtableMT...");
+ if (!UniToEntityL.Init(ENTITY_COUNT)) {
+ printf("FAILED\n");
+ exit (10);
+ }
+ printf("OK\n");
+
+ printf("Filling hash with %zd entries.\n", ENTITY_COUNT);
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Putting entry %u...", gEntities[i].mUnicode);
+ if (!UniToEntityL.Put(gEntities[i].mUnicode, gEntities[i].mStr)) {
+ printf("FAILED\n");
+ exit (11);
+ }
+ printf("OK...\n");
+ }
+
+ printf("Testing Get:\n");
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Getting entry %u...", gEntities[i].mUnicode);
+ if (!UniToEntityL.Get(gEntities[i].mUnicode, &str)) {
+ printf("FAILED\n");
+ exit (12);
+ }
+
+ printf("Found %s\n", str);
+ }
+
+ printf("Testing non-existent entries...");
+ if (UniToEntityL.Get(99446, &str)) {
+ printf("FOUND! BAD!\n");
+ exit (13);
+ }
+
+ printf("not found; good.\n");
+
+ printf("Enumerating:\n");
+
+ count = UniToEntityL.EnumerateRead(nsDEnumRead, nsnull);
+ if (count != ENTITY_COUNT) {
+ printf(" Bad count!\n");
+ exit (14);
+ }
+
+ printf("Clearing...");
+ UniToEntityL.Clear();
+ printf("OK\n");
+
+ printf("Checking count...");
+ count = UniToEntityL.Enumerate(nsDEnum, nsnull);
+ if (count) {
+ printf(" Clear did not remove all entries.\n");
+ exit (15);
+ }
+
+ printf("OK\n");
+
+ //
+ // now check a class-hashtable
+ //
+
+ nsClassHashtable<nsCStringHashKey,TestUniChar> EntToUniClass;
+
+ printf("Initializing nsClassHashtable...");
+ if (!EntToUniClass.Init(ENTITY_COUNT)) {
+ printf("FAILED\n");
+ exit (16);
+ }
+ printf("OK\n");
+
+ printf("Filling hash with %zd entries.\n", ENTITY_COUNT);
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Putting entry %u...", gEntities[i].mUnicode);
+ TestUniChar* temp = new TestUniChar(gEntities[i].mUnicode);
+
+ if (!EntToUniClass.Put(nsDependentCString(gEntities[i].mStr), temp)) {
+ printf("FAILED\n");
+ delete temp;
+ exit (17);
+ }
+ printf("OK...\n");
+ }
+
+ printf("Testing Get:\n");
+ TestUniChar* myChar;
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Getting entry %s...", gEntities[i].mStr);
+ if (!EntToUniClass.Get(nsDependentCString(gEntities[i].mStr), &myChar)) {
+ printf("FAILED\n");
+ exit (18);
+ }
+
+ printf("Found %c\n", myChar->GetChar());
+ }
+
+ printf("Testing non-existent entries...");
+ if (EntToUniClass.Get(NS_LITERAL_CSTRING("xxxx"), &myChar)) {
+ printf("FOUND! BAD!\n");
+ exit (19);
+ }
+
+ printf("not found; good.\n");
+
+ printf("Enumerating:\n");
+
+ count = EntToUniClass.EnumerateRead(nsCEnumRead, nsnull);
+ if (count != ENTITY_COUNT) {
+ printf(" Bad count!\n");
+ exit (20);
+ }
+
+ printf("Clearing...\n");
+ EntToUniClass.Clear();
+ printf(" Clearing OK\n");
+
+ printf("Checking count...");
+ count = EntToUniClass.Enumerate(nsCEnum, nsnull);
+ if (count) {
+ printf(" Clear did not remove all entries.\n");
+ exit (21);
+ }
+
+ printf("OK\n");
+
+ //
+ // now check a thread-safe class-hashtable
+ //
+
+ nsClassHashtableMT<nsCStringHashKey,TestUniChar> EntToUniClassL;
+
+ printf("Initializing nsClassHashtableMT...");
+ if (!EntToUniClassL.Init(ENTITY_COUNT)) {
+ printf("FAILED\n");
+ exit (16);
+ }
+ printf("OK\n");
+
+ printf("Filling hash with %zd entries.\n", ENTITY_COUNT);
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Putting entry %u...", gEntities[i].mUnicode);
+ TestUniChar* temp = new TestUniChar(gEntities[i].mUnicode);
+
+ if (!EntToUniClassL.Put(nsDependentCString(gEntities[i].mStr), temp)) {
+ printf("FAILED\n");
+ delete temp;
+ exit (17);
+ }
+ printf("OK...\n");
+ }
+
+ printf("Testing Get:\n");
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Getting entry %s...", gEntities[i].mStr);
+ if (!EntToUniClassL.Get(nsDependentCString(gEntities[i].mStr), &myChar)) {
+ printf("FAILED\n");
+ exit (18);
+ }
+
+ printf("Found %c\n", myChar->GetChar());
+ }
+
+ printf("Testing non-existent entries...");
+ if (EntToUniClassL.Get(NS_LITERAL_CSTRING("xxxx"), &myChar)) {
+ printf("FOUND! BAD!\n");
+ exit (19);
+ }
+
+ printf("not found; good.\n");
+
+ printf("Enumerating:\n");
+
+ count = EntToUniClassL.EnumerateRead(nsCEnumRead, nsnull);
+ if (count != ENTITY_COUNT) {
+ printf(" Bad count!\n");
+ exit (20);
+ }
+
+ printf("Clearing...\n");
+ EntToUniClassL.Clear();
+ printf(" Clearing OK\n");
+
+ printf("Checking count...");
+ count = EntToUniClassL.Enumerate(nsCEnum, nsnull);
+ if (count) {
+ printf(" Clear did not remove all entries.\n");
+ exit (21);
+ }
+
+ printf("OK\n");
+
+ //
+ // now check a data-hashtable with an interface key
+ //
+
+ nsDataHashtable<nsISupportsHashKey,PRUint32> EntToUniClass2;
+
+ printf("Initializing nsDataHashtable with interface key...");
+ if (!EntToUniClass2.Init(ENTITY_COUNT)) {
+ printf("FAILED\n");
+ exit (22);
+ }
+ printf("OK\n");
+
+ printf("Filling hash with %zd entries.\n", ENTITY_COUNT);
+
+ nsCOMArray<IFoo> fooArray;
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Putting entry %u...", gEntities[i].mUnicode);
+ nsCOMPtr<IFoo> foo;
+ CreateIFoo(getter_AddRefs(foo));
+ foo->SetString(nsDependentCString(gEntities[i].mStr));
+
+
+ fooArray.InsertObjectAt(foo, i);
+
+ if (!EntToUniClass2.Put(foo, gEntities[i].mUnicode)) {
+ printf("FAILED\n");
+ exit (23);
+ }
+ printf("OK...\n");
+ }
+
+ printf("Testing Get:\n");
+ PRUint32 myChar2;
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Getting entry %s...", gEntities[i].mStr);
+
+ if (!EntToUniClass2.Get(fooArray[i], &myChar2)) {
+ printf("FAILED\n");
+ exit (24);
+ }
+
+ printf("Found %c\n", myChar2);
+ }
+
+ printf("Testing non-existent entries...");
+ if (EntToUniClass2.Get((nsISupports*) 0x55443316, &myChar2)) {
+ printf("FOUND! BAD!\n");
+ exit (25);
+ }
+
+ printf("not found; good.\n");
+
+ printf("Enumerating:\n");
+
+ count = EntToUniClass2.EnumerateRead(nsIEnum2Read, nsnull);
+ if (count != ENTITY_COUNT) {
+ printf(" Bad count!\n");
+ exit (26);
+ }
+
+ printf("Clearing...\n");
+ EntToUniClass2.Clear();
+ printf(" Clearing OK\n");
+
+ printf("Checking count...");
+ count = EntToUniClass2.Enumerate(nsIEnum2, nsnull);
+ if (count) {
+ printf(" Clear did not remove all entries.\n");
+ exit (27);
+ }
+
+ printf("OK\n");
+
+ //
+ // now check an interface-hashtable with an PRUint32 key
+ //
+
+ nsInterfaceHashtable<nsUint32HashKey,IFoo> UniToEntClass2;
+
+ printf("Initializing nsInterfaceHashtable...");
+ if (!UniToEntClass2.Init(ENTITY_COUNT)) {
+ printf("FAILED\n");
+ exit (28);
+ }
+ printf("OK\n");
+
+ printf("Filling hash with %zd entries.\n", ENTITY_COUNT);
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Putting entry %u...", gEntities[i].mUnicode);
+ nsCOMPtr<IFoo> foo;
+ CreateIFoo(getter_AddRefs(foo));
+ foo->SetString(nsDependentCString(gEntities[i].mStr));
+
+ if (!UniToEntClass2.Put(gEntities[i].mUnicode, foo)) {
+ printf("FAILED\n");
+ exit (29);
+ }
+ printf("OK...\n");
+ }
+
+ printf("Testing Get:\n");
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Getting entry %s...", gEntities[i].mStr);
+
+ nsCOMPtr<IFoo> myEnt;
+ if (!UniToEntClass2.Get(gEntities[i].mUnicode, getter_AddRefs(myEnt))) {
+ printf("FAILED\n");
+ exit (30);
+ }
+
+ nsCAutoString str;
+ myEnt->GetString(str);
+ printf("Found %s\n", str.get());
+ }
+
+ printf("Testing non-existent entries...");
+ nsCOMPtr<IFoo> myEnt;
+ if (UniToEntClass2.Get(9462, getter_AddRefs(myEnt))) {
+ printf("FOUND! BAD!\n");
+ exit (31);
+ }
+
+ printf("not found; good.\n");
+
+ printf("Enumerating:\n");
+
+ count = UniToEntClass2.EnumerateRead(nsIEnumRead, nsnull);
+ if (count != ENTITY_COUNT) {
+ printf(" Bad count!\n");
+ exit (32);
+ }
+
+ printf("Clearing...\n");
+ UniToEntClass2.Clear();
+ printf(" Clearing OK\n");
+
+ printf("Checking count...");
+ count = UniToEntClass2.Enumerate(nsIEnum, nsnull);
+ if (count) {
+ printf(" Clear did not remove all entries.\n");
+ exit (33);
+ }
+
+ printf("OK\n");
+
+ //
+ // now check a thread-safe interface hashtable
+ //
+
+ nsInterfaceHashtableMT<nsUint32HashKey,IFoo> UniToEntClass2L;
+
+ printf("Initializing nsInterfaceHashtableMT...");
+ if (!UniToEntClass2L.Init(ENTITY_COUNT)) {
+ printf("FAILED\n");
+ exit (28);
+ }
+ printf("OK\n");
+
+ printf("Filling hash with %zd entries.\n", ENTITY_COUNT);
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Putting entry %u...", gEntities[i].mUnicode);
+ nsCOMPtr<IFoo> foo;
+ CreateIFoo(getter_AddRefs(foo));
+ foo->SetString(nsDependentCString(gEntities[i].mStr));
+
+ if (!UniToEntClass2L.Put(gEntities[i].mUnicode, foo)) {
+ printf("FAILED\n");
+ exit (29);
+ }
+ printf("OK...\n");
+ }
+
+ printf("Testing Get:\n");
+
+ for (i = 0; i < ENTITY_COUNT; ++i) {
+ printf(" Getting entry %s...", gEntities[i].mStr);
+
+ nsCOMPtr<IFoo> myEnt;
+ if (!UniToEntClass2L.Get(gEntities[i].mUnicode, getter_AddRefs(myEnt))) {
+ printf("FAILED\n");
+ exit (30);
+ }
+
+ nsCAutoString str;
+ myEnt->GetString(str);
+ printf("Found %s\n", str.get());
+ }
+
+ printf("Testing non-existent entries...");
+ if (UniToEntClass2L.Get(9462, getter_AddRefs(myEnt))) {
+ printf("FOUND! BAD!\n");
+ exit (31);
+ }
+
+ printf("not found; good.\n");
+
+ printf("Enumerating:\n");
+
+ count = UniToEntClass2L.EnumerateRead(nsIEnumRead, nsnull);
+ if (count != ENTITY_COUNT) {
+ printf(" Bad count!\n");
+ exit (32);
+ }
+
+ printf("Clearing...\n");
+ UniToEntClass2L.Clear();
+ printf(" Clearing OK\n");
+
+ printf("Checking count...");
+ count = UniToEntClass2L.Enumerate(nsIEnum, nsnull);
+ if (count) {
+ printf(" Clear did not remove all entries.\n");
+ exit (33);
+ }
+
+ printf("OK\n");
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestID.cpp b/src/libs/xpcom18a4/xpcom/tests/TestID.cpp
new file mode 100644
index 00000000..f91fda9f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestID.cpp
@@ -0,0 +1,77 @@
+/* -*- 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 <stdio.h>
+#include "plstr.h"
+#include "nsID.h"
+#include "prmem.h"
+
+static const char* const ids[] = {
+ "5C347B10-D55C-11D1-89B7-006008911B81",
+ "{5C347B10-D55C-11D1-89B7-006008911B81}",
+ "5c347b10-d55c-11d1-89b7-006008911b81",
+ "{5c347b10-d55c-11d1-89b7-006008911b81}",
+
+ "FC347B10-D55C-F1D1-F9B7-006008911B81",
+ "{FC347B10-D55C-F1D1-F9B7-006008911B81}",
+ "fc347b10-d55c-f1d1-f9b7-006008911b81",
+ "{fc347b10-d55c-f1d1-f9b7-006008911b81}",
+};
+#define NUM_IDS ((int) (sizeof(ids) / sizeof(ids[0])))
+
+int main(int argc, char** argv)
+{
+ nsID id;
+ for (int i = 0; i < NUM_IDS; i++) {
+ const char* idstr = ids[i];
+ if (!id.Parse(idstr)) {
+ fprintf(stderr, "TestID: Parse failed on test #%d\n", i);
+ return -1;
+ }
+ char* cp = id.ToString();
+ if (NULL == cp) {
+ fprintf(stderr, "TestID: ToString failed on test #%d\n", i);
+ return -1;
+ }
+ if (0 != PL_strcmp(cp, ids[4*(i/4) + 3])) {
+ fprintf(stderr, "TestID: compare of ToString failed on test #%d\n", i);
+ return -1;
+ }
+ PR_Free(cp);
+ }
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestMinStringAPI.cpp b/src/libs/xpcom18a4/xpcom/tests/TestMinStringAPI.cpp
new file mode 100644
index 00000000..811df138
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestMinStringAPI.cpp
@@ -0,0 +1,333 @@
+/* vim:set ts=2 sw=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 <stdio.h>
+#include "nsStringAPI.h"
+#include "nsCRT.h"
+
+static const char kAsciiData[] = "hello world";
+
+static const PRUnichar kUnicodeData[] =
+ {'h','e','l','l','o',' ','w','o','r','l','d','\0'};
+
+static PRBool test_basic_1()
+ {
+ nsCStringContainer s;
+ NS_CStringContainerInit(s);
+
+ const char *ptr;
+ PRUint32 len;
+ char *clone;
+
+ NS_CStringGetData(s, &ptr);
+ if (ptr == nsnull || *ptr != '\0')
+ {
+ NS_ERROR("unexpected result");
+ return PR_FALSE;
+ }
+
+ NS_CStringSetData(s, kAsciiData, PR_UINT32_MAX);
+ len = NS_CStringGetData(s, &ptr);
+ if (ptr == nsnull || strcmp(ptr, kAsciiData) != 0)
+ {
+ NS_ERROR("unexpected result");
+ return PR_FALSE;
+ }
+ if (len != sizeof(kAsciiData)-1)
+ {
+ NS_ERROR("unexpected result");
+ return PR_FALSE;
+ }
+
+ clone = NS_CStringCloneData(s);
+ if (ptr == nsnull || strcmp(ptr, kAsciiData) != 0)
+ {
+ NS_ERROR("unexpected result");
+ return PR_FALSE;
+ }
+ nsMemory::Free(clone);
+
+ nsCStringContainer temp;
+ NS_CStringContainerInit(temp);
+ NS_CStringCopy(temp, s);
+
+ len = NS_CStringGetData(temp, &ptr);
+ if (ptr == nsnull || strcmp(ptr, kAsciiData) != 0)
+ {
+ NS_ERROR("unexpected result");
+ return PR_FALSE;
+ }
+ if (len != sizeof(kAsciiData)-1)
+ {
+ NS_ERROR("unexpected result");
+ return PR_FALSE;
+ }
+
+ NS_CStringContainerFinish(temp);
+
+ NS_CStringContainerFinish(s);
+ return PR_TRUE;
+ }
+
+static PRBool test_basic_2()
+ {
+ nsStringContainer s;
+ NS_StringContainerInit(s);
+
+ const PRUnichar *ptr;
+ PRUint32 len;
+ PRUnichar *clone;
+
+ NS_StringGetData(s, &ptr);
+ if (ptr == nsnull || *ptr != '\0')
+ {
+ NS_ERROR("unexpected result");
+ return PR_FALSE;
+ }
+
+ NS_StringSetData(s, kUnicodeData, PR_UINT32_MAX);
+ len = NS_StringGetData(s, &ptr);
+ if (ptr == nsnull || nsCRT::strcmp(ptr, kUnicodeData) != 0)
+ {
+ NS_ERROR("unexpected result");
+ return PR_FALSE;
+ }
+ if (len != sizeof(kUnicodeData)/2 - 1)
+ {
+ NS_ERROR("unexpected result");
+ return PR_FALSE;
+ }
+
+ clone = NS_StringCloneData(s);
+ if (ptr == nsnull || nsCRT::strcmp(ptr, kUnicodeData) != 0)
+ {
+ NS_ERROR("unexpected result");
+ return PR_FALSE;
+ }
+ nsMemory::Free(clone);
+
+ nsStringContainer temp;
+ NS_StringContainerInit(temp);
+ NS_StringCopy(temp, s);
+
+ len = NS_StringGetData(temp, &ptr);
+ if (ptr == nsnull || nsCRT::strcmp(ptr, kUnicodeData) != 0)
+ {
+ NS_ERROR("unexpected result");
+ return PR_FALSE;
+ }
+ if (len != sizeof(kUnicodeData)/2 - 1)
+ {
+ NS_ERROR("unexpected result");
+ return PR_FALSE;
+ }
+
+ NS_StringContainerFinish(temp);
+
+ NS_StringContainerFinish(s);
+
+ return PR_TRUE;
+ }
+
+static PRBool test_convert()
+ {
+ nsStringContainer s;
+ NS_StringContainerInit(s);
+ NS_StringSetData(s, kUnicodeData, sizeof(kUnicodeData)/2 - 1);
+
+ nsCStringContainer temp;
+ NS_CStringContainerInit(temp);
+
+ const char *data;
+
+ NS_UTF16ToCString(s, NS_CSTRING_ENCODING_ASCII, temp);
+ NS_CStringGetData(temp, &data);
+ if (strcmp(data, kAsciiData) != 0)
+ return PR_FALSE;
+
+ NS_UTF16ToCString(s, NS_CSTRING_ENCODING_UTF8, temp);
+ NS_CStringGetData(temp, &data);
+ if (strcmp(data, kAsciiData) != 0)
+ return PR_FALSE;
+
+ NS_CStringContainerFinish(temp);
+
+ NS_StringContainerFinish(s);
+ return PR_TRUE;
+ }
+
+static PRBool test_append()
+ {
+ nsCStringContainer s;
+ NS_CStringContainerInit(s);
+
+ NS_CStringSetData(s, "foo");
+ NS_CStringAppendData(s, "bar");
+
+ NS_CStringContainerFinish(s);
+ return PR_TRUE;
+ }
+
+// Replace all occurances of |matchVal| with |newVal|
+static void ReplaceSubstring( nsACString& str,
+ const nsACString& matchVal,
+ const nsACString& newVal )
+ {
+ const char* sp, *mp, *np;
+ PRUint32 sl, ml, nl;
+
+ sl = NS_CStringGetData(str, &sp);
+ ml = NS_CStringGetData(matchVal, &mp);
+ nl = NS_CStringGetData(newVal, &np);
+
+ for (const char* iter = sp; iter <= sp + sl - ml; ++iter)
+ {
+ if (memcmp(iter, mp, ml) == 0)
+ {
+ PRUint32 offset = iter - sp;
+
+ NS_CStringSetDataRange(str, offset, ml, np, nl);
+
+ sl = NS_CStringGetData(str, &sp);
+
+ iter = sp + offset + nl - 1;
+ }
+ }
+ }
+
+static PRBool test_replace_driver(const char *strVal,
+ const char *matchVal,
+ const char *newVal,
+ const char *finalVal)
+ {
+ nsCStringContainer a;
+ NS_CStringContainerInit(a);
+ NS_CStringSetData(a, strVal);
+
+ nsCStringContainer b;
+ NS_CStringContainerInit(b);
+ NS_CStringSetData(b, matchVal);
+
+ nsCStringContainer c;
+ NS_CStringContainerInit(c);
+ NS_CStringSetData(c, newVal);
+
+ ReplaceSubstring(a, b, c);
+
+ const char *data;
+ NS_CStringGetData(a, &data);
+ if (strcmp(data, finalVal) != 0)
+ return PR_FALSE;
+
+ NS_CStringContainerFinish(c);
+ NS_CStringContainerFinish(b);
+ NS_CStringContainerFinish(a);
+ return PR_TRUE;
+ }
+
+static PRBool test_replace()
+ {
+ PRBool rv;
+
+ rv = test_replace_driver("hello world, hello again!",
+ "hello",
+ "goodbye",
+ "goodbye world, goodbye again!");
+ if (!rv)
+ return rv;
+
+ rv = test_replace_driver("foofoofoofoo!",
+ "foo",
+ "bar",
+ "barbarbarbar!");
+ if (!rv)
+ return rv;
+
+ rv = test_replace_driver("foo bar systems",
+ "xyz",
+ "crazy",
+ "foo bar systems");
+ if (!rv)
+ return rv;
+
+ rv = test_replace_driver("oh",
+ "xyz",
+ "crazy",
+ "oh");
+ if (!rv)
+ return rv;
+
+ return PR_TRUE;
+ }
+
+//----
+
+typedef PRBool (*TestFunc)();
+
+static const struct Test
+ {
+ const char* name;
+ TestFunc func;
+ }
+tests[] =
+ {
+ { "test_basic_1", test_basic_1 },
+ { "test_basic_2", test_basic_2 },
+ { "test_convert", test_convert },
+ { "test_append", test_append },
+ { "test_replace", test_replace },
+ { nsnull, nsnull }
+ };
+
+//----
+
+int main(int argc, char **argv)
+ {
+ int count = 1;
+ if (argc > 1)
+ count = atoi(argv[1]);
+
+ while (count--)
+ {
+ for (const Test* t = tests; t->name != nsnull; ++t)
+ {
+ printf("%25s : %s\n", t->name, t->func() ? "SUCCESS" : "FAILURE");
+ }
+ }
+
+ return 0;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestObserverService.cpp b/src/libs/xpcom18a4/xpcom/tests/TestObserverService.cpp
new file mode 100644
index 00000000..148400e2
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestObserverService.cpp
@@ -0,0 +1,250 @@
+/* -*- 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 "nsISupports.h"
+#include "nsIComponentManager.h"
+#include "nsIObserverService.h"
+#include "nsIObserver.h"
+#include "nsIEnumerator.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+#include "prprf.h"
+#include "nsWeakReference.h"
+
+static nsIObserverService *anObserverService = NULL;
+
+#ifdef VBOX
+static bool testResult( nsresult rv ) {
+ if ( NS_SUCCEEDED( rv ) ) {
+ printf("...ok\n");
+ return true;
+ }
+ printf("...failed, rv=0x%x\n", (int)rv);
+ return false;
+}
+#else
+static void testResult( nsresult rv ) {
+ if ( NS_SUCCEEDED( rv ) ) {
+ printf("...ok\n");
+ } else {
+ printf("...failed, rv=0x%x\n", (int)rv);
+ }
+ return;
+}
+#endif
+
+void printString(nsString &str) {
+#ifdef VBOX /* asan complains about mixing different allocators */
+ char *cstr = ToNewCString(str);
+ printf("%s", cstr);
+ nsMemory::Free(cstr);
+#else
+ const char *cstr = ToNewCString(str);
+ printf("%s", cstr);
+ delete [] (char*)cstr;
+#endif
+}
+
+class TestObserver : public nsIObserver, public nsSupportsWeakReference {
+public:
+ TestObserver( const nsAString &name )
+ : mName( name ) {
+ }
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIOBSERVER
+
+ nsString mName;
+
+private:
+ ~TestObserver() {}
+};
+
+NS_IMPL_ISUPPORTS2( TestObserver, nsIObserver, nsISupportsWeakReference )
+
+NS_IMETHODIMP
+TestObserver::Observe( nsISupports *aSubject,
+ const char *aTopic,
+ const PRUnichar *someData ) {
+ nsCString topic( aTopic );
+ nsString data( someData );
+ /*
+ The annoying double-cast below is to work around an annoying bug in
+ the compiler currently used on wensleydale. This is a test.
+ */
+ printString(mName);
+ printf(" has observed something: subject@%p", (void*)aSubject);
+ printf(" name=");
+ printString(NS_REINTERPRET_CAST(TestObserver*, NS_REINTERPRET_CAST(void*, aSubject))->mName);
+ printf(" aTopic=%s", topic.get());
+ printf(" someData=");
+ printString(data);
+ printf("\n");
+ return NS_OK;
+}
+
+int main(int argc, char *argv[])
+{
+ nsCString topicA; topicA.Assign( "topic-A" );
+ nsCString topicB; topicB.Assign( "topic-B" );
+ nsresult rv;
+
+ nsresult res = nsComponentManager::CreateInstance("@mozilla.org/observer-service;1",
+ NULL,
+ NS_GET_IID(nsIObserverService),
+ (void **) &anObserverService);
+#ifdef VBOX
+ bool fSuccess = res == NS_OK;
+#endif
+
+ if (res == NS_OK) {
+
+ nsIObserver *aObserver = new TestObserver(NS_LITERAL_STRING("Observer-A"));
+ aObserver->AddRef();
+ nsIObserver *bObserver = new TestObserver(NS_LITERAL_STRING("Observer-B"));
+ bObserver->AddRef();
+
+ printf("Adding Observer-A as observer of topic-A...\n");
+ rv = anObserverService->AddObserver(aObserver, topicA.get(), PR_FALSE);
+#ifdef VBOX
+ fSuccess = fSuccess &&
+#endif
+ testResult(rv);
+
+ printf("Adding Observer-B as observer of topic-A...\n");
+ rv = anObserverService->AddObserver(bObserver, topicA.get(), PR_FALSE);
+#ifdef VBOX
+ fSuccess = fSuccess &&
+#endif
+ testResult(rv);
+
+ printf("Adding Observer-B as observer of topic-B...\n");
+ rv = anObserverService->AddObserver(bObserver, topicB.get(), PR_FALSE);
+#ifdef VBOX
+ fSuccess = fSuccess &&
+#endif
+ testResult(rv);
+
+ printf("Testing Notify(observer-A, topic-A)...\n");
+ rv = anObserverService->NotifyObservers( aObserver,
+ topicA.get(),
+ NS_LITERAL_STRING("Testing Notify(observer-A, topic-A)").get() );
+#ifdef VBOX
+ fSuccess = fSuccess &&
+#endif
+ testResult(rv);
+
+ printf("Testing Notify(observer-B, topic-B)...\n");
+ rv = anObserverService->NotifyObservers( bObserver,
+ topicB.get(),
+ NS_LITERAL_STRING("Testing Notify(observer-B, topic-B)").get() );
+#ifdef VBOX
+ fSuccess = fSuccess &&
+#endif
+ testResult(rv);
+
+ printf("Testing EnumerateObserverList (for topic-A)...\n");
+ nsCOMPtr<nsISimpleEnumerator> e;
+ rv = anObserverService->EnumerateObservers(topicA.get(), getter_AddRefs(e));
+
+#ifdef VBOX
+ fSuccess = fSuccess &&
+#endif
+ testResult(rv);
+
+ printf("Enumerating observers of topic-A...\n");
+ if ( e ) {
+ nsCOMPtr<nsIObserver> observer;
+ PRBool loop = PR_TRUE;
+ while( NS_SUCCEEDED(e->HasMoreElements(&loop)) && loop)
+ {
+ e->GetNext(getter_AddRefs(observer));
+ printf("Calling observe on enumerated observer ");
+ printString(NS_REINTERPRET_CAST(TestObserver*,
+ NS_REINTERPRET_CAST(void*, observer.get()))->mName);
+ printf("...\n");
+ rv = observer->Observe( observer,
+ topicA.get(),
+ NS_LITERAL_STRING("during enumeration").get() );
+#ifdef VBOX
+ fSuccess = fSuccess &&
+#endif
+ testResult(rv);
+ }
+ }
+ printf("...done enumerating observers of topic-A\n");
+
+ printf("Removing Observer-A...\n");
+ rv = anObserverService->RemoveObserver(aObserver, topicA.get());
+#ifdef VBOX
+ fSuccess = fSuccess &&
+#endif
+ testResult(rv);
+
+
+ printf("Removing Observer-B (topic-A)...\n");
+ rv = anObserverService->RemoveObserver(bObserver, topicB.get());
+#ifdef VBOX
+ fSuccess = fSuccess &&
+#endif
+ testResult(rv);
+ printf("Removing Observer-B (topic-B)...\n");
+ rv = anObserverService->RemoveObserver(bObserver, topicA.get());
+#ifdef VBOX
+ fSuccess = fSuccess &&
+#endif
+ testResult(rv);
+
+#ifdef VBOX
+ /* Cleanup: */
+ nsrefcnt refs = bObserver->Release();
+ fSuccess = fSuccess && refs == 0;
+ if (refs != 0)
+ printf("bObserver->Release() -> %d, expected 0\n", (int)refs);
+
+ refs = aObserver->Release();
+ fSuccess = fSuccess && refs == 0;
+ if (refs != 0)
+ printf("aObserver->Release() -> %d, expected 0\n", (int)refs);
+#endif
+ }
+#ifdef VBOX
+ return fSuccess ? 0 : 1;
+#else
+ return NS_OK;
+#endif
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestPermanentAtoms.cpp b/src/libs/xpcom18a4/xpcom/tests/TestPermanentAtoms.cpp
new file mode 100644
index 00000000..09b0b2e9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestPermanentAtoms.cpp
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+// vim:cindent:ts=8:et:sw=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 TestPermanentAtoms.cpp.
+ *
+ * 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):
+ * L. David Baron <dbaron@dbaron.org> (original author)
+ *
+ * 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 "nsIAtom.h"
+#include "nsAtomTable.h"
+#include "nsCOMPtr.h"
+#include <stdio.h>
+#include "nsString.h"
+#include "nsReadableUtils.h"
+
+static void Assert(PRBool aCondition, const char* aStatement)
+{
+ printf("%s: %s\n", aCondition?"PASS":"FAIL", aStatement);
+}
+
+static void AssertString(nsIAtom *aAtom, const nsACString& aString)
+{
+ const char *str;
+ NS_STATIC_CAST(AtomImpl*,aAtom)->GetUTF8String(&str);
+ Assert(nsDependentCString(str) == aString, "string is correct");
+}
+
+static void AssertPermanence(nsIAtom *aAtom, PRBool aPermanence)
+{
+ Assert(NS_STATIC_CAST(AtomImpl*,aAtom)->IsPermanent() == aPermanence,
+ aPermanence ? "atom is permanent" : "atom is not permanent");
+}
+
+int main()
+{
+ nsCOMPtr<nsIAtom> foo = do_GetAtom("foo");
+ AssertString(foo, NS_LITERAL_CSTRING("foo"));
+ AssertPermanence(foo, PR_FALSE);
+
+ nsCOMPtr<nsIAtom> foop = do_GetPermanentAtom("foo");
+ AssertString(foop, NS_LITERAL_CSTRING("foo"));
+ AssertPermanence(foop, PR_TRUE);
+
+ Assert(foo == foop, "atoms are equal");
+
+ nsCOMPtr<nsIAtom> barp = do_GetPermanentAtom("bar");
+ AssertString(barp, NS_LITERAL_CSTRING("bar"));
+ AssertPermanence(barp, PR_TRUE);
+
+ nsCOMPtr<nsIAtom> bar = do_GetAtom("bar");
+ AssertString(bar, NS_LITERAL_CSTRING("bar"));
+ AssertPermanence(bar, PR_TRUE);
+
+ Assert(bar == barp, "atoms are equal");
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestPipes.cpp b/src/libs/xpcom18a4/xpcom/tests/TestPipes.cpp
new file mode 100644
index 00000000..2d798a5b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestPipes.cpp
@@ -0,0 +1,655 @@
+/* -*- 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):
+ * 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 "nsIThread.h"
+#include "nsIRunnable.h"
+#include "nsIInputStream.h"
+#include "nsIOutputStream.h"
+#include "nsIServiceManager.h"
+#include "prprf.h"
+#include "prinrval.h"
+#include "plstr.h"
+#include "nsCRT.h"
+#include "nsCOMPtr.h"
+#include <stdio.h>
+#include "nsIPipe.h" // new implementation
+#include "nsAutoLock.h"
+#include <stdlib.h> // for rand
+
+#define KEY 0xa7
+#define ITERATIONS 33333
+char kTestPattern[] = "My hovercraft is full of eels.\n";
+
+PRBool gTrace = PR_FALSE;
+
+static nsresult
+WriteAll(nsIOutputStream *os, const char *buf, PRUint32 bufLen, PRUint32 *lenWritten)
+{
+ const char *p = buf;
+ *lenWritten = 0;
+ while (bufLen) {
+ PRUint32 n;
+ nsresult rv = os->Write(p, bufLen, &n);
+ if (NS_FAILED(rv)) return rv;
+ p += n;
+ bufLen -= n;
+ *lenWritten += n;
+ }
+ return NS_OK;
+}
+
+class nsReceiver : public nsIRunnable {
+public:
+ NS_DECL_ISUPPORTS
+
+ NS_IMETHOD Run() {
+ nsresult rv;
+ char buf[101];
+ PRUint32 count;
+ PRIntervalTime start = PR_IntervalNow();
+ while (PR_TRUE) {
+ rv = mIn->Read(buf, 100, &count);
+ if (NS_FAILED(rv)) {
+ printf("read failed\n");
+ break;
+ }
+ if (count == 0) {
+// printf("EOF count = %d\n", mCount);
+ break;
+ }
+
+ if (gTrace) {
+ printf("read: ");
+ buf[count] = '\0';
+ printf(buf);
+ printf("\n");
+ }
+ mCount += count;
+ }
+ PRIntervalTime end = PR_IntervalNow();
+ printf("read %d bytes, time = %dms\n", mCount,
+ PR_IntervalToMilliseconds(end - start));
+ return rv;
+ }
+
+ nsReceiver(nsIInputStream* in) : mIn(in), mCount(0) {
+ NS_ADDREF(in);
+ }
+
+ PRUint32 GetBytesRead() { return mCount; }
+
+private:
+ ~nsReceiver() {
+ NS_RELEASE(mIn);
+ }
+
+protected:
+ nsIInputStream* mIn;
+ PRUint32 mCount;
+};
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsReceiver, nsIRunnable)
+
+nsresult
+TestPipe(nsIInputStream* in, nsIOutputStream* out)
+{
+ nsresult rv;
+ nsIThread* thread;
+ nsReceiver* receiver = new nsReceiver(in);
+ if (receiver == nsnull) return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(receiver);
+
+ rv = NS_NewThread(&thread, receiver, 0, PR_JOINABLE_THREAD);
+ if (NS_FAILED(rv)) return rv;
+
+ PRUint32 total = 0;
+ PRIntervalTime start = PR_IntervalNow();
+ for (PRUint32 i = 0; i < ITERATIONS; i++) {
+ PRUint32 writeCount;
+ char *buf = PR_smprintf("%d %s", i, kTestPattern);
+ PRUint32 len = strlen(buf);
+ rv = WriteAll(out, buf, len, &writeCount);
+ if (gTrace) {
+ printf("wrote: ");
+ for (PRUint32 j = 0; j < writeCount; j++) {
+ putc(buf[j], stdout);
+ }
+ printf("\n");
+ }
+ PR_smprintf_free(buf);
+ if (NS_FAILED(rv)) return rv;
+ total += writeCount;
+ }
+ rv = out->Close();
+ if (NS_FAILED(rv)) return rv;
+
+ PRIntervalTime end = PR_IntervalNow();
+
+ thread->Join();
+
+ printf("wrote %d bytes, time = %dms\n", total,
+ PR_IntervalToMilliseconds(end - start));
+ NS_ASSERTION(receiver->GetBytesRead() == total, "didn't read everything");
+
+ NS_RELEASE(thread);
+ NS_RELEASE(receiver);
+
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+class nsShortReader : public nsIRunnable {
+public:
+ NS_DECL_ISUPPORTS
+
+ NS_IMETHOD Run() {
+ nsresult rv;
+ char buf[101];
+ PRUint32 count;
+ PRUint32 total = 0;
+ while (PR_TRUE) {
+ //if (gTrace)
+ // printf("calling Read\n");
+ rv = mIn->Read(buf, 100, &count);
+ if (NS_FAILED(rv)) {
+ printf("read failed\n");
+ break;
+ }
+ if (count == 0) {
+ break;
+ }
+ buf[count] = '\0';
+ if (gTrace)
+ printf("read %d bytes: %s\n", count, buf);
+ Received(count);
+ total += count;
+ }
+ printf("read %d bytes\n", total);
+ return rv;
+ }
+
+ nsShortReader(nsIInputStream* in) : mIn(in), mReceived(0) {
+ NS_ADDREF(in);
+ }
+
+ void Received(PRUint32 count) {
+ nsAutoCMonitor mon(this);
+ mReceived += count;
+ mon.Notify();
+ }
+
+ PRUint32 WaitForReceipt() {
+ nsAutoCMonitor mon(this);
+ PRUint32 result = mReceived;
+ while (result == 0) {
+ mon.Wait();
+ NS_ASSERTION(mReceived >= 0, "failed to receive");
+ result = mReceived;
+ }
+ mReceived = 0;
+ return result;
+ }
+
+private:
+ ~nsShortReader() {
+ NS_RELEASE(mIn);
+ }
+
+protected:
+ nsIInputStream* mIn;
+ PRUint32 mReceived;
+};
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsShortReader, nsIRunnable)
+
+nsresult
+TestShortWrites(nsIInputStream* in, nsIOutputStream* out)
+{
+ nsresult rv;
+ nsIThread* thread;
+ nsShortReader* receiver = new nsShortReader(in);
+ if (receiver == nsnull) return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(receiver);
+
+ rv = NS_NewThread(&thread, receiver, 0, PR_JOINABLE_THREAD);
+ if (NS_FAILED(rv)) return rv;
+
+ PRUint32 total = 0;
+ for (PRUint32 i = 0; i < ITERATIONS; i++) {
+ PRUint32 writeCount;
+ char* buf = PR_smprintf("%d %s", i, kTestPattern);
+ PRUint32 len = strlen(buf);
+ len = len * rand() / RAND_MAX;
+ len = PR_MAX(1, len);
+ rv = WriteAll(out, buf, len, &writeCount);
+ if (NS_FAILED(rv)) return rv;
+ NS_ASSERTION(writeCount == len, "didn't write enough");
+ total += writeCount;
+
+ if (gTrace)
+ printf("wrote %d bytes: %s\n", writeCount, buf);
+ PR_smprintf_free(buf);
+ //printf("calling Flush\n");
+ out->Flush();
+ //printf("calling WaitForReceipt\n");
+ PRUint32 received = receiver->WaitForReceipt();
+ NS_ASSERTION(received == writeCount, "received wrong amount");
+ }
+ rv = out->Close();
+ if (NS_FAILED(rv)) return rv;
+
+ thread->Join();
+ printf("wrote %d bytes\n", total);
+
+ NS_RELEASE(thread);
+ NS_RELEASE(receiver);
+
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+#if 0
+
+class nsPipeObserver : public nsIInputStreamObserver,
+ public nsIOutputStreamObserver
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ NS_IMETHOD OnFull(nsIOutputStream *outStr) {
+ printf("OnFull outStr=%p\n", outStr);
+ return NS_OK;
+ }
+
+ NS_IMETHOD OnWrite(nsIOutputStream *outStr, PRUint32 amount) {
+ printf("OnWrite outStr=%p amount=%d\n", outStr, amount);
+ return NS_OK;
+ }
+
+ NS_IMETHOD OnEmpty(nsIInputStream* inStr) {
+ printf("OnEmpty inStr=%p\n", inStr);
+ return NS_OK;
+ }
+
+ NS_IMETHOD OnClose(nsIInputStream* inStr) {
+ printf("OnClose inStr=%p\n", inStr);
+ return NS_OK;
+ }
+
+ nsPipeObserver() { }
+
+private:
+ ~nsPipeObserver() {}
+};
+
+NS_IMPL_ISUPPORTS2(nsPipeObserver, nsIInputStreamObserver, nsIOutputStreamObserver)
+
+nsresult
+TestPipeObserver()
+{
+ nsresult rv;
+ nsPipeObserver* obs = new nsPipeObserver();
+ if (obs == nsnull) return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(obs);
+
+ printf("TestPipeObserver: OnWrite and OnFull should be called once, OnEmpty should be called twice.\n");
+ nsIInputStream* in;
+ nsIOutputStream* out;
+ rv = NS_NewPipe(&in, &out, 18, 36, PR_TRUE, PR_TRUE);
+ if (NS_FAILED(rv)) return rv;
+
+ nsCOMPtr<nsIObservableInputStream> observableIn(do_QueryInterface(in, &rv));
+ if (NS_FAILED(rv)) return rv;
+ nsCOMPtr<nsIObservableInputStream> observableOut(do_QueryInterface(out, &rv));
+ if (NS_FAILED(rv)) return rv;
+
+ rv = observableIn->SetObserver(obs);
+ if (NS_FAILED(rv)) return rv;
+ rv = observableOut->SetObserver(obs);
+ if (NS_FAILED(rv)) return rv;
+
+ char buf[] = "puirt a beul: a style of Gaelic vocal music intended for dancing.";
+ PRUint32 cnt;
+ printf("> should see OnWrite message:\n");
+ rv = out->Write(buf, 20, &cnt);
+ if (NS_FAILED(rv)) return rv;
+ NS_ASSERTION(cnt == 20, "Write failed");
+
+ printf("> should see OnWrite message followed by OnFull message:\n");
+ rv = out->Write(buf + 20, 20, &cnt);
+ if (NS_FAILED(rv)) return rv;
+ NS_ASSERTION(cnt == 16, "Write failed");
+
+ rv = in->Available(&cnt);
+ if (NS_FAILED(rv)) return rv;
+ printf("available = %u\n", cnt);
+ NS_ASSERTION(cnt == 36, "Available failed");
+
+ char buf2[40];
+ printf("> should see OnEmpty message:\n");
+ rv = in->Read(buf2, 40, &cnt);
+ if (NS_FAILED(rv)) return rv;
+ printf("cnt = %u\n", cnt);
+ NS_ASSERTION(cnt == 36, "Read failed");
+ NS_ASSERTION(nsCRT::strncmp(buf, buf2, 36) == 0, "Read wrong stuff");
+
+ rv = in->Available(&cnt);
+ if (NS_FAILED(rv)) return rv;
+ printf("available = %u\n", cnt);
+ NS_ASSERTION(cnt == 0, "Available failed");
+
+ printf("> should see OnEmpty message:\n");
+ rv = in->Read(buf2, 2, &cnt);
+ if (NS_FAILED(rv) && rv != NS_BASE_STREAM_WOULD_BLOCK) return rv;
+ NS_ASSERTION(cnt == 0 && rv == NS_BASE_STREAM_WOULD_BLOCK, "Read failed");
+
+ printf("> should see OnWrite message:\n");
+ rv = out->Write(buf, 20, &cnt);
+ if (NS_FAILED(rv)) return rv;
+ NS_ASSERTION(cnt == 20, "Write failed");
+
+ rv = in->Available(&cnt);
+ if (NS_FAILED(rv)) return rv;
+ printf("available = %u\n", cnt);
+ NS_ASSERTION(cnt == 20, "Available failed");
+
+ printf("> should see OnEmpty message:\n");
+ rv = in->Read(buf2, 20, &cnt);
+ if (NS_FAILED(rv)) return rv;
+ NS_ASSERTION(cnt == 20, "Read failed");
+
+ printf("> should see OnClose message:\n");
+ NS_RELEASE(obs);
+ NS_RELEASE(in);
+ NS_RELEASE(out);
+ return NS_OK;
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+
+class nsPump : public nsIRunnable
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ NS_IMETHOD Run() {
+ nsresult rv;
+ PRUint32 count;
+ while (PR_TRUE) {
+ nsAutoCMonitor mon(this);
+ rv = mOut->WriteFrom(mIn, ~0U, &count);
+ if (NS_FAILED(rv)) {
+ printf("Write failed\n");
+ break;
+ }
+ if (count == 0) {
+ printf("EOF count = %d\n", mCount);
+ break;
+ }
+
+ if (gTrace) {
+ printf("Wrote: %d\n", count);
+ }
+ mCount += count;
+ }
+ mOut->Close();
+ return rv;
+ }
+
+ nsPump(nsIInputStream* in,
+ nsIOutputStream* out)
+ : mIn(in), mOut(out), mCount(0) {
+ }
+
+private:
+ ~nsPump() {}
+
+protected:
+ nsCOMPtr<nsIInputStream> mIn;
+ nsCOMPtr<nsIOutputStream> mOut;
+ PRUint32 mCount;
+};
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsPump,
+ nsIRunnable)
+
+nsresult
+TestChainedPipes()
+{
+ nsresult rv;
+ printf("TestChainedPipes\n");
+
+ nsIInputStream* in1;
+ nsIOutputStream* out1;
+ rv = NS_NewPipe(&in1, &out1, 20, 1999);
+ if (NS_FAILED(rv)) return rv;
+
+ nsIInputStream* in2;
+ nsIOutputStream* out2;
+ rv = NS_NewPipe(&in2, &out2, 200, 401);
+ if (NS_FAILED(rv)) return rv;
+
+ nsIThread* thread;
+ nsPump* pump = new nsPump(in1, out2);
+ if (pump == nsnull) return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(pump);
+
+ rv = NS_NewThread(&thread, pump, 0, PR_JOINABLE_THREAD);
+ if (NS_FAILED(rv)) return rv;
+
+ nsIThread* receiverThread;
+ nsReceiver* receiver = new nsReceiver(in2);
+ if (receiver == nsnull) return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(receiver);
+
+ rv = NS_NewThread(&receiverThread, receiver, 0, PR_JOINABLE_THREAD);
+ if (NS_FAILED(rv)) return rv;
+
+ PRUint32 total = 0;
+ for (PRUint32 i = 0; i < ITERATIONS; i++) {
+ PRUint32 writeCount;
+ char* buf = PR_smprintf("%d %s", i, kTestPattern);
+ PRUint32 len = strlen(buf);
+ len = len * rand() / RAND_MAX;
+ len = PR_MAX(1, len);
+ rv = WriteAll(out1, buf, len, &writeCount);
+ if (NS_FAILED(rv)) return rv;
+ NS_ASSERTION(writeCount == len, "didn't write enough");
+ total += writeCount;
+
+ if (gTrace)
+ printf("wrote %d bytes: %s\n", writeCount, buf);
+
+ PR_smprintf_free(buf);
+ }
+ printf("wrote total of %d bytes\n", total);
+ rv = out1->Close();
+ if (NS_FAILED(rv)) return rv;
+
+ thread->Join();
+ receiverThread->Join();
+
+ NS_RELEASE(thread);
+ NS_RELEASE(pump);
+ NS_RELEASE(receiverThread);
+ NS_RELEASE(receiver);
+ NS_RELEASE(out2);
+ NS_RELEASE(in2);
+ NS_RELEASE(in1);
+ NS_RELEASE(out1);
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void
+RunTests(PRUint32 segSize, PRUint32 segCount)
+{
+ nsresult rv;
+ nsIInputStream* in = 0; /* bird: initialize to quiet gcc. */
+ nsIOutputStream* out = 0; /* ditto */
+ PRUint32 bufSize;
+
+ bufSize = segSize * segCount;
+ printf("Testing New Pipes: segment size %d buffer size %d\n", segSize, bufSize);
+
+ printf("Testing long writes...\n");
+ rv = NS_NewPipe(&in, &out, segSize, bufSize);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "NS_NewPipe failed");
+ rv = TestPipe(in, out);
+ NS_RELEASE(in);
+ NS_RELEASE(out);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "TestPipe failed");
+
+ printf("Testing short writes...\n");
+ rv = NS_NewPipe(&in, &out, segSize, bufSize);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "NS_NewPipe failed");
+ rv = TestShortWrites(in, out);
+ NS_RELEASE(in);
+ NS_RELEASE(out);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "TestPipe failed");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+#if 0
+void
+TestSearch(const char* delim, PRUint32 segSize)
+{
+ nsresult rv;
+ // need at least 2 segments to test boundary conditions:
+ PRUint32 bufDataSize = segSize * 2;
+ PRUint32 bufSize = segSize * 2;
+ nsIInputStream* in;
+ nsIOutputStream* out;
+ rv = NS_NewPipe(&in, &out, segSize, bufSize);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "NS_NewPipe failed");
+ out->SetNonBlocking(PR_TRUE);
+
+ PRUint32 i, j, amt;
+ PRUint32 delimLen = nsCRT::strlen(delim);
+ for (i = 0; i < bufDataSize; i++) {
+ // first fill the buffer
+ for (j = 0; j < i; j++) {
+ rv = out->Write("-", 1, &amt);
+ NS_ASSERTION(NS_SUCCEEDED(rv) && amt == 1, "Write failed");
+ }
+ rv = out->Write(delim, delimLen, &amt);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "Write failed");
+ if (i + amt < bufDataSize) {
+ for (j = i + amt; j < bufDataSize; j++) {
+ rv = out->Write("+", 1, &amt);
+ NS_ASSERTION(NS_SUCCEEDED(rv) && amt == 1, "Write failed");
+ }
+ }
+
+ // now search for the delimiter
+ PRBool found;
+ PRUint32 offset;
+ rv = in->Search(delim, PR_FALSE, &found, &offset);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "Search failed");
+
+ // print the results
+ char* bufferContents = new char[bufDataSize + 1];
+ rv = in->Read(bufferContents, bufDataSize, &amt);
+ NS_ASSERTION(NS_SUCCEEDED(rv) && amt == bufDataSize, "Read failed");
+ bufferContents[bufDataSize] = '\0';
+ printf("Buffer: %s\nDelim: %s %s offset: %d\n", bufferContents,
+ delim, (found ? "found" : "not found"), offset);
+ }
+ NS_RELEASE(in);
+ NS_RELEASE(out);
+}
+#endif
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef DEBUG
+extern NS_COM void
+TestSegmentedBuffer();
+#endif
+
+int
+main(int argc, char* argv[])
+{
+ nsresult rv;
+ nsIServiceManager* servMgr;
+
+ rv = NS_InitXPCOM2(&servMgr, NULL, NULL);
+ if (NS_FAILED(rv)) return rv;
+
+ if (argc > 1 && nsCRT::strcmp(argv[1], "-trace") == 0)
+ gTrace = PR_TRUE;
+
+#ifdef DEBUG
+ TestSegmentedBuffer();
+#endif
+
+#if 0 // obsolete old implementation
+ rv = NS_NewPipe(&in, &out, 4096 * 4);
+ if (NS_FAILED(rv)) {
+ printf("NewPipe failed\n");
+ return -1;
+ }
+
+ rv = TestPipe(in, out);
+ NS_RELEASE(in);
+ NS_RELEASE(out);
+ if (NS_FAILED(rv)) {
+ printf("TestPipe failed\n");
+ return -1;
+ }
+#endif
+#if 0
+ TestSearch("foo", 8);
+ TestSearch("bar", 6);
+ TestSearch("baz", 2);
+#endif
+
+ rv = TestChainedPipes();
+ NS_ASSERTION(NS_SUCCEEDED(rv), "TestChainedPipes failed");
+ RunTests(16, 1);
+ RunTests(4096, 16);
+ NS_RELEASE(servMgr);
+ rv = NS_ShutdownXPCOM( NULL );
+ NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestServMgr.cpp b/src/libs/xpcom18a4/xpcom/tests/TestServMgr.cpp
new file mode 100644
index 00000000..8eaaaa77
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestServMgr.cpp
@@ -0,0 +1,173 @@
+/* -*- 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 "MyService.h"
+#include "nsXPCOM.h"
+#include "nsIServiceManager.h"
+#include "nsIComponentManager.h"
+#include <stdio.h>
+
+static NS_DEFINE_CID(kIMyServiceCID, NS_IMYSERVICE_CID);
+
+////////////////////////////////////////////////////////////////////////////////
+
+IMyService* myServ = NULL;
+
+nsresult
+BeginTest(int testNumber)
+{
+ nsresult err;
+ NS_ASSERTION(myServ == NULL, "myServ not reset");
+ err = nsServiceManager::GetService(kIMyServiceCID, NS_GET_IID(IMyService),
+ (nsISupports**)&myServ);
+ return err;
+}
+
+nsresult
+EndTest(int testNumber)
+{
+ nsresult err = NS_OK;
+
+ if (myServ) {
+ err = myServ->Doit();
+ if (err != NS_OK) return err;
+
+ err = nsServiceManager::ReleaseService(kIMyServiceCID, myServ);
+ if (err != NS_OK) return err;
+ myServ = NULL;
+ }
+
+ printf("test %d succeeded\n", testNumber);
+ return NS_OK;
+}
+
+nsresult
+SimpleTest(int testNumber)
+{
+ // This test just gets a service, uses it and releases it.
+
+ nsresult err;
+ err = BeginTest(testNumber);
+ if (err != NS_OK) return err;
+ err = EndTest(testNumber);
+ return err;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+nsresult
+AsyncShutdown(int testNumber)
+{
+ nsresult err;
+
+ // If the AsyncShutdown was truly asynchronous and happened on another
+ // thread, we'd have to protect all accesses to myServ throughout this
+ // code with a monitor.
+
+ err = nsServiceManager::UnregisterService(kIMyServiceCID);
+ if (err == NS_ERROR_SERVICE_NOT_AVAILABLE) {
+ printf("async shutdown -- service not found\n");
+ return NS_OK;
+ }
+ return err;
+}
+
+nsresult
+AsyncNoShutdownTest(int testNumber)
+{
+ // This test gets a service, and also gets an async request for shutdown,
+ // but the service doesn't get shut down because some other client (who's
+ // not participating in the async shutdown game as he should) is
+ // continuing to hang onto the service. This causes myServ variable to
+ // get set to NULL, but the service doesn't get unloaded right away as
+ // it should.
+
+ nsresult err;
+
+ err = BeginTest(testNumber);
+ if (err != NS_OK) return err;
+
+ // Create some other user of kIMyServiceCID, preventing it from
+ // really going away:
+ IMyService* otherClient;
+ err = nsServiceManager::GetService(kIMyServiceCID, NS_GET_IID(IMyService),
+ (nsISupports**)&otherClient);
+ if (err != NS_OK) return err;
+
+ err = AsyncShutdown(testNumber);
+ if (err != NS_OK) return err;
+ err = EndTest(testNumber);
+
+ // Finally, release the other client.
+ err = nsServiceManager::ReleaseService(kIMyServiceCID, otherClient);
+
+ return err;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int
+main(void)
+{
+ nsresult err;
+ int testNumber = 0;
+
+ err = NS_InitXPCOM2(nsnull, nsnull, nsnull);
+ if (NS_FAILED(err)) {
+ printf("NS_InitXPCOM2 failed\n");
+ return -1;
+ }
+
+ err = SimpleTest(++testNumber);
+ if (err != NS_OK)
+ goto error;
+
+ err = AsyncNoShutdownTest(++testNumber);
+ if (err != NS_OK)
+ goto error;
+
+ AsyncShutdown(++testNumber);
+
+ printf("there was great success\n");
+ return 0;
+
+ error:
+ printf("test %d failed\n", testNumber);
+ return -1;
+}
+
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestShutdown.cpp b/src/libs/xpcom18a4/xpcom/tests/TestShutdown.cpp
new file mode 100644
index 00000000..259a7b31
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestShutdown.cpp
@@ -0,0 +1,78 @@
+/* -*- 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 "nsIServiceManager.h"
+
+// Gee this seems simple! It's for testing for memory leaks with Purify.
+
+void main(int argc, char* argv[])
+{
+ nsresult rv;
+ nsIServiceManager* servMgr;
+ rv = NS_InitXPCOM2(&servMgr, NULL, NULL);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "NS_InitXPCOM failed");
+
+ // try loading a component and releasing it to see if it leaks
+ if (argc > 1 && argv[1] != nsnull) {
+ char* cidStr = argv[1];
+ nsISupports* obj = nsnull;
+ if (cidStr[0] == '{') {
+ nsCID cid;
+ cid.Parse(cidStr);
+ rv = nsComponentManager::CreateInstance(cid, nsnull,
+ NS_GET_IID(nsISupports),
+ (void**)&obj);
+ }
+ else {
+ // contractID case:
+ rv = nsComponentManager::CreateInstance(cidStr, nsnull,
+ NS_GET_IID(nsISupports),
+ (void**)&obj);
+ }
+ if (NS_SUCCEEDED(rv)) {
+ printf("Successfully created %s\n", cidStr);
+ NS_RELEASE(obj);
+ }
+ else {
+ printf("Failed to create %s (%x)\n", cidStr, rv);
+ }
+ }
+
+ rv = NS_ShutdownXPCOM(servMgr);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestStackCrawl.cpp b/src/libs/xpcom18a4/xpcom/tests/TestStackCrawl.cpp
new file mode 100644
index 00000000..76187edd
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestStackCrawl.cpp
@@ -0,0 +1,11 @@
+#include <stdio.h>
+
+#include "nsISupportsUtils.h"
+#include "nsTraceRefCntImpl.h"
+
+int main(int argc, char* argv[])
+{
+ nsTraceRefcntImpl::WalkTheStack(stdout);
+ return 0;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestStrings.cpp b/src/libs/xpcom18a4/xpcom/tests/TestStrings.cpp
new file mode 100644
index 00000000..b1b725a4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestStrings.cpp
@@ -0,0 +1,643 @@
+/* vim:set ts=2 sw=2 et cindent: */
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darin Fisher <darin@meer.net>
+ *
+ * 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 <stdio.h>
+#include "nsString.h"
+#include "nsReadableUtils.h"
+#include "nsCRT.h"
+
+void test_assign_helper(const nsACString& in, nsACString &_retval)
+ {
+ _retval = in;
+ }
+
+PRBool test_assign()
+ {
+ nsCString result;
+ test_assign_helper(NS_LITERAL_CSTRING("a") + NS_LITERAL_CSTRING("b"), result);
+ PRBool r = strcmp(result.get(), "ab") == 0;
+ if (!r)
+ printf("[result=%s]\n", result.get());
+ return r;
+ }
+
+PRBool test_assign_c()
+ {
+ nsCString c; c.Assign('c');
+ PRBool r = strcmp(c.get(), "c") == 0;
+ if (!r)
+ printf("[result=%s]\n", c.get());
+ return r;
+ }
+
+PRBool test1()
+ {
+ NS_NAMED_LITERAL_STRING(empty, "");
+ const nsAString& aStr = empty;
+
+ nsAutoString buf(aStr);
+
+ PRInt32 n = buf.FindChar(',');
+
+ n = buf.Length();
+
+ buf.Cut(0, n + 1);
+ n = buf.FindChar(',');
+
+ if (n != kNotFound)
+ printf("n=%d\n", n);
+
+ return n == kNotFound;
+ }
+
+PRBool test2()
+ {
+ nsCString data("hello world");
+ const nsACString& aStr = data;
+
+ nsCString temp(aStr);
+ temp.Cut(0, 6);
+
+ PRBool r = strcmp(temp.get(), "world") == 0;
+ if (!r)
+ printf("[temp=%s]\n", temp.get());
+ return r;
+ }
+
+PRBool test_find()
+ {
+ nsCString src("<!DOCTYPE blah blah blah>");
+
+ PRInt32 i = src.Find("DOCTYPE", PR_TRUE, 2, 1);
+ if (i == 2)
+ return PR_TRUE;
+
+ printf("i=%d\n", i);
+ return PR_FALSE;
+ }
+
+PRBool test_rfind()
+ {
+ const char text[] = "<!DOCTYPE blah blah blah>";
+ const char term[] = "bLaH";
+ nsCString src(text);
+ PRInt32 i;
+
+ i = src.RFind(term, PR_TRUE, 3, -1);
+ if (i != kNotFound)
+ {
+ printf("unexpected result searching from offset=3, i=%d\n", i);
+ return PR_FALSE;
+ }
+
+ i = src.RFind(term, PR_TRUE, -1, -1);
+ if (i != 20)
+ {
+ printf("unexpected result searching from offset=-1, i=%d\n", i);
+ return PR_FALSE;
+ }
+
+ i = src.RFind(term, PR_TRUE, 13, -1);
+ if (i != 10)
+ {
+ printf("unexpected result searching from offset=13, i=%d\n", i);
+ return PR_FALSE;
+ }
+
+ i = src.RFind(term, PR_TRUE, 22, 3);
+ if (i != 20)
+ {
+ printf("unexpected result searching from offset=22, i=%d\n", i);
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+ }
+
+PRBool test_rfind_2()
+ {
+ const char text[] = "<!DOCTYPE blah blah blah>";
+ nsCString src(text);
+ PRInt32 i = src.RFind("TYPE", PR_FALSE, 5, -1);
+ if (i == 5)
+ return PR_TRUE;
+
+ printf("i=%d\n", i);
+ return PR_FALSE;
+ }
+
+PRBool test_rfind_3()
+ {
+ const char text[] = "urn:mozilla:locale:en-US:necko";
+ nsCAutoString value(text);
+ PRInt32 i = value.RFind(":");
+ if (i == 24)
+ return PR_TRUE;
+
+ printf("i=%d\n", i);
+ return PR_FALSE;
+ }
+
+PRBool test_rfind_4()
+ {
+ nsCString value("a.msf");
+ PRInt32 i = value.RFind(".msf");
+ if (i != 1)
+ {
+ printf("i=%d\n", i);
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+ }
+
+PRBool test_distance()
+ {
+ const char text[] = "abc-xyz";
+ nsCString s(text);
+ nsCString::const_iterator begin, end;
+ s.BeginReading(begin);
+ s.EndReading(end);
+ size_t d = Distance(begin, end);
+ PRBool r = (d == sizeof(text)-1);
+ if (!r)
+ printf("d=%zu\n", d);
+ return r;
+ }
+
+PRBool test_length()
+ {
+ const char text[] = "abc-xyz";
+ nsCString s(text);
+ size_t d = s.Length();
+ PRBool r = (d == sizeof(text)-1);
+ if (!r)
+ printf("d=%zu\n", d);
+ return r;
+ }
+
+PRBool test_trim()
+ {
+ const char text[] = " a\t $ ";
+ const char set[] = " \t$";
+
+ nsCString s(text);
+ s.Trim(set);
+ PRBool r = strcmp(s.get(), "a") == 0;
+ if (!r)
+ printf("[s=%s]\n", s.get());
+ return r;
+ }
+
+PRBool test_replace_substr()
+ {
+ const char text[] = "abc-ppp-qqq-ppp-xyz";
+ nsCString s(text);
+ s.ReplaceSubstring("ppp", "www");
+ PRBool r = strcmp(s.get(), "abc-www-qqq-www-xyz") == 0;
+ if (!r)
+ {
+ printf("[s=%s]\n", s.get());
+ return PR_FALSE;
+ }
+
+ s.Assign("foobar");
+ s.ReplaceSubstring("foo", "bar");
+ s.ReplaceSubstring("bar", "");
+ r = strcmp(s.get(), "") == 0;
+ if (!r)
+ {
+ printf("[s=%s]\n", s.get());
+ return PR_FALSE;
+ }
+
+ s.Assign("foofoofoo");
+ s.ReplaceSubstring("foo", "foo");
+ r = strcmp(s.get(), "foofoofoo") == 0;
+ if (!r)
+ {
+ printf("[s=%s]\n", s.get());
+ return PR_FALSE;
+ }
+
+ s.Assign("foofoofoo");
+ s.ReplaceSubstring("of", "fo");
+ r = strcmp(s.get(), "fofoofooo") == 0;
+ if (!r)
+ {
+ printf("[s=%s]\n", s.get());
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+ }
+
+PRBool test_replace_substr_2()
+ {
+ const char *oldName = nsnull;
+ const char *newName = "user";
+ nsString acctName; acctName.AssignLiteral("forums.foo.com");
+ nsAutoString newAcctName, oldVal, newVal;
+ oldVal.AssignWithConversion(oldName);
+ newVal.AssignWithConversion(newName);
+ newAcctName.Assign(acctName);
+
+ // here, oldVal is empty. we are testing that this function
+ // does not hang. see bug 235355.
+ newAcctName.ReplaceSubstring(oldVal, newVal);
+
+ // we expect that newAcctName will be unchanged.
+ if (!newAcctName.Equals(acctName))
+ return PR_FALSE;
+
+ return PR_TRUE;
+ }
+
+PRBool test_strip_ws()
+ {
+ const char text[] = " a $ ";
+ nsCString s(text);
+ s.StripWhitespace();
+ PRBool r = strcmp(s.get(), "a$") == 0;
+ if (!r)
+ printf("[s=%s]\n", s.get());
+ return r;
+ }
+
+PRBool test_equals_ic()
+ {
+ nsCString s;
+ PRBool r = s.LowerCaseEqualsLiteral("view-source");
+ if (r)
+ printf("[r=%d]\n", r);
+ return !r;
+ }
+
+PRBool test_fixed_string()
+ {
+ char buf[256] = "hello world";
+
+ nsFixedCString s(buf, sizeof(buf));
+
+ if (s.Length() != strlen(buf))
+ return PR_FALSE;
+
+ if (strcmp(s.get(), buf) != 0)
+ return PR_FALSE;
+
+ s.Assign("foopy doopy doo");
+ if (s.get() != buf)
+ return PR_FALSE;
+
+ return PR_TRUE;
+ }
+
+PRBool test_concat()
+ {
+ nsCString bar("bar");
+ const nsACString& barRef = bar;
+
+ const nsPromiseFlatCString& result =
+ PromiseFlatCString(NS_LITERAL_CSTRING("foo") +
+ NS_LITERAL_CSTRING(",") +
+ barRef);
+ if (strcmp(result.get(), "foo,bar") == 0)
+ return PR_TRUE;
+
+ printf("[result=%s]\n", result.get());
+ return PR_FALSE;
+ }
+
+PRBool test_concat_2()
+ {
+ nsCString fieldTextStr("xyz");
+ nsCString text("text");
+ const nsACString& aText = text;
+
+ nsCAutoString result( fieldTextStr + aText );
+
+ if (strcmp(result.get(), "xyztext") == 0)
+ return PR_TRUE;
+
+ printf("[result=%s]\n", result.get());
+ return PR_FALSE;
+ }
+
+#if 0
+PRBool test_concat_3()
+ {
+ nsCString a("a"), b("b");
+
+ // THIS DOES NOT COMPILE
+ const nsACString& r = a + b;
+
+ return PR_TRUE;
+ }
+#endif
+
+PRBool test_xpidl_string()
+ {
+ nsXPIDLCString a, b;
+ a = b;
+ if (a != b)
+ return PR_FALSE;
+
+ a.Adopt(0);
+ if (a != b)
+ return PR_FALSE;
+
+ a.Append("foopy");
+ a.Assign(b);
+ if (a != b)
+ return PR_FALSE;
+
+ a.Insert("", 0);
+ a.Assign(b);
+ if (a != b)
+ return PR_FALSE;
+
+ const char text[] = "hello world";
+ *getter_Copies(a) = nsCRT::strdup(text);
+ if (strcmp(a, text) != 0)
+ return PR_FALSE;
+
+ b = a;
+ if (strcmp(a, b) != 0)
+ return PR_FALSE;
+
+ a.Adopt(0);
+ nsACString::const_iterator begin, end;
+ a.BeginReading(begin);
+ a.EndReading(end);
+ char *r = ToNewCString(Substring(begin, end));
+ if (strcmp(r, "") != 0)
+ return PR_FALSE;
+ nsMemory::Free(r);
+
+ a.Adopt(0);
+ if (a != (const char*) 0)
+ return PR_FALSE;
+
+ /*
+ PRInt32 index = a.FindCharInSet("xyz");
+ if (index != kNotFound)
+ return PR_FALSE;
+ */
+
+ return PR_TRUE;
+ }
+
+PRBool test_empty_assign()
+ {
+ nsCString a;
+ a.AssignLiteral("");
+
+ a.AppendLiteral("");
+
+ nsCString b;
+ b.SetCapacity(0);
+ return PR_TRUE;
+ }
+
+PRBool test_set_length()
+ {
+ const char kText[] = "Default Plugin";
+ nsCString buf;
+ buf.SetCapacity(sizeof(kText)-1);
+ buf.Assign(kText);
+ buf.SetLength(sizeof(kText)-1);
+ if (strcmp(buf.get(), kText) != 0)
+ return PR_FALSE;
+ return PR_TRUE;
+ }
+
+PRBool test_substring()
+ {
+ nsCString super("hello world"), sub("hello");
+
+ // this tests that |super| starts with |sub|,
+
+ PRBool r = sub.Equals(StringHead(super, sub.Length()));
+ if (!r)
+ return PR_FALSE;
+
+ // and verifies that |sub| does not start with |super|.
+
+ r = super.Equals(StringHead(sub, super.Length()));
+ if (r)
+ return PR_FALSE;
+
+ return PR_TRUE;
+ }
+
+PRBool test_appendint64()
+ {
+ nsCString str;
+
+ PRInt64 max = LL_MaxInt();
+ static const char max_expected[] = "9223372036854775807";
+ PRInt64 min = LL_MinInt();
+ static const char min_expected[] = "-9223372036854775808";
+ static const char min_expected_oct[] = "1000000000000000000000";
+ PRInt64 maxint_plus1 = LL_INIT(1, 0);
+ static const char maxint_plus1_expected[] = "4294967296";
+ static const char maxint_plus1_expected_x[] = "100000000";
+
+ str.AppendInt(max);
+
+ if (!str.Equals(max_expected)) {
+ fprintf(stderr, "Error appending LL_MaxInt(): Got %s\n", str.get());
+ return PR_FALSE;
+ }
+
+ str.Truncate();
+ str.AppendInt(min);
+ if (!str.Equals(min_expected)) {
+ fprintf(stderr, "Error appending LL_MinInt(): Got %s\n", str.get());
+ return PR_FALSE;
+ }
+ str.Truncate();
+ str.AppendInt(min, 8);
+ if (!str.Equals(min_expected_oct)) {
+ fprintf(stderr, "Error appending LL_MinInt() (oct): Got %s\n", str.get());
+ return PR_FALSE;
+ }
+
+
+ str.Truncate();
+ str.AppendInt(maxint_plus1);
+ if (!str.Equals(maxint_plus1_expected)) {
+ fprintf(stderr, "Error appending PR_UINT32_MAX + 1: Got %s\n", str.get());
+ return PR_FALSE;
+ }
+ str.Truncate();
+ str.AppendInt(maxint_plus1, 16);
+ if (!str.Equals(maxint_plus1_expected_x)) {
+ fprintf(stderr, "Error appending PR_UINT32_MAX + 1 (hex): Got %s\n", str.get());
+ return PR_FALSE;
+ }
+
+
+ return PR_TRUE;
+ }
+
+PRBool test_findcharinset()
+ {
+ nsCString buf("hello, how are you?");
+
+ PRInt32 index = buf.FindCharInSet(",?", 5);
+ if (index != 5)
+ return PR_FALSE;
+
+ index = buf.FindCharInSet("helo", 0);
+ if (index != 0)
+ return PR_FALSE;
+
+ index = buf.FindCharInSet("z?", 6);
+ if (index != (PRInt32) buf.Length()-1)
+ return PR_FALSE;
+
+ return PR_TRUE;
+ }
+
+PRBool test_rfindcharinset()
+ {
+ nsCString buf("hello, how are you?");
+
+ PRInt32 index = buf.RFindCharInSet(",?", 5);
+ if (index != 5)
+ return PR_FALSE;
+
+ index = buf.RFindCharInSet("helo", 0);
+ if (index != 0)
+ return PR_FALSE;
+
+ index = buf.RFindCharInSet("z?", 6);
+ if (index != kNotFound)
+ return PR_FALSE;
+
+ index = buf.RFindCharInSet("l", 5);
+ if (index != 3)
+ return PR_FALSE;
+
+ buf.Assign("abcdefghijkabc");
+
+ index = buf.RFindCharInSet("ab");
+ if (index != 12)
+ return PR_FALSE;
+
+ index = buf.RFindCharInSet("ab", 11);
+ if (index != 11)
+ return PR_FALSE;
+
+ index = buf.RFindCharInSet("ab", 10);
+ if (index != 1)
+ return PR_FALSE;
+
+ index = buf.RFindCharInSet("ab", 0);
+ if (index != 0)
+ return PR_FALSE;
+
+ index = buf.RFindCharInSet("cd", 1);
+ if (index != kNotFound)
+ return PR_FALSE;
+
+ index = buf.RFindCharInSet("h");
+ if (index != 7)
+ return PR_FALSE;
+
+ return PR_TRUE;
+ }
+
+//----
+
+typedef PRBool (*TestFunc)();
+
+static const struct Test
+ {
+ const char* name;
+ TestFunc func;
+ }
+tests[] =
+ {
+ { "test_assign", test_assign },
+ { "test_assign_c", test_assign_c },
+ { "test1", test1 },
+ { "test2", test2 },
+ { "test_find", test_find },
+ { "test_rfind", test_rfind },
+ { "test_rfind_2", test_rfind_2 },
+ { "test_rfind_3", test_rfind_3 },
+ { "test_rfind_4", test_rfind_4 },
+ { "test_distance", test_distance },
+ { "test_length", test_length },
+ { "test_trim", test_trim },
+ { "test_replace_substr", test_replace_substr },
+ { "test_replace_substr_2", test_replace_substr_2 },
+ { "test_strip_ws", test_strip_ws },
+ { "test_equals_ic", test_equals_ic },
+ { "test_fixed_string", test_fixed_string },
+ { "test_concat", test_concat },
+ { "test_concat_2", test_concat_2 },
+ { "test_xpidl_string", test_xpidl_string },
+ { "test_empty_assign", test_empty_assign },
+ { "test_set_length", test_set_length },
+ { "test_substring", test_substring },
+ { "test_appendint64", test_appendint64 },
+ { "test_findcharinset", test_findcharinset },
+ { "test_rfindcharinset", test_rfindcharinset },
+ { nsnull, nsnull }
+ };
+
+//----
+
+int main(int argc, char **argv)
+ {
+ int count = 1;
+ if (argc > 1)
+ count = atoi(argv[1]);
+
+ while (count--)
+ {
+ for (const Test* t = tests; t->name != nsnull; ++t)
+ {
+ printf("%25s : %s\n", t->name, t->func() ? "SUCCESS" : "FAILURE <--");
+ }
+ }
+
+ return 0;
+ }
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestThreads.cpp b/src/libs/xpcom18a4/xpcom/tests/TestThreads.cpp
new file mode 100644
index 00000000..10025a05
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestThreads.cpp
@@ -0,0 +1,280 @@
+/* -*- 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):
+ * 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 "nsIThread.h"
+#include "nsIRunnable.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "nspr.h"
+#include "nsCOMPtr.h"
+#include "nsIServiceManager.h"
+
+class nsRunner : public nsIRunnable {
+public:
+ NS_DECL_ISUPPORTS
+
+ NS_IMETHOD Run() {
+ nsCOMPtr<nsIThread> thread;
+ nsresult rv = nsIThread::GetCurrent(getter_AddRefs(thread));
+ if (NS_FAILED(rv)) {
+ printf("failed to get current thread\n");
+ return rv;
+ }
+ printf("running %d on thread %p\n", mNum, (void *)thread.get());
+
+ // if we don't do something slow, we'll never see the other
+ // worker threads run
+ PR_Sleep(PR_MillisecondsToInterval(100));
+
+ return rv;
+ }
+
+ nsRunner(int num) : mNum(num) {
+ }
+
+protected:
+ int mNum;
+};
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsRunner, nsIRunnable)
+
+nsresult
+TestThreads()
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIThread> runner;
+ rv = NS_NewThread(getter_AddRefs(runner), new nsRunner(0), 0, PR_JOINABLE_THREAD);
+ if (NS_FAILED(rv)) {
+ printf("failed to create thread\n");
+ return rv;
+ }
+
+ nsCOMPtr<nsIThread> thread;
+ rv = nsIThread::GetCurrent(getter_AddRefs(thread));
+ if (NS_FAILED(rv)) {
+ printf("failed to get current thread\n");
+ return rv;
+ }
+
+ PRThreadScope scope;
+ rv = runner->GetScope(&scope);
+ if (NS_FAILED(rv)) {
+ printf("runner already exited\n");
+ }
+
+ rv = runner->Join(); // wait for the runner to die before quitting
+ if (NS_FAILED(rv)) {
+ printf("join failed\n");
+ }
+
+ rv = runner->GetScope(&scope); // this should fail after Join
+ if (NS_SUCCEEDED(rv)) {
+ printf("get scope failed\n");
+ }
+
+ rv = runner->Interrupt(); // this should fail after Join
+ if (NS_SUCCEEDED(rv)) {
+ printf("interrupt failed\n");
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // try an unjoinable thread
+ rv = NS_NewThread(getter_AddRefs(runner), new nsRunner(1));
+ if (NS_FAILED(rv)) {
+ printf("failed to create thread\n");
+ return rv;
+ }
+
+ rv = runner->Join(); // wait for the runner to die before quitting
+ if (NS_SUCCEEDED(rv)) {
+ printf("shouldn't have been able to join an unjoinable thread\n");
+ }
+
+ PR_Sleep(PR_MillisecondsToInterval(100)); // hopefully the runner will quit here
+
+ return NS_OK;
+}
+
+class nsStressRunner : public nsIRunnable {
+public:
+ NS_DECL_ISUPPORTS
+
+ NS_IMETHOD Run() {
+ NS_ASSERTION(!mWasRun, "run twice!");
+ mWasRun = PR_TRUE;
+ PR_Sleep(1);
+ if (!PR_AtomicDecrement(&gNum)) {
+ printf(" last thread was %d\n", mNum);
+ }
+ return NS_OK;
+ }
+
+ nsStressRunner(int num) : mNum(num), mWasRun(PR_FALSE) {
+ PR_AtomicIncrement(&gNum);
+ }
+
+ static PRInt32 GetGlobalCount() {return gNum;}
+
+private:
+ ~nsStressRunner() {
+ NS_ASSERTION(mWasRun, "never run!");
+ }
+
+protected:
+ static PRInt32 gNum;
+ PRInt32 mNum;
+ PRBool mWasRun;
+};
+
+PRInt32 nsStressRunner::gNum = 0;
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsStressRunner, nsIRunnable)
+
+static int Stress(int loops, int threads)
+{
+
+ for (int i = 0; i < loops; i++) {
+ printf("Loop %d of %d\n", i+1, loops);
+
+ int k;
+ nsIThread** array = new nsIThread*[threads];
+ NS_ASSERTION(array, "out of memory");
+
+ NS_ASSERTION(!nsStressRunner::GetGlobalCount(), "bad count of runnables");
+
+ for (k = 0; k < threads; k++) {
+ nsCOMPtr<nsIThread> t;
+ nsresult rv = NS_NewThread(getter_AddRefs(t),
+ new nsStressRunner(k),
+ 0, PR_JOINABLE_THREAD);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "can't create thread");
+ NS_ADDREF(array[k] = t);
+ }
+
+ for (k = threads-1; k >= 0; k--) {
+ array[k]->Join();
+ NS_RELEASE(array[k]);
+ }
+ delete [] array;
+ }
+ return 0;
+}
+
+PR_STATIC_CALLBACK(void) threadProc(void *arg)
+{
+ // printf(" running thread %d\n", (int) arg);
+ PR_Sleep(1);
+ PR_ASSERT(PR_JOINABLE_THREAD == PR_GetThreadState(PR_GetCurrentThread()));
+}
+
+static int StressNSPR(int loops, int threads)
+{
+
+ for (int i = 0; i < loops; i++) {
+ printf("Loop %d of %d\n", i+1, loops);
+
+ int k;
+ PRThread** array = new PRThread*[threads];
+ PR_ASSERT(array);
+
+ for (k = 0; k < threads; k++) {
+ array[k] = PR_CreateThread(PR_USER_THREAD,
+ threadProc, (void*)(uintptr_t)k,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+ PR_ASSERT(array[k]);
+ }
+
+ for (k = 0; k < threads; k++) {
+ PR_ASSERT(PR_JOINABLE_THREAD == PR_GetThreadState(array[k]));
+ }
+
+ for (k = threads-1; k >= 0; k--) {
+ PR_JoinThread(array[k]);
+ }
+ delete [] array;
+ }
+ return 0;
+}
+
+
+int
+main(int argc, char** argv)
+{
+ int retval = 0;
+ nsresult rv;
+
+ rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
+ if (NS_FAILED(rv)) return -1;
+
+ if (argc > 1 && !strcmp(argv[1], "-stress")) {
+ int loops;
+ int threads;
+ if (argc != 4 || *argv[2] != '-' || *argv[3] != '-' ||
+ !(loops = atoi(argv[2]+1)) || !(threads = atoi(argv[3]+1))) {
+ printf("To use -stress you must pass loop count and thread count...\n"
+ " TestThreads -stress -1000 -50\n");
+ } else {
+ printf("Running stress test with %d loops of %d threads each\n",
+ loops, threads);
+ retval = Stress(loops, threads);
+ }
+ } else if (argc > 1 && !strcmp(argv[1], "-stress-nspr")) {
+ int loops;
+ int threads;
+ if (argc != 4 || *argv[2] != '-' || *argv[3] != '-' ||
+ !(loops = atoi(argv[2]+1)) || !(threads = atoi(argv[3]+1))) {
+ printf("To use -stress-nspr you must pass loop count and thread count...\n"
+ " TestThreads -stress -1000 -50\n");
+ } else {
+ printf("Running stress test with %d loops of %d threads each\n",
+ loops, threads);
+ retval = StressNSPR(loops, threads);
+ }
+ } else {
+ rv = TestThreads();
+ if (NS_FAILED(rv)) return -1;
+ }
+
+ rv = NS_ShutdownXPCOM(nsnull);
+ if (NS_FAILED(rv)) return -1;
+ return retval;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestVoidBTree.cpp b/src/libs/xpcom18a4/xpcom/tests/TestVoidBTree.cpp
new file mode 100644
index 00000000..956f179f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestVoidBTree.cpp
@@ -0,0 +1,302 @@
+/* -*- 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) 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 <stdlib.h>
+#include <stdio.h>
+#include "nsVoidBTree.h"
+#include "nsVoidArray.h"
+
+#define COUNT 1024
+#define POINTER(i) NS_REINTERPRET_CAST(void*, 4 + 4 * (i))
+
+static PRBool
+Equal(const nsVoidArray& aControl, const nsVoidBTree& aTest)
+{
+ if (aControl.Count() != aTest.Count()) {
+ printf("counts not equal; ");
+ return PR_FALSE;
+ }
+
+ for (PRInt32 i = aControl.Count() - 1; i >= 0; --i) {
+ if (aControl[i] != aTest[i]) {
+ printf("element %d differs; ", i);
+ return PR_FALSE;
+ }
+ }
+
+ return PR_TRUE;
+}
+
+
+static void
+CheckForwardEnumeration(const nsVoidArray& aControl, const nsVoidBTree& aTest)
+{
+ PRInt32 index = 0;
+
+ nsVoidBTree::ConstIterator last = aTest.Last();
+ for (nsVoidBTree::ConstIterator element = aTest.First(); element != last; ++element, ++index) {
+ if (*element != aControl[index]) {
+ printf("failed forward enumeration\n");
+ exit(-1);
+ }
+ }
+
+ if (index != aControl.Count()) {
+ printf("erratic termination during forward enumeration\n");
+ exit(-1);
+ }
+}
+
+static void
+CheckBackwardEnumeration(const nsVoidArray& aControl, const nsVoidBTree& aTest)
+{
+ PRInt32 index = aControl.Count();
+ nsVoidBTree::ConstIterator first = aTest.First();
+ nsVoidBTree::ConstIterator element = aTest.Last();
+
+ if (first != element) {
+ do {
+ if (*--element != aControl[--index]) {
+ printf("failed backward enumeration\n");
+ exit(-1);
+ }
+ } while (element != first);
+ }
+
+ if (index != 0) {
+ printf("erratic termination during backward enumeration\n");
+ exit(-1);
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ nsVoidBTree btree;
+
+ PRInt32 i;
+
+ //----------------------------------------
+ // Tail fill
+ for (i = 0; i < COUNT; ++i)
+ btree.InsertElementAt(NS_REINTERPRET_CAST(void*, POINTER(i)), i);
+
+ for (i = 0; i < COUNT; ++i) {
+ if (btree[i] != POINTER(i)) {
+ printf("tail fill failed\n");
+ return -1;
+ }
+ }
+
+ printf("tail fill succeeded\n");
+
+ //----------------------------------------
+ // Tail empty
+ for (i = COUNT - 1; i >= 0; --i)
+ btree.RemoveElementAt(i);
+
+ if (btree.Count() != 0) {
+ printf("tail empty failed\n");
+ return -1;
+ }
+
+ printf("tail empty succeeded\n");
+
+ // N.B. no intervening Clear() to verify that we handle the re-use
+ // case.
+
+ //----------------------------------------
+ // Front fill
+ for (i = 0; i < COUNT; ++i)
+ btree.InsertElementAt(POINTER(i), 0);
+
+ for (i = 0; i < COUNT; ++i) {
+ if (btree[COUNT - (i + 1)] != POINTER(i)) {
+ printf("simple front fill failed\n");
+ return -1;
+ }
+ }
+
+ printf("front fill succeeded\n");
+
+ //----------------------------------------
+ // Front empty
+ for (i = COUNT - 1; i >= 0; --i)
+ btree.RemoveElementAt(0);
+
+ if (btree.Count() != 0) {
+ printf("front empty failed\n");
+ return -1;
+ }
+
+ printf("front empty succeeded\n");
+ fflush(stdout);
+
+ //----------------------------------------
+ // Test boundary conditions with small btree
+
+ {
+ printf("small btree boundary conditions ");
+ fflush(stdout);
+
+ nsVoidArray control;
+ btree.Clear();
+
+ CheckBackwardEnumeration(control, btree);
+ CheckForwardEnumeration(control, btree);
+
+ btree.AppendElement(POINTER(0));
+ control.AppendElement(POINTER(0));
+
+ CheckBackwardEnumeration(control, btree);
+ CheckForwardEnumeration(control, btree);
+
+ btree.AppendElement(POINTER(1));
+ control.AppendElement(POINTER(1));
+
+ CheckBackwardEnumeration(control, btree);
+ CheckForwardEnumeration(control, btree);
+
+ btree.RemoveElementAt(0);
+ btree.RemoveElementAt(0);
+ control.RemoveElementAt(0);
+ control.RemoveElementAt(0);
+
+ CheckBackwardEnumeration(control, btree);
+ CheckForwardEnumeration(control, btree);
+
+ printf("succeeded\n");
+ }
+
+ //----------------------------------------
+ // Iterator
+ {
+ nsVoidArray control;
+ btree.Clear();
+
+ // Fill
+ for (i = 0; i < COUNT; ++i) {
+ PRInt32 slot = i ? rand() % i : 0;
+
+ btree.InsertElementAt(POINTER(i), slot);
+ control.InsertElementAt(POINTER(i), slot);
+
+ if (! Equal(control, btree)) {
+ printf("failed\n");
+ return -1;
+ }
+ }
+
+ for (nsVoidBTree::Iterator m = btree.First(); m != btree.Last(); ++m) {
+ nsVoidBTree::Iterator n;
+ for (n = m, ++n; n != btree.Last(); ++n) {
+ if (*m > *n) {
+ void* tmp = *m;
+ *m = *n;
+ *n = tmp;
+ }
+ }
+ }
+
+ nsVoidBTree::Iterator el;
+ for (el = btree.First(), i = 0; el != btree.Last(); ++el, ++i) {
+ if (*el != POINTER(i)) {
+ printf("bubble sort failed\n");
+ return -1;
+ }
+ }
+
+ printf("iteration succeeded\n");
+ }
+
+ //----------------------------------------
+ // Random hammering
+
+ printf("random fill/empty: ");
+
+ for (PRInt32 iter = 10; iter >= 1; --iter) {
+ printf("%d ", iter);
+ fflush(stdout);
+
+ nsVoidArray control;
+ btree.Clear();
+
+ // Fill
+ for (i = 0; i < COUNT; ++i) {
+ PRInt32 slot = i ? rand() % i : 0;
+
+ btree.InsertElementAt(POINTER(i), slot);
+ control.InsertElementAt(POINTER(i), slot);
+
+ if (! Equal(control, btree)) {
+ printf("failed\n");
+ return -1;
+ }
+ }
+
+ // IndexOf
+ for (i = 0; i < COUNT; ++i) {
+ void* element = control[i];
+ if (btree.IndexOf(element) != i) {
+ printf("failed IndexOf at %d\n", i);
+ return -1;
+ }
+ }
+
+ // Backward enumeration
+ CheckBackwardEnumeration(control, btree);
+
+ // Forward enumeration
+ CheckForwardEnumeration(control, btree);
+
+ // Empty
+ for (i = COUNT - 1; i >= 0; --i) {
+ PRInt32 slot = i ? rand() % i : 0;
+
+ btree.RemoveElementAt(slot);
+ control.RemoveElementAt(slot);
+
+ if (! Equal(control, btree)) {
+ printf("failed\n");
+ return -1;
+ }
+ }
+ }
+
+ printf("succeeded\n");
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/TestXPIDLString.cpp b/src/libs/xpcom18a4/xpcom/tests/TestXPIDLString.cpp
new file mode 100644
index 00000000..f2802e1f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/TestXPIDLString.cpp
@@ -0,0 +1,18 @@
+#include "nsString.h"
+#include "nsReadableUtils.h"
+#include "nsXPIDLString.h"
+
+static void
+nsXPIDLStringTest_Value(PRUnichar** aResult)
+{
+ *aResult = ToNewUnicode(NS_LITERAL_STRING("Hello, World"));
+}
+
+int
+main(int argc, char* argv[])
+{
+ nsXPIDLString s1;
+ nsXPIDLStringTest_Value(getter_Copies(s1));
+ return 0;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/dynamic/.cvsignore b/src/libs/xpcom18a4/xpcom/tests/dynamic/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/dynamic/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/tests/dynamic/Makefile.in b/src/libs/xpcom18a4/xpcom/tests/dynamic/Makefile.in
new file mode 100644
index 00000000..c17318c0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/dynamic/Makefile.in
@@ -0,0 +1,61 @@
+#
+# ***** 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
+
+IS_COMPONENT = 1
+MODULE_NAME = nsTestDynamicModule
+MODULE = xpcom
+LIBRARY_NAME = testdynamic
+SHORT_LIBNAME = tdynamic
+
+CPPSRCS = TestDynamic.cpp
+
+include $(topsrcdir)/config/config.mk
+
+LOCAL_INCLUDES = -I$(srcdir)/.. -I$(srcdir)/../../public
+
+include $(topsrcdir)/config/rules.mk
+
+EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS)
+
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/dynamic/TestDynamic.cpp b/src/libs/xpcom18a4/xpcom/tests/dynamic/TestDynamic.cpp
new file mode 100644
index 00000000..a27d8ea9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/dynamic/TestDynamic.cpp
@@ -0,0 +1,76 @@
+/* -*- 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):
+ * Suresh Duddi <dp@netscape.com>
+ * Christopher Blizzard <blizzard@mozilla.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 ***** */
+
+#include <stdio.h>
+#include "TestFactory.h"
+#include "nsIGenericFactory.h"
+
+/**
+ * ITestClass implementation
+ */
+
+class TestDynamicClassImpl: public ITestClass {
+ NS_DECL_ISUPPORTS
+
+ TestDynamicClassImpl() {
+ }
+ void Test();
+};
+
+NS_IMPL_ISUPPORTS1(TestDynamicClassImpl, ITestClass)
+
+void TestDynamicClassImpl::Test() {
+ printf("hello, dynamic world!\n");
+}
+
+/**
+ * Generic Module
+ */
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(TestDynamicClassImpl)
+
+static const nsModuleComponentInfo components[] =
+{
+ { "Test Dynamic", NS_TESTLOADEDFACTORY_CID, NS_TESTLOADEDFACTORY_CONTRACTID,
+ TestDynamicClassImplConstructor
+ }
+};
+
+NS_IMPL_NSGETMODULE(nsTestDynamicModule, components)
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/dynamic/win32.order b/src/libs/xpcom18a4/xpcom/tests/dynamic/win32.order
new file mode 100644
index 00000000..bf181a81
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/dynamic/win32.order
@@ -0,0 +1 @@
+_NSGetModule ; 1
diff --git a/src/libs/xpcom18a4/xpcom/tests/nsIFileEnumerator.cpp b/src/libs/xpcom18a4/xpcom/tests/nsIFileEnumerator.cpp
new file mode 100644
index 00000000..a5f3551d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/nsIFileEnumerator.cpp
@@ -0,0 +1,95 @@
+#include "nsILocalFile.h"
+#include "nsDependentString.h"
+#include "nsString.h"
+
+#include <stdio.h>
+#include "nsIComponentRegistrar.h"
+#include "nsIComponentManager.h"
+#include "nsIServiceManager.h"
+#include "nsMemory.h"
+#include "nsXPIDLString.h"
+#include "nsISimpleEnumerator.h"
+
+
+PRBool LoopInDir(nsILocalFile* file)
+{
+ nsresult rv;
+ nsCOMPtr<nsISimpleEnumerator> entries;
+ rv = file->GetDirectoryEntries(getter_AddRefs(entries));
+ if(NS_FAILED(rv) || !entries)
+ return PR_FALSE;
+
+ PRBool hasMore;
+ while(NS_SUCCEEDED(entries->HasMoreElements(&hasMore)) && hasMore)
+ {
+ nsCOMPtr<nsISupports> sup;
+ entries->GetNext(getter_AddRefs(sup));
+ if(!sup)
+ return PR_FALSE;
+
+ nsCOMPtr<nsILocalFile> file = do_QueryInterface(sup);
+ if(!file)
+ return PR_FALSE;
+
+ nsCAutoString name;
+ if(NS_FAILED(file->GetNativeLeafName(name)))
+ return PR_FALSE;
+
+ PRBool isDir;
+ printf("%s\n", name.get());
+ rv = file->IsDirectory(&isDir);
+ if (NS_FAILED(rv))
+ {
+ printf("IsDirectory Failed!!!\n");
+ return PR_FALSE;
+ }
+
+ if (isDir == PR_TRUE)
+ {
+ nsCOMPtr<nsILocalFile> lfile = do_QueryInterface(file);
+ LoopInDir(lfile);
+ }
+ }
+ return PR_TRUE;
+}
+
+
+int
+main(int argc, char* argv[])
+{
+ nsresult rv;
+ {
+ nsCOMPtr<nsILocalFile> topDir;
+
+ nsCOMPtr<nsIServiceManager> servMan;
+ rv = NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull);
+ if (NS_FAILED(rv)) return -1;
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan);
+ NS_ASSERTION(registrar, "Null nsIComponentRegistrar");
+ if (registrar)
+ registrar->AutoRegister(nsnull);
+
+ if (argc > 1 && argv[1] != nsnull)
+ {
+ char* pathStr = argv[1];
+ NS_NewNativeLocalFile(nsDependentCString(pathStr), PR_FALSE, getter_AddRefs(topDir));
+ }
+
+ if (!topDir)
+ {
+ printf("No Top Dir\n");
+ return -1;
+ }
+ PRInt32 startTime = PR_IntervalNow();
+
+ LoopInDir(topDir);
+
+ PRInt32 endTime = PR_IntervalNow();
+
+ printf("\nTime: %d\n", PR_IntervalToMilliseconds(endTime - startTime));
+ } // this scopes the nsCOMPtrs
+ // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
+ rv = NS_ShutdownXPCOM(nsnull);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/nsIFileTest.cpp b/src/libs/xpcom18a4/xpcom/tests/nsIFileTest.cpp
new file mode 100644
index 00000000..1dd2cd54
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/nsIFileTest.cpp
@@ -0,0 +1,475 @@
+#include "nsILocalFile.h"
+#if 0 /* too new */
+#include "nsStringGlue.h"
+#else
+#include "nsString.h"
+#endif
+
+#include <stdio.h>
+#include "nsXPCOM.h"
+#include "nsIComponentManager.h"
+#include "nsIComponentRegistrar.h"
+#include "nsIServiceManager.h"
+#include "nsIMemory.h"
+
+#include "nsComponentManagerUtils.h"
+#include "nsCOMPtr.h"
+
+void Passed();
+void Failed(const char* explanation = nsnull);
+void Inspect();
+void Banner(const char* bannerString);
+
+void VerifyResult(nsresult rv)
+{
+ if (NS_FAILED(rv))
+ {
+ Failed("rv failed");
+ printf("rv = %d\n", rv);
+ }
+}
+//----------------------------------------------------------------------------
+void Banner(const char* bannerString)
+//----------------------------------------------------------------------------
+{
+ printf("---------------------------\n");
+ printf("%s\n", bannerString);
+ printf("---------------------------\n");
+}
+
+//----------------------------------------------------------------------------
+void Passed()
+//----------------------------------------------------------------------------
+{
+ printf("Test passed.");
+}
+
+//----------------------------------------------------------------------------
+void Failed(const char* explanation)
+//----------------------------------------------------------------------------
+{
+ printf("ERROR : Test failed.\n");
+ printf("REASON: %s.\n", explanation);
+}
+
+//----------------------------------------------------------------------------
+void Inspect()
+//----------------------------------------------------------------------------
+{
+ printf("^^^^^^^^^^ PLEASE INSPECT OUTPUT FOR ERRORS\n");
+}
+
+void GetPaths(nsILocalFile* file)
+{
+ nsresult rv;
+ nsCAutoString pathName;
+
+ printf("Getting Path\n");
+
+ rv = file->GetNativePath(pathName);
+ VerifyResult(rv);
+
+ printf("filepath: %s\n", pathName.get());
+}
+
+void InitTest(const char* creationPath, const char* appendPath)
+{
+ nsILocalFile* file = nsnull;
+ nsresult rv = CallCreateInstance(NS_LOCAL_FILE_CONTRACTID, &file);
+
+
+ if (NS_FAILED(rv) || (!file))
+ {
+ printf("create nsILocalFile failed\n");
+ return;
+ }
+
+ nsCAutoString leafName;
+
+ Banner("InitWithPath");
+ printf("creationPath == %s\nappendPath == %s\n", creationPath, appendPath);
+
+ rv = file->InitWithNativePath(nsDependentCString(creationPath));
+ VerifyResult(rv);
+
+ printf("Getting Filename\n");
+ rv = file->GetNativeLeafName(leafName);
+ printf(" %s\n", leafName.get());
+ VerifyResult(rv);
+
+ printf("Appending %s \n", appendPath);
+ rv = file->AppendNative(nsDependentCString(appendPath));
+ VerifyResult(rv);
+
+ printf("Getting Filename\n");
+ rv = file->GetNativeLeafName(leafName);
+ printf(" %s\n", leafName.get());
+ VerifyResult(rv);
+
+ GetPaths(file);
+
+
+ printf("Check For Existence\n");
+
+ PRBool exists;
+ file->Exists(&exists);
+
+ NS_RELEASE(file);
+
+ if (exists)
+ printf("Yup!\n");
+ else
+ printf("no.\n");
+}
+
+
+void CreationTest(const char* creationPath, const char* appendPath,
+ PRInt32 whatToCreate, PRInt32 perm)
+{
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> file =
+ do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
+
+ if (NS_FAILED(rv) || (!file))
+ {
+ printf("create nsILocalFile failed\n");
+ return;
+ }
+
+ Banner("Creation Test");
+ printf("creationPath == %s\nappendPath == %s\n", creationPath, appendPath);
+
+ rv = file->InitWithNativePath(nsDependentCString(creationPath));
+ VerifyResult(rv);
+
+ printf("Appending %s\n", appendPath);
+ rv = file->AppendRelativeNativePath(nsDependentCString(appendPath));
+ VerifyResult(rv);
+
+ printf("Check For Existence\n");
+
+ PRBool exists;
+ file->Exists(&exists);
+
+ if (exists)
+ printf("Yup!\n");
+ else
+ printf("no.\n");
+
+
+ rv = file->Create(whatToCreate, perm);
+ VerifyResult(rv);
+
+ rv = file->Exists(&exists);
+ VerifyResult(rv);
+
+
+ if (!exists)
+ {
+ Failed("Did not create file system object!");
+ return;
+ }
+
+}
+
+void CreateUniqueTest(const char* creationPath, const char* appendPath,
+ PRInt32 whatToCreate, PRInt32 perm)
+{
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> file =
+ do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
+
+ if (NS_FAILED(rv) || (!file))
+ {
+ printf("create nsILocalFile failed\n");
+ return;
+ }
+
+ Banner("Creation Test");
+ printf("creationPath == %s\nappendPath == %s\n", creationPath, appendPath);
+
+ rv = file->InitWithNativePath(nsDependentCString(creationPath));
+ VerifyResult(rv);
+
+ printf("Appending %s\n", appendPath);
+ rv = file->AppendNative(nsDependentCString(appendPath));
+ VerifyResult(rv);
+
+ printf("Check For Existence\n");
+
+ PRBool exists;
+ file->Exists(&exists);
+
+ if (exists)
+ printf("Yup!\n");
+ else
+ printf("no.\n");
+
+
+ rv = file->CreateUnique(whatToCreate, perm);
+ VerifyResult(rv);
+
+ rv = file->Exists(&exists);
+ VerifyResult(rv);
+
+
+ if (!exists)
+ {
+ Failed("Did not create file system object!");
+ return;
+ }
+
+}
+
+
+void
+CopyTest(const char *testFile, const char *targetDir)
+{
+ printf("start copy test\n");
+
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> file =
+ do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
+
+ if (NS_FAILED(rv) || (!file))
+ {
+ printf("create nsILocalFile failed\n");
+ return;
+ }
+
+ rv = file->InitWithNativePath(nsDependentCString(testFile));
+ VerifyResult(rv);
+
+ nsCOMPtr<nsILocalFile> dir =
+ do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
+
+ if (NS_FAILED(rv) || (!dir))
+ {
+ printf("create nsILocalFile failed\n");
+ return;
+ }
+
+ rv = dir->InitWithNativePath(nsDependentCString(targetDir));
+ VerifyResult(rv);
+
+ rv = file->CopyTo(dir, EmptyString());
+ VerifyResult(rv);
+
+ printf("end copy test\n");
+}
+
+void
+DeletionTest(const char* creationPath, const char* appendPath, PRBool recursive)
+{
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> file =
+ do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
+
+ if (NS_FAILED(rv) || (!file))
+ {
+ printf("create nsILocalFile failed\n");
+ return;
+ }
+
+ Banner("Deletion Test");
+ printf("creationPath == %s\nappendPath == %s\n", creationPath, appendPath);
+
+ rv = file->InitWithNativePath(nsDependentCString(creationPath));
+ VerifyResult(rv);
+
+ printf("Appending %s\n", appendPath);
+ rv = file->AppendNative(nsDependentCString(appendPath));
+ VerifyResult(rv);
+
+ printf("Check For Existance\n");
+
+ PRBool exists;
+ file->Exists(&exists);
+
+ if (exists)
+ printf("Yup!\n");
+ else
+ printf("no.\n");
+
+ rv = file->Remove(recursive);
+ VerifyResult(rv);
+
+ rv = file->Exists(&exists);
+ VerifyResult(rv);
+
+ if (exists)
+ {
+ Failed("Did not create delete system object!");
+ return;
+ }
+
+}
+
+void
+MoveTest(const char *testFile, const char *targetDir)
+{
+ Banner("Move Test");
+
+ printf("start move test\n");
+
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> file(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
+
+ if (!file)
+ {
+ printf("create nsILocalFile failed\n");
+ return;
+ }
+
+ rv = file->InitWithNativePath(nsDependentCString(testFile));
+ VerifyResult(rv);
+
+ nsCOMPtr<nsILocalFile> dir(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
+
+ if (!dir)
+ {
+ printf("create nsILocalFile failed\n");
+ return;
+ }
+
+ rv = dir->InitWithNativePath(nsDependentCString(targetDir));
+ VerifyResult(rv);
+
+ rv = file->MoveToNative(dir, NS_LITERAL_CSTRING("newtemp"));
+ VerifyResult(rv);
+ if (NS_FAILED(rv))
+ {
+ printf("MoveToNative() test Failed.\n");
+ }
+ printf("end move test\n");
+}
+
+// move up the number of directories in moveUpCount, then append "foo/bar"
+void
+NormalizeTest(const char *testPath, int moveUpCount,
+ const char *expected)
+{
+ Banner("Normalize Test");
+
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> file(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
+
+ if (!file)
+ {
+ printf("create nsILocalFile failed\n");
+ return;
+ }
+
+ rv = file->InitWithNativePath(nsDependentCString(testPath));
+ VerifyResult(rv);
+
+ nsCOMPtr<nsIFile> parent;
+ nsAutoString path;
+ for (int i=0; i < moveUpCount; i++)
+ {
+ rv = file->GetParent(getter_AddRefs(parent));
+ VerifyResult(rv);
+ rv = parent->GetPath(path);
+ VerifyResult(rv);
+ rv = file->InitWithPath(path);
+ VerifyResult(rv);
+ }
+
+ if (!parent) {
+ printf("Getting parent failed!\n");
+ return;
+ }
+
+ rv = parent->Append(NS_LITERAL_STRING("foo"));
+ VerifyResult(rv);
+ rv = parent->Append(NS_LITERAL_STRING("bar"));
+ VerifyResult(rv);
+
+ rv = parent->Normalize();
+ VerifyResult(rv);
+
+ nsCAutoString newPath;
+ rv = parent->GetNativePath(newPath);
+ VerifyResult(rv);
+
+ nsCOMPtr<nsILocalFile>
+ expectedFile(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
+
+ if (!expectedFile)
+ {
+ printf("create nsILocalFile failed\n");
+ return;
+ }
+ rv = expectedFile->InitWithNativePath(nsDependentCString(expected));
+ VerifyResult(rv);
+
+ rv = expectedFile->Normalize();
+ VerifyResult(rv);
+
+ nsCAutoString expectedPath;
+ rv = expectedFile->GetNativePath(expectedPath);
+ VerifyResult(rv);
+
+ if (!newPath.Equals(expectedPath)) {
+ printf("ERROR: Normalize() test Failed!\n");
+ printf(" Got: %s\n", newPath.get());
+ printf("Expected: %s\n", expectedPath.get());
+ }
+
+ printf("end normalize test.\n");
+}
+
+int main(void)
+{
+ nsCOMPtr<nsIServiceManager> servMan;
+ NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull);
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan);
+ NS_ASSERTION(registrar, "Null nsIComponentRegistrar");
+ registrar->AutoRegister(nsnull);
+
+#if defined(XP_WIN) || defined(XP_OS2)
+ InitTest("c:\\temp\\", "sub1/sub2/"); // expect failure
+ InitTest("d:\\temp\\", "sub1\\sub2\\"); // expect failure
+
+ CreationTest("c:\\temp\\", "file.txt", nsIFile::NORMAL_FILE_TYPE, 0644);
+ DeletionTest("c:\\temp\\", "file.txt", PR_FALSE);
+
+ MoveTest("c:\\newtemp\\", "d:");
+
+ CreationTest("c:\\temp\\", "mumble\\a\\b\\c\\d\\e\\f\\g\\h\\i\\j\\k\\", nsIFile::DIRECTORY_TYPE, 0644);
+ DeletionTest("c:\\temp\\", "mumble", PR_TRUE);
+
+ CreateUniqueTest("c:\\temp\\", "foo", nsIFile::NORMAL_FILE_TYPE, 0644);
+ CreateUniqueTest("c:\\temp\\", "foo", nsIFile::NORMAL_FILE_TYPE, 0644);
+ CreateUniqueTest("c:\\temp\\", "bar.xx", nsIFile::DIRECTORY_TYPE, 0644);
+ CreateUniqueTest("c:\\temp\\", "bar.xx", nsIFile::DIRECTORY_TYPE, 0644);
+ DeletionTest("c:\\temp\\", "foo", PR_TRUE);
+ DeletionTest("c:\\temp\\", "foo-1", PR_TRUE);
+ DeletionTest("c:\\temp\\", "bar.xx", PR_TRUE);
+ DeletionTest("c:\\temp\\", "bar-1.xx", PR_TRUE);
+
+#else
+#ifdef XP_UNIX
+ InitTest("/tmp/", "sub1/sub2/"); // expect failure
+
+ CreationTest("/tmp", "file.txt", nsIFile::NORMAL_FILE_TYPE, 0644);
+ DeletionTest("/tmp/", "file.txt", PR_FALSE);
+
+ CreationTest("/tmp", "mumble/a/b/c/d/e/f/g/h/i/j/k/", nsIFile::DIRECTORY_TYPE, 0644);
+ DeletionTest("/tmp", "mumble", PR_TRUE);
+
+ CreationTest("/tmp", "file", nsIFile::NORMAL_FILE_TYPE, 0644);
+ CopyTest("/tmp/file", "/tmp/newDir");
+ MoveTest("/tmp/file", "/tmp/newDir/anotherNewDir");
+ DeletionTest("/tmp", "newDir", PR_TRUE);
+
+ CreationTest("/tmp", "qux/quux", nsIFile::NORMAL_FILE_TYPE, 0644);
+ CreationTest("/tmp", "foo/bar", nsIFile::NORMAL_FILE_TYPE, 0644);
+ NormalizeTest("/tmp/qux/quux/..", 1, "/tmp/foo/bar");
+ DeletionTest("/tmp", "qux", PR_TRUE);
+ DeletionTest("/tmp", "foo", PR_TRUE);
+
+#endif /* XP_UNIX */
+#endif /* XP_WIN || XP_OS2 */
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/resources.h b/src/libs/xpcom18a4/xpcom/tests/resources.h
new file mode 100644
index 00000000..b82df25e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/resources.h
@@ -0,0 +1,52 @@
+/* -*- 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):
+ * 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 ***** */
+#ifndef resources_h___
+#define resources_h___
+
+#define TIMER_1SECOND 40000
+#define TIMER_5SECOND 40001
+#define TIMER_10SECOND 40002
+
+#define TIMER_1REPEAT 40003
+#define TIMER_5REPEAT 40004
+#define TIMER_10REPEAT 40005
+
+#define TIMER_CANCEL 40006
+#define TIMER_EXIT 40010
+
+#endif /* resources_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/tests/services/.cvsignore b/src/libs/xpcom18a4/xpcom/tests/services/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/services/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/tests/services/Makefile.in b/src/libs/xpcom18a4/xpcom/tests/services/Makefile.in
new file mode 100644
index 00000000..84cd3c84
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/services/Makefile.in
@@ -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.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
+IS_COMPONENT = 1
+MODULE_NAME = MyService
+LIBRARY_NAME = MyService
+SHORT_LIBNAME = MyServce
+
+CPPSRCS = MyService.cpp
+
+LOCAL_INCLUDES = -I$(srcdir)/..
+
+EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS)
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/services/MyService.cpp b/src/libs/xpcom18a4/xpcom/tests/services/MyService.cpp
new file mode 100644
index 00000000..aec78449
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/services/MyService.cpp
@@ -0,0 +1,93 @@
+/* -*- 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 "MyService.h"
+#include "nsIServiceManager.h"
+#include "nsIGenericFactory.h"
+#include <stdio.h>
+
+////////////////////////////////////////////////////////////////////////////////
+
+class MyService : public IMyService {
+public:
+
+ NS_IMETHOD
+ Doit(void);
+
+ MyService();
+ NS_DECL_ISUPPORTS
+
+private:
+ ~MyService();
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// MyService Implementation
+
+NS_IMPL_ISUPPORTS1(MyService, IMyService)
+
+MyService::MyService()
+{
+ printf(" creating my service\n");
+}
+
+MyService::~MyService()
+{
+ printf(" destroying my service\n");
+}
+
+nsresult
+MyService::Doit(void)
+{
+ printf(" invoking my service\n");
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// MyServiceFactory Implementation
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(MyService)
+
+static const nsModuleComponentInfo myService_components[] = {
+ { "MyService", NS_IMYSERVICE_CID, nsnull, MyServiceConstructor },
+};
+
+NS_IMPL_NSGETMODULE(MyService, myService_components)
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/services/MyService.h b/src/libs/xpcom18a4/xpcom/tests/services/MyService.h
new file mode 100644
index 00000000..30b0e30a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/services/MyService.h
@@ -0,0 +1,69 @@
+/* -*- 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 ***** */
+
+#ifndef MyService_h__
+#define MyService_h__
+
+#include "nsISupports.h"
+
+#define NS_IMYSERVICE_IID \
+{ /* fedc3380-3648-11d2-8163-006008119d7a */ \
+ 0xfedc3380, \
+ 0x3648, \
+ 0x11d2, \
+ {0x81, 0x63, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \
+}
+
+class IMyService : public nsISupports {
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IMYSERVICE_IID)
+
+ NS_IMETHOD
+ Doit(void) = 0;
+
+};
+
+#define NS_IMYSERVICE_CID \
+{ /* 34876550-364b-11d2-8163-006008119d7a */ \
+ 0x34876550, \
+ 0x364b, \
+ 0x11d2, \
+ {0x81, 0x63, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \
+}
+
+#endif // MyService_h__
diff --git a/src/libs/xpcom18a4/xpcom/tests/services/win32.order b/src/libs/xpcom18a4/xpcom/tests/services/win32.order
new file mode 100644
index 00000000..132a4357
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/services/win32.order
@@ -0,0 +1 @@
+_NSCanUnload ; 1
diff --git a/src/libs/xpcom18a4/xpcom/tests/test.properties b/src/libs/xpcom18a4/xpcom/tests/test.properties
new file mode 100644
index 00000000..4ed37783
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/test.properties
@@ -0,0 +1,46 @@
+# ***** 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 *****
+1=1
+ 2=2
+3 =3
+ 4 =4
+5=5
+6= 6
+7=7
+8= 8
+# this is a comment
+9=this is the first part of a continued line \
+ and here is the 2nd part
diff --git a/src/libs/xpcom18a4/xpcom/tests/utils/WhatError.cpp b/src/libs/xpcom18a4/xpcom/tests/utils/WhatError.cpp
new file mode 100644
index 00000000..13942f3b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/utils/WhatError.cpp
@@ -0,0 +1,61 @@
+/* -*- 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 "nsError.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+int
+main(int argc, char **argv)
+{
+ int errorCode = 0;
+ char buffer[100];
+
+ if (argc != 2)
+ return -1;
+
+ sscanf( argv[1], "0x%x", &errorCode);
+ sprintf(buffer, "%d", errorCode);
+ sscanf( buffer, "%d", &errorCode);
+
+ printf( "Code: %d, Module: %d, Severity: %d\n",
+ NS_ERROR_GET_CODE(errorCode),
+ NS_ERROR_GET_MODULE(errorCode),
+ NS_ERROR_GET_SEVERITY(errorCode));
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/utils/cp.js b/src/libs/xpcom18a4/xpcom/tests/utils/cp.js
new file mode 100644
index 00000000..a38c120b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/utils/cp.js
@@ -0,0 +1,111 @@
+const nsILocalFile = Components.interfaces.nsILocalFile;
+var prefix = "";
+
+function rename(source, newName)
+{
+ try {
+ var sourceFile = Components.classes["@mozilla.org/file/local;1"].
+ createInstance(nsILocalFile);
+ sourceFile.initWithPath(source);
+
+ }
+ catch (e) {
+ dump("Could not create nsILocalFile\n");
+ }
+
+
+ try {
+ sourceFile.copyTo(null, newName);
+ }
+ catch (e) {
+ dump("error coping" + e + "\n");
+ }
+}
+
+
+function cp(source, dest, followLinks, newName)
+{
+ try {
+ var sourceFile = Components.classes["@mozilla.org/file/local;1"].
+ createInstance(nsILocalFile);
+ sourceFile.initWithPath(source);
+
+ var destFile = Components.classes["@mozilla.org/file/local;1"].
+ createInstance(nsILocalFile);
+ destFile.initWithPath(dest);
+
+ }
+ catch (e) {
+ dump("Could not create nsILocalFile\n");
+ }
+
+ try {
+
+ if (! destFile.isDirectory())
+ {
+ dump("destination not a directory!\n");
+ return;
+ }
+ }
+ catch (e) {
+ dump("error accessing dest");
+ }
+
+ try {
+ if (followLinks)
+ {
+ sourceFile.copyToFollowingLinks(destFile, newName);
+ }
+ else
+ {
+ sourceFile.copyTo(destFile, newName);
+ }
+ }
+ catch (e) {
+ dump("error coping" + e + "\n");
+ }
+}
+
+
+function mv(source, dest, followLinks, newName)
+{
+ try {
+ var sourceFile = Components.classes["@mozilla.org/file/local;1"].
+ createInstance(nsILocalFile);
+ sourceFile.initWithPath(source);
+
+ var destFile = Components.classes["@mozilla.org/file/local;1"].
+ createInstance(nsILocalFile);
+ destFile.initWithPath(dest);
+
+ }
+ catch (e) {
+ dump("Could not create nsILocalFile\n");
+ }
+
+ try {
+
+ if (! destFile.isDirectory())
+ {
+ dump("destination not a directory!\n");
+ return;
+ }
+ }
+ catch (e) {
+ dump("error accessing dest");
+ }
+
+ try {
+ if (followLinks)
+ {
+ sourceFile.moveToFollowingLinks(destFile, newName);
+ }
+ else
+ {
+ sourceFile.moveTo(destFile, newName);
+ }
+ }
+ catch (e) {
+ dump("error coping" + e + "\n");
+ }
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/utils/dirs.js b/src/libs/xpcom18a4/xpcom/tests/utils/dirs.js
new file mode 100644
index 00000000..c3fc2479
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/utils/dirs.js
@@ -0,0 +1,155 @@
+function dumpPathOfProperty(prop)
+{
+ dump(prop +' = ');
+
+ try
+ {
+ var file = dsprops.get(prop, Components.interfaces.nsIFile);
+ dump(file.path + '\n');
+ }
+ catch (ar)
+ {
+ dump('undefined or error \n');
+ }
+}
+
+var dscontractid = "@mozilla.org/file/directory_service;1"; // XXX old-style
+var ds = Components.classes[dscontractid].getService();
+var dsprops = ds.QueryInterface(Components.interfaces.nsIProperties);
+
+dump("xpcom locations::\n");
+// XPCOM Locations:
+ dumpPathOfProperty ("xpcom.currentProcess");
+ dumpPathOfProperty ("xpcom.currentProcess.componentRegistry");
+ dumpPathOfProperty ("xpcom.currentProcess.componentDirectory");
+ dumpPathOfProperty ("system.OS_DriveDirectory");
+ dumpPathOfProperty ("system.OS_TemporaryDirectory");
+ dumpPathOfProperty ("system.OS_CurrentProcessDirectory");
+ dumpPathOfProperty ("system.OS_CurrentWorkingDirectory");
+
+dump("Mac locations::\n");
+// Mac
+ dumpPathOfProperty ("system.SystemDirectory");
+ dumpPathOfProperty ("system.DesktopDirectory");
+ dumpPathOfProperty ("system.TrashDirectory");
+ dumpPathOfProperty ("system.StartupDirectory");
+ dumpPathOfProperty ("system.ShutdownDirectory");
+ dumpPathOfProperty ("system.AppleMenuDirectory");
+ dumpPathOfProperty ("system.ControlPanelDirectory");
+ dumpPathOfProperty ("system.ExtensionDirectory");
+ dumpPathOfProperty ("system.FontsDirectory");
+ dumpPathOfProperty ("system.PreferencesDirectory");
+ dumpPathOfProperty ("system.DocumentsDirectory");
+ dumpPathOfProperty ("system.InternetSearchDirectory");
+
+dump("PC locations::\n");
+// PC
+ dumpPathOfProperty ("system.SystemDirectory");
+ dumpPathOfProperty ("system.WindowsDirectory");
+ dumpPathOfProperty ("system.HomeDirectory");
+ dumpPathOfProperty ("system.Desktop");
+ dumpPathOfProperty ("system.Programs");
+ dumpPathOfProperty ("system.Controls");
+ dumpPathOfProperty ("system.Printers");
+ dumpPathOfProperty ("system.Personal");
+ dumpPathOfProperty ("system.Favorites");
+ dumpPathOfProperty ("system.Startup");
+ dumpPathOfProperty ("system.Recent");
+ dumpPathOfProperty ("system.Sendto");
+ dumpPathOfProperty ("system.Bitbucket");
+ dumpPathOfProperty ("system.Startmenu");
+ dumpPathOfProperty ("system.Desktopdirectory");
+ dumpPathOfProperty ("system.Drives");
+ dumpPathOfProperty ("system.Network");
+ dumpPathOfProperty ("system.Nethood");
+ dumpPathOfProperty ("system.Fonts");
+ dumpPathOfProperty ("system.Templates");
+ dumpPathOfProperty ("system.Common_Startmenu");
+ dumpPathOfProperty ("system.Common_Programs");
+ dumpPathOfProperty ("system.Common_Startup");
+ dumpPathOfProperty ("system.Common_Desktopdirectory");
+ dumpPathOfProperty ("system.Appdata");
+ dumpPathOfProperty ("system.Printhood");
+
+dump("Unix locations::\n");
+// Unix
+
+ dumpPathOfProperty ("system.LocalDirectory");
+ dumpPathOfProperty ("system.LibDirectory");
+ dumpPathOfProperty ("system.HomeDirectory");
+
+dump("Beos locations::\n");
+// Beos
+
+ dumpPathOfProperty ("system.SettingsDirectory");
+ dumpPathOfProperty ("system.HomeDirectory");
+ dumpPathOfProperty ("system.DesktopDirectory");
+ dumpPathOfProperty ("system.SystemDirectory");
+
+dump("OS2 locations::\n");
+// OS2
+ dumpPathOfProperty ("system.SystemDirectory");
+ dumpPathOfProperty ("system.OS2Directory");
+ dumpPathOfProperty ("system.DesktopDirectory");
+
+
+// XPFE locations:
+
+
+// application Directories:
+ dumpPathOfProperty ("app.res.directory");
+ dumpPathOfProperty ("app.defaults.directory");
+ dumpPathOfProperty ("app.chrome.directory");
+ dumpPathOfProperty ("app.chrome.user.directory");
+ dumpPathOfProperty ("app.plugins.directory");
+
+// application Files:
+
+ dumpPathOfProperty ("app.registry.file.4");
+ dumpPathOfProperty ("app.registry.file.5");
+ dumpPathOfProperty ("app.local.store.file.5");
+ dumpPathOfProperty ("app.history.file.5");
+ dumpPathOfProperty ("app.user.panels.5");
+
+// Preferences:
+
+// dumpPathOfProperty ("app.prefs.directory.3");
+// dumpPathOfProperty ("app.prefs.directory.4");
+ dumpPathOfProperty ("app.prefs.directory.5");
+ dumpPathOfProperty ("app.pref.default.directory.5");
+
+// dumpPathOfProperty ("app.prefs.file.3");
+// dumpPathOfProperty ("app.prefs.file.4");
+ dumpPathOfProperty ("app.prefs.file.5");
+
+// Profile:
+
+// dumpPathOfProperty ("app.profile.user.directory.3");
+// dumpPathOfProperty ("app.profile.user.directory.4");
+ dumpPathOfProperty ("app.profile.user.directory.5");
+// dumpPathOfProperty ("app.profile.default.user.directory.3");
+// dumpPathOfProperty ("app.profile.default.user.directory.4");
+ dumpPathOfProperty ("app.profile.default.user.directory.5");
+// dumpPathOfProperty ("app.profile.defaults.directory.3");
+// dumpPathOfProperty ("app.profile.defaults.directory.4");
+ dumpPathOfProperty ("app.profile.defaults.directory.5");
+
+
+
+// Bookmarks:
+
+// dumpPathOfProperty ("app.bookmark.file.3");
+// dumpPathOfProperty ("app.bookmark.file.4");
+ dumpPathOfProperty ("app.bookmark.file.5");
+
+// Search
+ dumpPathOfProperty ("app.search.file.5");
+ dumpPathOfProperty ("app.search.directory.5");
+
+
+// MailNews:
+
+ dumpPathOfProperty ("app.mail.directory.5");
+ dumpPathOfProperty ("app.mail.imap.directory.5");
+ dumpPathOfProperty ("app.mail.news.directory.5");
+ dumpPathOfProperty ("app.mail.messenger.cache.directory.5");
diff --git a/src/libs/xpcom18a4/xpcom/tests/utils/ls.js b/src/libs/xpcom18a4/xpcom/tests/utils/ls.js
new file mode 100644
index 00000000..8ae62f06
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/utils/ls.js
@@ -0,0 +1,64 @@
+const nsILocalFile = Components.interfaces.nsILocalFile;
+var prefix = "";
+
+function ls(path, recur)
+{
+ var file = Components.classes["@mozilla.org/file/local;1"].
+ createInstance(nsILocalFile);
+ try {
+ file.initWithPath( path );
+
+ if (file.isDirectory() && arguments.length == 1)
+ ls_dir(file, recur);
+ else
+ ls_file(file, recur);
+ }
+ catch (e) {
+ dump("Error Returned " + e + "\n");
+ }
+}
+function ls_file(file, recur)
+{
+ dump(prefix);
+
+ try {
+ if (file.isDirectory()) {
+ dump("directory " + file.leafName + "\n");
+ if(recur)
+ ls_dir(file, true);
+ return;
+ }
+
+ dump(file.leafName + " " + file.fileSize);
+ if (file.isSymlink())
+ dump(" -> " + file.target);
+ dump("\n");
+ }
+
+ catch (e) {
+ dump(file.leafName + " (error accessing)\n");
+ }
+}
+
+function ls_dir(file, recur)
+{
+ var leafName = file.leafName;
+
+ var old = prefix;
+ prefix = prefix + " ";
+
+ iter = file.directoryEntries;
+ dump(iter + "\n");
+
+ foreach_iter(iter,
+ function (file) { ls_file(file, recur); });
+ prefix = old;
+}
+
+function foreach_iter(iter, fun)
+{
+ while (iter.hasMoreElements()) {
+ var item = iter.getNext().QueryInterface(nsILocalFile);
+ fun(item);
+ }
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/windows/.cvsignore b/src/libs/xpcom18a4/xpcom/tests/windows/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/windows/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/tests/windows/Makefile.in b/src/libs/xpcom18a4/xpcom/tests/windows/Makefile.in
new file mode 100644
index 00000000..8bd782c8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/windows/Makefile.in
@@ -0,0 +1,60 @@
+#
+# ***** 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
+# 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
+
+REQUIRES = string
+
+CPPSRCS = TestCOM.cpp
+#TestHelloXPLoop.cpp nsStringTest.cpp
+
+SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))
+
+include $(topsrcdir)/config/config.mk
+
+include $(topsrcdir)/config/rules.mk
+
+OS_LIBS = $(call EXPAND_LIBNAME,rpcrt4 uuid)
+
+LIBS = $(XPCOM_LIBS) $(NSPR_LIBS)
diff --git a/src/libs/xpcom18a4/xpcom/tests/windows/TestCOM.cpp b/src/libs/xpcom18a4/xpcom/tests/windows/TestCOM.cpp
new file mode 100644
index 00000000..b76eccb4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/windows/TestCOM.cpp
@@ -0,0 +1,181 @@
+/* -*- 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):
+ * 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 <windows.h>
+#include <unknwn.h>
+#include <stdio.h>
+#include "nsISupports.h"
+#include "nsIFactory.h"
+
+// unknwn.h is needed to build with WIN32_LEAN_AND_MEAN
+#include <unknwn.h>
+
+// {5846BA30-B856-11d1-A98A-00805F8A7AC4}
+#define NS_ITEST_COM_IID \
+{ 0x5846ba30, 0xb856, 0x11d1, \
+ { 0xa9, 0x8a, 0x0, 0x80, 0x5f, 0x8a, 0x7a, 0xc4 } }
+
+class nsITestCom: public nsISupports
+{
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_ITEST_COM_IID)
+ NS_IMETHOD Test() = 0;
+};
+
+/*
+ * nsTestCom
+ */
+
+class nsTestCom: public nsITestCom {
+ NS_DECL_ISUPPORTS
+
+public:
+ nsTestCom() {
+ }
+
+ NS_IMETHOD Test() {
+ printf("Accessed nsITestCom::Test() from COM\n");
+ return NS_OK;
+ }
+
+private:
+ ~nsTestCom() {
+ printf("nsTestCom instance successfully deleted\n");
+ }
+};
+
+NS_IMPL_QUERY_INTERFACE1(nsTestCom, nsITestCom)
+
+nsrefcnt nsTestCom::AddRef()
+{
+ nsrefcnt res = ++mRefCnt;
+ NS_LOG_ADDREF(this, mRefCnt, "nsTestCom", sizeof(*this));
+ printf("nsTestCom: Adding ref = %d\n", res);
+ return res;
+}
+
+nsrefcnt nsTestCom::Release()
+{
+ nsrefcnt res = --mRefCnt;
+ NS_LOG_RELEASE(this, mRefCnt, "nsTestCom");
+ printf("nsTestCom: Releasing = %d\n", res);
+ if (res == 0) {
+ delete this;
+ }
+ return res;
+}
+
+class nsTestComFactory: public nsIFactory {
+ NS_DECL_ISUPPORTS
+public:
+ nsTestComFactory() {
+ }
+
+ NS_IMETHOD CreateInstance(nsISupports *aOuter,
+ const nsIID &aIID,
+ void **aResult);
+
+ NS_IMETHOD LockFactory(PRBool aLock) {
+ printf("nsTestComFactory: ");
+ printf("%s", (aLock == PR_TRUE ? "Locking server" : "Unlocking server"));
+ printf("\n");
+ return S_OK;
+ }
+};
+
+NS_IMPL_ISUPPORTS1(nsTestComFactory, nsIFactory)
+
+nsresult nsTestComFactory::CreateInstance(nsISupports *aOuter,
+ const nsIID &aIID,
+ void **aResult)
+{
+ if (aOuter != NULL) {
+ return NS_ERROR_NO_AGGREGATION;
+ }
+
+ nsTestCom *t = new nsTestCom();
+
+ if (t == NULL) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ NS_ADDREF(t);
+ nsresult res = t->QueryInterface(aIID, aResult);
+ NS_RELEASE(t);
+
+ if (NS_SUCCEEDED(res)) {
+ printf("nsTestComFactory: successfully created nsTestCom instance\n");
+ }
+
+ return res;
+}
+
+/*
+ * main
+ */
+
+int main(int argc, char *argv[])
+{
+ nsTestComFactory *inst = new nsTestComFactory();
+ IClassFactory *iFactory;
+ inst->QueryInterface(NS_GET_IID(nsIFactory), (void **) &iFactory);
+
+ IUnknown *iUnknown;
+ nsITestCom *iTestCom;
+
+ nsresult res;
+ iFactory->LockServer(TRUE);
+ res = iFactory->CreateInstance(NULL,
+ IID_IUnknown,
+ (void **) &iUnknown);
+ iFactory->LockServer(FALSE);
+
+ GUID testGUID = NS_ITEST_COM_IID;
+ HRESULT hres;
+ hres= iUnknown->QueryInterface(testGUID,
+ (void **) &iTestCom);
+
+ iTestCom->Test();
+
+ iUnknown->Release();
+ iTestCom->Release();
+ iFactory->Release();
+
+ return 0;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/windows/TestHelloXPLoop.cpp b/src/libs/xpcom18a4/xpcom/tests/windows/TestHelloXPLoop.cpp
new file mode 100644
index 00000000..fdfa1218
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/windows/TestHelloXPLoop.cpp
@@ -0,0 +1,177 @@
+/* -*- 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 the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Travis Bogard <travis@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 "nsIServiceManager.h"
+#include "nsCOMPtr.h"
+#include "nsCNativeApp.h"
+#include "nsIEventLoop.h"
+#include <windows.h>
+
+static NS_DEFINE_CID(kNativeAppCID, NS_NATIVE_APP_CID);
+
+LRESULT CALLBACK WndProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+void ErrorBox(LPSTR text)
+{
+ MessageBox(NULL, text, "XP Event Loop", MB_OK | MB_ICONSTOP);
+}
+
+void InfoBox(LPSTR text)
+{
+ MessageBox(NULL, text, "XP Event Loop", MB_OK | MB_ICONINFORMATION);
+}
+
+int WINAPI WinMain(HINSTANCE inst,
+ HINSTANCE prevInstance,
+ LPSTR lpszCmdLine,
+ int nShowCmd)
+{
+ char* lpszAppName = "HelloWorld";
+ HWND wnd;
+ WNDCLASSEX wndclass;
+ int retCode;
+
+ { // Needed to scope all nsCOMPtr within XPCOM Init and Shutdown
+ nsresult rv;
+ nsCOMPtr<nsIServiceManager> servMan;
+ rv = NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull);
+ if(NS_FAILED(rv))
+ {
+ ErrorBox("Failed to initalize xpcom.");
+ return -1;
+ }
+
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan);
+ NS_ASSERTION(registrar, "Null nsIComponentRegistrar");
+ registrar->AutoRegister(nsnull);
+
+ nsCOMPtr<nsINativeApp> nativeAppService(do_GetService(kNativeAppCID, &rv));
+
+ if(NS_FAILED(rv))
+ {
+ ErrorBox("Failed to get nativeAppService");
+ return -1;
+ }
+ wndclass.cbSize = sizeof(wndclass);
+ wndclass.style = CS_HREDRAW | CS_VREDRAW;
+ wndclass.lpfnWndProc = WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = inst;
+ wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = lpszAppName;
+ wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
+
+ RegisterClassEx(&wndclass) ;
+
+ wnd = CreateWindow(lpszAppName, "The Hello World",
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ NULL, NULL, inst, NULL);
+
+ ShowWindow(wnd, nShowCmd);
+ UpdateWindow(wnd);
+
+ nsCOMPtr<nsIEventLoop> eventLoop;
+
+ if(NS_FAILED(nativeAppService->CreateEventLoop(L"_MainLoop",
+ nsEventLoopTypes::MainAppLoop, getter_AddRefs(eventLoop))))
+ {
+ ErrorBox("Failed to create event Loop");
+ return 0;
+ }
+
+ eventLoop->Run(nsnull, nsnull, nsnull, &retCode);
+ eventLoop = nsnull; // Clear out before Shutting down XPCOM
+
+ InfoBox("Hello World app is out of loop");
+ }
+ NS_ShutdownXPCOM(nsnull);
+ InfoBox("Hello World app is exiting");
+ return retCode;
+}
+
+LRESULT CALLBACK WndProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HDC hdc;
+ PAINTSTRUCT ps;
+ RECT rect;
+
+ switch(msg)
+ {
+ case WM_PAINT:
+ hdc = BeginPaint(wnd, &ps);
+
+ GetClientRect(wnd, &rect);
+
+ DrawText(hdc, "Hello, XP Event Loop!", -1, &rect,
+ DT_SINGLELINE | DT_CENTER | DT_VCENTER);
+
+ EndPaint(wnd, &ps);
+ return 0;
+
+ case WM_DESTROY:
+ {
+ nsresult rv;
+ nsCOMPtr<nsINativeApp> nativeAppService =
+ do_GetService(kNativeAppCID, &rv);
+ if(NS_FAILED(rv))
+ {
+ ErrorBox("Could not get NativeAppService");
+ return 0;
+ }
+ nsCOMPtr<nsIEventLoop> eventLoop;
+
+ if(NS_FAILED(nativeAppService->FindEventLoop(L"_MainLoop",
+ getter_AddRefs(eventLoop))))
+ {
+ ErrorBox("Failed to find event Loop");
+ return 0;
+ }
+ eventLoop->Exit(0);
+ }
+ return 0;
+ }
+
+ return DefWindowProc(wnd, msg, wParam, lParam);
+}
diff --git a/src/libs/xpcom18a4/xpcom/tests/windows/nsStringTest.cpp b/src/libs/xpcom18a4/xpcom/tests/windows/nsStringTest.cpp
new file mode 100644
index 00000000..6719ed38
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/windows/nsStringTest.cpp
@@ -0,0 +1,33 @@
+
+#include <iostream.h>
+#include "nsStr.h"
+#include "nsStringTest2.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+
+int main(){
+
+ nsString temp("\t\t\n\r\n\r25,* \t \n\n \t");
+ temp.CompressWhitespace();
+
+ nsString temp1("\t\t\n\r\n\r25,* \t \n\n \t");
+ temp1.CompressSet("\t\n\r ",' ',false,false);
+
+ nsString temp3("");
+ char* s = ToNewCString(temp3);
+ delete s;
+
+ char* f = ToNewCString(nsAutoString(""));
+ char* f1 = ToNewCString(nsCAutoString(""));
+ delete f;
+ delete f1;
+
+
+ CStringTester gStringTester;
+
+ gStringTester.TestI18nString();
+
+ return 0;
+}
+
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/windows/nsStringTest.h b/src/libs/xpcom18a4/xpcom/tests/windows/nsStringTest.h
new file mode 100644
index 00000000..8244a5a1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/windows/nsStringTest.h
@@ -0,0 +1,2277 @@
+/********************************************************************************************
+ *
+ * MODULES NOTES:
+ *
+ * This file is designed to help test the new nsString classes.
+ *
+ * Contributor(s):
+ * Rick Gessner <rickg@netscape.com>
+ *
+ * History:
+ *
+ * 02.29.2000: Original files (rickg)
+ * 03.02.2000: Flesh out the interface to be compatible with old library (rickg)
+ *
+ ********************************************************************************************/
+
+#ifndef _STRINGTEST
+#define _STRINGTEST
+
+
+#include "nsString.h"
+#include "nsReadableUtils.h"
+#include <time.h>
+
+#define USE_STL
+
+#ifdef USE_STL
+#include <string>
+using namespace std;
+#endif
+
+#define USE_WIDE 1
+#ifdef USE_WIDE
+ #define stringtype nsString
+ #define astringtype nsAutoString
+ #define chartype PRUnichar
+#else
+ #define stringtype nsCString
+ #define astringtype nsCAutoString
+ #define chartype char
+#endif
+
+
+#include <stdio.h>
+
+
+
+static const char* kConstructorError = "constructor error";
+static const char* kComparisonError = "Comparision error!";
+static const char* kEqualsError = "Equals error!";
+
+static char* kNumbers[]={"0123456789","0\01\02\03\04\05\06\07\08\09\0\0\0"};
+static char* kLetters[]={"abcdefghij","a\0b\0c\0d\0e\0f\0g\0h\0i\0j\0\0\0"};
+static char* kAAA[]={"AAA","A\0A\0A\0\0\0"};
+static char* kBBB[]={"BBB","B\0B\0B\0\0\0"};
+static char* kHello[]={"hello","h\0e\0l\0l\0o\0\0\0"};
+static char* kWSHello[]={" hello "," \0 \0h\0e\0l\0l\0o\0 \0 \0\0\0"};
+
+
+
+/********************************************************
+
+ This class's only purpose in life is to test the
+ netscape string library. We exercise the string
+ API's here, and do a bit of performance testing
+ against the standard c++ library string (from STL).
+
+ ********************************************************/
+class CStringTester {
+public:
+ CStringTester() {
+ TestConstructors();
+ TestAutoStrings();
+ TestAppend();
+ TestAssignAndAdd();
+ TestInsert();
+ TestDelete();
+ TestTruncate();
+ TestLogical();
+ TestLexomorphic();
+ TestCreators();
+ TestNumerics();
+ TestExtractors();
+ TestSearching();
+ TestSubsumables();
+ TestRandomOps();
+ TestReplace();
+ TestRegressions();
+ TestStringPerformance();
+ TestWideStringPerformance();
+ }
+protected:
+ int TestConstructors();
+ int TestLogical();
+ int TestAutoStrings();
+ int TestAppend();
+ int TestAssignAndAdd();
+ int TestInsert();
+ int TestDelete();
+ int TestTruncate();
+ int TestLexomorphic();
+ int TestCreators();
+ int TestNumerics();
+ int TestExtractors();
+ int TestSearching();
+ int TestSubsumables();
+ int TestRandomOps();
+ int TestReplace();
+ int TestStringPerformance();
+ int TestWideStringPerformance();
+ int TestRegressions();
+};
+
+
+class Stopwatch {
+public:
+ Stopwatch() {
+ start=clock();
+ }
+
+ void Stop() {
+ stop=clock();
+ }
+
+ double Elapsed() {
+ return (double)(stop - start) / CLOCKS_PER_SEC;
+ }
+
+ void Print(const char* msg= "") {
+ printf("%s %f\n",msg,Elapsed());
+ }
+
+ clock_t start,stop;
+};
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestSearching(){
+ int result=0;
+
+
+
+ PRUnichar pbuf[10]={'e','f','g',0};
+ PRUnichar pbuf2[10]={'a','b','c',0};
+
+
+ //Since there is so much ground to cover with searching, we use a typedef to
+ //allow you to vary the string type being searched...
+
+
+ stringtype theDest("abcdefghijkabc");
+ nsString s1("ijk");
+ nsCString c1("ijk");
+
+ PRInt32 pos=theDest.Find(pbuf);
+ NS_ASSERTION(pos==4,"Error: Find routine");
+
+ pos=theDest.Find(pbuf2,PR_FALSE,-1);
+ NS_ASSERTION(pos==0,"Error: Find routine");
+
+ pos=theDest.Find(pbuf2,PR_FALSE,pos+1);
+ NS_ASSERTION(pos==11,"Error: Find routine");
+
+ pos=theDest.FindChar('a');
+ NS_ASSERTION(pos==0,"Error: Find routine");
+
+ pos=theDest.FindChar('a',PR_FALSE,pos+1);
+ NS_ASSERTION(pos==11,"Error: Find routine");
+
+ pos=theDest.Find("efg");
+ NS_ASSERTION(pos==4,"Error: Find routine");
+
+ pos=theDest.Find("EFG",PR_TRUE);
+ NS_ASSERTION(pos==4,"Error: Find routine");
+
+ pos=theDest.FindChar('d');
+ NS_ASSERTION(pos==3,"Error: Find char routine");
+
+ pos=theDest.Find(s1);
+ NS_ASSERTION(pos==8,"Error: Find char routine");
+
+ pos=theDest.FindCharInSet("12k");
+ NS_ASSERTION(pos==10,"Error: Findcharinset routine");
+
+ pos=theDest.FindCharInSet(pbuf);
+ NS_ASSERTION(pos==4,"Error: Findcharinset routine");
+
+ pos=theDest.FindCharInSet(s1);
+ NS_ASSERTION(pos==8,"Error: Findcharinset routine");
+
+ pos=theDest.Find("efg",PR_FALSE,2);
+ NS_ASSERTION(pos==4,"Error: Find routine");
+
+ pos=theDest.RFindCharInSet("12k");
+ NS_ASSERTION(pos==10,"Error: RFindcharinset routine");
+
+ pos=theDest.RFindCharInSet("xyz");
+ NS_ASSERTION(pos==-1,"Error: RFindcharinset routine");
+
+ pos=theDest.RFindCharInSet(pbuf);
+ NS_ASSERTION(pos==6,"Error: RFindcharinset routine");
+
+ pos=theDest.RFindCharInSet(s1);
+ NS_ASSERTION(pos==10,"Error: RFindcharinset routine");
+
+ pos=theDest.RFind("efg");
+ NS_ASSERTION(pos==4,"Error: RFind routine");
+
+ pos=theDest.RFind("xxx");
+ NS_ASSERTION(pos==-1,"Error: RFind routine"); //this should fail
+
+ pos=theDest.RFind("");
+ NS_ASSERTION(pos==-1,"Error: RFind routine"); //this too should fail.
+
+ pos=theDest.RFindChar('a',PR_FALSE,4);
+ NS_ASSERTION(pos==-1,"Error: RFind routine");
+
+
+ //now try searching with FindChar using offset and count...
+ {
+ stringtype s1("hello there rick");
+
+ PRInt32 pos=s1.FindChar('r'); //this will search from the beginning, and for the length of the string.
+ NS_ASSERTION(pos==9,"Error: FindChar() with offset and count");
+
+ pos=s1.FindChar('r',PR_FALSE,0,5); //this will search from the front using count. THIS WILL FAIL!
+ NS_ASSERTION(pos==-1,"Error: FindChar() with offset and count");
+
+ pos=s1.FindChar('r',PR_FALSE,0,10); //this will search from the front using count. THIS WILL SUCCEED!
+ NS_ASSERTION(pos==9,"Error: FindChar() with offset and count");
+
+ pos=s1.FindChar('i',PR_FALSE,5,5); //this will search from the middle using count. THIS WILL FAIL!
+ NS_ASSERTION(pos==-1,"Error: FindChar() with offset and count");
+
+ pos=s1.FindChar('i',PR_FALSE,5,10); //this will search from the middle using count. THIS WILL SUCCEED!
+ NS_ASSERTION(pos==13,"Error: FindChar() with offset and count");
+
+ pos=s1.FindChar('k',PR_FALSE,10,2); //this will search from near the end using count. THIS WILL FAIL!
+ NS_ASSERTION(pos==-1,"Error: FindChar() with offset and count");
+
+ pos=s1.FindChar('k',PR_FALSE,10,7); //this will search from near the end using count. THIS WILL SUCCEED!
+ NS_ASSERTION(pos==15,"Error: FindChar() with offset and count");
+
+ //now let's try a few with bad data...
+
+ pos=s1.FindChar('k',PR_FALSE,100,2); //this will search from a bad offset. THIS WILL FAIL!
+ NS_ASSERTION(pos==-1,"Error: FindChar() with offset and count");
+
+ pos=s1.FindChar('k',PR_FALSE,10,0); //this will search for a bad count. THIS WILL FAIL!
+ NS_ASSERTION(pos==-1,"Error: FindChar() with offset and count");
+
+ pos=s1.FindChar('k',PR_FALSE,10,20); //this will search for a bad count. THIS WILL SUCCEED!
+ NS_ASSERTION(pos==15,"Error: FindChar() with offset and count");
+
+ pos=s1.FindChar('k',PR_FALSE,10,4); //this will search for a bad count. THIS WILL FAIL!
+ NS_ASSERTION(pos==-1,"Error: FindChar() with offset and count");
+
+ pos=10;
+ }
+
+ //now try searching with RFindChar using offset and count...
+ {
+ stringtype s1("hello there rick");
+
+ PRInt32 pos=s1.RFindChar('o'); //this will search from the end, and for the length of the string.
+ NS_ASSERTION(pos==4,"Error: RFindChar() with offset and count");
+
+ pos=s1.RFindChar('i'); //this will search from the end, and for the length of the string.
+ NS_ASSERTION(pos==13,"Error: RFindChar() with offset and count");
+
+ pos=s1.RFindChar(' ',PR_FALSE,-1,4); //this will search from the end, and for the length of the string.
+ NS_ASSERTION(pos==-1,"Error: RFindChar() with offset and count"); //THIS WILL FAIL
+
+ pos=s1.RFindChar(' ',PR_FALSE,12,1); //this will search from the middle, and for the length of 1.
+ NS_ASSERTION(pos==-1,"Error: RFindChar() with offset and count"); //THIS WILL FAIL
+
+ pos=s1.RFindChar(' ',PR_FALSE,12,2); //this will search from the middle, and for the length of 2.
+ NS_ASSERTION(pos==11,"Error: RFindChar() with offset and count"); //THIS WILL SUCCEED
+
+ pos=s1.RFindChar('o',PR_FALSE,-1,5); //this will search from the end using count. THIS WILL FAIL!
+ NS_ASSERTION(pos==-1,"Error: RFindChar() with offset and count");
+
+ pos=s1.RFindChar('o',PR_FALSE,-1,12); //this will search from the front using count. THIS WILL SUCCEED!
+ NS_ASSERTION(pos==4,"Error: RFindChar() with offset and count");
+
+ pos=s1.RFindChar('l',PR_FALSE,8,2); //this will search from the middle using count. THIS WILL FAIL!
+ NS_ASSERTION(pos==-1,"Error: RFindChar() with offset and count");
+
+ pos=s1.RFindChar('l',PR_FALSE,8,7); //this will search from the middle using count. THIS WILL SUCCEED!
+ NS_ASSERTION(pos==3,"Error: RFindChar() with offset and count");
+
+//***
+
+ pos=s1.RFindChar('h',PR_FALSE,3,2); //this will search from near the end using count. THIS WILL FAIL!
+ NS_ASSERTION(pos==-1,"Error: RFindChar() with offset and count");
+
+ pos=s1.RFindChar('h',PR_FALSE,3,7); //this will search from near the end using count. THIS WILL SUCCEED!
+ NS_ASSERTION(pos==0,"Error: RFindChar() with offset and count");
+
+ //now let's try a few with bad data...
+
+ pos=s1.RFindChar('k',PR_FALSE,100,2); //this will search from a bad offset. THIS WILL FAIL!
+ NS_ASSERTION(pos==-1,"Error: RFindChar() with offset and count");
+
+ pos=s1.RFindChar('k',PR_FALSE,10,0); //this will search for a bad count. THIS WILL FAIL!
+ NS_ASSERTION(pos==-1,"Error: RFindChar() with offset and count");
+
+ pos=10;
+ }
+
+ //now try searching with Find() using offset and count...
+ {
+ stringtype s1("hello there rick");
+
+ PRInt32 pos= s1.Find("there",PR_FALSE,0,4); //first search from front using offset
+ NS_ASSERTION(pos==-1,"Error: Find() with offset and count"); //THIS WILL FAIL
+
+ pos= s1.Find("there",PR_FALSE,0,8); //first search from front using count
+ NS_ASSERTION(pos==6,"Error: Find) with offset and count"); //THIS WILL SUCCEED
+
+ pos= s1.Find("there",PR_FALSE,4,1); //first search from front using count
+ NS_ASSERTION(pos==-1,"Error: Find() with offset and count"); //THIS WILL FAIL
+
+ pos= s1.Find("there",PR_FALSE,5,2); //first search from front using count
+ NS_ASSERTION(pos==6,"Error: Find() with offset and count"); //THIS WILL SUCCEED
+
+ pos= s1.Find("there",PR_FALSE,6,1); //first search from front using count
+ NS_ASSERTION(pos==6,"Error: Find() with offset and count"); //THIS WILL SUCCEED
+
+ pos= s1.Find("there",PR_FALSE,6,0); //first search from front using a bogus count
+ NS_ASSERTION(pos==-1,"Error: Find() with offset and count"); //THIS WILL FAIL
+
+ pos= s1.Find("k",PR_FALSE,15,1); //first search from end using a count
+ NS_ASSERTION(pos==15,"Error: Find() with offset and count"); //THIS WILL SUCCEED
+
+ pos= s1.Find("k",PR_FALSE,15,10); //first search from end using a LARGE count
+ NS_ASSERTION(pos==15,"Error: Find() with offset and count"); //THIS WILL SUCCEED
+
+ pos= s1.Find("k",PR_FALSE,25,10); //first search from bogus offset using a LARGE count
+ NS_ASSERTION(pos==-1,"Error: Find() with offset and count"); //THIS WILL FAIL
+
+ pos=10;
+ }
+
+ //now try substringsearching with RFind() using offset and count...
+ {
+ nsString s1("abcdefghijklmnopqrstuvwxyz");
+
+ PRInt32 pos= s1.RFind("ghi"); //first search from end using count
+ NS_ASSERTION(pos==6,"Error: RFind() with offset and count"); //THIS WILL SUCCEED!
+
+ pos= s1.RFind("nop",PR_FALSE,-1,4); //first search from end using count
+ NS_ASSERTION(pos==-1,"Error: RFind() with offset and count"); //THIS WILL FAIL
+
+ pos= s1.RFind("nop",PR_FALSE,-1,15); //first search from end using count
+ NS_ASSERTION(pos==13,"Error: RFind() with offset and count"); //THIS WILL SUCCEED
+
+ pos= s1.RFind("nop",PR_FALSE,16,3); //first search from middle using count
+ NS_ASSERTION(pos==-1,"Error: RFind() with offset and count"); //THIS WILL FAIL
+
+ pos= s1.RFind("nop",PR_FALSE,16,7); //first search from middle using count
+ NS_ASSERTION(pos==13,"Error: RFind() with offset and count"); //THIS WILL SUCCEED
+
+ pos= s1.RFind("nop",PR_FALSE,0,1); //first search from front using count
+ NS_ASSERTION(pos==-1,"Error: RFind() with offset and count"); //THIS WILL FAIL
+
+ pos= s1.RFind("abc",PR_FALSE,0,1); //first search from middle using count
+ NS_ASSERTION(pos==0,"Error: RFind() with offset and count"); //THIS WILL SUCCEED
+
+ pos= s1.RFind("foo",PR_FALSE,10,100); //first search from front using bogus count
+ NS_ASSERTION(pos==-1,"Error: RFind() with offset and count"); //THIS WILL FAIL
+
+ pos= s1.RFind("ghi",PR_FALSE,30,1); //first search from middle using bogus offset
+ NS_ASSERTION(pos==-1,"Error: RFind() with offset and count"); //THIS WILL FAIL
+
+ pos=10;
+ }
+
+ //Various UNICODE tests...
+ {
+ //do some searching against chinese unicode chars...
+
+ PRUnichar chinese[] = {0x4e41,0x4e42, 0x4e43, 0x0000}; // 3 chinese unicode
+
+ nsString T2(chinese);
+ nsString T2copy(chinese);
+
+ pos = T2.FindCharInSet("A");
+ NS_ASSERTION(kNotFound==pos,"Error in FindCharInSet");
+
+ pos=T2.RFindCharInSet("A",2);
+ NS_ASSERTION(kNotFound==pos,"Error in RFindCharInSet");
+
+ pos=T2.Find("A", PR_FALSE, 0, 1);
+ NS_ASSERTION(kNotFound==pos,"Error in Find");
+
+ pos=T2.RFind("A", PR_FALSE, 2, 1);
+ NS_ASSERTION(kNotFound==pos,"Error in RFind");
+
+ T2.ReplaceChar("A",' ');
+ NS_ASSERTION(T2==T2copy,"Error in ReplaceChar");
+
+ //Here's the 3rd FTang unicode test...
+
+ static char test4[]="ABCDEF";
+ static char test4b[]=" BCDEF";
+
+ PRUnichar test5[]={0x4e41, 0x0000};
+ PRUnichar test6[]={0x0041, 0x0000};
+
+ nsCString T4(test4);
+ nsCString T4copy(test4);
+ nsCString T4copyb(test4b);
+ nsCString T5(test5);
+ nsCString T6(test6);
+
+ pos = T4.FindCharInSet(T5.get());
+ NS_ASSERTION(0==pos,"Error in FindcharInSet"); //This should succeed.
+
+ pos = T4.FindCharInSet(T6.get());
+ NS_ASSERTION(kNotFound<pos,"Error in FindcharInSet"); //This should succeed.
+
+ pos = T4.RFindCharInSet(T5.get(),2);
+ NS_ASSERTION(0==pos,"Error in RFindCharInSet"); //This should fail.
+
+ pos = T4.RFindCharInSet(T6.get(),2);
+ NS_ASSERTION(kNotFound<pos,"Error in RFindCharInSet"); //This should fail.
+
+ pos = T4.Find(T5.get(), PR_FALSE, 0, 1);
+ NS_ASSERTION(0==pos,"Error in Find"); //This should succeed.
+
+ pos= T4.Find(T6.get(), PR_FALSE, 0, 1);
+ NS_ASSERTION(kNotFound<pos,"Error in Find"); //This should fail.
+
+ pos = T4.RFind(T5.get(), PR_FALSE, 2, 1);
+ NS_ASSERTION(kNotFound==pos,"Error in RFind");
+
+ pos =T4.RFind(T6.get(), PR_FALSE, 2, 1);
+ NS_ASSERTION(kNotFound==pos,"Error in RFind");
+
+
+/*
+ NOT WORKING IN NEW STRING YET...
+
+ T4.ReplaceChar(PRUnichar(0x4E41),PRUnichar(' '));
+ if(T4 != T4copy)
+ printf("nsCString::ReplaceChar(PRUnichar, PRUnichar) error- replace when it should not\n");
+
+ T4 = test4;
+ T4.ReplaceChar(PRUnichar(0x0041),PRUnichar(' '));
+ if(T4 != T4copyb)
+ printf("nsCString::ReplaceChar(PRUnichar, PRUnichar) error- not replace when it should\n");
+
+*/
+
+ }
+
+ return result;
+}
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestConstructors(){
+ int result=0;
+ PRUnichar pbuf[10]={'f','o','o',0};
+ PRUnichar* buf=pbuf;
+
+ nsString s1("hello world");
+ nsCString c1("what's up");
+
+
+ //Test nsCString constructors...
+ {
+ nsCString temp0;
+ nsCString temp1(s1);
+ NS_ASSERTION(temp1==s1,"nsCString Constructor error");
+
+ nsCString temp2(c1);
+ NS_ASSERTION(temp2==c1,"nsCString Constructor error");
+
+ nsCString temp3("hello world");
+ NS_ASSERTION(temp3=="hello world","nsCString Constructor error");
+
+ nsCString temp4(pbuf);
+ NS_ASSERTION(temp4==pbuf,"nsCString Constructor error");
+
+ nsCString temp5('a');
+ NS_ASSERTION(temp5=="a","nsCString Constructor error");
+
+ nsCString temp6(PRUnichar('a'));
+ NS_ASSERTION(temp5=="a","nsCString Constructor error");
+ }
+
+ //now just for fun, let's construct 2byte from 1byte and back...
+ {
+ nsCString temp0("hello");
+ nsString temp1(temp0);
+ nsCString temp2(temp1);
+ }
+
+ return result;
+}
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestLogical(){
+ int result=0;
+ stringtype temp8("aaaa");
+ stringtype temp8a("AAAA");
+ stringtype temp9("bbbb");
+
+ const char* aaaa="aaaa";
+ const char* bbbb="bbbb";
+
+
+ //First, test a known error that got checked into the tree...
+ {
+ nsString mURL("file:///c|/test/foo.txt");
+ PRBool result=mURL.Equals("file:/",PR_FALSE);
+ NS_ASSERTION(!result,kEqualsError);
+ result=mURL.Equals("file:/",PR_FALSE,5);
+ NS_ASSERTION(result,kEqualsError);
+ result=mURL.Equals("file:/",PR_FALSE,-1);
+ NS_ASSERTION(!result,kEqualsError);
+
+ nsString s1("rick");
+ result=s1.Equals("rick",PR_FALSE,6);
+ result++;
+ }
+
+
+ {
+ //this little piece of code tests to see whether the PL_strcmp series works
+ //correctly even when we have strings whose buffers contain nulls.
+
+ char *buf1 = "what's up \0\0 doc?";
+ char *buf2 = "what's up \0\0 dog?";
+
+ nsString s1(buf2,17);
+
+ PRInt32 result=s1.Compare(buf1,PR_TRUE,17);
+ result=s1.FindChar('?');
+ result++;
+ }
+
+ {
+ nsString foo("__moz_text");
+ PRInt32 cmp=foo.Compare("pre",PR_FALSE,-1);
+ cmp=cmp;
+ }
+
+ //First test the string compare routines...
+
+ NS_ASSERTION(0>temp8.Compare(bbbb),kComparisonError);
+ NS_ASSERTION(0>temp8.Compare(temp9),kComparisonError);
+ NS_ASSERTION(0<temp9.Compare(temp8),kComparisonError);
+ NS_ASSERTION(0==temp8.Compare(temp8a,PR_TRUE),kComparisonError);
+ NS_ASSERTION(0==temp8.Compare(aaaa),kComparisonError);
+
+ //Now test the boolean operators...
+ NS_ASSERTION(temp8==temp8,kComparisonError);
+ NS_ASSERTION(temp8==aaaa,kComparisonError);
+
+ NS_ASSERTION(temp8!=temp9,kComparisonError);
+ NS_ASSERTION(temp8!=bbbb,kComparisonError);
+
+ NS_ASSERTION(((temp8<temp9) && (temp9>=temp8)),kComparisonError);
+
+ NS_ASSERTION(((temp9>temp8) && (temp8<=temp9)),kComparisonError);
+ NS_ASSERTION(temp9>aaaa,kComparisonError);
+
+ NS_ASSERTION(temp8<=temp8,kComparisonError);
+ NS_ASSERTION(temp8<=temp9,kComparisonError);
+ NS_ASSERTION(temp8<=bbbb,kComparisonError);
+
+ NS_ASSERTION(((temp9>=temp8) && (temp8<temp9)),kComparisonError);
+ NS_ASSERTION(temp9>=temp8,kComparisonError);
+ NS_ASSERTION(temp9>=aaaa,kComparisonError);
+
+ NS_ASSERTION(temp8.Equals(temp8),kEqualsError);
+ NS_ASSERTION(temp8.Equals(aaaa),kEqualsError);
+
+ stringtype temp10(temp8);
+ ToUpperCase(temp10);
+ NS_ASSERTION(temp8.Equals(temp10,PR_TRUE),kEqualsError);
+ NS_ASSERTION(temp8.Equals("AAAA",PR_TRUE),kEqualsError);
+
+
+ //now test the new string Equals APIs..
+ {
+ nsCString s1("hello there");
+ NS_ASSERTION(s1.Equals("hello there"),kEqualsError);
+ NS_ASSERTION(s1.Equals("hello rick",PR_FALSE,5),kEqualsError);
+ NS_ASSERTION(!s1.Equals("hello rick",PR_FALSE-1),kEqualsError);
+
+ nsCString s2("");
+ NS_ASSERTION(s2.Equals(""),kEqualsError);
+
+ nsCString s3("view-source:");
+ NS_ASSERTION(s3.Equals("VIEW-SOURCE:",PR_TRUE,12),kEqualsError);
+ }
+
+ //now test the count argument...
+ {
+ nsString s1("rickgessner");
+ nsString s2("rickricardo");
+ PRInt32 result=s1.Compare(s2); //assume no case conversion, and full-length comparison...
+ result=s1.Compare(s2,PR_FALSE,4);
+ result=s1.Compare(s2,PR_FALSE,5);
+
+ PRBool b=s1.Equals(s2);
+ b=s1.Equals("rick",PR_FALSE,4);
+ b=s1.Equals("rickz",PR_FALSE,5);
+
+ result=10;
+
+ nsString s3("view");
+
+#define kString "view-source"
+
+ b=s3.Equals(kString);
+ result=10;
+ }
+
+ return result;
+}
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestAssignAndAdd(){
+ int result=0;
+
+ static const char* s1="hello";
+ static const char* s2="world";
+ static const PRUnichar pbuf[] = {' ','w','o','r','l','d',0};
+
+ nsString ns1("I'm an nsString");
+ nsCString nc1("I'm an nsCString");
+
+ nsAutoString as1("nsAutoString source");
+ nsCAutoString ac1("nsCAutoString source");
+
+
+ {
+ //**** Test assignments to nsCString...
+
+ nsCString theDest;
+ theDest.Assign(theDest); //assign nsString to itself
+ theDest.Assign(ns1); //assign an nsString to an nsString
+ NS_ASSERTION(theDest==ns1,"Assignment error");
+
+ theDest.Assign(nc1); //assign an nsCString to an nsString
+ NS_ASSERTION(theDest==nc1,"Assignment error");
+
+ theDest.Assign(as1); //assign an nsAutoString to an nsString
+// NS_ASSERTION(theDest==as1,"Assignment error");
+
+ theDest.Assign(ac1); //assign an nsCAutoString to an nsString
+// NS_ASSERTION(theDest==ac1,"Assignment error");
+
+ theDest.Assign("simple char*"); //assign a char* to an nsString
+ NS_ASSERTION(theDest=="simple char*","Assignment error");
+
+ theDest.Assign(pbuf); //assign a PRUnichar* to an nsString
+ NS_ASSERTION(theDest==pbuf,"Assignment error");
+
+ theDest.Assign('!'); //assign a char to an nsString
+ NS_ASSERTION(theDest=="!","Assignment error");
+
+ theDest.Assign(PRUnichar('$')); //assign a char to an nsString
+ NS_ASSERTION(theDest=="$","Assignment error");
+
+ theDest=ns1;
+ NS_ASSERTION(theDest==ns1,"Assignment error");
+
+ theDest=nc1;
+ NS_ASSERTION(theDest==nc1,"Assignment error");
+
+ theDest='a';
+ NS_ASSERTION(theDest=="a","Assignment error");
+
+ theDest=PRUnichar('a');
+ NS_ASSERTION(theDest=="a","Assignment error");
+
+ theDest=s1;
+ NS_ASSERTION(theDest==s1,"Assignment error");
+
+ theDest=pbuf;
+ NS_ASSERTION(theDest==pbuf,"Assignment error");
+
+ }
+
+ //test operator+()...
+ {
+
+ /* NOT WORKING YET...
+ nsString s1("hello");
+ nsString s2(" world");
+ nsCString c1(" world");
+
+ stringtype theDest;
+
+ theDest=s1+s2;
+ NS_ASSERTION(theDest=="hello world","Assignment error");
+
+ theDest=s1+c1;
+ NS_ASSERTION(theDest=="hello world","Assignment error");
+
+ theDest=s1+" world";
+ NS_ASSERTION(theDest=="hello world","Assignment error");
+
+ theDest=s1+pbuf;
+ NS_ASSERTION(theDest=="hello world","Assignment error");
+
+ theDest=s1+'!';
+ NS_ASSERTION(theDest=="hello!","Assignment error");
+
+ theDest=s1+PRUnichar('!');
+ NS_ASSERTION(theDest=="hello!","Assignment error");
+*/
+
+ }
+
+ return result;
+}
+
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestAppend(){
+ int result=0;
+
+
+ static const char* s1="hello";
+ static const char* s2="world";
+ static const PRUnichar pbuf[] = {' ','w','o','r','l','d',0};
+ static const PRUnichar pbuf1[] = {'a','b','c','d','l','d'};
+
+
+ stringtype theDest;
+ theDest.Append((float)100.100);
+ NS_ASSERTION(theDest=="100.1","Append(float) error");
+
+ theDest.Truncate();
+ theDest.Append(12345);
+ NS_ASSERTION(theDest=="12345","Append(int) error");
+
+ theDest.Truncate();
+ theDest.Append(pbuf1,1);
+ NS_ASSERTION(theDest=="a","Append(PRUnichar*,count) error");
+
+ theDest.Truncate();
+ theDest.Append('a');
+ NS_ASSERTION(theDest=="a","Append(char) error");
+
+
+ static const PRUnichar pbuf2[] = {'w','h','a','t','s',' ','u','p',' ','d','o','c','?',0};
+
+ theDest.Truncate();
+ theDest.Append(pbuf,20); //try appending more chars than actual length of pbuf
+ NS_ASSERTION(theDest!=pbuf,"Append(PRUnichar*) error");
+ //(NOTE: if you tell me to append X chars, I'll assume you really have X chars, and the length
+ // get's set accordingly. This test really is correct; it just seems odd.
+
+ theDest.Truncate(0);
+ theDest.Append(pbuf,5); //try appending fewer chars than actual length of pbuf
+ NS_ASSERTION(theDest==" worl","Append(PRUnichar*) error");
+
+ theDest.Truncate(0);
+ theDest.Append(pbuf); //try appending all of pbuf
+ NS_ASSERTION(theDest==pbuf,"Append(PRUnichar*) error");
+
+ char* ss=0;
+ theDest.Truncate();
+ theDest.Append(ss); //try appending NULL
+ NS_ASSERTION(theDest=="","Append(nullstr) error");
+
+ theDest.Append(pbuf,0); //try appending nothing
+ NS_ASSERTION(theDest=="","Append(nullstr) error");
+
+
+ {
+ //test improvement to unichar appends...
+ stringtype s1("hello");
+ char c='!';
+ s1+=c;
+ NS_ASSERTION(s1=="hello!","operator+=() error");
+
+ c=(char)0xfa;
+ s1+=c;
+ s1.Append(c);
+
+ PRUnichar theChar='f';
+ s1+=theChar;
+
+ char theChar2='g';
+ s1+=theChar2;
+
+// long theLong= 1234;
+// s1+=theLong;
+
+ }
+
+ {
+ //this just proves we can append nulls in our buffers...
+ stringtype c("hello");
+ stringtype s(" there");
+ c.Append(s);
+ char buf[]={'a','b',0,'d','e'};
+ s.Append(buf,5);
+ }
+
+
+ stringtype temp2("there");
+
+ theDest.Append(temp2);
+ theDest.Append(" xxx ");
+ theDest.Append(pbuf);
+ theDest.Append('4');
+ theDest.Append(PRUnichar('Z'));
+
+ stringtype a(s1);
+ stringtype b(s2);
+
+ theDest.Truncate();
+ temp2.Truncate();
+
+/* NOT WORKING YET...
+ theDest=a+b;
+ temp2=a+"world!";
+ temp2=a+pbuf;
+ stringtype temp3;
+ temp3=temp2+'!';
+*/
+ return result;
+}
+
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestExtractors(){
+ int result=0;
+
+ //first test the 2 byte version...
+
+
+ {
+ nsString temp1("hello there rick");
+ nsString temp2;
+
+ temp1.Left(temp2,10);
+ NS_ASSERTION(temp2=="hello ther","Left() error");
+
+ temp1.Mid(temp2,6,5);
+ NS_ASSERTION(temp2=="there","Mid() error");
+
+ temp1.Right(temp2,4);
+ NS_ASSERTION(temp2=="rick","Right() error");
+
+ //Now test the character accessor methods...
+ nsString theString("hello");
+ PRUint32 len=theString.Length();
+ PRUnichar theChar;
+ for(PRUint32 i=0;i<len;i++) {
+ theChar=theString.CharAt(i);
+ }
+
+/* NOT WORKING YET...
+ theChar=theString.First();
+ theChar=theString.Last();
+ theChar=theString[3];
+ theString.SetCharAt('X',3);
+*/
+ }
+
+ //now test the 1 byte version
+ {
+ nsCString temp1("hello there rick");
+ nsCString temp2;
+ temp1.Left(temp2,10);
+ temp1.Mid(temp2,6,5);
+ temp1.Right(temp2,4);
+
+ //Now test the character accessor methods...
+ nsCString theString("hello");
+ PRUint32 len=theString.Length();
+ char ch;
+ for(PRUint32 i=0;i<len;i++) {
+ ch=theString.CharAt(i);
+ }
+
+/* NOT WORKING YET...
+
+ ch=theString.First();
+ ch=theString.Last();
+ ch=theString[3];
+ theString.SetCharAt('X',3);
+*/
+ }
+
+
+ return result;
+}
+
+
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestCreators(){
+ int result=0;
+
+/* NOT WORKING YET
+ {
+ nsString theString5("");
+ char* str0 = ToNewCString(theString5);
+ Recycle(str0);
+
+ theString5+="hello rick";
+ nsString* theString6=theString5.ToNewString();
+ delete theString6;
+
+ nsString theString1("hello again");
+ PRUnichar* thePBuf=ToNewUnicode(theString1);
+ if(thePBuf)
+ Recycle(thePBuf);
+
+ char* str = ToNewCString(theString5);
+ if(str)
+ Recycle(str);
+
+ char buffer[6];
+ theString5.ToCString(buffer,sizeof(buffer));
+
+ }
+
+ {
+ nsCString theString5("hello rick");
+ nsCString* theString6=theString5.ToNewString();
+ delete theString6;
+
+ PRUnichar* thePBuf=ToNewUnicode(theString5);
+ if(thePBuf)
+ Recycle(thePBuf);
+
+ char* str = ToNewCString(theString5);
+ if(str)
+ Recycle(str);
+
+ char buffer[100];
+ theString5.ToCString(buffer,sizeof(buffer)-1);
+ nsCString theOther=theString5.GetBuffer();
+ }
+ */
+ return result;
+}
+
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestInsert(){
+ int result=0;
+
+ {
+ static const char pbuf[] = " world";
+
+ nsCString temp1("hello rick");
+ temp1.Insert("there ",6); //char* insertion
+ NS_ASSERTION(temp1=="hello there rick","Insert error");
+
+ temp1.Insert(pbuf,3); //prunichar* insertion
+ NS_ASSERTION(temp1=="hel worldlo there rick","Insert error");
+
+ temp1.Insert("?",10); //char insertion
+ NS_ASSERTION(temp1=="hel worldl?o there rick","Insert error");
+
+ temp1.Insert('*',10); //char insertion
+ NS_ASSERTION(temp1=="hel worldl*?o there rick","Insert error");
+
+ temp1.Insert("xxx",100,3); //this should append.
+ NS_ASSERTION(temp1=="hel worldl*?o there rickxxx","Insert error");
+
+ nsCString temp2("abcdefghijklmnopqrstuvwxyz");
+// temp2.Insert(temp1,10);
+ temp2.Cut(20,5);
+ NS_ASSERTION(temp2=="abcdefghijklmnopqrstz","Insert error");
+
+ temp2.Cut(100,100); //this should fail.
+ NS_ASSERTION(temp2=="abcdefghijklmnopqrstz","Insert error");
+
+ }
+
+ {
+ static const PRUnichar pbuf[] = {' ','w','o','r','l','d',0};
+
+
+ nsString temp1("llo rick");
+
+ temp1.Insert("he",0); //char* insertion
+ NS_ASSERTION(temp1=="hello rick","Insert error");
+
+ temp1.Insert("there ",6); //char* insertion
+ NS_ASSERTION(temp1=="hello there rick","Insert error");
+
+ temp1.Insert(pbuf,3); //prunichar* insertion
+ NS_ASSERTION(temp1=="hel worldlo there rick","Insert error");
+
+ temp1.Insert("?",10); //char insertion
+ NS_ASSERTION(temp1=="hel worldl?o there rick","Insert error");
+
+ temp1.Insert('*',10); //char insertion
+ NS_ASSERTION(temp1=="hel worldl*?o there rick","Insert error");
+
+ temp1.Insert("xxx",100,3); //this should append.
+ NS_ASSERTION(temp1=="hel worldl*?o there rickxxx","Insert error");
+
+ nsString temp2("abcdefghijklmnopqrstuvwxyz");
+// temp2.Insert(temp1,10);
+ temp2.Cut(20,5);
+ NS_ASSERTION(temp2=="abcdefghijklmnopqrstz","Insert error");
+
+ temp2.Cut(100,100); //this should fail.
+ NS_ASSERTION(temp2=="abcdefghijklmnopqrstz","Insert error");
+
+ }
+
+ return result;
+}
+
+
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestDelete(){
+ int result=0;
+
+ //NOTE: You need to run this test program twice for this method to work.
+ // Once with USE_WIDE defined, and once without (to test nsCString)
+
+ //let's try some whacky string deleting calls
+ {
+ const char* pbuf = "whats up doc?";
+
+ nsCString s1(pbuf);
+ s1.Cut(3,20); //try deleting more chars than actual length of pbuf
+ NS_ASSERTION(s1=="wha","Cut error");
+
+ s1=pbuf;
+ s1.Cut(3,-10);
+ NS_ASSERTION(s1==pbuf,"Cut error");
+
+ s1=pbuf;
+ s1.Cut(3,2);
+ NS_ASSERTION(s1=="wha up doc?","Cut error");
+
+ }
+
+ //let's try some whacky string deleting calls
+ {
+ const PRUnichar pbuf[] = {'w','h','a','t','s',' ','u','p',' ','d','o','c','?',0};
+
+ nsString s1(pbuf);
+ s1.Cut(3,20); //try deleting more chars than actual length of pbuf
+ NS_ASSERTION(s1=="wha","Cut error");
+
+ s1=pbuf;
+ s1.Cut(3,-10);
+ NS_ASSERTION(s1==pbuf,"Cut error");
+
+ s1=pbuf;
+ s1.Cut(3,2);
+ NS_ASSERTION(s1=="wha up doc?","Cut error");
+ }
+
+
+ {
+ nsCString s;
+ int i;
+ for(i=0;i<518;i++) {
+ s.Append("0123456789");
+ }
+ s+="abc";
+ s.Cut(0,5);
+ }
+
+ {
+ astringtype ab("ab");
+ stringtype abcde("cde");
+ stringtype cut("abcdef");
+ cut.Cut(7,10); //this is out of bounds, so ignore...
+ //cut.DebugDump(cout);
+ cut.Cut(5,2); //cut last chars
+ //cut.DebugDump(cout);
+ cut.Cut(1,1); //cut first char
+ //cut.DebugDump(cout);
+ cut.Cut(2,1); //cut one from the middle
+ //cut.DebugDump(cout);
+ cut="Hello there Rick";
+ //cut.DebugDump(cout);
+}
+
+ return result;
+}
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestTruncate(){
+ int result=0;
+ //test delete against a twobyte string...
+
+ {
+ nsCString s0;
+ nsCString s1(kNumbers[0]);
+ s0=s1;
+ s0.Truncate(100); //should fail
+ s0.Truncate(5); //should work
+ s0.Truncate(0); //should work
+ }
+
+ {
+ nsString s0;
+ nsString s1(kNumbers[0]);
+ s0=s1;
+ s0.Truncate(100); //should fail
+ s0.Truncate(5); //should work
+ s0.Truncate(0); //should work
+ }
+ return result;
+}
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestNumerics(){
+ int result=0;
+
+ //try a few numeric conversion routines...
+ {
+ nsCString str1("-12345");
+ NS_ASSERTION(str1=="-12345","Append(int) error");
+
+ nsString str2("hello");
+ nsString str3;
+ nsString str4("0");
+ nsString str5("&#183;");
+ nsString str6("&xi;");
+ nsString str7("#xe3;");
+ nsString str8("#FF;");
+ nsCString str9("-#xa?a;"); //should return -10 (decimal)
+ nsCString str10("&#191;");
+ nsCString str11("&#vvv;");
+ nsCString str12("-vvv;");
+ nsCString str13("-f");
+
+ PRInt32 err;
+ PRInt32 theInt=str1.ToInteger(&err);
+ theInt=str2.ToInteger(&err);
+ NS_ASSERTION(theInt==14,"ToInteger error");
+
+ theInt=str3.ToInteger(&err);
+ NS_ASSERTION(theInt==0,"ToInteger error");
+
+ theInt=str4.ToInteger(&err);
+ NS_ASSERTION(theInt==0,"ToInteger error");
+
+ theInt=str5.ToInteger(&err);
+ NS_ASSERTION(theInt==183,"ToInteger error");
+
+ theInt=str6.ToInteger(&err);
+ NS_ASSERTION(theInt==0,"ToInteger error");
+
+ theInt=str7.ToInteger(&err,16);
+ NS_ASSERTION(theInt==227,"ToInteger error");
+
+ theInt=str8.ToInteger(&err,kAutoDetect);
+ NS_ASSERTION(theInt==255,"ToInteger error");
+
+ theInt=str9.ToInteger(&err,kAutoDetect);
+ NS_ASSERTION(theInt==-10,"ToInteger error");
+
+ theInt=str10.ToInteger(&err);
+ NS_ASSERTION(theInt==191,"ToInteger error");
+
+ theInt=str11.ToInteger(&err);
+ NS_ASSERTION(theInt==0,"ToInteger error");
+
+ theInt=str12.ToInteger(&err);
+ NS_ASSERTION(theInt==0,"ToInteger error");
+
+ theInt=str13.ToInteger(&err);
+ NS_ASSERTION(theInt==-15,"ToInteger error");
+
+
+ Stopwatch watch;
+ int i;
+ for(i=0;i<1000000;i++){
+ theInt=str1.ToInteger(&err,16);
+ }
+ watch.Stop();
+ watch.Print("ToInteger() ");
+
+ str1="100.100";
+ float theFloat=str1.ToFloat(&err);
+ }
+ //try a few numeric conversion routines...
+ {
+ nsCString str1("10000");
+ nsCString str2("hello");
+ nsCString str3;
+ PRInt32 err;
+ PRInt32 theInt=str1.ToInteger(&err);
+ NS_ASSERTION(theInt==10000,"ToInteger error");
+
+ theInt=str2.ToInteger(&err);
+ NS_ASSERTION(theInt==14,"ToInteger error");
+
+ theInt=str3.ToInteger(&err);
+ NS_ASSERTION(theInt==0,"ToInteger error");
+
+ str1="100.100";
+ float theFloat=str1.ToFloat(&err);
+ }
+ return 0;
+}
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestLexomorphic(){
+ int result=0;
+ //test delete against a twobyte string...
+
+ //NOTE: You need to run this test program twice for this method to work.
+ // Once with USE_WIDE defined, and once without (to test nsCString)
+
+
+ {
+ nsString theTag("FOO");
+ nsString theLower;
+ theTag.ToLowerCase(theLower);
+ int x=5;
+ }
+
+ PRUnichar pbuf[] = {'h','e','l','l','o','\n','\n','\n','\n',250,'\n','\n','\n','\n','\n','\n','r','i','c','k',0};
+
+ //and hey, why not do a few lexo-morphic tests...
+ nsString s0(pbuf);
+ ToUpperCase(s0);
+ ToLowerCase(s0);
+ s0.StripChars("l");
+ s0.StripChars("\n");
+ s0.StripChar(250);
+ NS_ASSERTION(s0=="heorick","Stripchars error");
+
+ {
+ nsAutoString s1(pbuf);
+ s1.CompressSet("\n ",' ');
+ }
+
+ {
+
+ char pbuf[] = { 0x1C, 0x04, 0x1D, 0x04, 0x20, 0x00, 0x2D, 0x00, 0x20, 0x00, 0x23, 0x04, 0x20, 0x00, 0x40, 0x04,
+ 0x43, 0x04, 0x3B, 0x04, 0x4F, 0x04, 0x20, 0x00, 0x30, 0x04, 0x40, 0x04, 0x3C, 0x04, 0x38, 0x04,
+ 0x38, 0x04, 0x20, 0x00, 0x2D, 0x00, 0x20, 0x00, 0x32, 0x04, 0x42, 0x04, 0x3E, 0x04, 0x40, 0x04,
+ 0x3E, 0x04, 0x41, 0x04, 0x42, 0x04, 0x35, 0x04, 0x3F, 0x04, 0x35, 0x04, 0x3D, 0x04, 0x3D, 0x04,
+ 0x4B, 0x04, 0x35, 0x04, 0x20, 0x00, 0x3B, 0x04, 0x38, 0x04, 0x46, 0x04, 0x30, 0x04, 0x20, 0x00,
+ 0x2D, 0x00, 0x20, 0x00, 0x30, 0x00, 0x39, 0x00, 0x2F, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00,
+ 0x30, 0x00, 0x00, 0x00};
+
+ nsAutoString temp((PRUnichar*)pbuf);
+ nsAutoString temp1(temp);
+ temp.CompressWhitespace();
+ PRBool equals=temp.Equals(temp1);
+
+ }
+
+ {
+ nsString s1(" ");
+ s1.Trim("; \t");
+ s1="helvetica";
+ s1.Trim("; \t");
+ }
+
+ s0.Insert(" ",0);
+ NS_ASSERTION(s0==" heorick","Stripchars error");
+
+ s0.Append(" ");
+ NS_ASSERTION(s0==" heorick ","Stripchars error");
+
+ s0.Trim(" ",PR_TRUE,PR_TRUE);
+ NS_ASSERTION(s0=="heorick","Stripchars error");
+
+ s0.Append(" abc 123 xyz ");
+ s0.CompressWhitespace();
+ NS_ASSERTION(s0=="heorick abc 123 xyz","CompressWS error");
+
+ s0.ReplaceChar('r','b');
+ NS_ASSERTION(s0=="heobick abc 123 xyz","ReplaceChar error");
+
+ s0=pbuf;
+ ToUpperCase(s0);
+ ToLowerCase(s0);
+ s0.Append("\n\n\n \r \r \r \t \t \t");
+ s0.StripWhitespace();
+
+ nsCAutoString s1("\n\r hello \n\n\n\r\r\r\t rick \t\t ");
+ ToUpperCase(s1);
+ ToLowerCase(s1);
+ s1.StripChars("o");
+ s1.Trim(" ",PR_TRUE,PR_TRUE);
+ s1.CompressWhitespace();
+ NS_ASSERTION(s1=="hell rick","Compress Error");
+
+ s1.ReplaceChar('h','w');
+ NS_ASSERTION(s1=="well rick","Compress Error");
+
+ ToUpperCase(s1);
+ NS_ASSERTION(s1=="WELL RICK","Compress Error");
+
+ ToLowerCase(s1);
+ s1.Append("\n\n\n \r \r \r \t \t \t");
+ s1.StripWhitespace();
+ NS_ASSERTION(s1=="wellrick","Compress Error");
+
+ {
+ nsCString temp("aaaa");
+ int i;
+ for(i=0;i<100;i++) {
+ temp+="0123456789.";
+ }
+ temp.StripChars("a2468");
+ i=5;
+
+ temp=" hello rick ";
+ temp.StripChars("\n\r\t\b ");
+ NS_ASSERTION(temp=="hellorick","This isn't good");
+ }
+
+ return result;
+}
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestAutoStrings(){
+ int result=0;
+
+ PRUnichar pbuf[] = {'h','e','l','l','o',0};
+
+ //this test makes sure that autostrings who assume ownership of a buffer,
+ //don't also try to copy that buffer onto itself... (was a bug)
+ {
+ nsAutoString temp0;
+ nsAutoString temp1("hello rick");
+ nsAutoString temp3(pbuf);
+
+/* NOT WORKING...
+ nsAutoString temp4(CBufDescriptor((char*)pbuf,PR_TRUE,5,5));
+*/
+ nsAutoString temp5(temp3);
+ nsString s(pbuf);
+ nsAutoString temp6(s);
+
+/* NOT WORKING...
+ char buffer[500];
+ nsAutoString temp7(CBufDescriptor((PRUnichar*)buffer,PR_TRUE,sizeof(buffer)-10/2,0));
+ temp7="hello, my name is inigo montoya.";
+*/
+
+ nsAutoString as;
+ int i;
+ for(i=0;i<30;i++){
+ as+='a';
+ }
+ PRBool b=PR_TRUE; //this line doesn't do anything, it just gives a convenient breakpoint.
+ NS_ASSERTION(as=="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","error in operator+=()");
+ }
+
+
+ {
+ nsCAutoString temp0;
+ nsCAutoString temp1("hello rick");
+
+
+ //nsCAutoString temp2("hello rick",PR_TRUE,5);
+ nsCAutoString temp3(pbuf);
+
+ {
+ const char* buf="hello rick";
+ int len=strlen(buf);
+
+// nsAutoString temp4(CBufDescriptor(buf,PR_TRUE,len+1,len)); //NOT WORKING
+ }
+
+ nsCAutoString temp5(temp3);
+ nsString s(pbuf);
+ nsCAutoString temp6(s); //create one from a nsString
+
+ nsCAutoString as;
+ int i;
+ for(i=0;i<30;i++){
+ as+='a';
+ }
+ PRBool b=PR_TRUE;
+
+#if 0
+
+/* NOT WORKING
+ char buffer[500];
+
+ nsCAutoString s3(CBufDescriptor(buffer,PR_TRUE,sizeof(buffer)-1,0));
+ s3="hello, my name is inigo montoya.";
+ */
+ //make an autostring that copies an nsString...
+ nsString s0("eat icecream");
+ nsCAutoString s4(s0);
+ nsCAutoString s5(s0.get());
+ nsString aaa("hi there rick");
+#endif
+ }
+
+ const char* st="hello again";
+ nsString s; //this also forces nsString to run it's selftest.
+ s=st;
+ nsAutoString astr;
+ astr=st;
+
+ return result;
+}
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestSubsumables(){
+ int result=0;
+ char* buf="hello rick";
+
+ return result;
+}
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestRandomOps(){
+ int result=0;
+
+#if 0
+
+ char* str[]={"abc ","xyz ","123 ","789 ","*** ","... "};
+
+ string theSTLString;
+ nsString theString;
+ nsString thePrevString;
+
+ enum ops {eNOP,eAppend,eDelete,eInsert};
+ char* opStrs[] = {"nop","append","delete","insert"};
+
+ srand( (unsigned)time( NULL ) );
+
+ int err[] = {1,7,9,6,0,4,1,1,1,1};
+
+ ops theOp=eNOP;
+ int pos,len,index;
+
+ fstream output("c:/temp/out.file",ios::out);
+ output<<"dump!";
+
+ for(int theOpIndex=0;theOpIndex<1000000;theOpIndex++){
+
+ int r=rand();
+ char buf[100];
+ sprintf(buf,"%i",r);
+ len=strlen(buf);
+ index=buf[len-1]-'0';
+
+ //debug... index=err[theOp];
+
+ switch(index) {
+ case 0:
+ case 1:
+ case 2:
+ theSTLString.append(str[index]);
+ theString.Append(str[index]);
+ theOp=eAppend;
+ break;
+
+ case 3:
+ case 4:
+ case 5:
+ theOp=eInsert;
+ if (theString.Length()>2) {
+ pos=theString.Length()/2;
+ theSTLString.insert(pos,str[index],4);
+ theString.Insert(str[index],pos);
+ }
+ break;
+
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ theOp=eDelete;
+ if(theString.Length()>10) {
+ len=theString.Length()/2;
+ pos=theString.Length()/4;
+ theSTLString.erase(pos,len);
+ theString.Cut(pos,len);
+ }
+ break;
+
+ default:
+ theOp=eNOP;
+
+ } //for
+
+ if(eNOP<theOp) {
+
+ int lendiff=theString.Length()-theSTLString.length();
+ PRBool equals=theString.Equals(theSTLString.c_str());
+ if(((lendiff)) || (!equals)) {
+ printf("Error in %s at:%i len:%i (%s)!\n",opStrs[theOp],pos,len,str[index]);
+ output.close();
+ theString.Equals(theSTLString.c_str());
+
+ if(theOp==eInsert) {
+ thePrevString.Insert(str[index],pos);
+ }
+ else if(theOp==eAppend) {
+ thePrevString.Append(str[index]);
+ }
+ return 0;
+ }
+
+#if FOO
+ output<< opStrs[theOp];
+ if((eInsert==theOp) || (eAppend==theOp)){
+ output<< "(" << str[index] << ", " << pos << ") ";
+ }
+
+ thePrevString.ToCString(buffer,1000,0);
+ output << " Old: [" << buffer << "]";
+ theString.ToCString(buffer,1000,0);
+ output << " New: [" << buffer << "]";
+ output << " STL: [" << theSTLString.c_str() << "]" << endl;
+
+ if(theString.mStringValue.mLength>300) {
+ theString.Truncate();
+ theSTLString.erase();
+ }
+#endif
+ thePrevString=theString;
+ }
+ }
+#endif
+ return result;
+}
+
+
+/**
+ *
+ * @update gess10/30/98
+ * @param
+ * @return
+ */
+int CStringTester::TestReplace(){
+ int result=0;
+
+ const char* find="..";
+ const char* rep= "+";
+
+ const char* s1="hello..there..rick..gessner.";
+ const char* s2="hello+there+rick+gessner.";
+
+ nsCString s(s1);
+ s.ReplaceSubstring(find,rep);
+ NS_ASSERTION(s==s2,"ReplaceSubstring error");
+
+ s.ReplaceSubstring(rep,find);
+ NS_ASSERTION(s==s1,"ReplaceSubstring error");
+
+ return result;
+}
+
+
+/**
+ * This method tests the performance of various methods.
+ *
+ *
+ * @return
+ */
+int CStringTester::TestWideStringPerformance() {
+
+ printf("Widestring performance tests...\n");
+
+ char* libname[] = {"STL","nsString",0};
+
+
+ //**************************************************
+ //Test Construction against STL::wstring...
+ //**************************************************
+ {
+ nsString theConst;
+ for(int z=0;z<10;z++){
+ theConst.Append("0123456789");
+ }
+
+ Stopwatch watch1;
+ int i;
+ for(i=0;i<1000000;i++){
+ nsString s(theConst);
+ }
+ watch1.Stop();
+
+ wchar_t wbuf[] = {'a','b','c','d','e','f','g','h','i','j',0};
+ wstring theConst2;
+ for(int w=0;w<10;w++){
+ theConst2.append(wbuf);
+ }
+
+ Stopwatch watch2;
+#ifdef USE_STL
+ for(i=0;i<1000000;i++){
+ wstring s(theConst2);
+ }
+#endif
+ watch2.Stop();
+
+ printf("Construct(abcde) NSString: %f STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+ }
+
+
+ //**************************************************
+ //Test append("abcde") against STL::wstring...
+ //**************************************************
+ {
+
+ PRUnichar pbuf[10]={'a','b','c','d','e',0};
+
+ Stopwatch watch1;
+ int i;
+ for(i=0;i<1000;i++){
+ nsString s;
+ for(int j=0;j<200;j++){
+ s.Append("abcde");
+ }
+ }
+ watch1.Stop();
+
+ wchar_t wbuf[10] = {'a','b','c','d','e',0};
+
+ Stopwatch watch2;
+#ifdef USE_STL
+ for(i=0;i<1000;i++){
+ wstring s;
+ for(int j=0;j<200;j++){
+ s.append(wbuf);
+ }
+ }
+#endif
+ watch2.Stop();
+
+ printf("Append(abcde) NSString: %f STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+ }
+
+ //**************************************************
+ //Test append(char) against STL::wstring
+ //**************************************************
+ {
+
+ Stopwatch watch1;
+ int i;
+ for(i=0;i<500;i++){
+ nsString s;
+ for(int j=0;j<200;j++){
+ s.Append('a');
+ }
+ }
+ watch1.Stop();
+
+
+ Stopwatch watch2;
+#ifdef USE_STL
+ for(i=0;i<500;i++){
+ wstring s;
+ wchar_t theChar('a');
+ for(int j=0;j<200;j++){
+ s.append('a',1);
+ }
+ }
+#endif
+ watch2.Stop();
+
+ printf("Append('a') NSString: %f STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+ int x=0;
+ }
+
+ //**************************************************
+ //Test insert("123") against STL::wstring
+ //**************************************************
+ {
+
+ PRUnichar pbuf1[10]={'a','b','c','d','e','f',0};
+ PRUnichar pbuf2[10]={'1','2','3',0};
+
+ Stopwatch watch1;
+ int i;
+ for(i=0;i<1000;i++){
+ nsString s("abcdef");
+ int inspos=3;
+ for(int j=0;j<100;j++){
+ s.Insert(pbuf2,inspos);
+ inspos+=3;
+ }
+ }
+ watch1.Stop();
+
+
+ wchar_t wbuf1[10] = {'a','b','c','d','e','f',0};
+ wchar_t wbuf2[10] = {'1','2','3',0};
+
+ Stopwatch watch2;
+#ifdef USE_STL
+ for(i=0;i<1000;i++){
+ wstring s(wbuf1);
+ int inspos=3;
+ for(int j=0;j<100;j++){
+ s.insert(inspos,wbuf2);
+ inspos+=3;
+ }
+ }
+#endif
+ watch2.Stop();
+
+ printf("Insert(123) NSString: %f STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+ int x=0;
+ }
+
+ //**************************************************
+ //Let's test substring searching performance...
+ //**************************************************
+ {
+ PRUnichar pbuf1[] = {'a','a','a','a','a','a','a','a','a','a','b',0};
+ PRUnichar pbuf2[] = {'a','a','b',0};
+
+ nsString s(pbuf1);
+ nsString target(pbuf2);
+
+ Stopwatch watch1;
+ int i;
+ for(i=-1;i<200000;i++) {
+ PRInt32 result=s.Find(target,PR_FALSE);
+ }
+ watch1.Stop();
+
+ Stopwatch watch2;
+#ifdef USE_STL
+ wchar_t wbuf1[] = {'a','a','a','a','a','a','a','a','a','a','b',0};
+ wchar_t wbuf2[] = {'a','a','b',0};
+ wstring ws(wbuf1);
+ wstring wtarget(wbuf2);
+
+ for(i=-1;i<200000;i++) {
+ PRInt32 result=ws.find(wtarget);
+ }
+#endif
+ watch2.Stop();
+
+ printf("Find(aab) NSString: %f STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+ }
+
+ //**************************************************
+ //Now let's test comparisons...
+ //**************************************************
+ {
+ nsString s("aaaaaaaaaaaaaaaaaaab");
+ PRUnichar target[]={'a','a','a','a','a','a','a','a','a','a','a','a','a','b',0};
+ size_t theLen=(sizeof(target)-1)/2;
+
+ Stopwatch watch1;
+ int result=0;
+ int i;
+ for(i=-1;i<1000000;i++) {
+ result=s.Compare(target,PR_FALSE,theLen);
+ result++;
+ }
+ watch1.Stop();
+
+ Stopwatch watch2;
+#ifdef USE_STL
+ wchar_t buf[]={'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','b',0};
+ wstring ws(buf);
+ wchar_t wtarget[]={'a','a','a','a','a','a','a','a','a','a','a','a','a','b',0};
+
+ for(i=-1;i<1000000;i++) {
+ result=ws.compare(0,theLen,wtarget);
+ result++;
+ }
+#endif
+ watch2.Stop();
+
+ printf("Compare(aaaaaaaab) NSString: %f STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+
+ }
+
+ //**************************************************
+ //Now lets test string deletions...
+ //**************************************************
+ {
+
+ int strcount=6000;
+ int outerIter=100;
+ int innerIter=100;
+
+ PRUnichar pbuf[] = {'1','2','3','4','5','6','7','8','9','0',0};
+ nsString source1; //build up our target string...
+ int i;
+ for(i=0;i<strcount;i++) {
+ source1.Append(pbuf);
+ }
+
+ Stopwatch watch1;
+
+ for(i=0;i<outerIter;i++) {
+ nsString s1(source1);
+ for(int j=0;j<100;j++){
+ s1.Cut(20,50);
+ }
+ }
+ watch1.Stop();
+ printf("Cut(...) NSString: %f ",watch1.Elapsed());
+
+#ifdef USE_STL
+
+ wchar_t wbuf[] = {'1','2','3','4','5','6','7','8','9','0',0};
+ wstring source2; //build up our target string...
+
+ for(i=0;i<strcount;i++) {
+ source2.append(wbuf);
+ }
+
+ Stopwatch watch2;
+
+ for(i=0;i<outerIter;i++) {
+ wstring s2(source2);
+ for(int j=0;j<100;j++){
+ s2.erase(20,50);
+ }
+ }
+ watch2.Stop();
+
+ printf(" STL: %f",watch2.Elapsed());
+#endif
+ printf("\n");
+
+ }
+
+ //**************************************************
+ //Now let's test the findChar routine...
+ //**************************************************
+ {
+
+ nsString s1;
+ int i;
+ for(i=0;i<100;i++) {
+ s1.Append("1234567890",10);
+ }
+ s1+="xyz";
+
+ Stopwatch watch1;
+ for(i=0;i<100000;i++) {
+ int f=s1.FindChar('z',PR_FALSE,0);
+ }
+ watch1.Stop();
+ printf("FindChar('z') NSString: %f",watch1.Elapsed());
+
+#ifdef USE_STL
+ wchar_t wbuf[] = {'1','2','3','4','5','6','7','8','9','0',0};
+ wstring s2;
+ for( i=0;i<100;i++) {
+ s2.append(wbuf);
+ }
+ wchar_t wbuf2[] = {'x','y','z',0};
+ s2.append(wbuf2);
+
+ Stopwatch watch2;
+
+ for(i=0;i<100000;i++) {
+ int f=s2.find_first_of('z',0);
+ }
+ watch2.Stop();
+ printf(" STL: %f",watch2.Elapsed());
+#endif
+ printf("\n");
+
+ }
+ return 0;
+}
+
+
+/************************************************************************************************
+ *
+ * This method tests the performance of various methods.
+ *
+ ************************************************************************************************/
+int CStringTester::TestStringPerformance() {
+ printf("c-String performance tests...\n");
+
+ char* libname[] = {"STL","nsString",0};
+
+ //**************************************************
+ //Test Construction against STL::wstring...
+ //**************************************************
+ {
+ nsCString theConst;
+ for(int z=0;z<10;z++){
+ theConst.Append("0123456789");
+ }
+
+ Stopwatch watch1;
+ int i;
+ for(i=0;i<1000000;i++){
+ nsCString s(theConst);
+ }
+ watch1.Stop();
+
+ char wbuf[] = {'a','b','c','d','e','f','g','h','i','j',0};
+ string theConst2;
+ for(int w=0;w<10;w++){
+ theConst2.append(wbuf);
+ }
+
+ Stopwatch watch2;
+#ifdef USE_STL
+ for(i=0;i<1000000;i++){
+ string s(theConst2);
+ }
+#endif
+ watch2.Stop();
+
+ printf("Construct(abcde) NSCString: %f STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+ }
+
+ //**************************************************
+ //Test append("abcde") against STL...
+ //**************************************************
+
+ {
+
+ Stopwatch watch1;
+ int i;
+ for(i=0;i<1000;i++){
+ nsCString s;
+ for(int j=0;j<200;j++){
+ s.Append("abcde",5);
+ }
+ }
+ watch1.Stop();
+
+ Stopwatch watch2;
+#ifdef USE_STL
+ for(i=0;i<1000;i++){
+ string s;
+ for(int j=0;j<200;j++){
+ s.append("abcde",5);
+ }
+ }
+#endif
+ watch2.Stop();
+
+ printf("Append(abcde) NSCString: %f STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+ int x=0;
+ }
+
+ //**************************************************
+ //Test append(char) against STL
+ //**************************************************
+ {
+
+ Stopwatch watch1;
+ int i;
+ for(i=0;i<500;i++){
+ nsCString s;
+ for(int j=0;j<200;j++){
+ s.Append('a');
+ }
+ }
+ watch1.Stop();
+
+ Stopwatch watch2;
+#ifdef USE_STL
+ for(i=0;i<500;i++){
+ string s;
+ wchar_t theChar('a');
+ for(int j=0;j<200;j++){
+ s.append('a',1);
+ }
+ }
+#endif
+ watch2.Stop();
+
+ printf("Append('a') NSCString: %f STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+ int x=0;
+ }
+
+ //**************************************************
+ //Test insert("123") against STL
+ //**************************************************
+ {
+
+ char pbuf1[10]={'a','b','c','d','e','f',0};
+ char pbuf2[10]={'1','2','3',0};
+
+ Stopwatch watch1;
+ int i;
+ for(i=0;i<1000;i++){
+ nsCString s("abcdef");
+ int inspos=3;
+ for(int j=0;j<100;j++){
+ s.Insert(pbuf2,inspos);
+ inspos+=3;
+ }
+ }
+ watch1.Stop();
+
+ Stopwatch watch2;
+#ifdef USE_STL
+ for(i=0;i<1000;i++){
+ string s(pbuf1);
+ int inspos=3;
+ for(int j=0;j<100;j++){
+ s.insert(inspos,pbuf2);
+ inspos+=3;
+ }
+ }
+#endif
+ watch2.Stop();
+
+ printf("insert(123) NSCString: %f STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+ int x=0;
+ }
+
+ //**************************************************
+ //Let's test substring searching performance...
+ //**************************************************
+ {
+ char *pbuf1 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aab";
+
+ char *pbuf2 = "aab";
+
+ nsCString s(pbuf1);
+
+ Stopwatch watch1;
+ int i;
+ for(i=-1;i<20000;i++) {
+ PRInt32 result=s.Find(pbuf2,PR_FALSE);
+ }
+ watch1.Stop();
+
+ Stopwatch watch2;
+#ifdef USE_STL
+ string ws(pbuf1);
+ for(i=-1;i<20000;i++) {
+ PRInt32 result=ws.find(pbuf2);
+ }
+#endif
+ watch2.Stop();
+
+ printf("Find(aab) NSCString: %f STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+ }
+
+ //**************************************************
+ //Now let's test comparisons...
+ //**************************************************
+ {
+ char* target="aaaaaaaaaaaaab";
+ size_t theLen=strlen(target);
+
+ Stopwatch watch1;
+ nsCString s("aaaaaaaaaaaaaaaaaaab");
+ int result=0;
+ int i;
+ for(i=-1;i<1000000;i++) {
+ result=s.Compare(target,PR_FALSE,theLen);
+ result++;
+ }
+ watch1.Stop();
+
+ Stopwatch watch2;
+#ifdef USE_STL
+ string ws("aaaaaaaaaaaaaaaaaaab");
+ for(i=-1;i<1000000;i++) {
+ result=ws.compare(0,theLen,target);
+ result++;
+ }
+#endif
+ watch2.Stop();
+
+ printf("Compare(aaaaaaaab) NSCString: %f STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+
+ }
+
+ //**************************************************
+ //Now lets test string deletions...
+ //**************************************************
+ {
+
+ int strcount=6000;
+ int outerIter=100;
+ int innerIter=100;
+
+ char* buffer = "1234567890";
+ nsCString source1; //build up our target string...
+ int i;
+ for(i=0;i<strcount;i++) {
+ source1.Append(buffer);
+ }
+
+ Stopwatch watch1;
+ for(i=0;i<outerIter;i++) {
+ nsCString s1(source1);
+ for(int j=0;j<innerIter;j++){
+ s1.Cut(20,50);
+ }
+ }
+ watch1.Stop();
+ printf("Cut(...) NSCString: %f ",watch1.Elapsed());
+
+#ifdef USE_STL
+ string source2; //build up our target string...
+ for(i=0;i<strcount;i++) {
+ source2.append(buffer);
+ }
+
+ Stopwatch watch2;
+ for(i=0;i<outerIter;i++) {
+ string s2(source2);
+ for(int j=0;j<innerIter;j++){
+ s2.erase(20,50);
+ }
+ }
+ watch2.Stop();
+
+ printf(" STL: %f",watch2.Elapsed());
+#endif
+ printf("\n");
+ }
+
+
+ //**************************************************
+ //Now let's test the findChar routine...
+ //**************************************************
+ {
+
+ nsCString s1;
+ int i;
+ for(i=0;i<100;i++) {
+ s1.Append("1234567890",10);
+ }
+ s1+="xyz";
+
+ Stopwatch watch1;
+ for(i=0;i<100000;i++) {
+ int f=s1.FindChar('z',PR_FALSE,0);
+ }
+ watch1.Stop();
+ printf("FindChar('z') NSCString: %f ",watch1.Elapsed());
+
+#ifdef USE_STL
+ string s2;
+ for( i=0;i<100;i++) {
+ s2.append("1234567890");
+ }
+ s2.append("xyz");
+
+ Stopwatch watch2;
+ for(i=0;i<100000;i++) {
+ int f=s2.find_first_of('z',0);
+ }
+ watch2.Stop();
+ printf(" STL: %f\n",watch1.Elapsed(),watch2.Elapsed());
+#endif
+ printf("\n");
+
+ }
+ return 0;
+}
+
+
+/**
+ * This method is here as a place to put known regressions...
+ *
+ *
+ * @return
+ */
+int CStringTester::TestRegressions() {
+
+ nsString s("FTP: Netscape</a>");
+ PRInt32 result=s.Find("</A>",PR_TRUE);
+
+ //this was a known bug...
+ {
+ nsString s0("");
+ PRInt32 pos=s0.RFind("-->");
+ nsString s1("debug");
+ pos=s1.RFind("b");
+ pos=s1.RFind("de",PR_FALSE,1);
+ pos=10;
+ }
+
+ //this was a known bug...
+ {
+ nsString s0("RDF:RDF");
+ PRInt32 pos=s0.Find(":");
+ pos=10;
+ }
+
+ return result;
+}
+
+#endif
+
diff --git a/src/libs/xpcom18a4/xpcom/tests/windows/nsStringTest2.h b/src/libs/xpcom18a4/xpcom/tests/windows/nsStringTest2.h
new file mode 100644
index 00000000..16ffc11a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tests/windows/nsStringTest2.h
@@ -0,0 +1,444 @@
+/********************************************************************************************
+ *
+ * MODULES NOTES:
+ *
+ * This file is designed to help test the new nsString classes.
+ *
+ * Contributor(s):
+ * Rick Gessner <rickg@netscape.com>
+ *
+ * History:
+ *
+ * 02.29.2000: Original files (rickg)
+ * 03.02.2000: Flesh out the interface to be compatible with old library (rickg)
+ *
+ ********************************************************************************************/
+
+#ifndef _STRINGTEST2
+#define _STRINGTEST2
+
+
+#include "nsString.h"
+#include <time.h>
+
+#define USE_STL
+
+#ifdef USE_STL
+#include <string>
+using namespace std;
+#endif
+
+#define USE_WIDE 1
+#ifdef USE_WIDE
+ #define stringtype nsString
+ #define astringtype nsAutoString
+ #define chartype PRUnichar
+#else
+ #define stringtype nsCString
+ #define astringtype nsCAutoString
+ #define chartype char
+#endif
+
+#include <stdio.h>
+const double gTicks = 1.0e-7;
+
+
+
+
+
+/********************************************************
+
+ This class's only purpose in life is to test the
+ netscape string library. We exercise the string
+ API's here, and do a bit of performance testing
+ against the standard c++ library string (from STL).
+
+ ********************************************************/
+class CStringTester {
+
+public:
+
+ int TestI18nString();
+
+};
+
+
+
+
+//test 1: unicode char is stripped correctly using StripChars()
+void nsStringTest1(){
+ PRUnichar test[]={0x0041,0x0051,0x0052,0x0000};
+ nsString T(test);
+ PRUnichar result[]={0x0051,0x0052,0x0000};
+ nsString R(result);
+ T.StripChars("ABC");
+ NS_ASSERTION(T.Equals(R), "Test 1: Unicode comparison error");
+}
+//test 2: unicode char is not matched and stripped when high-order byte is not 0x00
+void nsStringTest2(){
+ PRUnichar test[]={0x4e41,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[]={0x4e41,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString R(result);
+ T.StripChars("ABC");
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+ //test 3: unicode char is not matched and stripped when high-order byte is 0xFF
+void nsStringTest3(){
+
+ PRUnichar test[] = {0xFF41,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0xFF41,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString R(test);
+ T.StripChars("ABC");
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+void nsStringTest4(){
+ //test 4: unicode char is matched and stripped correctly using StripChar()
+ PRUnichar test[] = {0x0041,0x0051,0x0052,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0x0051,0x0052,0x0000};
+ nsAutoString R(result);
+ T.StripChar('A');
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+void nsStringTest5(){
+ //test 5: unicode char is not matched and stripped when high-order byte is not 0x00
+
+ PRUnichar test[]={0x4e41,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[]={0x4e41,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString R(result);
+ T.StripChar('A');
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+void nsStringTest6(){
+ //test 6: unicode char is not matched and stripped when high-order byte is 0xFF
+
+ PRUnichar test[] = {0xFF41,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0xFF41,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString R(result);
+ T.StripChar('A');
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+void nsStringTest7(){
+ //test 7: unicode char is matched and replaced correctly using ReplaceChar()
+
+ PRUnichar test[] = {0x0041,0x0051,0x0052,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0x0050,0x0051,0x0052,0x0000};
+ nsAutoString R(result);
+ T.ReplaceChar('A',0x50);
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+void nsStringTest8(){
+ //test 8: unicode char is not matched or replaced when high-order byte != 0x00
+
+ PRUnichar test[] = {0x4e41,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0x4e41,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString R(result);
+ T.ReplaceChar('A',0x50);
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+void nsStringTest9(){
+ //test 9: unicode char is not matched or replaced when high-order byte matches search char
+
+ PRUnichar test[] = {0x4150,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0x4150,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString R(result);
+ T.ReplaceChar('A',0x50);
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+void nsStringTest10(){
+ //test 10: unicode char is not matched or replaced when high-order byte == 0xFF
+
+ PRUnichar test[] = {0xFFc1,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0xFFc1,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString R(result);
+ T.ReplaceChar('A',0x50);
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+
+void nsStringTest11(){
+ //test 11: unicode char is correctly replaced when parameter 1 is a string
+
+ PRUnichar test[] = {0x0041,0x0051,0x0052,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0x0050,0x0051,0x0052,0x0000};
+ nsAutoString R(result);
+ T.ReplaceChar("ABC",0x50);
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+void nsStringTest12(){
+ //test 12: unicode char is not replaced when high-order byte != 0x00
+
+ PRUnichar test[] = {0x4e41,0x0051,0x0052,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0x4e41,0x0051,0x0052,0x0000};
+ nsAutoString R(result);
+ T.ReplaceChar("ABC",0x50);
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+
+}
+void nsStringTest13(){
+ //test 13: unicode char is not replaced when high-order byte matches char in search string
+ PRUnichar test[] = {0x4150,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0x4150,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString R(result);
+ T.ReplaceChar("ABC",'T');
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+
+}
+void nsStringTest14(){
+ PRUnichar test[] = {0xFFc2,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0xFFc2,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString R(result);
+ T.ReplaceChar("ABC",'T');
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+void nsStringTest15(){
+ PRUnichar test[] = {0xFFc2,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0xFFc2,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString R(result);
+ PRUnichar s = 0xc2; //compiler error on this line
+ T.ReplaceChar(s,'T');
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+
+void nsStringTest16(){
+ /* TESTS for ReplaceSubstring()*/
+
+ PRUnichar test[] = {0x0041,0x0042,0x0043,0x0044,0x0045,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0x0044,0x0045,0x0046,0x0044,0x0045};
+ nsAutoString R(result);
+ T.ReplaceSubstring("ABC","DEF");
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+
+}
+void nsStringTest17(){
+
+ PRUnichar test[] = {0x0041,0x4e42,0x0043,0x0044,0x0045,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0x0041,0x4e42,0x0043,0x0044,0x0045,0x0000};
+ nsAutoString R(result);
+ T.ReplaceSubstring("ABC","DEF");
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+void nsStringTest18(){
+ /*TESTS for Trim()*/
+
+ PRUnichar test[] = {0x0041,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString R (result);
+ T.Trim("ABC");
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+void nsStringTest19(){
+ PRUnichar test[] = {0x4e41,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0x4e41,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString R(result);
+ T.Trim("ABC");
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+}
+void nsStringTest22(){
+ PRUnichar test[] = {0x4e51,0x4e52,0x4e53,0x4e41,0x0000};
+ nsAutoString T(test);
+ PRUnichar result[] = {0x4e51,0x4e52,0x4e53,0x4e41,0x0000};
+ nsAutoString R(result);
+ T.Trim("ABC");
+ NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+
+}
+//void nsStringTest23(){
+// PRUnichar test[] = {0x4e51,0x4e52,0x4e53,0x4e22,0x0000};
+// nsAutoString T(test);
+// PRUnichar s(0x4e22);
+// PRUnichar result[] = {0x4e51,0x4e52,0x4e53,0x0000};
+// nsAutoString R(result);
+// T.Trim(s,PR_TRUE,PR_TRUE,PR_FALSE);
+// NS_ASSERTION(T.Equals(R), "Unicode comparison error");
+//}
+void nsStringTest24(){
+ /*TESTS for Find()*/
+ PRUnichar test[] = {0x0041,0x0042,0x0043,0x0051,0x0052,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.Find("ABC") == 0, "Unicode comparison error");
+
+}
+void nsStringTest25(){
+ PRUnichar test[] = {0x4e41,0x4e42,0x4e43,0x4e53,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.Find("ABC") == -1, "Unicode comparison error");
+
+}
+void nsStringTest26(){
+ PRUnichar test[] = {0xFFc1,0x0051,0x0052,0x0053,0x0000};
+ nsAutoString T(test);
+ PRUnichar str[] = {0xc1,0x51,0x52};
+ nsAutoString S(str);
+ NS_ASSERTION(T.Find(S) == -1, "Unicode comparison error");
+}
+void nsStringTest27(){
+ /*TESTS for FindChar()*/
+
+ PRUnichar test[] = {0x0041,0x0051,0x0052,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.FindChar('A') == 0, "Unicode comparison error");
+}
+void nsStringTest28(){
+ PRUnichar test[] = {0x4e41,0x4e42,0x4e43,0x4e53,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.FindChar('A') == -1, "Unicode comparison error");
+}
+void nsStringTest29(){
+ PRUnichar test[] = {0xFFc1,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.FindChar(0xc1) == -1, "Unicode comparison error");
+
+}
+void nsStringTest30(){
+ PRUnichar test[] = {0x4132,0x0051,0x0052,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.FindChar('A1') == -1, "Unicode comparison error");
+}
+ /*TESTS for FindCharInSet()*/
+void nsStringTest31(){
+ PRUnichar test[] = {0x0041,0x0051,0x0052,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.FindCharInSet("ABC") == 0, "Unicode comparison error");
+}
+void nsStringTest32(){
+ PRUnichar test[] = {0x4e41,0x4e42,0x4e43,0x4e53,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.FindCharInSet("ABC") == -1, "Unicode comparison error");
+
+}
+void nsStringTest33(){
+ PRUnichar test[] = {0xFFc1,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar str[] = {0xc1,0x51,0x52};
+ nsAutoString s(str);
+ NS_ASSERTION(T.FindCharInSet(s) == -1, "Unicode comparison error");
+}
+void nsStringTest34(){
+ PRUnichar test[] = {0x4132,0x5132,0x5232,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.FindCharInSet("ABC") == -1, "Unicode comparison error");
+}
+ /*TESTS for RFind()*/
+void nsStringTest35(){
+
+ PRUnichar test[] = {0x0051,0x0052,0x0041,0x0042,0x0043,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.RFind("ABC") == 2, "Unicode comparison error");
+}
+void nsStringTest36(){
+ PRUnichar test[] = {0x4e41,0x4e42,0x4e43,0x4e53,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.RFind("ABC") == -1, "Unicode comparison error");
+}
+void nsStringTest37(){
+ PRUnichar test[] = {0xFFc1,0xFFc2,0xFFc3,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar str[] = {0xc1,0xc2,0xc3};
+ nsAutoString s(str);
+ NS_ASSERTION(T.RFind(s) == -1, "Unicode comparison error");
+}
+ /*TESTS for RFindCharInSet*/
+void nsStringTest38(){
+
+ PRUnichar test[] = {0x0041,0x0042,0x0043,0x0000};
+ nsAutoString T(test);
+ int res = T.RFindCharInSet("ABC");
+ NS_ASSERTION(res==0, "Unicode comparison error");
+}
+void nsStringTest39(){
+ PRUnichar test[] = {0x4e41,0x4e42,0x4e43,0x4e53,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.RFindCharInSet("ABC") == -1, "Unicode comparison error");
+}
+void nsStringTest40(){
+ PRUnichar test[] = {0xFFc1,0x4e51,0x4e52,0x4e53,0x0000};
+ nsAutoString T(test);
+ PRUnichar str[] = {0xc1,0xc2,0xc3};
+ nsAutoString s(str);
+ NS_ASSERTION(T.RFindCharInSet(s) == -1, "Unicode comparison error");
+}
+void nsStringTest41(){
+ PRUnichar test[] = {0x4132,0x0051,0x0052,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.RFindCharInSet("ABC") == -1, "Unicode comparison error");
+}
+ /* TESTS for Compare() */
+void nsStringTest42(){
+ PRUnichar test[] = {0x0041,0x0042,0x0043,0x0000};
+ nsAutoString T(test);
+ NS_ASSERTION(T.Compare("ABC") == 0, "Unicode comparison error");
+}
+void nsStringTest43(){
+ PRUnichar test[] = {0xc341,0xc342,0xc343};
+ nsAutoString T(test);
+ NS_ASSERTION(T.Compare("ABC") == 1, "Unicode comparison error");
+}
+
+
+int CStringTester::TestI18nString(){
+ nsStringTest1();
+ nsStringTest2();
+ nsStringTest3();
+ nsStringTest4();
+ nsStringTest5();
+ nsStringTest6();
+ nsStringTest7();
+ nsStringTest8();
+ nsStringTest9();
+ nsStringTest10();
+ nsStringTest11();
+ nsStringTest12();
+ nsStringTest13();
+ nsStringTest14();
+ nsStringTest15();
+ nsStringTest16();
+ nsStringTest17();
+ nsStringTest18();
+ nsStringTest19();
+ //nsStringTest20();
+ //nsStringTest21();
+ nsStringTest22();
+ //nsStringTest23();
+ nsStringTest24();
+ nsStringTest25();
+ nsStringTest26();
+ nsStringTest27();
+ nsStringTest28();
+ nsStringTest29();
+ nsStringTest30();
+ nsStringTest31();
+ nsStringTest32();
+ nsStringTest33();
+ nsStringTest34();
+ nsStringTest35();
+ nsStringTest36();
+ nsStringTest37();
+ nsStringTest38();
+ nsStringTest39();
+ nsStringTest40();
+ nsStringTest41();
+ nsStringTest42();
+ nsStringTest43();
+
+ return 0;
+}
+
+#endif
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/.cvsignore b/src/libs/xpcom18a4/xpcom/threads/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/threads/Makefile.in b/src/libs/xpcom18a4/xpcom/threads/Makefile.in
new file mode 100644
index 00000000..83433706
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/Makefile.in
@@ -0,0 +1,105 @@
+#
+# ***** 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
+ifeq ($(OS_ARCH),WINNT)
+XPIDL_MODULE = xpcom_thread
+else
+XPIDL_MODULE = xpcom_threads
+endif
+LIBRARY_NAME = xpcomthreads_s
+GRE_MODULE = 1
+REQUIRES = string \
+ $(NULL)
+
+
+CSRCS = \
+ plevent.c \
+ $(NULL)
+
+CPPSRCS = \
+ nsAutoLock.cpp \
+ nsEnvironment.cpp \
+ nsEventQueue.cpp \
+ nsEventQueueService.cpp \
+ nsThread.cpp \
+ nsTimerImpl.cpp \
+ nsProcessCommon.cpp \
+ TimerThread.cpp \
+ $(NULL)
+
+EXPORTS = \
+ nsAutoLock.h \
+ plevent.h \
+ nsProcess.h \
+ nsEventQueueUtils.h \
+ $(NULL)
+
+XPIDLSRCS = \
+ nsIThread.idl \
+ nsITimer.idl \
+ nsITimerInternal.idl \
+ nsITimerManager.idl \
+ nsIRunnable.idl \
+ nsIEventTarget.idl \
+ nsIEventQueue.idl \
+ nsIEventQueueService.idl \
+ nsIEnvironment.idl \
+ nsIProcess.idl \
+ $(NULL)
+
+EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
+
+LOCAL_INCLUDES = -I$(srcdir)/../components
+
+# 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/threads/TimerThread.cpp b/src/libs/xpcom18a4/xpcom/threads/TimerThread.cpp
new file mode 100644
index 00000000..94076892
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/TimerThread.cpp
@@ -0,0 +1,462 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * ***** 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
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Stuart Parmenter <pavlov@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 "nsTimerImpl.h"
+#include "TimerThread.h"
+
+#include "nsAutoLock.h"
+#include "pratom.h"
+
+#include "nsIObserverService.h"
+#include "nsIServiceManager.h"
+
+NS_IMPL_THREADSAFE_ISUPPORTS3(TimerThread, nsIRunnable, nsISupportsWeakReference, nsIObserver)
+
+TimerThread::TimerThread() :
+ mInitInProgress(0),
+ mInitialized(PR_FALSE),
+ mLock(nsnull),
+ mCondVar(nsnull),
+ mShutdown(PR_FALSE),
+ mWaiting(PR_FALSE),
+ mSleeping(PR_FALSE),
+ mDelayLineCounter(0),
+ mMinTimerPeriod(0),
+ mTimeoutAdjustment(0)
+{
+}
+
+TimerThread::~TimerThread()
+{
+ if (mCondVar)
+ PR_DestroyCondVar(mCondVar);
+ if (mLock)
+ PR_DestroyLock(mLock);
+
+ mThread = nsnull;
+
+ PRInt32 n = mTimers.Count();
+ while (--n >= 0) {
+ nsTimerImpl *timer = NS_STATIC_CAST(nsTimerImpl *, mTimers[n]);
+ NS_RELEASE(timer);
+ }
+
+ nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1");
+ if (observerService) {
+ observerService->RemoveObserver(this, "sleep_notification");
+ observerService->RemoveObserver(this, "wake_notification");
+ }
+
+}
+
+nsresult
+TimerThread::InitLocks()
+{
+ NS_ASSERTION(!mLock, "InitLocks called twice?");
+ mLock = PR_NewLock();
+ if (!mLock)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ mCondVar = PR_NewCondVar(mLock);
+ if (!mCondVar)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return NS_OK;
+}
+
+nsresult TimerThread::Init()
+{
+ if (mInitialized) {
+ if (!mThread)
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+ }
+
+ if (PR_AtomicSet(&mInitInProgress, 1) == 0) {
+ nsresult rv;
+
+ mEventQueueService = do_GetService("@mozilla.org/event-queue-service;1", &rv);
+ if (NS_SUCCEEDED(rv)) {
+ nsCOMPtr<nsIObserverService> observerService
+ (do_GetService("@mozilla.org/observer-service;1", &rv));
+
+ if (NS_SUCCEEDED(rv)) {
+ // We hold on to mThread to keep the thread alive.
+ rv = NS_NewThread(getter_AddRefs(mThread),
+ NS_STATIC_CAST(nsIRunnable*, this),
+ 0,
+ PR_JOINABLE_THREAD,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD);
+
+ if (NS_FAILED(rv)) {
+ mThread = nsnull;
+ }
+ else {
+ observerService->AddObserver(this, "sleep_notification", PR_TRUE);
+ observerService->AddObserver(this, "wake_notification", PR_TRUE);
+ }
+ }
+ }
+
+ PR_Lock(mLock);
+ mInitialized = PR_TRUE;
+ PR_NotifyAllCondVar(mCondVar);
+ PR_Unlock(mLock);
+ }
+ else {
+ PR_Lock(mLock);
+ while (!mInitialized) {
+ PR_WaitCondVar(mCondVar, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(mLock);
+ }
+
+ if (!mThread)
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+nsresult TimerThread::Shutdown()
+{
+ if (!mThread)
+ return NS_ERROR_NOT_INITIALIZED;
+
+ { // lock scope
+ nsAutoLock lock(mLock);
+
+ mShutdown = PR_TRUE;
+
+ // notify the cond var so that Run() can return
+ if (mCondVar && mWaiting)
+ PR_NotifyCondVar(mCondVar);
+
+ nsTimerImpl *timer;
+ for (PRInt32 i = mTimers.Count() - 1; i >= 0; i--) {
+ timer = NS_STATIC_CAST(nsTimerImpl*, mTimers[i]);
+ RemoveTimerInternal(timer);
+ }
+ }
+
+ mThread->Join(); // wait for the thread to die
+ return NS_OK;
+}
+
+// Keep track of how early (positive slack) or late (negative slack) timers
+// are running, and use the filtered slack number to adaptively estimate how
+// early timers should fire to be "on time".
+void TimerThread::UpdateFilter(PRUint32 aDelay, PRIntervalTime aTimeout,
+ PRIntervalTime aNow)
+{
+ PRInt32 slack = (PRInt32) (aTimeout - aNow);
+ double smoothSlack = 0;
+ PRUint32 i, filterLength;
+ static PRIntervalTime kFilterFeedbackMaxTicks =
+ PR_MillisecondsToInterval(FILTER_FEEDBACK_MAX);
+
+ if (slack > 0) {
+ if (slack > (PRInt32)kFilterFeedbackMaxTicks)
+ slack = kFilterFeedbackMaxTicks;
+ } else {
+ if (slack < -(PRInt32)kFilterFeedbackMaxTicks)
+ slack = -(PRInt32)kFilterFeedbackMaxTicks;
+ }
+ mDelayLine[mDelayLineCounter & DELAY_LINE_LENGTH_MASK] = slack;
+ if (++mDelayLineCounter < DELAY_LINE_LENGTH) {
+ // Startup mode: accumulate a full delay line before filtering.
+ PR_ASSERT(mTimeoutAdjustment == 0);
+ filterLength = 0;
+ } else {
+ // Past startup: compute number of filter taps based on mMinTimerPeriod.
+ if (mMinTimerPeriod == 0) {
+ mMinTimerPeriod = (aDelay != 0) ? aDelay : 1;
+ } else if (aDelay != 0 && aDelay < mMinTimerPeriod) {
+ mMinTimerPeriod = aDelay;
+ }
+
+ filterLength = (PRUint32) (FILTER_DURATION / mMinTimerPeriod);
+ if (filterLength > DELAY_LINE_LENGTH)
+ filterLength = DELAY_LINE_LENGTH;
+ else if (filterLength < 4)
+ filterLength = 4;
+
+ for (i = 1; i <= filterLength; i++)
+ smoothSlack += mDelayLine[(mDelayLineCounter-i) & DELAY_LINE_LENGTH_MASK];
+ smoothSlack /= filterLength;
+
+ // XXXbe do we need amplification? hacking a fudge factor, need testing...
+ mTimeoutAdjustment = (PRInt32) (smoothSlack * 1.5);
+ }
+
+#ifdef DEBUG_TIMERS
+ if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
+ PR_LOG(gTimerLog, PR_LOG_DEBUG,
+ ("UpdateFilter: smoothSlack = %g, filterLength = %u\n",
+ smoothSlack, filterLength));
+ }
+#endif
+}
+
+/* void Run(); */
+NS_IMETHODIMP TimerThread::Run()
+{
+ nsAutoLock lock(mLock);
+
+ while (!mShutdown) {
+ PRIntervalTime waitFor;
+
+ if (mSleeping) {
+ // Sleep for 0.1 seconds while not firing timers.
+ waitFor = PR_MillisecondsToInterval(100);
+ } else {
+ waitFor = PR_INTERVAL_NO_TIMEOUT;
+ PRIntervalTime now = PR_IntervalNow();
+ nsTimerImpl *timer = nsnull;
+
+ if (mTimers.Count() > 0) {
+ timer = NS_STATIC_CAST(nsTimerImpl*, mTimers[0]);
+
+ if (!TIMER_LESS_THAN(now, timer->mTimeout + mTimeoutAdjustment)) {
+ next:
+ // NB: AddRef before the Release under RemoveTimerInternal to avoid
+ // mRefCnt passing through zero, in case all other refs than the one
+ // from mTimers have gone away (the last non-mTimers[i]-ref's Release
+ // must be racing with us, blocked in gThread->RemoveTimer waiting
+ // for TimerThread::mLock, under nsTimerImpl::Release.
+
+ NS_ADDREF(timer);
+ RemoveTimerInternal(timer);
+
+ // We release mLock around the Fire call to avoid deadlock.
+ lock.unlock();
+
+#ifdef DEBUG_TIMERS
+ if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
+ PR_LOG(gTimerLog, PR_LOG_DEBUG,
+ ("Timer thread woke up %dms from when it was supposed to\n",
+ (now >= timer->mTimeout)
+ ? PR_IntervalToMilliseconds(now - timer->mTimeout)
+ : -(PRInt32)PR_IntervalToMilliseconds(timer->mTimeout-now))
+ );
+ }
+#endif
+
+ // We are going to let the call to PostTimerEvent here handle the
+ // release of the timer so that we don't end up releasing the timer
+ // on the TimerThread instead of on the thread it targets.
+ timer->PostTimerEvent();
+ timer = nsnull;
+
+ lock.lock();
+ if (mShutdown)
+ break;
+
+ // Update now, as PostTimerEvent plus the locking may have taken a
+ // tick or two, and we may goto next below.
+ now = PR_IntervalNow();
+ }
+ }
+
+ if (mTimers.Count() > 0) {
+ timer = NS_STATIC_CAST(nsTimerImpl *, mTimers[0]);
+
+ PRIntervalTime timeout = timer->mTimeout + mTimeoutAdjustment;
+
+ // Don't wait at all (even for PR_INTERVAL_NO_WAIT) if the next timer
+ // is due now or overdue.
+ if (!TIMER_LESS_THAN(now, timeout))
+ goto next;
+ waitFor = timeout - now;
+ }
+
+#ifdef DEBUG_TIMERS
+ if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
+ if (waitFor == PR_INTERVAL_NO_TIMEOUT)
+ PR_LOG(gTimerLog, PR_LOG_DEBUG,
+ ("waiting for PR_INTERVAL_NO_TIMEOUT\n"));
+ else
+ PR_LOG(gTimerLog, PR_LOG_DEBUG,
+ ("waiting for %u\n", PR_IntervalToMilliseconds(waitFor)));
+ }
+#endif
+ }
+
+ mWaiting = PR_TRUE;
+ PR_WaitCondVar(mCondVar, waitFor);
+ mWaiting = PR_FALSE;
+ }
+
+ return NS_OK;
+}
+
+nsresult TimerThread::AddTimer(nsTimerImpl *aTimer)
+{
+ nsAutoLock lock(mLock);
+
+ // Add the timer to our list.
+ PRInt32 i = AddTimerInternal(aTimer);
+ if (i < 0)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Awaken the timer thread.
+ if (mCondVar && mWaiting && i == 0)
+ PR_NotifyCondVar(mCondVar);
+
+ return NS_OK;
+}
+
+nsresult TimerThread::TimerDelayChanged(nsTimerImpl *aTimer)
+{
+ nsAutoLock lock(mLock);
+
+ // Our caller has a strong ref to aTimer, so it can't go away here under
+ // ReleaseTimerInternal.
+ RemoveTimerInternal(aTimer);
+
+ PRInt32 i = AddTimerInternal(aTimer);
+ if (i < 0)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Awaken the timer thread.
+ if (mCondVar && mWaiting && i == 0)
+ PR_NotifyCondVar(mCondVar);
+
+ return NS_OK;
+}
+
+nsresult TimerThread::RemoveTimer(nsTimerImpl *aTimer)
+{
+ nsAutoLock lock(mLock);
+
+ // Remove the timer from our array. Tell callers that aTimer was not found
+ // by returning NS_ERROR_NOT_AVAILABLE. Unlike the TimerDelayChanged case
+ // immediately above, our caller may be passing a (now-)weak ref in via the
+ // aTimer param, specifically when nsTimerImpl::Release loses a race with
+ // TimerThread::Run, must wait for the mLock auto-lock here, and during the
+ // wait Run drops the only remaining ref to aTimer via RemoveTimerInternal.
+
+ if (!RemoveTimerInternal(aTimer))
+ return NS_ERROR_NOT_AVAILABLE;
+
+ // Awaken the timer thread.
+ if (mCondVar && mWaiting)
+ PR_NotifyCondVar(mCondVar);
+
+ return NS_OK;
+}
+
+// This function must be called from within a lock
+PRInt32 TimerThread::AddTimerInternal(nsTimerImpl *aTimer)
+{
+ PRIntervalTime now = PR_IntervalNow();
+ PRInt32 count = mTimers.Count();
+ PRInt32 i = 0;
+ for (; i < count; i++) {
+ nsTimerImpl *timer = NS_STATIC_CAST(nsTimerImpl *, mTimers[i]);
+
+ // Don't break till we have skipped any overdue timers. Do not include
+ // mTimeoutAdjustment here, because we are really trying to avoid calling
+ // TIMER_LESS_THAN(t, u), where the t is now + DELAY_INTERVAL_MAX, u is
+ // now - overdue, and DELAY_INTERVAL_MAX + overdue > DELAY_INTERVAL_LIMIT.
+ // In other words, we want to use now-based time, now adjusted time, even
+ // though "overdue" ultimately depends on adjusted time.
+
+ // XXX does this hold for TYPE_REPEATING_PRECISE? /be
+
+ if (TIMER_LESS_THAN(now, timer->mTimeout) &&
+ TIMER_LESS_THAN(aTimer->mTimeout, timer->mTimeout)) {
+ break;
+ }
+ }
+
+ if (!mTimers.InsertElementAt(aTimer, i))
+ return -1;
+
+ aTimer->mArmed = PR_TRUE;
+ NS_ADDREF(aTimer);
+ return i;
+}
+
+PRBool TimerThread::RemoveTimerInternal(nsTimerImpl *aTimer)
+{
+ if (!mTimers.RemoveElement(aTimer))
+ return PR_FALSE;
+
+ // Order is crucial here -- see nsTimerImpl::Release.
+ aTimer->mArmed = PR_FALSE;
+ NS_RELEASE(aTimer);
+ return PR_TRUE;
+}
+
+void TimerThread::DoBeforeSleep()
+{
+ mSleeping = PR_TRUE;
+}
+
+void TimerThread::DoAfterSleep()
+{
+ for (PRInt32 i = 0; i < mTimers.Count(); i ++) {
+ nsTimerImpl *timer = NS_STATIC_CAST(nsTimerImpl*, mTimers[i]);
+ // get and set the delay to cause its timeout to be recomputed
+ PRUint32 delay;
+ timer->GetDelay(&delay);
+ timer->SetDelay(delay);
+ }
+
+ // nuke the stored adjustments, so they get recalibrated
+ mTimeoutAdjustment = 0;
+ mDelayLineCounter = 0;
+ mSleeping = PR_FALSE;
+}
+
+
+/* void observe (in nsISupports aSubject, in string aTopic, in wstring aData); */
+NS_IMETHODIMP
+TimerThread::Observe(nsISupports* /* aSubject */, const char *aTopic, const PRUnichar* /* aData */)
+{
+ if (strcmp(aTopic, "sleep_notification") == 0)
+ DoBeforeSleep();
+ else if (strcmp(aTopic, "wake_notification") == 0)
+ DoAfterSleep();
+
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/threads/TimerThread.h b/src/libs/xpcom18a4/xpcom/threads/TimerThread.h
new file mode 100644
index 00000000..fa23cfc9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/TimerThread.h
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * ***** 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
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Stuart Parmenter <pavlov@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 TimerThread_h___
+#define TimerThread_h___
+
+#include "nsWeakReference.h"
+
+#include "nsIEventQueueService.h"
+#include "nsIObserver.h"
+#include "nsIRunnable.h"
+#include "nsIThread.h"
+
+#include "nsTimerImpl.h"
+
+#include "nsVoidArray.h"
+
+#include "prcvar.h"
+#include "prinrval.h"
+#include "prlock.h"
+
+class TimerThread : public nsSupportsWeakReference,
+ public nsIRunnable,
+ public nsIObserver
+{
+public:
+ TimerThread();
+ NS_HIDDEN_(nsresult) InitLocks();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIRUNNABLE
+ NS_DECL_NSIOBSERVER
+
+ NS_HIDDEN_(nsresult) Init();
+ NS_HIDDEN_(nsresult) Shutdown();
+
+ nsresult AddTimer(nsTimerImpl *aTimer);
+ nsresult TimerDelayChanged(nsTimerImpl *aTimer);
+ nsresult RemoveTimer(nsTimerImpl *aTimer);
+
+#define FILTER_DURATION 1e3 /* one second */
+#define FILTER_FEEDBACK_MAX 100 /* 1/10th of a second */
+
+ void UpdateFilter(PRUint32 aDelay, PRIntervalTime aTimeout,
+ PRIntervalTime aNow);
+
+ // For use by nsTimerImpl::Fire()
+ nsCOMPtr<nsIEventQueueService> mEventQueueService;
+
+ void DoBeforeSleep();
+ void DoAfterSleep();
+
+private:
+ ~TimerThread();
+
+ PRInt32 mInitInProgress;
+ PRBool mInitialized;
+
+ // These two internal helper methods must be called while mLock is held.
+ // AddTimerInternal returns the position where the timer was added in the
+ // list, or -1 if it failed.
+ PRInt32 AddTimerInternal(nsTimerImpl *aTimer);
+ PRBool RemoveTimerInternal(nsTimerImpl *aTimer);
+
+ nsCOMPtr<nsIThread> mThread;
+ PRLock *mLock;
+ PRCondVar *mCondVar;
+
+ PRPackedBool mShutdown;
+ PRPackedBool mWaiting;
+ PRPackedBool mSleeping;
+
+ nsVoidArray mTimers;
+
+#define DELAY_LINE_LENGTH_LOG2 5
+#define DELAY_LINE_LENGTH_MASK PR_BITMASK(DELAY_LINE_LENGTH_LOG2)
+#define DELAY_LINE_LENGTH PR_BIT(DELAY_LINE_LENGTH_LOG2)
+
+ PRInt32 mDelayLine[DELAY_LINE_LENGTH];
+ PRUint32 mDelayLineCounter;
+ PRUint32 mMinTimerPeriod; // milliseconds
+ PRInt32 mTimeoutAdjustment;
+};
+
+#endif /* TimerThread_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsAutoLock.cpp b/src/libs/xpcom18a4/xpcom/threads/nsAutoLock.cpp
new file mode 100644
index 00000000..df89408c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsAutoLock.cpp
@@ -0,0 +1,435 @@
+/* -*- 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 "nsAutoLock.h"
+
+#ifdef DEBUG
+
+#include "plhash.h"
+#include "prprf.h"
+#include "prlock.h"
+#include "prthread.h"
+#include "nsDebug.h"
+#include "nsVoidArray.h"
+
+#ifdef NS_TRACE_MALLOC_XXX
+# include <stdio.h>
+# include "nsTraceMalloc.h"
+#endif
+
+static PRUintn LockStackTPI = (PRUintn)-1;
+static PLHashTable* OrderTable = 0;
+static PRLock* OrderTableLock = 0;
+
+static const char* const LockTypeNames[] = {"Lock", "Monitor", "CMonitor"};
+
+struct nsNamedVector : public nsVoidArray {
+ const char* mName;
+
+#ifdef NS_TRACE_MALLOC_XXX
+ // Callsites for the inner locks/monitors stored in our base nsVoidArray.
+ // This array parallels our base nsVoidArray.
+ nsVoidArray mInnerSites;
+#endif
+
+ nsNamedVector(const char* name = 0, PRUint32 initialSize = 0)
+ : nsVoidArray(initialSize),
+ mName(name)
+ {
+ }
+};
+
+static void * PR_CALLBACK
+_hash_alloc_table(void *pool, PRSize size)
+{
+ return operator new(size);
+}
+
+static void PR_CALLBACK
+_hash_free_table(void *pool, void *item)
+{
+ operator delete(item);
+}
+
+static PLHashEntry * PR_CALLBACK
+_hash_alloc_entry(void *pool, const void *key)
+{
+ return new PLHashEntry;
+}
+
+/*
+ * Because monitors and locks may be associated with an nsAutoLockBase,
+ * without having had their associated nsNamedVector created explicitly in
+ * nsAutoMonitor::NewMonitor/DeleteMonitor, we need to provide a freeEntry
+ * PLHashTable hook, to avoid leaking nsNamedVectors which are replaced by
+ * nsAutoMonitor::NewMonitor.
+ *
+ * There is still a problem with the OrderTable containing orphaned
+ * nsNamedVector entries, for manually created locks wrapped by nsAutoLocks.
+ * (there should be no manually created monitors wrapped by nsAutoMonitors:
+ * you should use nsAutoMonitor::NewMonitor and nsAutoMonitor::DestroyMonitor
+ * instead of PR_NewMonitor and PR_DestroyMonitor). These lock vectors don't
+ * strictly leak, as they are killed on shutdown, but there are unnecessary
+ * named vectors in the hash table that outlive their associated locks.
+ *
+ * XXX so we should have nsLock, nsMonitor, etc. and strongly type their
+ * XXX nsAutoXXX counterparts to take only the non-auto types as inputs
+ */
+static void PR_CALLBACK
+_hash_free_entry(void *pool, PLHashEntry *entry, PRUintn flag)
+{
+ nsNamedVector* vec = (nsNamedVector*) entry->value;
+ if (vec) {
+ entry->value = 0;
+ delete vec;
+ }
+ if (flag == HT_FREE_ENTRY)
+ delete entry;
+}
+
+static const PLHashAllocOps _hash_alloc_ops = {
+ _hash_alloc_table, _hash_free_table,
+ _hash_alloc_entry, _hash_free_entry
+};
+
+PR_STATIC_CALLBACK(PRIntn)
+_purge_one(PLHashEntry* he, PRIntn cnt, void* arg)
+{
+ nsNamedVector* vec = (nsNamedVector*) he->value;
+
+ if (he->key == arg)
+ return HT_ENUMERATE_REMOVE;
+ vec->RemoveElement(arg);
+ return HT_ENUMERATE_NEXT;
+}
+
+PR_STATIC_CALLBACK(void)
+OnMonitorRecycle(void* addr)
+{
+ PR_Lock(OrderTableLock);
+ PL_HashTableEnumerateEntries(OrderTable, _purge_one, addr);
+ PR_Unlock(OrderTableLock);
+}
+
+PR_STATIC_CALLBACK(PLHashNumber)
+_hash_pointer(const void* key)
+{
+ return PLHashNumber(NS_PTR_TO_INT32(key)) >> 2;
+}
+
+// Must be single-threaded here, early in primordial thread.
+static void InitAutoLockStatics()
+{
+ (void) PR_NewThreadPrivateIndex(&LockStackTPI, 0);
+ OrderTable = PL_NewHashTable(64, _hash_pointer,
+ PL_CompareValues, PL_CompareValues,
+ &_hash_alloc_ops, 0);
+ if (OrderTable && !(OrderTableLock = PR_NewLock())) {
+ PL_HashTableDestroy(OrderTable);
+ OrderTable = 0;
+ }
+ PR_CSetOnMonitorRecycle(OnMonitorRecycle);
+}
+
+void _FreeAutoLockStatics()
+{
+ PLHashTable* table = OrderTable;
+ if (!table) return;
+
+ // Called at shutdown, so we don't need to lock.
+ PR_CSetOnMonitorRecycle(0);
+ PR_DestroyLock(OrderTableLock);
+ OrderTableLock = 0;
+ PL_HashTableDestroy(table);
+ OrderTable = 0;
+}
+
+static nsNamedVector* GetVector(PLHashTable* table, const void* key)
+{
+ PLHashNumber hash = _hash_pointer(key);
+ PLHashEntry** hep = PL_HashTableRawLookup(table, hash, key);
+ PLHashEntry* he = *hep;
+ if (he)
+ return (nsNamedVector*) he->value;
+ nsNamedVector* vec = new nsNamedVector();
+ if (vec)
+ PL_HashTableRawAdd(table, hep, hash, key, vec);
+ return vec;
+}
+
+// We maintain an acyclic graph in OrderTable, so recursion can't diverge.
+static PRBool Reachable(PLHashTable* table, const void* goal, const void* start)
+{
+ PR_ASSERT(goal);
+ PR_ASSERT(start);
+ nsNamedVector* vec = GetVector(table, start);
+ for (PRUint32 i = 0, n = vec->Count(); i < n; i++) {
+ void* addr = vec->ElementAt(i);
+ if (addr == goal || Reachable(table, goal, addr))
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+static PRBool WellOrdered(const void* addr1, const void* addr2,
+ const void *callsite2, PRUint32* index2p,
+ nsNamedVector** vec1p, nsNamedVector** vec2p)
+{
+ PRBool rv = PR_TRUE;
+ PLHashTable* table = OrderTable;
+ if (!table) return rv;
+ PR_Lock(OrderTableLock);
+
+ // Check whether we've already asserted (addr1 < addr2).
+ nsNamedVector* vec1 = GetVector(table, addr1);
+ if (vec1) {
+ PRUint32 i, n;
+
+ for (i = 0, n = vec1->Count(); i < n; i++)
+ if (vec1->ElementAt(i) == addr2)
+ break;
+
+ if (i == n) {
+ // Now check for (addr2 < addr1) and return false if so.
+ nsNamedVector* vec2 = GetVector(table, addr2);
+ if (vec2) {
+ for (i = 0, n = vec2->Count(); i < n; i++) {
+ void* addri = vec2->ElementAt(i);
+ PR_ASSERT(addri);
+ if (addri == addr1 || Reachable(table, addr1, addri)) {
+ *index2p = i;
+ *vec1p = vec1;
+ *vec2p = vec2;
+ rv = PR_FALSE;
+ break;
+ }
+ }
+
+ if (rv) {
+ // Assert (addr1 < addr2) into the order table.
+ // XXX fix plvector/nsVector to use const void*
+ vec1->AppendElement((void*) addr2);
+#ifdef NS_TRACE_MALLOC_XXX
+ vec1->mInnerSites.AppendElement((void*) callsite2);
+#endif
+ }
+ }
+ }
+ }
+
+ PR_Unlock(OrderTableLock);
+ return rv;
+}
+
+nsAutoLockBase::nsAutoLockBase(void* addr, nsAutoLockType type)
+{
+ if (LockStackTPI == PRUintn(-1))
+ InitAutoLockStatics();
+
+ nsAutoLockBase* stackTop =
+ (nsAutoLockBase*) PR_GetThreadPrivate(LockStackTPI);
+ if (stackTop) {
+ if (stackTop->mAddr == addr) {
+ // Ignore reentry: it's legal for monitors, and NSPR will assert
+ // if you reenter a PRLock.
+ } else if (!addr) {
+ // Ignore null addresses: the caller promises not to use the
+ // lock at all, and NSPR will assert if you enter it.
+ } else {
+ const void* node =
+#ifdef NS_TRACE_MALLOC_XXX
+ NS_GetStackTrace(1)
+#else
+ nsnull
+#endif
+ ;
+ nsNamedVector* vec1;
+ nsNamedVector* vec2;
+ PRUint32 i2;
+
+ if (!WellOrdered(stackTop->mAddr, addr, node, &i2, &vec1, &vec2)) {
+ char buf[128];
+ PR_snprintf(buf, sizeof buf,
+ "Potential deadlock between %s%s@%p and %s%s@%p",
+ vec1->mName ? vec1->mName : "",
+ LockTypeNames[stackTop->mType],
+ stackTop->mAddr,
+ vec2->mName ? vec2->mName : "",
+ LockTypeNames[type],
+ addr);
+#ifdef NS_TRACE_MALLOC_XXX
+ fprintf(stderr, "\n*** %s\n\nCurrent stack:\n", buf);
+ NS_DumpStackTrace(node, stderr);
+
+ fputs("\nPrevious stack:\n", stderr);
+ NS_DumpStackTrace(vec2->mInnerSites.ElementAt(i2), stderr);
+ putc('\n', stderr);
+#endif
+ NS_ERROR(buf);
+ }
+ }
+ }
+
+ mAddr = addr;
+ mDown = stackTop;
+ mType = type;
+ if (mAddr)
+ (void) PR_SetThreadPrivate(LockStackTPI, this);
+}
+
+nsAutoLockBase::~nsAutoLockBase()
+{
+ if (mAddr)
+ (void) PR_SetThreadPrivate(LockStackTPI, mDown);
+}
+
+void nsAutoLockBase::Show()
+{
+ if (!mAddr)
+ return;
+ nsAutoLockBase* curr = (nsAutoLockBase*) PR_GetThreadPrivate(LockStackTPI);
+ nsAutoLockBase* prev = nsnull;
+ while (curr != mDown) {
+ prev = curr;
+ curr = prev->mDown;
+ }
+ if (!prev)
+ PR_SetThreadPrivate(LockStackTPI, this);
+ else
+ prev->mDown = this;
+}
+
+void nsAutoLockBase::Hide()
+{
+ if (!mAddr)
+ return;
+ nsAutoLockBase* curr = (nsAutoLockBase*) PR_GetThreadPrivate(LockStackTPI);
+ nsAutoLockBase* prev = nsnull;
+ while (curr != this) {
+ prev = curr;
+ curr = prev->mDown;
+ }
+ if (!prev)
+ PR_SetThreadPrivate(LockStackTPI, mDown);
+ else
+ prev->mDown = mDown;
+}
+
+#endif /* DEBUG */
+
+PRMonitor* nsAutoMonitor::NewMonitor(const char* name)
+{
+ PRMonitor* mon = PR_NewMonitor();
+#ifdef DEBUG
+ if (mon && OrderTable) {
+ nsNamedVector* value = new nsNamedVector(name);
+ if (value) {
+ PR_Lock(OrderTableLock);
+ PL_HashTableAdd(OrderTable, mon, value);
+ PR_Unlock(OrderTableLock);
+ }
+ }
+#endif
+ return mon;
+}
+
+void nsAutoMonitor::DestroyMonitor(PRMonitor* mon)
+{
+#ifdef DEBUG
+ if (OrderTable)
+ OnMonitorRecycle(mon);
+#endif
+ PR_DestroyMonitor(mon);
+}
+
+void nsAutoMonitor::Enter()
+{
+#ifdef DEBUG
+ if (!mAddr) {
+ NS_ERROR("It is not legal to enter a null monitor");
+ return;
+ }
+ nsAutoLockBase* stackTop =
+ (nsAutoLockBase*) PR_GetThreadPrivate(LockStackTPI);
+ NS_ASSERTION(stackTop == mDown, "non-LIFO nsAutoMonitor::Enter");
+ mDown = stackTop;
+ (void) PR_SetThreadPrivate(LockStackTPI, this);
+#endif
+ PR_EnterMonitor(mMonitor);
+ mLockCount += 1;
+}
+
+void nsAutoMonitor::Exit()
+{
+#ifdef DEBUG
+ if (!mAddr) {
+ NS_ERROR("It is not legal to exit a null monitor");
+ return;
+ }
+ (void) PR_SetThreadPrivate(LockStackTPI, mDown);
+#endif
+ PRStatus status = PR_ExitMonitor(mMonitor);
+ NS_ASSERTION(status == PR_SUCCESS, "PR_ExitMonitor failed");
+ mLockCount -= 1;
+}
+
+// XXX we don't worry about cached monitors being destroyed behind our back.
+// XXX current NSPR (mozilla/nsprpub/pr/src/threads/prcmon.c) never destroys
+// XXX a cached monitor! potential resource pig in conjunction with necko...
+
+void nsAutoCMonitor::Enter()
+{
+#ifdef DEBUG
+ nsAutoLockBase* stackTop =
+ (nsAutoLockBase*) PR_GetThreadPrivate(LockStackTPI);
+ NS_ASSERTION(stackTop == mDown, "non-LIFO nsAutoCMonitor::Enter");
+ mDown = stackTop;
+ (void) PR_SetThreadPrivate(LockStackTPI, this);
+#endif
+ PR_CEnterMonitor(mLockObject);
+ mLockCount += 1;
+}
+
+void nsAutoCMonitor::Exit()
+{
+#ifdef DEBUG
+ (void) PR_SetThreadPrivate(LockStackTPI, mDown);
+#endif
+ PRStatus status = PR_CExitMonitor(mLockObject);
+ NS_ASSERTION(status == PR_SUCCESS, "PR_CExitMonitor failed");
+ mLockCount -= 1;
+}
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsAutoLock.h b/src/libs/xpcom18a4/xpcom/threads/nsAutoLock.h
new file mode 100644
index 00000000..a82d6ffc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsAutoLock.h
@@ -0,0 +1,383 @@
+/* -*- 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 ***** */
+
+
+/*
+ A stack-based lock object that makes using PRLock a bit more
+ convenient. It acquires the monitor when constructed, and releases
+ it when it goes out of scope.
+
+ For example,
+
+ class Foo {
+ private:
+ PRLock* mLock;
+
+ public:
+ Foo(void) {
+ mLock = PR_NewLock();
+ }
+
+ ~Foo(void) {
+ PR_DestroyLock(mLock);
+ }
+
+ void ThreadSafeMethod(void) {
+ // we're don't hold the lock yet...
+
+ nsAutoLock lock(mLock);
+ // ...but now we do.
+
+ // we even can do wacky stuff like return from arbitrary places w/o
+ // worrying about forgetting to release the lock
+ if (some_weird_condition)
+ return;
+
+ // otherwise do some other stuff
+ }
+
+ void ThreadSafeBlockScope(void) {
+ // we're not in the lock here...
+
+ {
+ nsAutoLock lock(mLock);
+ // but we are now, at least until the block scope closes
+ }
+
+ // ...now we're not in the lock anymore
+ }
+ };
+
+ A similar stack-based locking object is available for PRMonitor. The
+ major difference is that the PRMonitor must be created and destroyed
+ via the static methods on nsAutoMonitor.
+
+ For example:
+ Foo::Foo() {
+ mMon = nsAutoMonitor::NewMonitor("FooMonitor");
+ }
+ nsresult Foo::MyMethod(...) {
+ nsAutoMonitor mon(mMon);
+ ...
+ // go ahead and do deeply nested returns...
+ return NS_ERROR_FAILURE;
+ ...
+ // or call Wait or Notify...
+ mon.Wait();
+ ...
+ // cleanup is automatic
+ }
+ */
+
+#ifndef nsAutoLock_h__
+#define nsAutoLock_h__
+
+#include "nscore.h"
+#include "prlock.h"
+#include "prlog.h"
+
+/**
+ * nsAutoLockBase
+ * This is the base class for the stack-based locking objects.
+ * Clients of derived classes need not play with this superclass.
+ **/
+class NS_COM nsAutoLockBase {
+protected:
+ nsAutoLockBase() {}
+ enum nsAutoLockType {eAutoLock, eAutoMonitor, eAutoCMonitor};
+
+#ifdef DEBUG
+ nsAutoLockBase(void* addr, nsAutoLockType type);
+ ~nsAutoLockBase();
+
+ void Show();
+ void Hide();
+
+ void* mAddr;
+ nsAutoLockBase* mDown;
+ nsAutoLockType mType;
+#else
+ nsAutoLockBase(void* addr, nsAutoLockType type) {}
+ ~nsAutoLockBase() {}
+
+ void Show() {}
+ void Hide() {}
+#endif
+};
+
+/**
+ * nsAutoLock
+ * Stack-based locking object for PRLock.
+ **/
+class NS_COM nsAutoLock : public nsAutoLockBase {
+private:
+ PRLock* mLock;
+ PRBool mLocked;
+
+ // Not meant to be implemented. This makes it a compiler error to
+ // construct or assign an nsAutoLock object incorrectly.
+ nsAutoLock(void);
+ nsAutoLock(const nsAutoLock& /*aLock*/);
+ nsAutoLock& operator =(const nsAutoLock& /*aLock*/);
+
+ // Not meant to be implemented. This makes it a compiler error to
+ // attempt to create an nsAutoLock object on the heap.
+ static void* operator new(size_t /*size*/) CPP_THROW_NEW;
+ static void operator delete(void* /*memory*/);
+
+public:
+ /**
+ * Constructor
+ * The constructor aquires the given lock. The destructor
+ * releases the lock.
+ *
+ * @param aLock A valid PRLock* returned from the NSPR's
+ * PR_NewLock() function.
+ **/
+ nsAutoLock(PRLock* aLock)
+ : nsAutoLockBase(aLock, eAutoLock),
+ mLock(aLock),
+ mLocked(PR_TRUE) {
+ PR_ASSERT(mLock);
+
+ // This will assert deep in the bowels of NSPR if you attempt
+ // to re-enter the lock.
+ PR_Lock(mLock);
+ }
+
+ ~nsAutoLock(void) {
+ if (mLocked)
+ PR_Unlock(mLock);
+ }
+
+ /**
+ * lock
+ * Client may call this to reaquire the given lock. Take special
+ * note that attempting to aquire a locked lock will hang or crash.
+ **/
+ void lock() {
+ Show();
+ PR_ASSERT(!mLocked);
+ PR_Lock(mLock);
+ mLocked = PR_TRUE;
+ }
+
+
+ /**
+ * unlock
+ * Client may call this to release the given lock. Take special
+ * note unlocking an unlocked lock has undefined results.
+ **/
+ void unlock() {
+ PR_ASSERT(mLocked);
+ PR_Unlock(mLock);
+ mLocked = PR_FALSE;
+ Hide();
+ }
+};
+
+#include "prcmon.h"
+#include "nsError.h"
+#include "nsDebug.h"
+
+class NS_COM nsAutoMonitor : public nsAutoLockBase {
+public:
+
+ /**
+ * NewMonitor
+ * Allocates a new PRMonitor for use with nsAutoMonitor.
+ * @param name A (unique /be?) name which can reference this monitor
+ * @returns nsnull if failure
+ * A valid PRMonitor* is successful while must be destroyed
+ * by nsAutoMonitor::DestroyMonitor()
+ **/
+ static PRMonitor* NewMonitor(const char* name);
+ static void DestroyMonitor(PRMonitor* mon);
+
+
+ /**
+ * Constructor
+ * The constructor locks the given monitor. During destruction
+ * the monitor will be unlocked.
+ *
+ * @param mon A valid PRMonitor* returned from
+ * nsAutoMonitor::NewMonitor().
+ **/
+ nsAutoMonitor(PRMonitor* mon)
+ : nsAutoLockBase((void*)mon, eAutoMonitor),
+ mMonitor(mon), mLockCount(0)
+ {
+ NS_ASSERTION(mMonitor, "null monitor");
+ if (mMonitor) {
+ PR_EnterMonitor(mMonitor);
+ mLockCount = 1;
+ }
+ }
+
+ ~nsAutoMonitor() {
+ NS_ASSERTION(mMonitor, "null monitor");
+ if (mMonitor && mLockCount) {
+#ifdef DEBUG
+ PRStatus status =
+#endif
+ PR_ExitMonitor(mMonitor);
+ NS_ASSERTION(status == PR_SUCCESS, "PR_ExitMonitor failed");
+ }
+ }
+
+ /**
+ * Enter
+ * Client may call this to reenter the given monitor.
+ * @see prmon.h
+ **/
+ void Enter();
+
+ /**
+ * Exit
+ * Client may call this to exit the given monitor.
+ * @see prmon.h
+ **/
+ void Exit();
+
+ /**
+ * Wait
+ * @see prmon.h
+ **/
+ nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT) {
+ return PR_Wait(mMonitor, interval) == PR_SUCCESS
+ ? NS_OK : NS_ERROR_FAILURE;
+ }
+
+ /**
+ * Notify
+ * @see prmon.h
+ **/
+ nsresult Notify() {
+ return PR_Notify(mMonitor) == PR_SUCCESS
+ ? NS_OK : NS_ERROR_FAILURE;
+ }
+
+ /**
+ * NotifyAll
+ * @see prmon.h
+ **/
+ nsresult NotifyAll() {
+ return PR_NotifyAll(mMonitor) == PR_SUCCESS
+ ? NS_OK : NS_ERROR_FAILURE;
+ }
+
+private:
+ PRMonitor* mMonitor;
+ PRInt32 mLockCount;
+
+ // Not meant to be implemented. This makes it a compiler error to
+ // construct or assign an nsAutoLock object incorrectly.
+ nsAutoMonitor(void);
+ nsAutoMonitor(const nsAutoMonitor& /*aMon*/);
+ nsAutoMonitor& operator =(const nsAutoMonitor& /*aMon*/);
+
+ // Not meant to be implemented. This makes it a compiler error to
+ // attempt to create an nsAutoLock object on the heap.
+ static void* operator new(size_t /*size*/) CPP_THROW_NEW;
+ static void operator delete(void* /*memory*/);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// Once again, this time with a cache...
+// (Using this avoids the need to allocate a PRMonitor, which may be useful when
+// a large number of objects of the same class need associated monitors.)
+
+#include "prcmon.h"
+#include "nsError.h"
+
+class NS_COM nsAutoCMonitor : public nsAutoLockBase {
+public:
+ nsAutoCMonitor(void* lockObject)
+ : nsAutoLockBase(lockObject, eAutoCMonitor),
+ mLockObject(lockObject), mLockCount(0)
+ {
+ NS_ASSERTION(lockObject, "null lock object");
+ PR_CEnterMonitor(mLockObject);
+ mLockCount = 1;
+ }
+
+ ~nsAutoCMonitor() {
+ if (mLockCount) {
+#ifdef DEBUG
+ PRStatus status =
+#endif
+ PR_CExitMonitor(mLockObject);
+ NS_ASSERTION(status == PR_SUCCESS, "PR_CExitMonitor failed");
+ }
+ }
+
+ void Enter();
+ void Exit();
+
+ nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT) {
+ return PR_CWait(mLockObject, interval) == PR_SUCCESS
+ ? NS_OK : NS_ERROR_FAILURE;
+ }
+
+ nsresult Notify() {
+ return PR_CNotify(mLockObject) == PR_SUCCESS
+ ? NS_OK : NS_ERROR_FAILURE;
+ }
+
+ nsresult NotifyAll() {
+ return PR_CNotifyAll(mLockObject) == PR_SUCCESS
+ ? NS_OK : NS_ERROR_FAILURE;
+ }
+
+private:
+ void* mLockObject;
+ PRInt32 mLockCount;
+
+ // Not meant to be implemented. This makes it a compiler error to
+ // construct or assign an nsAutoLock object incorrectly.
+ nsAutoCMonitor(void);
+ nsAutoCMonitor(const nsAutoCMonitor& /*aMon*/);
+ nsAutoCMonitor& operator =(const nsAutoCMonitor& /*aMon*/);
+
+ // Not meant to be implemented. This makes it a compiler error to
+ // attempt to create an nsAutoLock object on the heap.
+ static void* operator new(size_t /*size*/) CPP_THROW_NEW;
+ static void operator delete(void* /*memory*/);
+};
+
+#endif // nsAutoLock_h__
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsEnvironment.cpp b/src/libs/xpcom18a4/xpcom/threads/nsEnvironment.cpp
new file mode 100644
index 00000000..139b24a6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsEnvironment.cpp
@@ -0,0 +1,202 @@
+/* -*- 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 embedding code.
+ *
+ * The Initial Developers of the Original Code are
+ * Benjamin Smedberg <bsmedberg@covad.net> and
+ * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2003/2004
+ * 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 "nsEnvironment.h"
+#include "prenv.h"
+#include "prprf.h"
+#include "nsAutoLock.h"
+#include "nsBaseHashtable.h"
+#include "nsHashKeys.h"
+#include "nsPromiseFlatString.h"
+#include "nsDependentString.h"
+#include "nsNativeCharsetUtils.h"
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsEnvironment, nsIEnvironment)
+
+NS_METHOD
+nsEnvironment::Create(nsISupports *aOuter, REFNSIID aIID,
+ void **aResult)
+{
+ nsresult rv;
+ *aResult = nsnull;
+
+ if (aOuter != nsnull) {
+ return NS_ERROR_NO_AGGREGATION;
+ }
+
+ nsEnvironment* obj = new nsEnvironment();
+ if (!obj) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ obj->mLock = PR_NewLock();
+ if (!obj->mLock) {
+ delete obj;
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ rv = obj->QueryInterface(aIID, aResult);
+ if (NS_FAILED(rv)) {
+ delete obj;
+ }
+ return rv;
+}
+
+nsEnvironment::~nsEnvironment()
+{
+ if (mLock)
+ PR_DestroyLock(mLock);
+}
+
+NS_IMETHODIMP
+nsEnvironment::Exists(const nsAString& aName, PRBool *aOutValue)
+{
+ nsCAutoString nativeName;
+ nsresult rv = NS_CopyUnicodeToNative(aName, nativeName);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCAutoString nativeVal;
+#if defined(XP_UNIX)
+ /* For Unix/Linux platforms we follow the Unix definition:
+ * An environment variable exists when |getenv()| returns a non-NULL value.
+ * An environment variable does not exist when |getenv()| returns NULL.
+ */
+ const char *value = PR_GetEnv(nativeName.get());
+
+ *aOutValue = (value)?(PR_TRUE):(PR_FALSE);
+#else
+ /* For non-Unix/Linux platforms we have to fall back to a
+ * "portable" definition (which is incorrect for Unix/Linux!!!!)
+ * which simply checks whether the string returned by |Get()| is empty
+ * or not.
+ */
+ nsAutoString value;
+ Get(aName, value);
+ *aOutValue = (value.IsEmpty())?(PR_FALSE):(PR_TRUE);
+#endif /* XP_UNIX */
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEnvironment::Get(const nsAString& aName, nsAString& aOutValue)
+{
+ nsCAutoString nativeName;
+ nsresult rv = NS_CopyUnicodeToNative(aName, nativeName);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCAutoString nativeVal;
+ const char *value = PR_GetEnv(nativeName.get());
+ if (value) {
+ rv = NS_CopyNativeToUnicode(nsDependentCString(value), aOutValue);
+ } else {
+ aOutValue.Truncate();
+ rv = NS_OK;
+ }
+
+ return rv;
+}
+
+/* Environment strings must have static duration; We're gonna leak all of this
+ * at shutdown: this is by design, caused how Unix/Linux implement environment
+ * vars.
+ */
+
+typedef nsBaseHashtableET<nsCStringHashKey,char*> EnvEntryType;
+typedef nsTHashtable<EnvEntryType> EnvHashType;
+
+static EnvHashType *gEnvHash = nsnull;
+
+static PRBool
+EnsureEnvHash()
+{
+ if (gEnvHash)
+ return PR_TRUE;
+
+ gEnvHash = new EnvHashType;
+ if (!gEnvHash)
+ return PR_FALSE;
+
+ if(gEnvHash->Init())
+ return PR_TRUE;
+
+ delete gEnvHash;
+ gEnvHash = nsnull;
+ return PR_FALSE;
+}
+
+NS_IMETHODIMP
+nsEnvironment::Set(const nsAString& aName, const nsAString& aValue)
+{
+ nsCAutoString nativeName;
+ nsCAutoString nativeVal;
+
+ nsresult rv = NS_CopyUnicodeToNative(aName, nativeName);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = NS_CopyUnicodeToNative(aValue, nativeVal);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoLock lock(mLock); // autolock unlocks automagically
+
+ if (!EnsureEnvHash()){
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ EnvEntryType* entry = gEnvHash->PutEntry(nativeName);
+ if (!entry) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ char* newData = PR_smprintf("%s=%s",
+ nativeName.get(),
+ nativeVal.get());
+ if (!newData) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ PR_SetEnv(newData);
+ if (entry->mData) {
+ PR_smprintf_free(entry->mData);
+ }
+ entry->mData = newData;
+ return NS_OK;
+}
+
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsEnvironment.h b/src/libs/xpcom18a4/xpcom/threads/nsEnvironment.h
new file mode 100644
index 00000000..46e8d66a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsEnvironment.h
@@ -0,0 +1,67 @@
+/* -*- 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 embedding code.
+ *
+ * The Initial Developers of the Original Code are
+ * Benjamin Smedberg <bsmedberg@covad.net> and
+ * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2003/2004
+ * 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 nsEnvironment_h__
+#define nsEnvironment_h__
+
+#include "nsIEnvironment.h"
+#include "prlock.h"
+
+#define NS_ENVIRONMENT_CID \
+ { 0X3D68F92UL, 0X9513, 0X4E25, \
+ { 0X9B, 0XE9, 0X7C, 0XB2, 0X39, 0X87, 0X41, 0X72 } }
+#define NS_ENVIRONMENT_CONTRACTID "@mozilla.org/process/environment;1"
+
+class nsEnvironment : public nsIEnvironment
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIENVIRONMENT
+
+ static NS_METHOD Create(nsISupports *aOuter, REFNSIID aIID,
+ void **aResult);
+
+private:
+ nsEnvironment() { }
+ ~nsEnvironment();
+
+ PRLock *mLock;
+};
+
+#endif /* !nsEnvironment_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsEventQueue.cpp b/src/libs/xpcom18a4/xpcom/threads/nsEventQueue.cpp
new file mode 100644
index 00000000..7dc8f089
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsEventQueue.cpp
@@ -0,0 +1,632 @@
+/* -*- 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 "nsCOMPtr.h"
+#include "nsEventQueue.h"
+#include "nsIEventQueueService.h"
+#include "nsIThread.h"
+
+#include "nsIServiceManager.h"
+#include "nsIObserverService.h"
+
+#include "nsString.h"
+
+#include "prlog.h"
+
+#ifdef NS_DEBUG
+#include "prprf.h"
+#endif
+
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+/* found these logs useful in conjunction with netlibStreamEvent logging
+ from netwerk. */
+PRLogModuleInfo* gEventQueueLog = 0;
+PRUint32 gEventQueueLogCount = 0;
+PRUint32 gEventQueueLogPPCount = 0;
+static int gEventQueueLogPPLevel = 0;
+static PLEventQueue *gEventQueueLogQueue = 0;
+static PRThread *gEventQueueLogThread = 0;
+#endif
+
+// in a real system, these would be members in a header class...
+static const char gActivatedNotification[] = "nsIEventQueueActivated";
+static const char gDestroyedNotification[] = "nsIEventQueueDestroyed";
+
+nsEventQueueImpl::nsEventQueueImpl()
+{
+ NS_ADDREF_THIS();
+ /* The slightly weird ownership model for eventqueues goes like this:
+
+ General:
+ There's an addref from the factory generally held by whoever asked for
+ the queue. The queue addrefs itself (right here) and releases itself
+ after someone calls StopAcceptingEvents() on the queue and when it is
+ dark and empty (in CheckForDeactivation()).
+
+ Chained queues:
+
+ Eldest queue:
+ The eldest queue in a chain is held on to by the EventQueueService
+ in a hash table, so it is possible that the eldest queue may not be
+ released until the EventQueueService is shutdown.
+ You may not call StopAcceptingEvents() on this queue until you have
+ done so on all younger queues.
+
+ General:
+ Each queue holds a reference to their immediate elder link and a weak
+ reference to their immediate younger link. Because you must shut down
+ queues from youngest to eldest, all the references will be removed.
+
+ It happens something like:
+ queue->StopAcceptingEvents()
+ {
+ CheckForDeactivation()
+ {
+ -- hopefully we are able to shutdown now --
+ Unlink()
+ {
+ -- remove the reference we hold to our elder queue --
+ -- NULL out our elder queues weak reference to us --
+ }
+ RELEASE ourself (to balance the ADDREF here in the constructor)
+ -- and we should go away. --
+ }
+ }
+
+
+ Notes:
+ A dark queue no longer accepts events. An empty queue simply has no events.
+ */
+
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: Created [queue=%lx]",(long)mEventQueue));
+ ++gEventQueueLogCount;
+#endif
+
+ mYoungerQueue = nsnull;
+ mEventQueue = nsnull;
+ mAcceptingEvents = PR_TRUE;
+ mCouldHaveEvents = PR_TRUE;
+}
+
+nsEventQueueImpl::~nsEventQueueImpl()
+{
+ Unlink();
+
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: Destroyed [queue=%lx]",(long)mEventQueue));
+ ++gEventQueueLogCount;
+#endif
+
+ if (mEventQueue) {
+ NotifyObservers(gDestroyedNotification);
+ PL_DestroyEventQueue(mEventQueue);
+ }
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::Init(PRBool aNative)
+{
+ PRThread *thread = PR_GetCurrentThread();
+ if (aNative)
+ mEventQueue = PL_CreateNativeEventQueue("Thread event queue...", thread);
+ else
+ mEventQueue = PL_CreateMonitoredEventQueue("Thread event queue...", thread);
+ NotifyObservers(gActivatedNotification);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::InitFromPRThread(PRThread* thread, PRBool aNative)
+{
+ if (thread == NS_CURRENT_THREAD)
+ {
+ thread = PR_GetCurrentThread();
+ }
+ else if (thread == NS_UI_THREAD)
+ {
+ nsCOMPtr<nsIThread> mainIThread;
+ nsresult rv;
+
+ // Get the primordial thread
+ rv = nsIThread::GetMainThread(getter_AddRefs(mainIThread));
+ if (NS_FAILED(rv)) return rv;
+
+ rv = mainIThread->GetPRThread(&thread);
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ if (aNative)
+ mEventQueue = PL_CreateNativeEventQueue("Thread event queue...", thread);
+ else
+ mEventQueue = PL_CreateMonitoredEventQueue("Thread event queue...", thread);
+ NotifyObservers(gActivatedNotification);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::InitFromPLQueue(PLEventQueue* aQueue)
+{
+ mEventQueue = aQueue;
+ NotifyObservers(gActivatedNotification);
+ return NS_OK;
+}
+
+/* nsISupports interface implementation... */
+NS_IMPL_THREADSAFE_ISUPPORTS3(nsEventQueueImpl,
+ nsIEventQueue,
+ nsIEventTarget,
+ nsPIEventQueueChain)
+
+/* nsIEventQueue interface implementation... */
+
+NS_IMETHODIMP
+nsEventQueueImpl::StopAcceptingEvents()
+{
+ // this assertion is bogus. I should be able to shut down the eldest queue,
+ // as long as there are no younger children
+
+
+ NS_ASSERTION(mElderQueue || !mYoungerQueue, "attempted to disable eldest queue in chain");
+ mAcceptingEvents = PR_FALSE;
+ CheckForDeactivation();
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: StopAccepting [queue=%lx, accept=%d, could=%d]",
+ (long)mEventQueue,(int)mAcceptingEvents,(int)mCouldHaveEvents));
+ ++gEventQueueLogCount;
+#endif
+ return NS_OK;
+}
+
+// utility funtion to send observers a notification
+void
+nsEventQueueImpl::NotifyObservers(const char *aTopic)
+{
+ nsresult rv;
+
+ nsCOMPtr<nsIObserverService> os = do_GetService("@mozilla.org/observer-service;1", &rv);
+ if (NS_SUCCEEDED(rv)) {
+ nsCOMPtr<nsIEventQueue> kungFuDeathGrip(this);
+ nsCOMPtr<nsISupports> us(do_QueryInterface(kungFuDeathGrip));
+ os->NotifyObservers(us, aTopic, NULL);
+ }
+}
+
+
+NS_IMETHODIMP
+nsEventQueueImpl::InitEvent(PLEvent* aEvent,
+ void* owner,
+ PLHandleEventProc handler,
+ PLDestroyEventProc destructor)
+{
+ PL_InitEvent(aEvent, owner, handler, destructor);
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsEventQueueImpl::PostEvent(PLEvent* aEvent)
+{
+ if (!mAcceptingEvents) {
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: Punt posted event [queue=%lx, accept=%d, could=%d]",
+ (long)mEventQueue,(int)mAcceptingEvents,(int)mCouldHaveEvents));
+ ++gEventQueueLogCount;
+#endif
+ nsresult rv = NS_ERROR_FAILURE;
+ NS_ASSERTION(mElderQueue, "event dropped because event chain is dead");
+ if (mElderQueue) {
+ nsCOMPtr<nsIEventQueue> elder(do_QueryInterface(mElderQueue));
+ if (elder)
+ rv = elder->PostEvent(aEvent);
+ }
+ return rv;
+ }
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: Posting event [queue=%lx]", (long)mEventQueue));
+ ++gEventQueueLogCount;
+#endif
+ return PL_PostEvent(mEventQueue, aEvent) == PR_SUCCESS ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::PostSynchronousEvent(PLEvent* aEvent, void** aResult)
+{
+ if (!mAcceptingEvents) {
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: Punt posted synchronous event [queue=%lx, accept=%d, could=%d]",
+ (long)mEventQueue,(int)mAcceptingEvents,(int)mCouldHaveEvents));
+ ++gEventQueueLogCount;
+#endif
+ nsresult rv = NS_ERROR_NO_INTERFACE;
+ NS_ASSERTION(mElderQueue, "event dropped because event chain is dead");
+ if (mElderQueue) {
+ nsCOMPtr<nsIEventQueue> elder(do_QueryInterface(mElderQueue));
+ if (elder)
+ rv = elder->PostSynchronousEvent(aEvent, aResult);
+ return rv;
+ }
+ return NS_ERROR_ABORT;
+ }
+
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: Posting synchronous event [queue=%lx]", (long)mEventQueue));
+ ++gEventQueueLogCount;
+#endif
+ void* result = PL_PostSynchronousEvent(mEventQueue, aEvent);
+ if (aResult)
+ *aResult = result;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::EnterMonitor()
+{
+ PL_ENTER_EVENT_QUEUE_MONITOR(mEventQueue);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::ExitMonitor()
+{
+ PL_EXIT_EVENT_QUEUE_MONITOR(mEventQueue);
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsEventQueueImpl::RevokeEvents(void* owner)
+{
+ PL_RevokeEvents(mEventQueue, owner);
+ if (mElderQueue) {
+ nsCOMPtr<nsIEventQueue> elder(do_QueryInterface(mElderQueue));
+ if (elder)
+ elder->RevokeEvents(owner);
+ }
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsEventQueueImpl::GetPLEventQueue(PLEventQueue** aEventQueue)
+{
+ if (!mEventQueue)
+ return NS_ERROR_NULL_POINTER;
+
+ *aEventQueue = mEventQueue;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::IsOnCurrentThread(PRBool *aResult)
+{
+ *aResult = PL_IsQueueOnCurrentThread( mEventQueue );
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsEventQueueImpl::IsQueueNative(PRBool *aResult)
+{
+ *aResult = PL_IsQueueNative(mEventQueue);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::PendingEvents(PRBool *aResult)
+{
+ *aResult = PL_EventAvailable(mEventQueue);
+ if (!*aResult && mElderQueue) {
+ nsCOMPtr<nsIEventQueue> elder(do_QueryInterface(mElderQueue));
+ if (elder)
+ return elder->EventAvailable(*aResult);
+ }
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsEventQueueImpl::ProcessPendingEvents()
+{
+ PRBool correctThread = PL_IsQueueOnCurrentThread(mEventQueue);
+
+ NS_ASSERTION(correctThread, "attemping to process events on the wrong thread");
+
+ if (!correctThread)
+ return NS_ERROR_FAILURE;
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ ++gEventQueueLogPPLevel;
+ if ((gEventQueueLogQueue != mEventQueue || gEventQueueLogThread != PR_GetCurrentThread() ||
+ gEventQueueLogCount != gEventQueueLogPPCount) && gEventQueueLogPPLevel == 1) {
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: Process pending [queue=%lx, accept=%d, could=%d]",
+ (long)mEventQueue,(int)mAcceptingEvents,(int)mCouldHaveEvents));
+ gEventQueueLogPPCount = ++gEventQueueLogCount;
+ gEventQueueLogQueue = mEventQueue;
+ gEventQueueLogThread = PR_GetCurrentThread();
+ }
+#endif
+ PL_ProcessPendingEvents(mEventQueue);
+
+ // if we're no longer accepting events and there are still events in the
+ // queue, then process remaining events.
+ if (!mAcceptingEvents && PL_EventAvailable(mEventQueue))
+ PL_ProcessPendingEvents(mEventQueue);
+
+ CheckForDeactivation();
+
+ if (mElderQueue) {
+ nsCOMPtr<nsIEventQueue> elder(do_QueryInterface(mElderQueue));
+ if (elder)
+ elder->ProcessPendingEvents();
+ }
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ --gEventQueueLogPPLevel;
+#endif
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::EventLoop()
+{
+ PRBool correctThread = PL_IsQueueOnCurrentThread(mEventQueue);
+
+ NS_ASSERTION(correctThread, "attemping to process events on the wrong thread");
+
+ if (!correctThread)
+ return NS_ERROR_FAILURE;
+
+ PL_EventLoop(mEventQueue);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::EventAvailable(PRBool& aResult)
+{
+ aResult = PL_EventAvailable(mEventQueue);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::GetEvent(PLEvent** aResult)
+{
+ *aResult = PL_GetEvent(mEventQueue);
+ CheckForDeactivation();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::HandleEvent(PLEvent* aEvent)
+{
+ PRBool correctThread = PL_IsQueueOnCurrentThread(mEventQueue);
+ NS_ASSERTION(correctThread, "attemping to process events on the wrong thread");
+ if (!correctThread)
+ return NS_ERROR_FAILURE;
+
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: handle event [queue=%lx, accept=%d, could=%d]",
+ (long)mEventQueue,(int)mAcceptingEvents,(int)mCouldHaveEvents));
+ ++gEventQueueLogCount;
+#endif
+ PL_HandleEvent(aEvent);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::WaitForEvent(PLEvent** aResult)
+{
+ PRBool correctThread = PL_IsQueueOnCurrentThread(mEventQueue);
+ NS_ASSERTION(correctThread, "attemping to process events on the wrong thread");
+ if (!correctThread)
+ return NS_ERROR_FAILURE;
+
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: wait for event [queue=%lx, accept=%d, could=%d]",
+ (long)mEventQueue,(int)mAcceptingEvents,(int)mCouldHaveEvents));
+ ++gEventQueueLogCount;
+#endif
+ *aResult = PL_WaitForEvent(mEventQueue);
+ CheckForDeactivation();
+ return NS_OK;
+}
+
+NS_IMETHODIMP_(PRInt32)
+nsEventQueueImpl::GetEventQueueSelectFD()
+{
+ return PL_GetEventQueueSelectFD(mEventQueue);
+}
+
+NS_METHOD
+nsEventQueueImpl::Create(nsISupports *aOuter,
+ REFNSIID aIID,
+ void **aResult)
+{
+ nsEventQueueImpl* evt = new nsEventQueueImpl();
+ if (evt == NULL)
+ return NS_ERROR_OUT_OF_MEMORY;
+ nsresult rv = evt->QueryInterface(aIID, aResult);
+ if (NS_FAILED(rv)) {
+ delete evt;
+ }
+ return rv;
+}
+
+// ---------------- nsPIEventQueueChain -----------------
+
+NS_IMETHODIMP
+nsEventQueueImpl::AppendQueue(nsIEventQueue *aQueue)
+{
+ nsresult rv;
+ nsCOMPtr<nsIEventQueue> end;
+ nsCOMPtr<nsPIEventQueueChain> queueChain(do_QueryInterface(aQueue));
+
+ if (!aQueue)
+ return NS_ERROR_NO_INTERFACE;
+
+/* this would be nice
+ NS_ASSERTION(aQueue->mYoungerQueue == NULL && aQueue->mElderQueue == NULL,
+ "event queue repeatedly appended to queue chain");
+*/
+ rv = NS_ERROR_NO_INTERFACE;
+
+#ifdef NS_DEBUG
+ int depth = 0;
+ nsEventQueueImpl *next = this;
+ while (next && depth < 100) {
+ next = NS_STATIC_CAST(nsEventQueueImpl *, next->mYoungerQueue);
+ ++depth;
+ }
+ if (depth > 5) {
+ char warning[80];
+ PR_snprintf(warning, sizeof(warning),
+ "event queue chain length is %d. this is almost certainly a leak.", depth);
+ NS_WARNING(warning);
+ }
+#endif
+
+ // (be careful doing this outside nsEventQueueService's mEventQMonitor)
+
+ GetYoungest(getter_AddRefs(end));
+ nsCOMPtr<nsPIEventQueueChain> endChain(do_QueryInterface(end));
+ if (endChain) {
+ endChain->SetYounger(queueChain);
+ queueChain->SetElder(endChain);
+ rv = NS_OK;
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::Unlink()
+{
+ nsCOMPtr<nsPIEventQueueChain> young = mYoungerQueue,
+ old = mElderQueue;
+
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: unlink [queue=%lx, younger=%lx, elder=%lx]",
+ (long)mEventQueue,(long)mYoungerQueue, (long)mElderQueue.get()));
+ ++gEventQueueLogCount;
+#endif
+
+ // this is probably OK, but shouldn't happen by design, so tell me if it does
+ NS_ASSERTION(!mYoungerQueue, "event queue chain broken in middle");
+
+ // break links early in case the Release cascades back onto us
+ mYoungerQueue = nsnull;
+ mElderQueue = nsnull;
+
+ if (young)
+ young->SetElder(old);
+ if (old) {
+ old->SetYounger(young);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::GetYoungest(nsIEventQueue **aQueue)
+{
+ if (mYoungerQueue)
+ return mYoungerQueue->GetYoungest(aQueue);
+
+ nsIEventQueue *answer = NS_STATIC_CAST(nsIEventQueue *, this);
+ NS_ADDREF(answer);
+ *aQueue = answer;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::GetYoungestActive(nsIEventQueue **aQueue)
+{
+ nsCOMPtr<nsIEventQueue> answer;
+
+ if (mYoungerQueue)
+ mYoungerQueue->GetYoungestActive(getter_AddRefs(answer));
+ if (!answer) {
+ if (mAcceptingEvents && mCouldHaveEvents)
+ answer = NS_STATIC_CAST(nsIEventQueue *, this);
+ }
+ *aQueue = answer;
+ NS_IF_ADDREF(*aQueue);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::SetYounger(nsPIEventQueueChain *aQueue)
+{
+ mYoungerQueue = aQueue;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::SetElder(nsPIEventQueueChain *aQueue)
+{
+ mElderQueue = aQueue;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::GetYounger(nsIEventQueue **aQueue)
+{
+ if (!mYoungerQueue) {
+ *aQueue = nsnull;
+ return NS_OK;
+ }
+ return mYoungerQueue->QueryInterface(NS_GET_IID(nsIEventQueue), (void**)&aQueue);
+}
+
+NS_IMETHODIMP
+nsEventQueueImpl::GetElder(nsIEventQueue **aQueue)
+{
+ if (!mElderQueue) {
+ *aQueue = nsnull;
+ return NS_OK;
+ }
+ return mElderQueue->QueryInterface(NS_GET_IID(nsIEventQueue), (void**)&aQueue);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsEventQueue.h b/src/libs/xpcom18a4/xpcom/threads/nsEventQueue.h
new file mode 100644
index 00000000..51f33e47
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsEventQueue.h
@@ -0,0 +1,89 @@
+/* -*- 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):
+ * 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 "prmon.h"
+#include "nsIEventQueue.h"
+#include "nsPIEventQueueChain.h"
+
+class nsEventQueueImpl : public nsIEventQueue,
+ public nsPIEventQueueChain
+{
+public:
+ nsEventQueueImpl();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIEVENTTARGET
+ NS_DECL_NSIEVENTQUEUE
+
+ // Helpers
+ static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+ static const nsCID& CID() { static nsCID cid = NS_EVENTQUEUE_CID; return cid; }
+
+ // nsPIEventQueueChain interface
+ NS_IMETHOD AppendQueue(nsIEventQueue *aQueue);
+ NS_IMETHOD Unlink();
+ NS_IMETHOD GetYoungest(nsIEventQueue **aQueue);
+ NS_IMETHOD GetYoungestActive(nsIEventQueue **aQueue);
+ NS_IMETHOD SetYounger(nsPIEventQueueChain *aQueue);
+ NS_IMETHOD GetYounger(nsIEventQueue **aQueue);
+ NS_IMETHOD SetElder(nsPIEventQueueChain *aQueue);
+ NS_IMETHOD GetElder(nsIEventQueue **aQueue);
+
+private:
+ ~nsEventQueueImpl();
+
+ PLEventQueue *mEventQueue;
+ PRBool mAcceptingEvents, // accept new events or pass them on?
+ mCouldHaveEvents; // accepting new ones, or still have old ones?
+ nsCOMPtr<nsPIEventQueueChain> mElderQueue; // younger can hold on to elder
+ nsPIEventQueueChain *mYoungerQueue; // but elder can't hold on to younger
+
+ void NotifyObservers(const char *aTopic);
+
+ void CheckForDeactivation() {
+ if (mCouldHaveEvents && !mAcceptingEvents && !PL_EventAvailable(mEventQueue)) {
+ if (PL_IsQueueOnCurrentThread(mEventQueue)) {
+ mCouldHaveEvents = PR_FALSE;
+ NS_RELEASE_THIS(); // balance ADDREF from the constructor
+ } else
+ NS_ERROR("CheckForDeactivation called from wrong thread!");
+ }
+ }
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsEventQueueService.cpp b/src/libs/xpcom18a4/xpcom/threads/nsEventQueueService.cpp
new file mode 100644
index 00000000..4fbb65aa
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsEventQueueService.cpp
@@ -0,0 +1,450 @@
+/* -*- 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):
+ * Rick Potts <rpotts@netscape.com>
+ * Ramiro Estrugo <ramiro@netscape.com>
+ * Warren Harris <warren@netscape.com>
+ * Leaf Nunes <leaf@mozilla.org>
+ * David Matiskella <davidm@netscape.com>
+ * David Hyatt <hyatt@netscape.com>
+ * Seth Spitzer <sspitzer@netscape.com>
+ * Suresh Duddi <dp@netscape.com>
+ * Bruce Mitchener <bruce@cybersight.com>
+ * Scott Collins <scc@netscape.com>
+ * Daniel Matejka <danm@netscape.com>
+ * Doug Turner <dougt@netscape.com>
+ * Stuart Parmenter <pavlov@netscape.com>
+ * Mike Kaply <mkaply@us.ibm.com>
+ * Dan Mosedale <dmose@mozilla.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 ***** */
+
+#include "nsEventQueueService.h"
+#include "prmon.h"
+#include "nsIComponentManager.h"
+#include "nsIThread.h"
+#include "nsPIEventQueueChain.h"
+
+#include "prlog.h"
+
+#if defined(PR_LOGGING) || defined(DEBUG_danm)
+extern PRLogModuleInfo* gEventQueueLog;
+extern PRUint32 gEventQueueLogCount;
+#endif
+
+static NS_DEFINE_CID(kEventQueueCID, NS_EVENTQUEUE_CID);
+
+nsEventQueueServiceImpl::nsEventQueueServiceImpl()
+{
+ mEventQMonitor = PR_NewMonitor();
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ if (!gEventQueueLog)
+ gEventQueueLog = PR_NewLogModule("nseventqueue");
+#endif
+}
+
+PR_STATIC_CALLBACK(PLDHashOperator)
+hash_enum_remove_queues(const void *aThread_ptr,
+ nsCOMPtr<nsIEventQueue>& aEldestQueue,
+ void* closure)
+{
+ // 'aQueue' should be the eldest queue.
+ nsCOMPtr<nsPIEventQueueChain> pie(do_QueryInterface(aEldestQueue));
+ nsCOMPtr<nsIEventQueue> q;
+
+ // stop accepting events for youngest to oldest
+ pie->GetYoungest(getter_AddRefs(q));
+ while (q) {
+ q->StopAcceptingEvents();
+
+ nsCOMPtr<nsPIEventQueueChain> pq(do_QueryInterface(q));
+ pq->GetElder(getter_AddRefs(q));
+ }
+
+ return PL_DHASH_REMOVE;
+}
+
+nsEventQueueServiceImpl::~nsEventQueueServiceImpl()
+{
+ // XXX make it so we only enum over this once
+ mEventQTable.Enumerate(hash_enum_remove_queues, nsnull); // call StopAcceptingEvents on everything and clear out the hashtable
+
+ PR_DestroyMonitor(mEventQMonitor);
+}
+
+nsresult
+nsEventQueueServiceImpl::Init()
+{
+ NS_ENSURE_TRUE(mEventQMonitor, NS_ERROR_OUT_OF_MEMORY);
+
+ // This will only be called once on the main thread, so it's safe to
+ // not enter the monitor here.
+ if (!mEventQTable.Init()) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ // ensure that a main thread event queue exists!
+ nsresult rv;
+ nsCOMPtr<nsIThread> mainThread;
+ rv = nsIThread::GetMainThread(getter_AddRefs(mainThread));
+ if (NS_SUCCEEDED(rv)) {
+ PRThread *thr;
+ rv = mainThread->GetPRThread(&thr);
+ if (NS_SUCCEEDED(rv))
+ rv = CreateEventQueue(thr, PR_TRUE);
+ }
+ return rv;
+}
+
+/* nsISupports interface implementation... */
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsEventQueueServiceImpl, nsIEventQueueService)
+
+/* nsIEventQueueService interface implementation... */
+
+NS_IMETHODIMP
+nsEventQueueServiceImpl::CreateThreadEventQueue()
+{
+ return CreateEventQueue(PR_GetCurrentThread(), PR_TRUE);
+}
+
+NS_IMETHODIMP
+nsEventQueueServiceImpl::CreateMonitoredThreadEventQueue()
+{
+ return CreateEventQueue(PR_GetCurrentThread(), PR_FALSE);
+}
+
+NS_IMETHODIMP
+nsEventQueueServiceImpl::CreateFromIThread(nsIThread *aThread, PRBool aNative,
+ nsIEventQueue **aResult)
+{
+ nsresult rv;
+ PRThread *prThread;
+
+ rv = aThread->GetPRThread(&prThread);
+ if (NS_SUCCEEDED(rv)) {
+ rv = CreateEventQueue(prThread, aNative); // addrefs
+ if (NS_SUCCEEDED(rv))
+ rv = GetThreadEventQueue(prThread, aResult); // addrefs
+ }
+ return rv;
+}
+
+// private method
+NS_IMETHODIMP
+nsEventQueueServiceImpl::MakeNewQueue(PRThread* thread,
+ PRBool aNative,
+ nsIEventQueue **aQueue)
+{
+ nsresult rv;
+ nsCOMPtr<nsIEventQueue> queue = do_CreateInstance(kEventQueueCID, &rv);
+
+ if (NS_SUCCEEDED(rv)) {
+ rv = queue->InitFromPRThread(thread, aNative);
+ }
+ *aQueue = queue;
+ NS_IF_ADDREF(*aQueue);
+ return rv;
+}
+
+// private method
+NS_IMETHODIMP
+nsEventQueueServiceImpl::CreateEventQueue(PRThread *aThread, PRBool aNative)
+{
+ nsresult rv = NS_OK;
+ /* Enter the lock that protects the EventQ hashtable... */
+ PR_EnterMonitor(mEventQMonitor);
+
+ /* create only one event queue chain per thread... */
+ if (!mEventQTable.GetWeak(aThread)) {
+ nsCOMPtr<nsIEventQueue> queue;
+
+ // we don't have one in the table
+ rv = MakeNewQueue(aThread, aNative, getter_AddRefs(queue)); // create new queue
+ mEventQTable.Put(aThread, queue); // add to the table (initial addref)
+ }
+
+ // Release the EventQ lock...
+ PR_ExitMonitor(mEventQMonitor);
+ return rv;
+}
+
+
+NS_IMETHODIMP
+nsEventQueueServiceImpl::DestroyThreadEventQueue(void)
+{
+ nsresult rv = NS_OK;
+
+ /* Enter the lock that protects the EventQ hashtable... */
+ PR_EnterMonitor(mEventQMonitor);
+
+ PRThread* currentThread = PR_GetCurrentThread();
+ nsIEventQueue* queue = mEventQTable.GetWeak(currentThread);
+ if (queue) {
+ queue->StopAcceptingEvents(); // tell the queue to stop accepting events
+ queue = nsnull; // Queue may die on the next line
+ mEventQTable.Remove(currentThread); // remove nsIEventQueue from hash table (releases)
+ }
+
+ // Release the EventQ lock...
+ PR_ExitMonitor(mEventQMonitor);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsEventQueueServiceImpl::CreateFromPLEventQueue(PLEventQueue* aPLEventQueue, nsIEventQueue** aResult)
+{
+ // Create our thread queue using the component manager
+ nsresult rv;
+ nsCOMPtr<nsIEventQueue> queue = do_CreateInstance(kEventQueueCID, &rv);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = queue->InitFromPLQueue(aPLEventQueue);
+ if (NS_FAILED(rv)) return rv;
+
+ *aResult = queue;
+ NS_IF_ADDREF(*aResult);
+ return NS_OK;
+}
+
+
+// Return the active event queue on our chain
+/* inline */
+nsresult nsEventQueueServiceImpl::GetYoungestEventQueue(nsIEventQueue *queue, nsIEventQueue **aResult)
+{
+ nsCOMPtr<nsIEventQueue> answer;
+
+ if (queue) {
+ nsCOMPtr<nsPIEventQueueChain> ourChain(do_QueryInterface(queue));
+ if (ourChain)
+ ourChain->GetYoungestActive(getter_AddRefs(answer));
+ else
+ answer = queue;
+ }
+
+ *aResult = answer;
+ NS_IF_ADDREF(*aResult);
+ return NS_OK;
+}
+
+
+// create new event queue, append it to the current thread's chain of event queues.
+// return it, addrefed.
+NS_IMETHODIMP
+nsEventQueueServiceImpl::PushThreadEventQueue(nsIEventQueue **aNewQueue)
+{
+ nsresult rv = NS_OK;
+ PRThread* currentThread = PR_GetCurrentThread();
+ PRBool native = PR_TRUE; // native by default as per old comment
+
+
+ NS_ASSERTION(aNewQueue, "PushThreadEventQueue called with null param");
+
+ /* Enter the lock that protects the EventQ hashtable... */
+ PR_EnterMonitor(mEventQMonitor);
+
+ nsIEventQueue* queue = mEventQTable.GetWeak(currentThread);
+
+ NS_ASSERTION(queue, "pushed event queue on top of nothing");
+
+ if (queue) { // find out what kind of queue our relatives are
+ nsCOMPtr<nsIEventQueue> youngQueue;
+ GetYoungestEventQueue(queue, getter_AddRefs(youngQueue));
+ if (youngQueue) {
+ youngQueue->IsQueueNative(&native);
+ }
+ }
+
+ nsIEventQueue* newQueue = nsnull;
+ MakeNewQueue(currentThread, native, &newQueue); // create new queue; addrefs
+
+ if (!queue) {
+ // shouldn't happen. as a fallback, we guess you wanted a native queue
+ mEventQTable.Put(currentThread, newQueue);
+ }
+
+ // append to the event queue chain
+ nsCOMPtr<nsPIEventQueueChain> ourChain(do_QueryInterface(queue)); // QI the queue in the hash table
+ if (ourChain)
+ ourChain->AppendQueue(newQueue); // append new queue to it
+
+ *aNewQueue = newQueue;
+
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ PLEventQueue *equeue;
+ (*aNewQueue)->GetPLEventQueue(&equeue);
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: Service push queue [queue=%lx]",(long)equeue));
+ ++gEventQueueLogCount;
+#endif
+
+ // Release the EventQ lock...
+ PR_ExitMonitor(mEventQMonitor);
+ return rv;
+}
+
+// disable and release the given queue (though the last one won't be released)
+NS_IMETHODIMP
+nsEventQueueServiceImpl::PopThreadEventQueue(nsIEventQueue *aQueue)
+{
+ PRThread* currentThread = PR_GetCurrentThread();
+
+ /* Enter the lock that protects the EventQ hashtable... */
+ PR_EnterMonitor(mEventQMonitor);
+
+ nsCOMPtr<nsIEventQueue> eldestQueue;
+ mEventQTable.Get(currentThread, getter_AddRefs(eldestQueue));
+
+ // If we are popping the eldest queue, remove its mEventQTable entry.
+ if (aQueue == eldestQueue)
+ mEventQTable.Remove(currentThread);
+
+ // Exit the monitor before processing pending events to avoid deadlock.
+ // Our reference from the eldestQueue nsCOMPtr will keep that object alive.
+ // Since it is thread-private, no one else can race with us here.
+ PR_ExitMonitor(mEventQMonitor);
+ if (!eldestQueue)
+ return NS_ERROR_FAILURE;
+
+#if defined(PR_LOGGING) && defined(DEBUG_danm)
+ PLEventQueue *equeue;
+ aQueue->GetPLEventQueue(&equeue);
+ PR_LOG(gEventQueueLog, PR_LOG_DEBUG,
+ ("EventQueue: Service pop queue [queue=%lx]",(long)equeue));
+ ++gEventQueueLogCount;
+#endif
+ aQueue->StopAcceptingEvents();
+ aQueue->ProcessPendingEvents(); // make sure we don't orphan any events
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueServiceImpl::GetThreadEventQueue(PRThread* aThread, nsIEventQueue** aResult)
+{
+ /* Parameter validation... */
+ if (NULL == aResult) return NS_ERROR_NULL_POINTER;
+
+ PRThread* keyThread = aThread;
+
+ if (keyThread == NS_CURRENT_THREAD)
+ {
+ keyThread = PR_GetCurrentThread();
+ }
+ else if (keyThread == NS_UI_THREAD)
+ {
+ nsCOMPtr<nsIThread> mainIThread;
+
+ // Get the primordial thread
+ nsresult rv = nsIThread::GetMainThread(getter_AddRefs(mainIThread));
+ if (NS_FAILED(rv)) return rv;
+
+ rv = mainIThread->GetPRThread(&keyThread);
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ /* Enter the lock that protects the EventQ hashtable... */
+ PR_EnterMonitor(mEventQMonitor);
+
+ nsCOMPtr<nsIEventQueue> queue;
+ mEventQTable.Get(keyThread, getter_AddRefs(queue));
+
+ PR_ExitMonitor(mEventQMonitor);
+
+ if (queue) {
+ GetYoungestEventQueue(queue, aResult); // get the youngest active queue
+ } else {
+ *aResult = nsnull;
+ }
+ // XXX: Need error code for requesting an event queue when none exists...
+ if (!*aResult) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsEventQueueServiceImpl::ResolveEventQueue(nsIEventQueue* queueOrConstant, nsIEventQueue* *resultQueue)
+{
+ if (queueOrConstant == NS_CURRENT_EVENTQ) {
+ return GetThreadEventQueue(NS_CURRENT_THREAD, resultQueue);
+ }
+ else if (queueOrConstant == NS_UI_THREAD_EVENTQ) {
+ return GetThreadEventQueue(NS_UI_THREAD, resultQueue);
+ }
+
+ *resultQueue = queueOrConstant;
+ NS_ADDREF(*resultQueue);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsEventQueueServiceImpl::GetSpecialEventQueue(PRInt32 aQueue,
+ nsIEventQueue* *_retval)
+{
+ nsresult rv;
+
+ // barf if someone gave us a zero pointer
+ //
+ if (!_retval) {
+ return NS_ERROR_NULL_POINTER;
+ }
+
+ // try and get the requested event queue, returning NS_ERROR_FAILURE if there
+ // is a problem. GetThreadEventQueue() does the AddRef() for us.
+ //
+ switch (aQueue) {
+ case CURRENT_THREAD_EVENT_QUEUE:
+ rv = GetThreadEventQueue(NS_CURRENT_THREAD, _retval);
+ if (NS_FAILED(rv)) {
+ return NS_ERROR_FAILURE;
+ }
+ break;
+
+ case UI_THREAD_EVENT_QUEUE:
+ rv = GetThreadEventQueue(NS_UI_THREAD, _retval);
+ if (NS_FAILED(rv)) {
+ return NS_ERROR_FAILURE;
+ }
+ break;
+
+ // somebody handed us a bogus constant
+ //
+ default:
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+
+ return NS_OK;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsEventQueueService.h b/src/libs/xpcom18a4/xpcom/threads/nsEventQueueService.h
new file mode 100644
index 00000000..6fddb941
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsEventQueueService.h
@@ -0,0 +1,77 @@
+/* -*- 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 nsEventQueueService_h__
+#define nsEventQueueService_h__
+
+#include "nsIEventQueueService.h"
+#include "nsInterfaceHashtable.h"
+#include "nsHashKeys.h"
+#include "nsIEventQueue.h"
+
+////////////////////////////////////////////////////////////////////////////////
+
+class nsEventQueueServiceImpl : public nsIEventQueueService
+{
+public:
+ nsEventQueueServiceImpl();
+
+ nsresult Init();
+
+ // nsISupports interface...
+ NS_DECL_ISUPPORTS
+
+ // nsIEventQueueService interface...
+ NS_DECL_NSIEVENTQUEUESERVICE
+
+private:
+ ~nsEventQueueServiceImpl();
+
+ /* Create a queue for the given thread if one does not exist.
+ Addref the descriptor in any case. parameter aNative is
+ ignored if the queue already exists. */
+ NS_IMETHOD CreateEventQueue(PRThread *aThread, PRBool aNative);
+ NS_IMETHOD MakeNewQueue(PRThread* thread, PRBool aNative, nsIEventQueue **aQueue);
+ inline nsresult GetYoungestEventQueue(nsIEventQueue *queue, nsIEventQueue **aResult);
+
+ nsInterfaceHashtable<nsVoidPtrHashKey, nsIEventQueue> mEventQTable;
+ PRMonitor *mEventQMonitor;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#endif // nsEventQueueService_h__
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsEventQueueUtils.h b/src/libs/xpcom18a4/xpcom/threads/nsEventQueueUtils.h
new file mode 100644
index 00000000..5df2e406
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsEventQueueUtils.h
@@ -0,0 +1,78 @@
+/* ***** 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.
+ *
+ * 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):
+ * Darin Fisher <darin@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 nsEventQueueUtils_h__
+#define nsEventQueueUtils_h__
+
+#include "nsIEventQueueService.h"
+#include "nsIServiceManager.h"
+#include "nsCOMPtr.h"
+
+inline nsresult
+NS_GetEventQueueService(nsIEventQueueService **result)
+{
+ static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
+ return CallGetService(kEventQueueServiceCID, result);
+}
+
+inline nsresult
+NS_GetCurrentEventQ(nsIEventQueue **result,
+ nsIEventQueueService *serv = nsnull)
+{
+ nsCOMPtr<nsIEventQueueService> eqs;
+ if (!serv) {
+ nsresult rv = NS_GetEventQueueService(getter_AddRefs(eqs));
+ if (NS_FAILED(rv)) return rv;
+ serv = eqs;
+ }
+ return serv->GetThreadEventQueue(NS_CURRENT_THREAD, result);
+}
+
+inline nsresult
+NS_GetMainEventQ(nsIEventQueue **result,
+ nsIEventQueueService *serv = nsnull)
+{
+ nsCOMPtr<nsIEventQueueService> eqs;
+ if (!serv) {
+ nsresult rv = NS_GetEventQueueService(getter_AddRefs(eqs));
+ if (NS_FAILED(rv)) return rv;
+ serv = eqs;
+ }
+ return serv->GetThreadEventQueue(NS_UI_THREAD, result);
+}
+
+#endif // !nsEventQueueUtils_h__
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsIEnvironment.idl b/src/libs/xpcom18a4/xpcom/threads/nsIEnvironment.idl
new file mode 100644
index 00000000..95351346
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsIEnvironment.idl
@@ -0,0 +1,89 @@
+/* -*- 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 embedding code.
+ *
+ * The Initial Developers of the Original Code are
+ * Benjamin Smedberg <bsmedberg@covad.net> and
+ * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2003/2004
+ * 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 "nsISupports.idl"
+
+/**
+ * Scriptable access to the current process environment.
+ *
+ */
+[scriptable, uuid(101d5941-d820-4e85-a266-9a3469940807)]
+interface nsIEnvironment : nsISupports
+{
+ /**
+ * Set the value of an environment variable.
+ *
+ * @param aName the variable name to set.
+ * @param aValue the value to set.
+ */
+ void set(in AString aName, in AString aValue);
+
+ /**
+ * Get the value of an environment variable.
+ *
+ * @param aName the variable name to retrieve.
+ * @return returns the value of the env variable. An empty string
+ * will be returned when the env variable does not exist or
+ * when the value itself is an empty string - please use
+ * |exists()| to probe whether the env variable exists
+ * or not.
+ */
+ AString get(in AString aName);
+
+ /**
+ * Check the existence of an environment variable.
+ * This method checks whether an environment variable is present in
+ * the environment or not.
+ *
+ * - For Unix/Linux platforms we follow the Unix definition:
+ * An environment variable exists when |getenv()| returns a non-NULL value.
+ * An environment variable does not exist when |getenv()| returns NULL.
+ * - For non-Unix/Linux platforms we have to fall back to a
+ * "portable" definition (which is incorrect for Unix/Linux!!!!)
+ * which simply checks whether the string returned by |Get()| is empty
+ * or not.
+ *
+ * @param aName the variable name to probe.
+ * @return if the variable has been set, the value returned is
+ * PR_TRUE. If the variable was not defined in the
+ * environment PR_FALSE will be returned.
+ */
+ boolean exists(in AString aName);
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsIEventQueue.idl b/src/libs/xpcom18a4/xpcom/threads/nsIEventQueue.idl
new file mode 100644
index 00000000..416c80a1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsIEventQueue.idl
@@ -0,0 +1,107 @@
+/* -*- 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.
+ *
+ * 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):
+ * David Hyatt <hyatt@netscape.com>
+ * Suresh Duddi <dp@netscape.com>
+ * Doug Turner <dougt@netscape.com>
+ * Judson Valeski <valeski@netscape.com>
+ * Dan Matejka <danm@netscape.com>
+ * Ray Whitmer <rayw@netscape.com>
+ * Dan Mosedale <dmose@mozilla.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 ***** */
+
+#include "nsIEventTarget.idl"
+
+%{C++
+#include "prthread.h"
+
+// {13D86C61-00A9-11d3-9F2A-00400553EEF0}
+#define NS_EVENTQUEUE_CID \
+{ 0x13d86c61, 0xa9, 0x11d3, { 0x9f, 0x2a, 0x0, 0x40, 0x5, 0x53, 0xee, 0xf0 } }
+
+#define NS_EVENTQUEUE_CONTRACTID "@mozilla.org/event-queue;1"
+#define NS_EVENTQUEUE_CLASSNAME "Event Queue"
+
+%}
+
+// some forward decls
+//
+[ptr] native PLEventQueuePtr(PLEventQueue);
+[ptr] native PRThreadPtr(PRThread);
+native PRStatus(PRStatus);
+[ref] native PRBoolRef(PRBool);
+native PLHandleEventProc(PLHandleEventProc);
+native PLDestroyEventProc(PLDestroyEventProc);
+
+[scriptable, uuid(176AFB41-00A4-11d3-9F2A-00400553EEF0)]
+interface nsIEventQueue : nsIEventTarget
+{
+ [noscript] void initEvent(in PLEventPtr aEvent,
+ in voidPtr owner,
+ in PLHandleEventProc handler,
+ in PLDestroyEventProc destructor);
+
+ [noscript] void postSynchronousEvent(in PLEventPtr aEvent,
+ out voidPtr aResult);
+
+ boolean pendingEvents();
+ void processPendingEvents();
+ void eventLoop();
+
+ [noscript] void eventAvailable(in PRBoolRef aResult);
+ [noscript] PLEventPtr getEvent();
+ [noscript] void handleEvent(in PLEventPtr aEvent);
+ [noscript] PLEventPtr waitForEvent();
+
+ [notxpcom] PRInt32 getEventQueueSelectFD();
+
+ void init(in boolean aNative);
+ [noscript] void initFromPRThread(in PRThreadPtr thread,
+ in boolean aNative);
+ [noscript] void initFromPLQueue(in PLEventQueuePtr aQueue);
+
+ void enterMonitor();
+ void exitMonitor();
+
+ [noscript] void revokeEvents(in voidPtr owner);
+ [noscript] PLEventQueuePtr getPLEventQueue();
+
+ boolean isQueueNative();
+
+ // effectively kill the queue. warning: the queue is allowed to delete
+ // itself any time after this.
+ void stopAcceptingEvents();
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsIEventQueueService.idl b/src/libs/xpcom18a4/xpcom/threads/nsIEventQueueService.idl
new file mode 100644
index 00000000..e9c93e86
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsIEventQueueService.idl
@@ -0,0 +1,151 @@
+/* -*- 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):
+ * Rick Potts <rpotts@netscape.com>
+ * David Matiskella <davidm@netscape.com>
+ * David Hyatt <hyatt@netscape.com>
+ * Suresh Duddi <dp@netscape.com>
+ * Scott Collins <scc@netscape.com>
+ * Dan Matejka <danm@netscape.com>
+ * Doug Turner <dougt@netscape.com>
+ * Ray Whitmer <rayw@netscape.com>
+ * Dan Mosedale <dmose@mozilla.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 ***** */
+
+#include "nsISupports.idl"
+#include "nsIEventQueue.idl"
+
+%{C++
+#include "prthread.h"
+#include "plevent.h"
+
+/* be761f00-a3b0-11d2-996c-0080c7cb1080 */
+#define NS_EVENTQUEUESERVICE_CID \
+{ 0xbe761f00, 0xa3b0, 0x11d2, \
+ {0x99, 0x6c, 0x00, 0x80, 0xc7, 0xcb, 0x10, 0x80} }
+
+#define NS_EVENTQUEUESERVICE_CONTRACTID "@mozilla.org/event-queue-service;1"
+#define NS_EVENTQUEUESERVICE_CLASSNAME "Event Queue Service"
+
+#define NS_CURRENT_THREAD ((PRThread*)0)
+#define NS_CURRENT_EVENTQ ((nsIEventQueue*)0)
+
+#define NS_UI_THREAD ((PRThread*)1)
+#define NS_UI_THREAD_EVENTQ ((nsIEventQueue*)1)
+
+%}
+
+/* a forward decl */
+interface nsIThread;
+
+[scriptable, uuid(a6cf90dc-15b3-11d2-932e-00805f8add32)]
+interface nsIEventQueueService : nsISupports
+{
+ /**
+ * Creates and holds a native event queue for the current thread.
+ * "Native" queues have an associated callback mechanism which is
+ * automatically triggered when an event is posted. See plevent.c for
+ * details.
+ * @return NS_OK on success, or a host of failure indications
+ */
+ void createThreadEventQueue();
+
+ /**
+ * Creates and hold a monitored event queue for the current thread.
+ * "Monitored" queues have no callback processing mechanism.
+ * @return NS_OK on success, or a host of failure indications
+ */
+ void createMonitoredThreadEventQueue();
+
+ /**
+ * Somewhat misnamed, this method releases the service's hold on the event
+ * queue(s) for this thread. Subsequent attempts to access this thread's
+ * queue (GetThreadEventQueue, for example) may fail, though the queue itself
+ * will be destroyed only after all references to it are released and the
+ * queue itself is no longer actively processing events.
+ * @return nonsense.
+ */
+ void destroyThreadEventQueue();
+
+ nsIEventQueue createFromIThread(in nsIThread aThread,
+ in boolean aNative);
+
+ [noscript] nsIEventQueue createFromPLEventQueue(in PLEventQueuePtr
+ aPLEventQueue);
+
+ // Add a new event queue for the current thread, making it the "current"
+ // queue. Return that queue, addrefed.
+ nsIEventQueue pushThreadEventQueue();
+
+ // release and disable the queue
+ void popThreadEventQueue(in nsIEventQueue aQueue);
+
+ [noscript] nsIEventQueue getThreadEventQueue(in PRThreadPtr aThread);
+
+ /**
+ * @deprecated in favor of getSpecialEventQueue, since that's
+ * scriptable and this isn't.
+ *
+ * Check for any "magic" event queue constants (NS_CURRENT_EVENTQ,
+ * NS_UI_THREAD_EVENTQ) and return the real event queue that they
+ * represent, AddRef()ed. Otherwise, return the event queue passed
+ * in, AddRef()ed. This is not scriptable because the arguments in
+ * question may be magic constants rather than real nsIEventQueues.
+ *
+ * @arg queueOrConstant either a real event queue or a magic
+ * constant to be resolved
+ *
+ * @return a real event queue, AddRef()ed
+ */
+ [noscript] nsIEventQueue resolveEventQueue(in nsIEventQueue queueOrConstant);
+
+ /**
+ * Returns the appropriate special event queue, AddRef()ed. Really
+ * just a scriptable version of ResolveEventQueue.
+ *
+ * @arg aQueue Either CURRENT_THREAD_EVENT_QUEUE or
+ * UI_THREAD_EVENT_QUEUE
+ * @return The requested nsIEventQueue, AddRef()ed
+ * @exception NS_ERROR_NULL_POINTER Zero pointer passed in for return value
+ * @exception NS_ERROR_ILLEGAL_VALUE Bogus constant passed in aQueue
+ * @exception NS_ERROR_FAILURE Error while calling
+ * GetThreadEventQueue()
+ */
+ nsIEventQueue getSpecialEventQueue(in long aQueue);
+
+ const long CURRENT_THREAD_EVENT_QUEUE = 0;
+ const long UI_THREAD_EVENT_QUEUE = 1;
+
+};
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsIEventTarget.idl b/src/libs/xpcom18a4/xpcom/threads/nsIEventTarget.idl
new file mode 100644
index 00000000..3b19d9ca
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsIEventTarget.idl
@@ -0,0 +1,67 @@
+/* ***** 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.
+ *
+ * The Initial Developer of the Original Code is IBM Corporation.
+ * Portions created by IBM Corporation are Copyright (C) 2003
+ * IBM Corporation. All Rights Reserved.
+ *
+ * Contributor(s):
+ * IBM Corp.
+ *
+ * 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"
+
+%{C++
+#include "plevent.h"
+%}
+
+[ptr] native PLEventPtr(PLEvent);
+
+/**
+ * nsIEventTarget
+ *
+ * This interface is used to dispatch events to a particular thread. In many
+ * cases the event target also supports nsIEventQueue.
+ */
+[scriptable, uuid(ea99ad5b-cc67-4efb-97c9-2ef620a59f2a)]
+interface nsIEventTarget : nsISupports
+{
+ /**
+ * Method for posting an asynchronous event to the event target. If this
+ * method succeeds, then the event will be dispatched on the target thread.
+ *
+ * @param aEvent
+ * The event to dispatched.
+ */
+ [noscript] void postEvent(in PLEventPtr aEvent);
+
+ /**
+ * This method returns true if the event target is the current thread.
+ */
+ boolean isOnCurrentThread();
+};
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsIProcess.idl b/src/libs/xpcom18a4/xpcom/threads/nsIProcess.idl
new file mode 100644
index 00000000..07769cb7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsIProcess.idl
@@ -0,0 +1,32 @@
+#include "nsIFile.idl"
+#include "nsISupports.idl"
+
+[scriptable, uuid(9da0b650-d07e-4617-a18a-250035572ac8)]
+
+interface nsIProcess : nsISupports
+{
+ void init(in nsIFile executable);
+ void initWithPid(in unsigned long pid);
+
+ void kill();
+
+ /** XXX what charset? **/
+ /** Executes the file this object was initialized with
+ * @param blocking Whether to wait until the process terminates before returning or not
+ * @param args An array of arguments to pass to the process
+ * @param count The length of the args array
+ * @return the PID of the newly spawned process */
+ unsigned long run(in boolean blocking, [array, size_is(count)] in string args, in unsigned long count);
+
+ readonly attribute nsIFile location;
+ readonly attribute unsigned long pid;
+ readonly attribute string processName;
+ readonly attribute unsigned long processSignature;
+ readonly attribute long exitValue;
+};
+
+%{C++
+
+#define NS_PROCESS_CONTRACTID "@mozilla.org/process/util;1"
+#define NS_PROCESS_CLASSNAME "Process Specification"
+%}
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsIRunnable.idl b/src/libs/xpcom18a4/xpcom/threads/nsIRunnable.idl
new file mode 100644
index 00000000..1cedda38
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsIRunnable.idl
@@ -0,0 +1,44 @@
+/* -*- 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 "nsISupports.idl"
+
+[scriptable, uuid(4a2abaf0-6886-11d3-9382-00104ba0fd40)]
+interface nsIRunnable : nsISupports
+{
+ void run();
+};
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsIThread.idl b/src/libs/xpcom18a4/xpcom/threads/nsIThread.idl
new file mode 100644
index 00000000..f28d6ec9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsIThread.idl
@@ -0,0 +1,144 @@
+/* -*- 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 "nsISupports.idl"
+
+%{C++
+#include "prthread.h"
+
+#define NS_THREAD_CID \
+{ /* 85CE5510-7808-11d3-A181-0050041CAF44 */ \
+ 0x85ce5510, \
+ 0x7808, \
+ 0x11d3, \
+ {0xa1, 0x81, 0x00, 0x50, 0x04, 0x1c, 0xaf, 0x44} \
+}
+
+#define NS_THREAD_CONTRACTID "@mozilla.org/thread;1"
+#define NS_THREAD_CLASSNAME "Thread"
+#if 0
+%}
+
+typedef PRUint32 PRThreadPriority;
+typedef PRUint32 PRThreadScope;
+typedef PRUint32 PRThreadState;
+
+%{C++
+#endif
+%}
+
+interface nsIRunnable;
+
+[ptr] native PRThread(PRThread);
+
+[scriptable, uuid(6be5e380-6886-11d3-9382-00104ba0fd40)]
+interface nsIThread : nsISupports
+{
+ // These must all match the values used in prthread.h
+ const PRUint32 PRIORITY_LOW = 0;
+ const PRUint32 PRIORITY_NORMAL = 1;
+ const PRUint32 PRIORITY_HIGH = 2;
+ const PRUint32 PRIORITY_URGENT = 3;
+
+ const PRUint32 SCOPE_LOCAL = 0;
+ const PRUint32 SCOPE_GLOBAL = 1;
+ const PRUint32 SCOPE_BOUND = 2;
+
+ const PRUint32 STATE_JOINABLE = 0;
+ const PRUint32 STATE_UNJOINABLE = 1;
+
+ void join();
+ void interrupt();
+
+ attribute PRThreadPriority priority;
+ readonly attribute PRThreadScope scope;
+ readonly attribute PRThreadState state;
+
+ [noscript] PRThread GetPRThread();
+
+ void init(in nsIRunnable aRunnable,
+ in PRUint32 aStackSize,
+ in PRThreadPriority aPriority,
+ in PRThreadScope aScope,
+ in PRThreadState aState);
+
+ /*
+ * Get the currently running thread (really a static method sort of thing).
+ */
+ readonly attribute nsIThread currentThread;
+
+ /*
+ * Sleep to at least this many milliseconds (only works on currrent thread).
+ */
+ void sleep(in PRUint32 msec);
+
+%{C++
+ // returns the nsIThread for the current thread:
+ static NS_COM nsresult GetCurrent(nsIThread* *result);
+
+ // returns the nsIThread for an arbitrary PRThread:
+ static NS_COM nsresult GetIThread(PRThread* prthread, nsIThread* *result);
+
+ // initializes the "main" thread (really, just saves the current thread
+ // at time of calling. meant to be called once at app startup, in lieu
+ // of proper static initializers, to save the primordial thread
+ // for later recall.)
+ static NS_COM nsresult SetMainThread();
+
+ // return the "main" thread
+ static NS_COM nsresult GetMainThread(nsIThread **result);
+
+ static NS_COM PRBool IsMainThread();
+%}
+};
+
+%{C++
+extern NS_COM nsresult
+NS_NewThread(nsIThread* *result,
+ nsIRunnable* runnable,
+ PRUint32 stackSize = 0,
+ PRThreadState state = PR_UNJOINABLE_THREAD,
+ PRThreadPriority priority = PR_PRIORITY_NORMAL,
+ PRThreadScope scope = PR_GLOBAL_THREAD);
+
+extern NS_COM nsresult
+NS_NewThread(nsIThread* *result,
+ PRUint32 stackSize = 0,
+ PRThreadState state = PR_UNJOINABLE_THREAD,
+ PRThreadPriority priority = PR_PRIORITY_NORMAL,
+ PRThreadScope scope = PR_GLOBAL_THREAD);
+%}
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsITimer.idl b/src/libs/xpcom18a4/xpcom/threads/nsITimer.idl
new file mode 100644
index 00000000..855d538d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsITimer.idl
@@ -0,0 +1,191 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * ***** 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):
+ *
+ * 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;
+
+%{C++
+/**
+ * The signature of the timer callback function passed to initWithCallback. This
+ * is the function that will get called when the timer expires if the timer is
+ * initialized via initWithCallback.
+ *
+ * @param aTimer the timer which has expired
+ * @param aClosure opaque parameter passed to initWithCallback
+ *
+ * Implementers should return the following:
+ *
+ * @return NS_OK
+ *
+ */
+class nsITimer;
+typedef void (*nsTimerCallbackFunc) (nsITimer *aTimer, void *aClosure);
+%}
+
+native nsTimerCallbackFunc(nsTimerCallbackFunc);
+
+/**
+ * The callback interface for timers.
+ */
+interface nsITimer;
+
+[scriptable, uuid(a796816d-7d47-4348-9ab8-c7aeb3216a7d)]
+interface nsITimerCallback : nsISupports
+{
+ /**
+ * @param aTimer the timer which has expired
+ */
+ void notify(in nsITimer timer);
+};
+
+
+/**
+ * nsITimer instances must be initialized by calling one of the "init" methods
+ * documented below. You may also re-initialize an existing instance with new
+ * delay to avoid the overhead of destroying and creating a timer. It is not
+ * necessary to cancel the timer in that case.
+ */
+[scriptable, uuid(29ee628e-a3ea-471f-965d-dc9f11d1c183)]
+interface nsITimer : nsISupports
+{
+ /* Timer types */
+
+ /**
+ * Type of a timer that fires once only.
+ */
+ const short TYPE_ONE_SHOT = 0;
+
+ /**
+ * After firing, a TYPE_REPEATING_SLACK timer is stopped and not restarted
+ * until its callback completes. Specified timer period will be at least
+ * the time between when processing for last firing the callback completes
+ * and when the next firing occurs.
+ *
+ * This is the preferable repeating type for most situations.
+ */
+ const short TYPE_REPEATING_SLACK = 1;
+
+ /**
+ * An TYPE_REPEATING_PRECISE repeating timer aims to have constant period
+ * between firings. The processing time for each timer callback should not
+ * influence the timer period. However, if the processing for the last
+ * timer firing could not be completed until just before the next firing
+ * occurs, then you could have two timer notification routines being
+ * executed in quick succession.
+ */
+ const short TYPE_REPEATING_PRECISE = 2;
+
+ /**
+ * Initialize a timer that will fire after the said delay.
+ * A user must keep a reference to this timer till it is
+ * is no longer needed or has been cancelled.
+ *
+ * @param aObserver the callback object that observes the
+ * ``timer-callback'' topic with the subject being
+ * the timer itself when the timer fires:
+ *
+ * observe(nsISupports aSubject, => nsITimer
+ * string aTopic, => ``timer-callback''
+ * wstring data => null
+ *
+ * @param aDelay delay in milliseconds for timer to fire
+ * @param aType timer type per TYPE* consts defined above
+ */
+ void init(in nsIObserver aObserver, in unsigned long aDelay,
+ in unsigned long aType);
+
+
+ /**
+ * Initialize a timer to fire after the given millisecond interval.
+ * This version takes a function to call and a closure to pass to
+ * that function.
+ *
+ * @param aFunc The function to invoke
+ * @param aClosure An opaque pointer to pass to that function
+ * @param aDelay The millisecond interval
+ * @param aType Timer type per TYPE* consts defined above
+ */
+ [noscript] void initWithFuncCallback(in nsTimerCallbackFunc aCallback,
+ in voidPtr aClosure,
+ in unsigned long aDelay,
+ in unsigned long aType);
+
+ /**
+ * Initialize a timer to fire after the given millisecond interval.
+ * This version takes a function to call and a closure to pass to
+ * that function.
+ *
+ * @param aFunc nsITimerCallback interface to call when timer expires
+ * @param aDelay The millisecond interval
+ * @param aType Timer type per TYPE* consts defined above
+ */
+ void initWithCallback(in nsITimerCallback aCallback,
+ in unsigned long aDelay,
+ in unsigned long aType);
+
+ /**
+ * Cancel the timer. This method works on all types, not just on repeating
+ * timers -- you might want to cancel a TYPE_ONE_SHOT timer, and even reuse
+ * it by re-initializing it (to avoid object destruction and creation costs
+ * by conserving one timer instance).
+ */
+ void cancel();
+
+ /**
+ * The millisecond delay of the timeout
+ */
+ attribute unsigned long delay;
+
+ /**
+ * The timer type : one shot or repeating
+ */
+ attribute unsigned long type;
+
+ /**
+ * The opaque pointer pass to initWithCallback.
+ */
+ [noscript] readonly attribute voidPtr closure;
+};
+
+%{C++
+#define NS_TIMER_CONTRACTID "@mozilla.org/timer;1"
+#define NS_TIMER_CALLBACK_TOPIC "timer-callback"
+%}
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsITimerInternal.idl b/src/libs/xpcom18a4/xpcom/threads/nsITimerInternal.idl
new file mode 100644
index 00000000..c334ae19
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsITimerInternal.idl
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * ***** 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):
+ *
+ * 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"
+
+
+[scriptable, uuid(6dd8f185-ceb8-4878-8e38-2d13edc2d079)]
+interface nsITimerInternal : nsISupports
+{
+ attribute boolean idle;
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsITimerManager.idl b/src/libs/xpcom18a4/xpcom/threads/nsITimerManager.idl
new file mode 100644
index 00000000..f391d313
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsITimerManager.idl
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * ***** 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):
+ * Stuart Parmenter <pavlov@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 "nsISupports.idl"
+
+[scriptable, uuid(8fce8c6a-1dd2-11b2-8352-8cdd2b965efc)]
+interface nsITimerManager : nsISupports
+{
+ /**
+ * A flag that turns on the use of idle timers on the main thread.
+ * this should only be called once.
+ *
+ * By default, idle timers are off.
+ *
+ * One this is set to TRUE, you are expected to call hasIdleTimers/fireNextIdleTimer
+ * when you have time in your main loop.
+ */
+ attribute boolean useIdleTimers;
+
+ boolean hasIdleTimers();
+
+ // Fire next idle timers waiting on the current thread
+ void fireNextIdleTimer();
+};
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsPIEventQueueChain.h b/src/libs/xpcom18a4/xpcom/threads/nsPIEventQueueChain.h
new file mode 100644
index 00000000..8d3c0933
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsPIEventQueueChain.h
@@ -0,0 +1,93 @@
+/* -*- 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 nsPIEventQueueChain_h__
+#define nsPIEventQueueChain_h__
+
+#include "nsISupports.h"
+
+// {8f310040-82a7-11d3-95bc-0060083a0bcf}
+#define NS_IEVENTQUEUECHAIN_IID \
+{ 0x8f310040, 0x82a7, 0x11d3, { 0x95, 0xbc, 0x0, 0x60, 0x8, 0x3a, 0xb, 0xcf } }
+
+class nsIEventQueue;
+
+class nsPIEventQueueChain : public nsISupports
+{
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IEVENTQUEUECHAIN_IID);
+
+ /**
+ * Add the given queue as the new youngest member of our chain.
+ * It will not be addrefed.
+ * @param aQueue the queue. must not be null.
+ * @return error indication
+ */
+ NS_IMETHOD AppendQueue(nsIEventQueue *aQueue) = 0;
+
+ /**
+ * Remove this element from the chain.
+ * @return NS_OK
+ */
+ NS_IMETHOD Unlink() = 0;
+
+ /**
+ * Fetch (and addref) the youngest member of the chain.
+ * @param *aQueue the youngest queue. aQueue must not be null.
+ * @return error indication
+ */
+ NS_IMETHOD GetYoungest(nsIEventQueue **aQueue) = 0;
+
+ /**
+ * Fetch (and addref) the youngest member of the chain which is
+ * still accepting events, or at least still contains events in need
+ * of processing.
+ * @param *aQueue the youngest such queue. aQueue must not be null.
+ * *aQueue will be returned null, if no such queue is found.
+ * @return error indication -- can be NS_OK even if *aQueue is 0
+ */
+ NS_IMETHOD GetYoungestActive(nsIEventQueue **aQueue) = 0;
+
+ NS_IMETHOD SetYounger(nsPIEventQueueChain *aQueue) = 0;
+ NS_IMETHOD GetYounger(nsIEventQueue **aQueue) = 0;
+
+ NS_IMETHOD SetElder(nsPIEventQueueChain *aQueue) = 0;
+ NS_IMETHOD GetElder(nsIEventQueue **aQueue) = 0;
+};
+
+#endif /* nsPIEventQueueChain_h___ */
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsProcess.h b/src/libs/xpcom18a4/xpcom/threads/nsProcess.h
new file mode 100644
index 00000000..f061fe1c
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsProcess.h
@@ -0,0 +1,71 @@
+/* -*- 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):
+ * Don Bragg <dbragg@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 _nsPROCESSWIN_H_
+#define _nsPROCESSWIN_H_
+
+#include "nsIProcess.h"
+#include "nsIFile.h"
+#include "nsString.h"
+#include "prproces.h"
+
+#define NS_PROCESS_CID \
+{0x7b4eeb20, 0xd781, 0x11d4, \
+ {0x8A, 0x83, 0x00, 0x10, 0xa4, 0xe0, 0xc9, 0xca}}
+
+class nsProcess : public nsIProcess
+{
+public:
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPROCESS
+
+ nsProcess();
+
+private:
+ ~nsProcess() {}
+
+ nsCOMPtr<nsIFile> mExecutable;
+ PRInt32 mExitValue;
+ nsCString mTargetPath;
+ PRProcess *mProcess;
+
+};
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsProcessCommon.cpp b/src/libs/xpcom18a4/xpcom/threads/nsProcessCommon.cpp
new file mode 100644
index 00000000..07087c2f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsProcessCommon.cpp
@@ -0,0 +1,363 @@
+/* -*- 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-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Don Bragg <dbragg@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 ***** */
+
+/*****************************************************************************
+ *
+ * nsProcess is used to execute new processes and specify if you want to
+ * wait (blocking) or continue (non-blocking).
+ *
+ *****************************************************************************
+ */
+
+#include "nsCOMPtr.h"
+#include "nsMemory.h"
+#include "nsProcess.h"
+#include "prtypes.h"
+#include "prio.h"
+#include "prenv.h"
+#include "nsCRT.h"
+
+#include <stdlib.h>
+
+#if defined( XP_WIN )
+#include "prmem.h"
+#include "nsString.h"
+#include "nsLiteralString.h"
+#include "nsReadableUtils.h"
+#include <windows.h>
+#endif
+
+//-------------------------------------------------------------------//
+// nsIProcess implementation
+//-------------------------------------------------------------------//
+NS_IMPL_ISUPPORTS1(nsProcess, nsIProcess)
+
+//Constructor
+nsProcess::nsProcess():mExitValue(-1),
+ mProcess(nsnull)
+{
+}
+
+NS_IMETHODIMP
+nsProcess::Init(nsIFile* executable)
+{
+ PRBool isFile;
+
+ //First make sure the file exists
+ nsresult rv = executable->IsFile(&isFile);
+ if (NS_FAILED(rv)) return rv;
+ if (!isFile)
+ return NS_ERROR_FAILURE;
+
+ //Store the nsIFile in mExecutable
+ mExecutable = executable;
+ //Get the path because it is needed by the NSPR process creation
+#ifdef XP_WIN
+ rv = mExecutable->GetNativeTarget(mTargetPath);
+ if (NS_FAILED(rv) || mTargetPath.IsEmpty() )
+#endif
+ rv = mExecutable->GetNativePath(mTargetPath);
+
+ return rv;
+}
+
+
+#if defined( XP_WIN )
+static int assembleCmdLine(char *const *argv, char **cmdLine)
+{
+ char *const *arg;
+ char *p, *q;
+ int cmdLineSize;
+ int numBackslashes;
+ int i;
+ int argNeedQuotes;
+
+ /*
+ * Find out how large the command line buffer should be.
+ */
+ cmdLineSize = 0;
+ for (arg = argv; *arg; arg++) {
+ /*
+ * \ and " need to be escaped by a \. In the worst case,
+ * every character is a \ or ", so the string of length
+ * may double. If we quote an argument, that needs two ".
+ * Finally, we need a space between arguments, and
+ * a null byte at the end of command line.
+ */
+ cmdLineSize += 2 * strlen(*arg) /* \ and " need to be escaped */
+ + 2 /* we quote every argument */
+ + 1; /* space in between, or final null */
+ }
+ p = *cmdLine = (char *) PR_MALLOC(cmdLineSize);
+ if (p == NULL) {
+ return -1;
+ }
+
+ for (arg = argv; *arg; arg++) {
+ /* Add a space to separates the arguments */
+ if (arg != argv) {
+ *p++ = ' ';
+ }
+ q = *arg;
+ numBackslashes = 0;
+ argNeedQuotes = 0;
+
+ /* If the argument contains white space, it needs to be quoted. */
+ if (strpbrk(*arg, " \f\n\r\t\v")) {
+ argNeedQuotes = 1;
+ }
+
+ if (argNeedQuotes) {
+ *p++ = '"';
+ }
+ while (*q) {
+ if (*q == '\\') {
+ numBackslashes++;
+ q++;
+ } else if (*q == '"') {
+ if (numBackslashes) {
+ /*
+ * Double the backslashes since they are followed
+ * by a quote
+ */
+ for (i = 0; i < 2 * numBackslashes; i++) {
+ *p++ = '\\';
+ }
+ numBackslashes = 0;
+ }
+ /* To escape the quote */
+ *p++ = '\\';
+ *p++ = *q++;
+ } else {
+ if (numBackslashes) {
+ /*
+ * Backslashes are not followed by a quote, so
+ * don't need to double the backslashes.
+ */
+ for (i = 0; i < numBackslashes; i++) {
+ *p++ = '\\';
+ }
+ numBackslashes = 0;
+ }
+ *p++ = *q++;
+ }
+ }
+
+ /* Now we are at the end of this argument */
+ if (numBackslashes) {
+ /*
+ * Double the backslashes if we have a quote string
+ * delimiter at the end.
+ */
+ if (argNeedQuotes) {
+ numBackslashes *= 2;
+ }
+ for (i = 0; i < numBackslashes; i++) {
+ *p++ = '\\';
+ }
+ }
+ if (argNeedQuotes) {
+ *p++ = '"';
+ }
+ }
+
+ *p = '\0';
+ return 0;
+}
+#endif
+
+// XXXldb |args| has the wrong const-ness
+NS_IMETHODIMP
+nsProcess::Run(PRBool blocking, const char **args, PRUint32 count, PRUint32 *pid)
+{
+ nsresult rv = NS_OK;
+
+ // make sure that when we allocate we have 1 greater than the
+ // count since we need to null terminate the list for the argv to
+ // pass into PR_CreateProcess
+ char **my_argv = NULL;
+#ifdef VBOX
+ my_argv = (char **)nsMemory::Alloc(sizeof(char *) * (count + 2) );
+#else
+ my_argv = (char **)malloc(sizeof(char *) * (count + 2) );
+#endif
+ if (!my_argv) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ // copy the args
+ PRUint32 i;
+ for (i=0; i < count; i++) {
+ my_argv[i+1] = NS_CONST_CAST(char*, args[i]);
+ }
+ // we need to set argv[0] to the program name.
+ my_argv[0] = mTargetPath.BeginWriting();
+ // null terminate the array
+ my_argv[count+1] = NULL;
+
+ #if defined(XP_WIN)
+ STARTUPINFO startupInfo;
+ PROCESS_INFORMATION procInfo;
+ BOOL retVal;
+ char *cmdLine;
+
+ if (assembleCmdLine(my_argv, &cmdLine) == -1) {
+ nsMemory::Free(my_argv);
+ return NS_ERROR_FILE_EXECUTION_FAILED;
+ }
+
+ ZeroMemory(&startupInfo, sizeof(startupInfo));
+ startupInfo.cb = sizeof(startupInfo);
+
+ retVal = CreateProcess(NULL,
+ // NS_CONST_CAST(char*, mTargetPath.get()),
+ cmdLine,
+ NULL, /* security attributes for the new
+ * process */
+ NULL, /* security attributes for the primary
+ * thread in the new process */
+ FALSE, /* inherit handles */
+ 0, /* creation flags */
+ NULL, /* env */
+ NULL, /* current drive and directory */
+ &startupInfo,
+ &procInfo
+ );
+ PR_FREEIF( cmdLine );
+ if (blocking) {
+
+ // if success, wait for process termination. the early returns and such
+ // are a bit ugly but preserving the logic of the nspr code I copied to
+ // minimize our risk abit.
+
+ if ( retVal == TRUE ) {
+ DWORD dwRetVal;
+ unsigned long exitCode;
+
+ dwRetVal = WaitForSingleObject(procInfo.hProcess, INFINITE);
+ if (dwRetVal == WAIT_FAILED) {
+ nsMemory::Free(my_argv);
+ return PR_FAILURE;
+ }
+ if (GetExitCodeProcess(procInfo.hProcess, &exitCode) == FALSE) {
+ mExitValue = exitCode;
+ nsMemory::Free(my_argv);
+ return PR_FAILURE;
+ }
+ mExitValue = exitCode;
+ CloseHandle(procInfo.hProcess);
+ }
+ else
+ rv = PR_FAILURE;
+ }
+ else {
+
+ // map return value into success code
+
+ if ( retVal == TRUE )
+ rv = PR_SUCCESS;
+ else
+ rv = PR_FAILURE;
+ }
+
+#else
+ if ( blocking ) {
+ mProcess = PR_CreateProcess(mTargetPath.get(), my_argv, NULL, NULL);
+ if (mProcess)
+ rv = PR_WaitProcess(mProcess, &mExitValue);
+ }
+ else {
+ rv = PR_CreateProcessDetached(mTargetPath.get(), my_argv, NULL, NULL);
+ }
+#endif
+
+ // free up our argv
+ nsMemory::Free(my_argv);
+
+ if (rv != PR_SUCCESS)
+ return NS_ERROR_FILE_EXECUTION_FAILED;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsProcess::InitWithPid(PRUint32 pid)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsProcess::GetLocation(nsIFile** aLocation)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsProcess::GetPid(PRUint32 *aPid)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsProcess::GetProcessName(char** aProcessName)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsProcess::GetProcessSignature(PRUint32 *aProcessSignature)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsProcess::Kill()
+{
+ nsresult rv = NS_OK;
+ if (mProcess)
+ rv = PR_KillProcess(mProcess);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsProcess::GetExitValue(PRInt32 *aExitValue)
+{
+ *aExitValue = mExitValue;
+
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsProcessMac.cpp b/src/libs/xpcom18a4/xpcom/threads/nsProcessMac.cpp
new file mode 100644
index 00000000..d6411f47
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsProcessMac.cpp
@@ -0,0 +1,188 @@
+/* -*- 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-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Don Bragg <dbragg@netscape.com>
+ * Samir Gehani <sgehani@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 ***** */
+
+/*****************************************************************************
+ *
+ * nsProcess is used to execute new processes and specify if you want to
+ * wait (blocking) or continue (non-blocking).
+ *
+ *****************************************************************************
+ */
+
+#include "nsCOMPtr.h"
+#include "nsMemory.h"
+
+#include "nsProcess.h"
+
+#include "prtypes.h"
+#include "prio.h"
+#include "prenv.h"
+#include "nsCRT.h"
+#include "prthread.h"
+
+#include <stdlib.h>
+#include <Processes.h>
+
+#include "nsILocalFileMac.h"
+
+//-------------------------------------------------------------------//
+// nsIProcess implementation
+//-------------------------------------------------------------------//
+NS_IMPL_ISUPPORTS1(nsProcess, nsIProcess)
+
+//Constructor
+nsProcess::nsProcess()
+:mExitValue(-1),
+ mProcess(nsnull)
+{
+}
+
+NS_IMETHODIMP
+nsProcess::Init(nsIFile* executable)
+{
+ PRBool isFile;
+
+ //First make sure the file exists
+ nsresult rv = executable->IsFile(&isFile);
+ if (NS_FAILED(rv)) return rv;
+
+ if (!isFile)
+ return NS_ERROR_FAILURE;
+
+ mExecutable = executable;
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsProcess::Run(PRBool blocking, const char **args, PRUint32 count, PRUint32 *pid)
+{
+ OSErr err = noErr;
+ LaunchParamBlockRec launchPB;
+ FSSpec resolvedSpec;
+ Boolean bDone = false;
+ ProcessInfoRec info;
+
+ nsCOMPtr<nsILocalFileMac> macExecutable = do_QueryInterface(mExecutable);
+ macExecutable->GetFSSpec(&resolvedSpec);
+
+ launchPB.launchAppSpec = &resolvedSpec;
+ launchPB.launchAppParameters = NULL;
+ launchPB.launchBlockID = extendedBlock;
+ launchPB.launchEPBLength = extendedBlockLen;
+ launchPB.launchFileFlags = NULL;
+ launchPB.launchControlFlags = launchContinue + launchNoFileFlags + launchUseMinimum;
+ if (!blocking)
+ launchPB.launchControlFlags += launchDontSwitch;
+
+ err = LaunchApplication(&launchPB);
+ if (err != noErr)
+ return NS_ERROR_FAILURE;
+
+ // NOTE: blocking mode assumes you are running on a thread
+ // other than the UI thread that has teh main event loop
+ if (blocking)
+ {
+ do
+ {
+ info.processInfoLength = sizeof(ProcessInfoRec);
+ info.processName = nil;
+ info.processAppSpec = nil;
+ err = GetProcessInformation(&launchPB.launchProcessSN, &info);
+
+ if (err == noErr)
+ {
+ // still running so sleep some more (200 msecs)
+ PR_Sleep(200);
+ }
+ else
+ {
+ // no longer in process manager's internal list: so assume done
+ bDone = true;
+ }
+ }
+ while (!bDone);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsProcess::InitWithPid(PRUint32 pid)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsProcess::GetLocation(nsIFile** aLocation)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsProcess::GetPid(PRUint32 *aPid)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsProcess::GetProcessName(char** aProcessName)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsProcess::GetProcessSignature(PRUint32 *aProcessSignature)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsProcess::Kill()
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsProcess::GetExitValue(PRInt32 *aExitValue)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsThread.cpp b/src/libs/xpcom18a4/xpcom/threads/nsThread.cpp
new file mode 100644
index 00000000..b4cc15f4
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsThread.cpp
@@ -0,0 +1,457 @@
+/* -*- 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 "nsThread.h"
+#include "prmem.h"
+#include "prlog.h"
+#include "nsAutoLock.h"
+
+PRUintn nsThread::kIThreadSelfIndex = 0;
+static nsIThread *gMainThread = 0;
+
+#if defined(PR_LOGGING)
+//
+// Log module for nsIThread logging...
+//
+// To enable logging (see prlog.h for full details):
+//
+// set NSPR_LOG_MODULES=nsIThread:5
+// set NSPR_LOG_FILE=nspr.log
+//
+// this enables PR_LOG_DEBUG level information and places all output in
+// the file nspr.log
+//
+// gSocketLog is defined in nsSocketTransport.cpp
+//
+PRLogModuleInfo* nsIThreadLog = nsnull;
+
+#endif /* PR_LOGGING */
+
+////////////////////////////////////////////////////////////////////////////////
+
+nsThread::nsThread()
+ : mThread(nsnull), mDead(PR_FALSE), mStartLock(nsnull)
+{
+#if defined(PR_LOGGING)
+ //
+ // Initialize the global PRLogModule for nsIThread logging
+ // if necessary...
+ //
+ if (nsIThreadLog == nsnull) {
+ nsIThreadLog = PR_NewLogModule("nsIThread");
+ }
+#endif /* PR_LOGGING */
+
+ // enforce matching of constants to enums in prthread.h
+ NS_ASSERTION(int(nsIThread::PRIORITY_LOW) == int(PR_PRIORITY_LOW) &&
+ int(nsIThread::PRIORITY_NORMAL) == int(PRIORITY_NORMAL) &&
+ int(nsIThread::PRIORITY_HIGH) == int(PRIORITY_HIGH) &&
+ int(nsIThread::PRIORITY_URGENT) == int(PRIORITY_URGENT) &&
+ int(nsIThread::SCOPE_LOCAL) == int(PR_LOCAL_THREAD) &&
+ int(nsIThread::SCOPE_GLOBAL) == int(PR_GLOBAL_THREAD) &&
+ int(nsIThread::STATE_JOINABLE) == int(PR_JOINABLE_THREAD) &&
+ int(nsIThread::STATE_UNJOINABLE) == int(PR_UNJOINABLE_THREAD),
+ "Bad constant in nsIThread!");
+}
+
+nsThread::~nsThread()
+{
+ if (mStartLock)
+ PR_DestroyLock(mStartLock);
+
+ PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
+ ("nsIThread %p destroyed\n", this));
+
+ // This code used to free the nsIThreadLog loginfo stuff
+ // Don't do that; loginfo structures are owned by nspr
+ // and would be freed if we ever called PR_Cleanup()
+ // see bug 142072
+}
+
+void
+nsThread::Main(void* arg)
+{
+ nsThread* self = (nsThread*)arg;
+
+ self->WaitUntilReadyToStartMain();
+
+ nsresult rv = NS_OK;
+ rv = self->RegisterThreadSelf();
+ NS_ASSERTION(rv == NS_OK, "failed to set thread self");
+
+ PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
+ ("nsIThread %p start run %p\n", self, self->mRunnable.get()));
+ rv = self->mRunnable->Run();
+ NS_ASSERTION(NS_SUCCEEDED(rv), "runnable failed");
+
+#ifdef DEBUG
+ // Because a thread can die after gMainThread dies and takes nsIThreadLog with it,
+ // we need to check for it being null so that we don't crash on shutdown.
+ if (nsIThreadLog) {
+ PRThreadState state;
+ rv = self->GetState(&state);
+ PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
+ ("nsIThread %p end run %p\n", self, self->mRunnable.get()));
+ }
+#endif
+
+ // explicitly drop the runnable now in case there are circular references
+ // between it and the thread object
+ self->mRunnable = nsnull;
+}
+
+void
+nsThread::Exit(void* arg)
+{
+ nsThread* self = (nsThread*)arg;
+
+ if (self->mDead) {
+ NS_ERROR("attempt to Exit() thread twice");
+ return;
+ }
+
+ self->mDead = PR_TRUE;
+
+#if defined(PR_LOGGING)
+ if (nsIThreadLog) {
+ PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
+ ("nsIThread %p exited\n", self));
+ }
+#endif
+ NS_RELEASE(self);
+}
+
+NS_METHOD
+nsThread::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
+{
+ nsThread* thread = new nsThread();
+ if (!thread) return NS_ERROR_OUT_OF_MEMORY;
+ nsresult rv = thread->QueryInterface(aIID, aResult);
+ if (NS_FAILED(rv)) delete thread;
+ return rv;
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsThread, nsIThread)
+
+NS_IMETHODIMP
+nsThread::Join()
+{
+ // don't check for mDead here because nspr calls Exit (cleaning up
+ // thread-local storage) before they let us join with the thread
+
+ PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
+ ("nsIThread %p start join\n", this));
+ if (!mThread)
+ return NS_ERROR_NOT_INITIALIZED;
+ PRStatus status = PR_JoinThread(mThread);
+ // XXX can't use NS_RELEASE here because the macro wants to set
+ // this to null (bad c++)
+ PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
+ ("nsIThread %p end join\n", this));
+ if (status == PR_SUCCESS) {
+ NS_RELEASE_THIS(); // most likely the final release of this thread
+ return NS_OK;
+ }
+ else
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsThread::GetPriority(PRThreadPriority *result)
+{
+ if (mDead)
+ return NS_ERROR_FAILURE;
+ if (!mThread)
+ return NS_ERROR_NOT_INITIALIZED;
+ *result = PR_GetThreadPriority(mThread);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsThread::SetPriority(PRThreadPriority value)
+{
+ if (mDead)
+ return NS_ERROR_FAILURE;
+ if (!mThread)
+ return NS_ERROR_NOT_INITIALIZED;
+ PR_SetThreadPriority(mThread, value);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsThread::Interrupt()
+{
+ if (mDead)
+ return NS_ERROR_FAILURE;
+ if (!mThread)
+ return NS_ERROR_NOT_INITIALIZED;
+ PRStatus status = PR_Interrupt(mThread);
+ return status == PR_SUCCESS ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsThread::GetScope(PRThreadScope *result)
+{
+ if (mDead)
+ return NS_ERROR_FAILURE;
+ if (!mThread)
+ return NS_ERROR_NOT_INITIALIZED;
+ *result = PR_GetThreadScope(mThread);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsThread::GetState(PRThreadState *result)
+{
+ if (mDead)
+ return NS_ERROR_FAILURE;
+ if (!mThread)
+ return NS_ERROR_NOT_INITIALIZED;
+ *result = PR_GetThreadState(mThread);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsThread::GetPRThread(PRThread* *result)
+{
+ if (mDead) {
+ *result = nsnull;
+ return NS_ERROR_FAILURE;
+ }
+ *result = mThread;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsThread::Init(nsIRunnable* runnable,
+ PRUint32 stackSize,
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state)
+{
+ NS_ENSURE_ARG_POINTER(runnable);
+ mRunnable = runnable;
+
+ NS_ADDREF_THIS(); // released in nsThread::Exit
+ if (state == PR_JOINABLE_THREAD)
+ NS_ADDREF_THIS(); // released in nsThread::Join
+ mStartLock = PR_NewLock();
+ if (mStartLock == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ PR_Lock(mStartLock);
+ mThread = PR_CreateThread(PR_USER_THREAD, Main, this,
+ priority, scope, state, stackSize);
+ PR_Unlock(mStartLock);
+ PR_LOG(nsIThreadLog, PR_LOG_DEBUG,
+ ("nsIThread %p created\n", this));
+
+ if (mThread == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return NS_OK;
+}
+
+/* readonly attribute nsIThread currentThread; */
+NS_IMETHODIMP
+nsThread::GetCurrentThread(nsIThread * *aCurrentThread)
+{
+ return GetIThread(PR_GetCurrentThread(), aCurrentThread);
+}
+
+/* void sleep (in PRUint32 msec); */
+NS_IMETHODIMP
+nsThread::Sleep(PRUint32 msec)
+{
+ if (PR_GetCurrentThread() != mThread)
+ return NS_ERROR_FAILURE;
+
+ if (PR_Sleep(PR_MillisecondsToInterval(msec)) != PR_SUCCESS)
+ return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+NS_COM nsresult
+NS_NewThread(nsIThread* *result,
+ nsIRunnable* runnable,
+ PRUint32 stackSize,
+ PRThreadState state,
+ PRThreadPriority priority,
+ PRThreadScope scope)
+{
+ nsresult rv;
+ nsThread* thread = new nsThread();
+ if (thread == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(thread);
+
+ rv = thread->Init(runnable, stackSize, priority, scope, state);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(thread);
+ return rv;
+ }
+
+ *result = thread;
+ return NS_OK;
+}
+
+NS_COM nsresult
+NS_NewThread(nsIThread* *result,
+ PRUint32 stackSize,
+ PRThreadState state,
+ PRThreadPriority priority,
+ PRThreadScope scope)
+{
+ nsThread* thread = new nsThread();
+ if (thread == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(thread);
+ *result = thread;
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+nsresult
+nsThread::RegisterThreadSelf()
+{
+ PRStatus status;
+
+ if (kIThreadSelfIndex == 0) {
+ status = PR_NewThreadPrivateIndex(&kIThreadSelfIndex, Exit);
+ if (status != PR_SUCCESS) return NS_ERROR_FAILURE;
+ }
+
+ status = PR_SetThreadPrivate(kIThreadSelfIndex, this);
+ if (status != PR_SUCCESS) return NS_ERROR_FAILURE;
+
+ return NS_OK;
+}
+
+void
+nsThread::WaitUntilReadyToStartMain()
+{
+ PR_Lock(mStartLock);
+ PR_Unlock(mStartLock);
+ PR_DestroyLock(mStartLock);
+ mStartLock = nsnull;
+}
+
+NS_COM nsresult
+nsIThread::GetCurrent(nsIThread* *result)
+{
+ return GetIThread(PR_GetCurrentThread(), result);
+}
+
+NS_COM nsresult
+nsIThread::GetIThread(PRThread* prthread, nsIThread* *result)
+{
+ PRStatus status;
+ nsThread* thread;
+
+ if (nsThread::kIThreadSelfIndex == 0) {
+ status = PR_NewThreadPrivateIndex(&nsThread::kIThreadSelfIndex, nsThread::Exit);
+ if (status != PR_SUCCESS) return NS_ERROR_FAILURE;
+ }
+
+ thread = (nsThread*)PR_GetThreadPrivate(nsThread::kIThreadSelfIndex);
+ if (thread == nsnull) {
+ // if the current thread doesn't have an nsIThread associated
+ // with it, make one
+ thread = new nsThread();
+ if (thread == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(thread); // released by Exit
+ thread->SetPRThread(prthread);
+ nsresult rv = thread->RegisterThreadSelf();
+ if (NS_FAILED(rv)) return rv;
+ }
+ NS_ADDREF(thread);
+ *result = thread;
+ return NS_OK;
+}
+
+NS_COM nsresult
+nsIThread::SetMainThread()
+{
+ // strictly speaking, it could be set twice. but practically speaking,
+ // it's almost certainly an error if it is
+ if (gMainThread != 0) {
+ NS_ERROR("Setting main thread twice?");
+ return NS_ERROR_FAILURE;
+ }
+ return GetCurrent(&gMainThread);
+}
+
+NS_COM nsresult
+nsIThread::GetMainThread(nsIThread **result)
+{
+ NS_ASSERTION(result, "bad result pointer");
+ if (gMainThread == 0)
+ return NS_ERROR_FAILURE;
+ *result = gMainThread;
+ NS_ADDREF(gMainThread);
+ return NS_OK;
+}
+
+NS_COM PRBool
+nsIThread::IsMainThread()
+{
+ if (gMainThread == 0)
+ return PR_TRUE;
+
+ PRThread *theMainThread;
+ gMainThread->GetPRThread(&theMainThread);
+ return theMainThread == PR_GetCurrentThread();
+}
+
+void
+nsThread::Shutdown()
+{
+ if (gMainThread) {
+ // XXX nspr doesn't seem to be calling the main thread's destructor
+ // callback, so let's help it out:
+ nsThread::Exit(NS_STATIC_CAST(nsThread*, gMainThread));
+ nsrefcnt cnt;
+ NS_RELEASE2(gMainThread, cnt);
+ NS_WARN_IF_FALSE(cnt == 0, "Main thread being held past XPCOM shutdown.");
+ gMainThread = nsnull;
+
+ kIThreadSelfIndex = 0;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsThread.h b/src/libs/xpcom18a4/xpcom/threads/nsThread.h
new file mode 100644
index 00000000..e75086a7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsThread.h
@@ -0,0 +1,92 @@
+/* -*- 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 *****
+ * 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
+ */
+
+#ifndef nsThread_h__
+#define nsThread_h__
+
+#include "nsIRunnable.h"
+#include "nsIThread.h"
+#include "nsCOMPtr.h"
+
+class nsThread : public nsIThread
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ // nsIThread methods:
+ NS_DECL_NSITHREAD
+
+ // nsThread methods:
+ nsThread();
+
+ nsresult RegisterThreadSelf();
+ void SetPRThread(PRThread* thread) { mThread = thread; }
+ void WaitUntilReadyToStartMain();
+
+ static void PR_CALLBACK Main(void* arg);
+ static void PR_CALLBACK Exit(void* arg);
+ static void PR_CALLBACK Shutdown();
+
+ static PRUintn kIThreadSelfIndex;
+
+ static NS_METHOD
+ Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+private:
+ ~nsThread();
+
+protected:
+ PRThread* mThread;
+ nsCOMPtr<nsIRunnable> mRunnable;
+ PRBool mDead;
+ PRLock* mStartLock;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#endif // nsThread_h__
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsTimerImpl.cpp b/src/libs/xpcom18a4/xpcom/threads/nsTimerImpl.cpp
new file mode 100644
index 00000000..dc19452f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsTimerImpl.cpp
@@ -0,0 +1,642 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * ***** 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
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Stuart Parmenter <pavlov@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 "nsTimerImpl.h"
+#include "TimerThread.h"
+#include "nsAutoLock.h"
+
+#include "nsVoidArray.h"
+
+#include "nsIEventQueue.h"
+
+#include "prmem.h"
+
+static PRInt32 gGenerator = 0;
+static TimerThread* gThread = nsnull;
+static PRBool gFireOnIdle = PR_FALSE;
+static nsTimerManager* gManager = nsnull;
+
+#ifdef DEBUG_TIMERS
+#include <math.h>
+
+double nsTimerImpl::sDeltaSumSquared = 0;
+double nsTimerImpl::sDeltaSum = 0;
+double nsTimerImpl::sDeltaNum = 0;
+
+static void
+myNS_MeanAndStdDev(double n, double sumOfValues, double sumOfSquaredValues,
+ double *meanResult, double *stdDevResult)
+{
+ double mean = 0.0, var = 0.0, stdDev = 0.0;
+ if (n > 0.0 && sumOfValues >= 0) {
+ mean = sumOfValues / n;
+ double temp = (n * sumOfSquaredValues) - (sumOfValues * sumOfValues);
+ if (temp < 0.0 || n <= 1)
+ var = 0.0;
+ else
+ var = temp / (n * (n - 1));
+ // for some reason, Windows says sqrt(0.0) is "-1.#J" (?!) so do this:
+ stdDev = var != 0.0 ? sqrt(var) : 0.0;
+ }
+ *meanResult = mean;
+ *stdDevResult = stdDev;
+}
+#endif
+
+NS_IMPL_THREADSAFE_QUERY_INTERFACE2(nsTimerImpl, nsITimer, nsITimerInternal)
+NS_IMPL_THREADSAFE_ADDREF(nsTimerImpl)
+
+NS_IMETHODIMP_(nsrefcnt) nsTimerImpl::Release(void)
+{
+ nsrefcnt count;
+
+ NS_PRECONDITION(0 != mRefCnt, "dup release");
+ count = PR_AtomicDecrement((PRInt32 *)&mRefCnt);
+ NS_LOG_RELEASE(this, count, "nsTimerImpl");
+ if (count == 0) {
+ mRefCnt = 1; /* stabilize */
+
+ /* enable this to find non-threadsafe destructors: */
+ /* NS_ASSERT_OWNINGTHREAD(nsTimerImpl); */
+ NS_DELETEXPCOM(this);
+ return 0;
+ }
+
+ // If only one reference remains, and mArmed is set, then the ref must be
+ // from the TimerThread::mTimers array, so we Cancel this timer to remove
+ // the mTimers element, and return 0 if Cancel in fact disarmed the timer.
+ //
+ // We use an inlined version of nsTimerImpl::Cancel here to check for the
+ // NS_ERROR_NOT_AVAILABLE code returned by gThread->RemoveTimer when this
+ // timer is not found in the mTimers array -- i.e., when the timer was not
+ // in fact armed once we acquired TimerThread::mLock, in spite of mArmed
+ // being true here. That can happen if the armed timer is being fired by
+ // TimerThread::Run as we race and test mArmed just before it is cleared by
+ // the timer thread. If the RemoveTimer call below doesn't find this timer
+ // in the mTimers array, then the last ref to this timer is held manually
+ // and temporarily by the TimerThread, so we should fall through to the
+ // final return and return 1, not 0.
+ //
+ // The original version of this thread-based timer code kept weak refs from
+ // TimerThread::mTimers, removing this timer's weak ref in the destructor,
+ // but that leads to double-destructions in the race described above, and
+ // adding mArmed doesn't help, because destructors can't be deferred, once
+ // begun. But by combining reference-counting and a specialized Release
+ // method with "is this timer still in the mTimers array once we acquire
+ // the TimerThread's lock" testing, we defer destruction until we're sure
+ // that only one thread has its hot little hands on this timer.
+ //
+ // Note that both approaches preclude a timer creator, and everyone else
+ // except the TimerThread who might have a strong ref, from dropping all
+ // their strong refs without implicitly canceling the timer. Timers need
+ // non-mTimers-element strong refs to stay alive.
+
+ if (count == 1 && mArmed) {
+ mCanceled = PR_TRUE;
+
+ if (NS_SUCCEEDED(gThread->RemoveTimer(this)))
+ return 0;
+ }
+
+ return count;
+}
+
+nsTimerImpl::nsTimerImpl() :
+ mClosure(nsnull),
+ mCallbackType(CALLBACK_TYPE_UNKNOWN),
+ mIdle(PR_TRUE),
+ mFiring(PR_FALSE),
+ mArmed(PR_FALSE),
+ mCanceled(PR_FALSE),
+ mGeneration(0),
+ mDelay(0),
+ mTimeout(0)
+{
+ // XXXbsmedberg: shouldn't this be in Init()?
+ nsIThread::GetCurrent(getter_AddRefs(mCallingThread));
+
+ mCallback.c = nsnull;
+
+#ifdef DEBUG_TIMERS
+ mStart = 0;
+ mStart2 = 0;
+#endif
+}
+
+nsTimerImpl::~nsTimerImpl()
+{
+ ReleaseCallback();
+}
+
+//static
+nsresult
+nsTimerImpl::Startup()
+{
+ nsresult rv;
+
+ gThread = new TimerThread();
+ if (!gThread) return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(gThread);
+ rv = gThread->InitLocks();
+
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(gThread);
+ }
+
+ return rv;
+}
+
+void nsTimerImpl::Shutdown()
+{
+#ifdef DEBUG_TIMERS
+ if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
+ double mean = 0, stddev = 0;
+ myNS_MeanAndStdDev(sDeltaNum, sDeltaSum, sDeltaSumSquared, &mean, &stddev);
+
+ PR_LOG(gTimerLog, PR_LOG_DEBUG, ("sDeltaNum = %f, sDeltaSum = %f, sDeltaSumSquared = %f\n", sDeltaNum, sDeltaSum, sDeltaSumSquared));
+ PR_LOG(gTimerLog, PR_LOG_DEBUG, ("mean: %fms, stddev: %fms\n", mean, stddev));
+ }
+#endif
+
+ if (!gThread)
+ return;
+
+ gThread->Shutdown();
+ NS_RELEASE(gThread);
+
+ gFireOnIdle = PR_FALSE;
+}
+
+
+nsresult nsTimerImpl::InitCommon(PRUint32 aType, PRUint32 aDelay)
+{
+ nsresult rv;
+
+ NS_ENSURE_TRUE(gThread, NS_ERROR_NOT_INITIALIZED);
+
+ rv = gThread->Init();
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ /**
+ * In case of re-Init, both with and without a preceding Cancel, clear the
+ * mCanceled flag and assign a new mGeneration. But first, remove any armed
+ * timer from the timer thread's list.
+ *
+ * If we are racing with the timer thread to remove this timer and we lose,
+ * the RemoveTimer call made here will fail to find this timer in the timer
+ * thread's list, and will return false harmlessly. We test mArmed here to
+ * avoid the small overhead in RemoveTimer of locking the timer thread and
+ * checking its list for this timer. It's safe to test mArmed even though
+ * it might be cleared on another thread in the next cycle (or even already
+ * be cleared by another CPU whose store hasn't reached our CPU's cache),
+ * because RemoveTimer is idempotent.
+ */
+ if (mArmed)
+ gThread->RemoveTimer(this);
+ mCanceled = PR_FALSE;
+ mGeneration = PR_AtomicIncrement(&gGenerator);
+
+ mType = (PRUint8)aType;
+ SetDelayInternal(aDelay);
+
+ return gThread->AddTimer(this);
+}
+
+NS_IMETHODIMP nsTimerImpl::InitWithFuncCallback(nsTimerCallbackFunc aFunc,
+ void *aClosure,
+ PRUint32 aDelay,
+ PRUint32 aType)
+{
+ ReleaseCallback();
+ mCallbackType = CALLBACK_TYPE_FUNC;
+ mCallback.c = aFunc;
+ mClosure = aClosure;
+
+ return InitCommon(aType, aDelay);
+}
+
+NS_IMETHODIMP nsTimerImpl::InitWithCallback(nsITimerCallback *aCallback,
+ PRUint32 aDelay,
+ PRUint32 aType)
+{
+ ReleaseCallback();
+ mCallbackType = CALLBACK_TYPE_INTERFACE;
+ mCallback.i = aCallback;
+ NS_ADDREF(mCallback.i);
+
+ return InitCommon(aType, aDelay);
+}
+
+NS_IMETHODIMP nsTimerImpl::Init(nsIObserver *aObserver,
+ PRUint32 aDelay,
+ PRUint32 aType)
+{
+ ReleaseCallback();
+ mCallbackType = CALLBACK_TYPE_OBSERVER;
+ mCallback.o = aObserver;
+ NS_ADDREF(mCallback.o);
+
+ return InitCommon(aType, aDelay);
+}
+
+NS_IMETHODIMP nsTimerImpl::Cancel()
+{
+ mCanceled = PR_TRUE;
+
+ if (gThread)
+ gThread->RemoveTimer(this);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsTimerImpl::SetDelay(PRUint32 aDelay)
+{
+ // If we're already repeating precisely, update mTimeout now so that the
+ // new delay takes effect in the future.
+ if (mTimeout != 0 && mType == TYPE_REPEATING_PRECISE)
+ mTimeout = PR_IntervalNow();
+
+ SetDelayInternal(aDelay);
+
+ if (!mFiring && gThread)
+ gThread->TimerDelayChanged(this);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsTimerImpl::GetDelay(PRUint32* aDelay)
+{
+ *aDelay = mDelay;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsTimerImpl::SetType(PRUint32 aType)
+{
+ mType = (PRUint8)aType;
+ // XXX if this is called, we should change the actual type.. this could effect
+ // repeating timers. we need to ensure in Fire() that if mType has changed
+ // during the callback that we don't end up with the timer in the queue twice.
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsTimerImpl::GetType(PRUint32* aType)
+{
+ *aType = mType;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP nsTimerImpl::GetClosure(void** aClosure)
+{
+ *aClosure = mClosure;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP nsTimerImpl::GetIdle(PRBool *aIdle)
+{
+ *aIdle = mIdle;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsTimerImpl::SetIdle(PRBool aIdle)
+{
+ mIdle = aIdle;
+ return NS_OK;
+}
+
+void nsTimerImpl::Fire()
+{
+ if (mCanceled)
+ return;
+
+ PRIntervalTime now = PR_IntervalNow();
+#ifdef DEBUG_TIMERS
+ if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
+ PRIntervalTime a = now - mStart; // actual delay in intervals
+ PRUint32 b = PR_MillisecondsToInterval(mDelay); // expected delay in intervals
+ PRUint32 d = PR_IntervalToMilliseconds((a > b) ? a - b : b - a); // delta in ms
+ sDeltaSum += d;
+ sDeltaSumSquared += double(d) * double(d);
+ sDeltaNum++;
+
+ PR_LOG(gTimerLog, PR_LOG_DEBUG, ("[this=%p] expected delay time %4dms\n", this, mDelay));
+ PR_LOG(gTimerLog, PR_LOG_DEBUG, ("[this=%p] actual delay time %4dms\n", this, PR_IntervalToMilliseconds(a)));
+ PR_LOG(gTimerLog, PR_LOG_DEBUG, ("[this=%p] (mType is %d) -------\n", this, mType));
+ PR_LOG(gTimerLog, PR_LOG_DEBUG, ("[this=%p] delta %4dms\n", this, (a > b) ? (PRInt32)d : -(PRInt32)d));
+
+ mStart = mStart2;
+ mStart2 = 0;
+ }
+#endif
+
+ PRIntervalTime timeout = mTimeout;
+ if (mType == TYPE_REPEATING_PRECISE) {
+ // Precise repeating timers advance mTimeout by mDelay without fail before
+ // calling Fire().
+ timeout -= PR_MillisecondsToInterval(mDelay);
+ }
+ gThread->UpdateFilter(mDelay, timeout, now);
+
+ mFiring = PR_TRUE;
+
+ switch (mCallbackType) {
+ case CALLBACK_TYPE_FUNC:
+ mCallback.c(this, mClosure);
+ break;
+ case CALLBACK_TYPE_INTERFACE:
+ mCallback.i->Notify(this);
+ break;
+ case CALLBACK_TYPE_OBSERVER:
+ mCallback.o->Observe(NS_STATIC_CAST(nsITimer*,this),
+ NS_TIMER_CALLBACK_TOPIC,
+ nsnull);
+ break;
+ default:;
+ }
+
+ mFiring = PR_FALSE;
+
+#ifdef DEBUG_TIMERS
+ if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
+ PR_LOG(gTimerLog, PR_LOG_DEBUG,
+ ("[this=%p] Took %dms to fire timer callback\n",
+ this, PR_IntervalToMilliseconds(PR_IntervalNow() - now)));
+ }
+#endif
+
+ if (mType == TYPE_REPEATING_SLACK) {
+ SetDelayInternal(mDelay); // force mTimeout to be recomputed.
+ if (gThread)
+ gThread->AddTimer(this);
+ }
+}
+
+
+struct TimerEventType : public PLEvent {
+ PRInt32 mGeneration;
+#ifdef DEBUG_TIMERS
+ PRIntervalTime mInitTime;
+#endif
+};
+
+
+void* handleTimerEvent(TimerEventType* event)
+{
+ nsTimerImpl* timer = NS_STATIC_CAST(nsTimerImpl*, event->owner);
+ if (event->mGeneration != timer->GetGeneration())
+ return nsnull;
+
+#ifdef DEBUG_TIMERS
+ if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
+ PRIntervalTime now = PR_IntervalNow();
+ PR_LOG(gTimerLog, PR_LOG_DEBUG,
+ ("[this=%p] time between PostTimerEvent() and Fire(): %dms\n",
+ event->owner, PR_IntervalToMilliseconds(now - event->mInitTime)));
+ }
+#endif
+
+ if (gFireOnIdle) {
+ PRBool idle = PR_FALSE;
+ timer->GetIdle(&idle);
+ if (idle) {
+ NS_ASSERTION(gManager, "Global Thread Manager is null!");
+ if (gManager)
+ gManager->AddIdleTimer(timer);
+ return nsnull;
+ }
+ }
+
+ timer->Fire();
+
+ return nsnull;
+}
+
+void destroyTimerEvent(TimerEventType* event)
+{
+ nsTimerImpl *timer = NS_STATIC_CAST(nsTimerImpl*, event->owner);
+ NS_RELEASE(timer);
+ PR_DELETE(event);
+}
+
+
+void nsTimerImpl::PostTimerEvent()
+{
+ // XXX we may want to reuse the PLEvent in the case of repeating timers.
+ TimerEventType* event;
+
+ // construct
+ event = PR_NEW(TimerEventType);
+ if (!event)
+ return;
+
+ // initialize
+ PL_InitEvent((PLEvent*)event, this,
+ (PLHandleEventProc)handleTimerEvent,
+ (PLDestroyEventProc)destroyTimerEvent);
+
+ // Since TimerThread addref'd 'this' for us, we don't need to addref here.
+ // We will release in destroyMyEvent. We do need to copy the generation
+ // number from this timer into the event, so we can avoid firing a timer
+ // that was re-initialized after being canceled.
+ event->mGeneration = mGeneration;
+
+#ifdef DEBUG_TIMERS
+ if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
+ event->mInitTime = PR_IntervalNow();
+ }
+#endif
+
+ // If this is a repeating precise timer, we need to calculate the time for
+ // the next timer to fire before we make the callback.
+ if (mType == TYPE_REPEATING_PRECISE) {
+ SetDelayInternal(mDelay);
+ if (gThread)
+ gThread->AddTimer(this);
+ }
+
+ PRThread *thread;
+ nsresult rv = mCallingThread->GetPRThread(&thread);
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Dropping timer event because thread is dead");
+ return;
+ }
+
+ nsCOMPtr<nsIEventQueue> queue;
+ if (gThread)
+ gThread->mEventQueueService->GetThreadEventQueue(thread, getter_AddRefs(queue));
+ if (queue)
+ queue->PostEvent(event);
+}
+
+void nsTimerImpl::SetDelayInternal(PRUint32 aDelay)
+{
+ PRIntervalTime delayInterval = PR_MillisecondsToInterval(aDelay);
+ if (delayInterval > DELAY_INTERVAL_MAX) {
+ delayInterval = DELAY_INTERVAL_MAX;
+ aDelay = PR_IntervalToMilliseconds(delayInterval);
+ }
+
+ mDelay = aDelay;
+
+ PRIntervalTime now = PR_IntervalNow();
+ if (mTimeout == 0 || mType != TYPE_REPEATING_PRECISE)
+ mTimeout = now;
+
+ mTimeout += delayInterval;
+
+#ifdef DEBUG_TIMERS
+ if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
+ if (mStart == 0)
+ mStart = now;
+ else
+ mStart2 = now;
+ }
+#endif
+}
+
+/**
+ * Timer Manager code
+ */
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsTimerManager, nsITimerManager)
+
+nsTimerManager::nsTimerManager()
+{
+ mLock = PR_NewLock();
+ gManager = this;
+}
+
+nsTimerManager::~nsTimerManager()
+{
+ gManager = nsnull;
+ PR_DestroyLock(mLock);
+
+ nsTimerImpl *theTimer;
+ PRInt32 count = mIdleTimers.Count();
+
+ for (PRInt32 i = 0; i < count; i++) {
+ theTimer = NS_STATIC_CAST(nsTimerImpl*, mIdleTimers[i]);
+ NS_IF_RELEASE(theTimer);
+ }
+}
+
+NS_IMETHODIMP nsTimerManager::SetUseIdleTimers(PRBool aUseIdleTimers)
+{
+ if (aUseIdleTimers == PR_FALSE && gFireOnIdle == PR_TRUE)
+ return NS_ERROR_FAILURE;
+
+ gFireOnIdle = aUseIdleTimers;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsTimerManager::GetUseIdleTimers(PRBool *aUseIdleTimers)
+{
+ *aUseIdleTimers = gFireOnIdle;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsTimerManager::HasIdleTimers(PRBool *aHasTimers)
+{
+ nsAutoLock lock (mLock);
+ PRUint32 count = mIdleTimers.Count();
+ *aHasTimers = (count != 0);
+ return NS_OK;
+}
+
+nsresult nsTimerManager::AddIdleTimer(nsITimer* timer)
+{
+ if (!timer)
+ return NS_ERROR_FAILURE;
+ nsAutoLock lock(mLock);
+ mIdleTimers.AppendElement(timer);
+ NS_ADDREF(timer);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsTimerManager::FireNextIdleTimer()
+{
+ if (!gFireOnIdle || !nsIThread::IsMainThread()) {
+ return NS_OK;
+ }
+
+ nsTimerImpl *theTimer = nsnull;
+
+ {
+ nsAutoLock lock (mLock);
+ PRUint32 count = mIdleTimers.Count();
+
+ if (count == 0)
+ return NS_OK;
+
+ theTimer = NS_STATIC_CAST(nsTimerImpl*, mIdleTimers[0]);
+ mIdleTimers.RemoveElement(theTimer);
+ }
+
+ theTimer->Fire();
+
+ NS_RELEASE(theTimer);
+
+ return NS_OK;
+}
+
+
+// NOT FOR PUBLIC CONSUMPTION!
+nsresult
+NS_NewTimer(nsITimer* *aResult, nsTimerCallbackFunc aCallback, void *aClosure,
+ PRUint32 aDelay, PRUint32 aType)
+{
+ nsTimerImpl* timer = new nsTimerImpl();
+ if (timer == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(timer);
+
+ nsresult rv = timer->InitWithFuncCallback(aCallback, aClosure,
+ aDelay, aType);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(timer);
+ return rv;
+ }
+
+ *aResult = timer;
+ return NS_OK;
+}
diff --git a/src/libs/xpcom18a4/xpcom/threads/nsTimerImpl.h b/src/libs/xpcom18a4/xpcom/threads/nsTimerImpl.h
new file mode 100644
index 00000000..98596f4e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/nsTimerImpl.h
@@ -0,0 +1,195 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * ***** 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
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Stuart Parmenter <pavlov@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 nsTimerImpl_h___
+#define nsTimerImpl_h___
+
+//#define FORCE_PR_LOG /* Allow logging in the release build */
+
+#include "nsITimer.h"
+#include "nsVoidArray.h"
+#include "nsIThread.h"
+#include "nsITimerInternal.h"
+#include "nsIObserver.h"
+
+#include "nsCOMPtr.h"
+
+#include "prlog.h"
+
+#if defined(PR_LOGGING)
+static PRLogModuleInfo *gTimerLog = PR_NewLogModule("nsTimerImpl");
+#define DEBUG_TIMERS 1
+#else
+#undef DEBUG_TIMERS
+#endif
+
+#define NS_TIMER_CLASSNAME "Timer"
+#define NS_TIMER_CID \
+{ /* 5ff24248-1dd2-11b2-8427-fbab44f29bc8 */ \
+ 0x5ff24248, \
+ 0x1dd2, \
+ 0x11b2, \
+ {0x84, 0x27, 0xfb, 0xab, 0x44, 0xf2, 0x9b, 0xc8} \
+}
+
+enum {
+ CALLBACK_TYPE_UNKNOWN = 0,
+ CALLBACK_TYPE_INTERFACE = 1,
+ CALLBACK_TYPE_FUNC = 2,
+ CALLBACK_TYPE_OBSERVER = 3
+};
+
+// Two timer deadlines must differ by less than half the PRIntervalTime domain.
+#define DELAY_INTERVAL_LIMIT PR_BIT(8 * sizeof(PRIntervalTime) - 1)
+
+// Maximum possible delay (XXX rework to use ms rather than interval ticks).
+#define DELAY_INTERVAL_MAX (DELAY_INTERVAL_LIMIT - 1)
+
+// Is interval-time t less than u, even if t has wrapped PRIntervalTime?
+#define TIMER_LESS_THAN(t, u) ((t) - (u) > DELAY_INTERVAL_LIMIT)
+
+class nsTimerImpl : public nsITimer, public nsITimerInternal
+{
+public:
+
+ nsTimerImpl();
+
+ static NS_HIDDEN_(nsresult) Startup();
+ static NS_HIDDEN_(void) Shutdown();
+
+ friend class TimerThread;
+
+ void Fire();
+ void PostTimerEvent();
+ void SetDelayInternal(PRUint32 aDelay);
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSITIMER
+ NS_DECL_NSITIMERINTERNAL
+
+ PRInt32 GetGeneration() { return mGeneration; }
+
+private:
+ ~nsTimerImpl();
+
+ nsresult InitCommon(PRUint32 aType, PRUint32 aDelay);
+
+ void ReleaseCallback()
+ {
+ if (mCallbackType == CALLBACK_TYPE_INTERFACE)
+ NS_RELEASE(mCallback.i);
+ else if (mCallbackType == CALLBACK_TYPE_OBSERVER)
+ NS_RELEASE(mCallback.o);
+ }
+
+ nsCOMPtr<nsIThread> mCallingThread;
+
+ void * mClosure;
+
+ union {
+ nsTimerCallbackFunc c;
+ nsITimerCallback * i;
+ nsIObserver * o;
+ } mCallback;
+
+ // These members are set by Init (called from NS_NewTimer) and never reset.
+ PRUint8 mCallbackType;
+ PRPackedBool mIdle;
+
+ // These members are set by the initiating thread, when the timer's type is
+ // changed and during the period where it fires on that thread.
+ PRUint8 mType;
+ PRPackedBool mFiring;
+
+
+ // Use a PRBool (int) here to isolate loads and stores of these two members
+ // done on various threads under the protection of TimerThread::mLock, from
+ // loads and stores done on the initiating/type-changing/timer-firing thread
+ // to the above PRUint8/PRPackedBool members.
+ PRBool mArmed;
+ PRBool mCanceled;
+
+ // The generation number of this timer, re-generated each time the timer is
+ // initialized so one-shot timers can be canceled and re-initialized by the
+ // arming thread without any bad race conditions.
+ PRInt32 mGeneration;
+
+ PRUint32 mDelay;
+ PRIntervalTime mTimeout;
+
+#ifdef DEBUG_TIMERS
+ PRIntervalTime mStart, mStart2;
+ static double sDeltaSum;
+ static double sDeltaSumSquared;
+ static double sDeltaNum;
+#endif
+
+};
+
+#define NS_TIMERMANAGER_CONTRACTID "@mozilla.org/timer/manager;1"
+#define NS_TIMERMANAGER_CLASSNAME "Timer Manager"
+#define NS_TIMERMANAGER_CID \
+{ /* 4fe206fa-1dd2-11b2-8a0a-88bacbecc7d2 */ \
+ 0x4fe206fa, \
+ 0x1dd2, \
+ 0x11b2, \
+ {0x8a, 0x0a, 0x88, 0xba, 0xcb, 0xec, 0xc7, 0xd2} \
+}
+
+#include "nsITimerManager.h"
+
+class nsTimerManager : nsITimerManager
+{
+public:
+ nsTimerManager();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSITIMERMANAGER
+
+ nsresult AddIdleTimer(nsITimer* timer);
+private:
+ ~nsTimerManager();
+
+ PRLock *mLock;
+ nsVoidArray mIdleTimers;
+};
+
+
+#endif /* nsTimerImpl_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/threads/plevent.c b/src/libs/xpcom18a4/xpcom/threads/plevent.c
new file mode 100644
index 00000000..c5e9040f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/plevent.c
@@ -0,0 +1,1774 @@
+/* -*- 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 ***** */
+
+#if defined(_WIN32)
+#include <windows.h>
+#endif
+
+#if defined(XP_OS2)
+#define INCL_DOS
+#define INCL_DOSERRORS
+#define INCL_WIN
+#include <os2.h>
+#define DefWindowProc WinDefWindowProc
+#endif /* XP_OS2 */
+
+#include "nspr.h"
+#include "plevent.h"
+
+#if !defined(WIN32)
+#include <errno.h>
+#include <stddef.h>
+#if !defined(XP_OS2)
+#include <unistd.h>
+#endif /* !XP_OS2 */
+#endif /* !Win32 */
+
+#if defined(XP_UNIX)
+/* for fcntl */
+#include <sys/types.h>
+#include <fcntl.h>
+#endif
+
+#if defined(XP_BEOS)
+#include <kernel/OS.h>
+#endif
+
+#if defined(XP_MACOSX)
+#if defined(MOZ_WIDGET_COCOA)
+#include <CoreFoundation/CoreFoundation.h>
+#define MAC_USE_CFRUNLOOPSOURCE
+#elif defined(TARGET_CARBON)
+/* #include <CarbonEvents.h> */
+/* #define MAC_USE_CARBON_EVENT */
+#include <CoreFoundation/CoreFoundation.h>
+#define MAC_USE_CFRUNLOOPSOURCE
+#endif
+#endif
+
+#include "private/pprthred.h"
+
+#if defined(VMS)
+/*
+** On OpenVMS, XtAppAddInput doesn't want a regular fd, instead it
+** wants an event flag. So, we don't create and use a pipe for
+** notification of when an event queue has something ready, instead
+** we use an event flag. Shouldn't be a problem if we only have
+** a few event queues.
+*/
+#include <lib$routines.h>
+#include <starlet.h>
+#include <stsdef.h>
+#endif /* VMS */
+
+#if defined(_WIN32)
+/* Comment out the following USE_TIMER define to prevent
+ * WIN32 from using a WIN32 native timer for PLEvent notification.
+ * With USE_TIMER defined we will use a timer when pending input
+ * or paint events are starved, otherwise it will use a posted
+ * WM_APP msg for PLEvent notification.
+ */
+#define USE_TIMER
+
+/* Threshold defined in milliseconds for determining when the input
+ * and paint events have been held in the WIN32 msg queue too long
+ */
+#define INPUT_STARVATION_LIMIT 50
+/* The paint starvation limit is set to the smallest value which
+ * does not cause performance degradation while running page load tests
+ */
+#define PAINT_STARVATION_LIMIT 750
+/* The WIN9X paint starvation limit is larger because it was
+ * determined that the following value was required to prevent performance
+ * degradation on page load tests for WIN98/95 only.
+ */
+#define WIN9X_PAINT_STARVATION_LIMIT 3000
+
+#define TIMER_ID 0
+/* If _md_PerformanceSetting <=0 then no event starvation otherwise events will be starved */
+static PRInt32 _md_PerformanceSetting = 0;
+static PRUint32 _md_StarvationDelay = 0;
+static PRUint32 _md_SwitchTime = 0;
+#endif
+
+static PRLogModuleInfo *event_lm = NULL;
+
+/*******************************************************************************
+ * Private Stuff
+ ******************************************************************************/
+
+/*
+** EventQueueType -- Defines notification type for an event queue
+**
+*/
+typedef enum {
+ EventQueueIsNative = 1,
+ EventQueueIsMonitored = 2
+} EventQueueType;
+
+
+struct PLEventQueue {
+ const char* name;
+ PRCList queue;
+ PRMonitor* monitor;
+ PRThread* handlerThread;
+ EventQueueType type;
+ PRPackedBool processingEvents;
+ PRPackedBool notified;
+#if defined(_WIN32)
+ PRPackedBool timerSet;
+#endif
+
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
+#if defined(VMS)
+ int efn;
+#else
+ PRInt32 eventPipe[2];
+#endif
+ PLGetEventIDFunc idFunc;
+ void* idFuncClosure;
+#elif defined(_WIN32) || defined(XP_OS2)
+ HWND eventReceiverWindow;
+ PRBool removeMsg;
+#elif defined(XP_BEOS)
+ port_id eventport;
+#elif defined(XP_MACOSX)
+#if defined(MAC_USE_CFRUNLOOPSOURCE)
+ CFRunLoopSourceRef mRunLoopSource;
+ CFRunLoopRef mMainRunLoop;
+ CFStringRef mRunLoopModeStr; /* vbox */
+#elif defined(MAC_USE_CARBON_EVENT)
+ EventHandlerUPP eventHandlerUPP;
+ EventHandlerRef eventHandlerRef;
+#endif
+#endif
+};
+
+#define PR_EVENT_PTR(_qp) \
+ ((PLEvent*) ((char*) (_qp) - offsetof(PLEvent, link)))
+
+static PRStatus _pl_SetupNativeNotifier(PLEventQueue* self);
+static void _pl_CleanupNativeNotifier(PLEventQueue* self);
+static PRStatus _pl_NativeNotify(PLEventQueue* self);
+static PRStatus _pl_AcknowledgeNativeNotify(PLEventQueue* self);
+static void _md_CreateEventQueue( PLEventQueue *eventQueue );
+static PRInt32 _pl_GetEventCount(PLEventQueue* self);
+
+
+#if defined(_WIN32) || defined(XP_OS2)
+#if defined(XP_OS2)
+ULONG _pr_PostEventMsgId;
+#else
+UINT _pr_PostEventMsgId;
+#endif /* OS2 */
+static char *_pr_eventWindowClass = "XPCOM:EventWindow";
+#endif /* Win32, OS2 */
+
+#if defined(_WIN32)
+
+static LPCTSTR _md_GetEventQueuePropName() {
+ static ATOM atom = 0;
+ if (!atom) {
+ atom = GlobalAddAtom("XPCOM_EventQueue");
+ }
+ return MAKEINTATOM(atom);
+}
+#endif
+
+#if defined(MAC_USE_CARBON_EVENT)
+enum {
+ kEventClassPL = FOUR_CHAR_CODE('PLEC'),
+
+ kEventProcessPLEvents = 1,
+
+ kEventParamPLEventQueue = FOUR_CHAR_CODE('OWNQ')
+};
+
+static pascal Boolean _md_CarbonEventComparator(EventRef inEvent, void *inCompareData);
+#endif
+
+/*******************************************************************************
+ * Event Queue Operations
+ ******************************************************************************/
+
+/*
+** _pl_CreateEventQueue() -- Create the event queue
+**
+**
+*/
+static PLEventQueue * _pl_CreateEventQueue(const char *name,
+ PRThread *handlerThread,
+ EventQueueType qtype)
+{
+ PRStatus err;
+ PLEventQueue* self = NULL;
+ PRMonitor* mon = NULL;
+
+ if (event_lm == NULL)
+ event_lm = PR_NewLogModule("event");
+
+ self = PR_NEWZAP(PLEventQueue);
+ if (self == NULL) return NULL;
+
+ mon = PR_NewNamedMonitor(name);
+ if (mon == NULL) goto error;
+
+ self->name = name;
+ self->monitor = mon;
+ self->handlerThread = handlerThread;
+ self->processingEvents = PR_FALSE;
+ self->type = qtype;
+#if defined(_WIN32)
+ self->timerSet = PR_FALSE;
+#endif
+#if defined(_WIN32) || defined(XP_OS2)
+ self->removeMsg = PR_TRUE;
+#endif
+
+ self->notified = PR_FALSE;
+
+ PR_INIT_CLIST(&self->queue);
+ if ( qtype == EventQueueIsNative ) {
+ err = _pl_SetupNativeNotifier(self);
+ if (err) goto error;
+ _md_CreateEventQueue( self );
+ }
+ return self;
+
+ error:
+ if (mon != NULL)
+ PR_DestroyMonitor(mon);
+ PR_DELETE(self);
+ return NULL;
+}
+
+PR_IMPLEMENT(PLEventQueue*)
+PL_CreateEventQueue(const char* name, PRThread* handlerThread)
+{
+ return( _pl_CreateEventQueue( name, handlerThread, EventQueueIsNative ));
+}
+
+PR_EXTERN(PLEventQueue *)
+PL_CreateNativeEventQueue(const char *name, PRThread *handlerThread)
+{
+ return( _pl_CreateEventQueue( name, handlerThread, EventQueueIsNative ));
+}
+
+PR_EXTERN(PLEventQueue *)
+PL_CreateMonitoredEventQueue(const char *name, PRThread *handlerThread)
+{
+ return( _pl_CreateEventQueue( name, handlerThread, EventQueueIsMonitored ));
+}
+
+PR_IMPLEMENT(PRMonitor*)
+PL_GetEventQueueMonitor(PLEventQueue* self)
+{
+ return self->monitor;
+}
+
+static void PR_CALLBACK
+_pl_destroyEvent(PLEvent* event, void* data, PLEventQueue* queue)
+{
+ PL_DequeueEvent(event, queue);
+ PL_DestroyEvent(event);
+}
+
+PR_IMPLEMENT(void)
+PL_DestroyEventQueue(PLEventQueue* self)
+{
+ PR_EnterMonitor(self->monitor);
+
+ /* destroy undelivered events */
+ PL_MapEvents(self, _pl_destroyEvent, NULL);
+
+ if ( self->type == EventQueueIsNative )
+ _pl_CleanupNativeNotifier(self);
+
+ /* destroying the monitor also destroys the name */
+ PR_ExitMonitor(self->monitor);
+ PR_DestroyMonitor(self->monitor);
+ PR_DELETE(self);
+
+}
+
+PR_IMPLEMENT(PRStatus)
+PL_PostEvent(PLEventQueue* self, PLEvent* event)
+{
+ PRStatus err = PR_SUCCESS;
+ PRMonitor* mon;
+
+ if (self == NULL)
+ return PR_FAILURE;
+
+ mon = self->monitor;
+ PR_EnterMonitor(mon);
+
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
+ if (self->idFunc && event)
+ event->id = self->idFunc(self->idFuncClosure);
+#endif
+
+ /* insert event into thread's event queue: */
+ if (event != NULL) {
+ PR_APPEND_LINK(&event->link, &self->queue);
+ }
+
+ if (self->type == EventQueueIsNative && !self->notified) {
+ err = _pl_NativeNotify(self);
+
+ if (err != PR_SUCCESS)
+ goto error;
+
+ self->notified = PR_TRUE;
+ }
+
+ /*
+ * This may fall on deaf ears if we're really notifying the native
+ * thread, and no one has called PL_WaitForEvent (or PL_EventLoop):
+ */
+ err = PR_Notify(mon);
+
+error:
+ PR_ExitMonitor(mon);
+ return err;
+}
+
+PR_IMPLEMENT(void*)
+PL_PostSynchronousEvent(PLEventQueue* self, PLEvent* event)
+{
+ void* result;
+
+ if (self == NULL)
+ return NULL;
+
+ PR_ASSERT(event != NULL);
+
+ if (PR_GetCurrentThread() == self->handlerThread) {
+ /* Handle the case where the thread requesting the event handling
+ * is also the thread that's supposed to do the handling. */
+ result = event->handler(event);
+ }
+ else {
+ int i, entryCount;
+
+ event->lock = PR_NewLock();
+ if (!event->lock) {
+ return NULL;
+ }
+ event->condVar = PR_NewCondVar(event->lock);
+ if(!event->condVar) {
+ PR_DestroyLock(event->lock);
+ event->lock = NULL;
+ return NULL;
+ }
+
+ PR_Lock(event->lock);
+
+ entryCount = PR_GetMonitorEntryCount(self->monitor);
+
+ event->synchronousResult = (void*)PR_TRUE;
+
+ PL_PostEvent(self, event);
+
+ /* We need temporarily to give up our event queue monitor if
+ we're holding it, otherwise, the thread we're going to wait
+ for notification from won't be able to enter it to process
+ the event. */
+ if (entryCount) {
+ for (i = 0; i < entryCount; i++)
+ PR_ExitMonitor(self->monitor);
+ }
+
+ event->handled = PR_FALSE;
+
+ while (!event->handled) {
+ /* wait for event to be handled or destroyed */
+ PR_WaitCondVar(event->condVar, PR_INTERVAL_NO_TIMEOUT);
+ }
+
+ if (entryCount) {
+ for (i = 0; i < entryCount; i++)
+ PR_EnterMonitor(self->monitor);
+ }
+
+ result = event->synchronousResult;
+ event->synchronousResult = NULL;
+ PR_Unlock(event->lock);
+ }
+
+ /* For synchronous events, they're destroyed here on the caller's
+ thread before the result is returned. See PL_HandleEvent. */
+ PL_DestroyEvent(event);
+
+ return result;
+}
+
+PR_IMPLEMENT(PLEvent*)
+PL_GetEvent(PLEventQueue* self)
+{
+ PLEvent* event = NULL;
+ PRStatus err = PR_SUCCESS;
+
+ if (self == NULL)
+ return NULL;
+
+ PR_EnterMonitor(self->monitor);
+
+ if (!PR_CLIST_IS_EMPTY(&self->queue)) {
+ if ( self->type == EventQueueIsNative &&
+ self->notified &&
+ !self->processingEvents &&
+ 0 == _pl_GetEventCount(self) )
+ {
+ err = _pl_AcknowledgeNativeNotify(self);
+ self->notified = PR_FALSE;
+ }
+ if (err)
+ goto done;
+
+ /* then grab the event and return it: */
+ event = PR_EVENT_PTR(self->queue.next);
+ PR_REMOVE_AND_INIT_LINK(&event->link);
+ }
+
+ done:
+ PR_ExitMonitor(self->monitor);
+ return event;
+}
+
+PR_IMPLEMENT(PRBool)
+PL_EventAvailable(PLEventQueue* self)
+{
+ PRBool result = PR_FALSE;
+
+ if (self == NULL)
+ return PR_FALSE;
+
+ PR_EnterMonitor(self->monitor);
+
+ if (!PR_CLIST_IS_EMPTY(&self->queue))
+ result = PR_TRUE;
+
+ PR_ExitMonitor(self->monitor);
+ return result;
+}
+
+PR_IMPLEMENT(void)
+PL_MapEvents(PLEventQueue* self, PLEventFunProc fun, void* data)
+{
+ PRCList* qp;
+
+ if (self == NULL)
+ return;
+
+ PR_EnterMonitor(self->monitor);
+ qp = self->queue.next;
+ while (qp != &self->queue) {
+ PLEvent* event = PR_EVENT_PTR(qp);
+ qp = qp->next;
+ (*fun)(event, data, self);
+ }
+ PR_ExitMonitor(self->monitor);
+}
+
+static void PR_CALLBACK
+_pl_DestroyEventForOwner(PLEvent* event, void* owner, PLEventQueue* queue)
+{
+ PR_ASSERT(PR_GetMonitorEntryCount(queue->monitor) > 0);
+ if (event->owner == owner) {
+ PR_LOG(event_lm, PR_LOG_DEBUG,
+ ("$$$ \tdestroying event %0x for owner %0x", event, owner));
+ PL_DequeueEvent(event, queue);
+
+ if (event->synchronousResult == (void*)PR_TRUE) {
+ PR_Lock(event->lock);
+ event->synchronousResult = NULL;
+ event->handled = PR_TRUE;
+ PR_NotifyCondVar(event->condVar);
+ PR_Unlock(event->lock);
+ }
+ else {
+ PL_DestroyEvent(event);
+ }
+ }
+ else {
+ PR_LOG(event_lm, PR_LOG_DEBUG,
+ ("$$$ \tskipping event %0x for owner %0x", event, owner));
+ }
+}
+
+PR_IMPLEMENT(void)
+PL_RevokeEvents(PLEventQueue* self, void* owner)
+{
+ if (self == NULL)
+ return;
+
+ PR_LOG(event_lm, PR_LOG_DEBUG,
+ ("$$$ revoking events for owner %0x", owner));
+
+ /*
+ ** First we enter the monitor so that no one else can post any events
+ ** to the queue:
+ */
+ PR_EnterMonitor(self->monitor);
+ PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ owner %0x, entered monitor", owner));
+
+ /*
+ ** Discard any pending events for this owner:
+ */
+ PL_MapEvents(self, _pl_DestroyEventForOwner, owner);
+
+#ifdef DEBUG
+ {
+ PRCList* qp = self->queue.next;
+ while (qp != &self->queue) {
+ PLEvent* event = PR_EVENT_PTR(qp);
+ qp = qp->next;
+ PR_ASSERT(event->owner != owner);
+ }
+ }
+#endif /* DEBUG */
+
+ PR_ExitMonitor(self->monitor);
+
+ PR_LOG(event_lm, PR_LOG_DEBUG,
+ ("$$$ revoking events for owner %0x", owner));
+}
+
+static PRInt32
+_pl_GetEventCount(PLEventQueue* self)
+{
+ PRCList* node;
+ PRInt32 count = 0;
+
+ PR_EnterMonitor(self->monitor);
+ node = PR_LIST_HEAD(&self->queue);
+ while (node != &self->queue) {
+ count++;
+ node = PR_NEXT_LINK(node);
+ }
+ PR_ExitMonitor(self->monitor);
+
+ return count;
+}
+
+PR_IMPLEMENT(void)
+PL_ProcessPendingEvents(PLEventQueue* self)
+{
+ PRInt32 count;
+
+ if (self == NULL)
+ return;
+
+
+ PR_EnterMonitor(self->monitor);
+
+ if (self->processingEvents) {
+ _pl_AcknowledgeNativeNotify(self);
+ self->notified = PR_FALSE;
+ PR_ExitMonitor(self->monitor);
+ return;
+ }
+ self->processingEvents = PR_TRUE;
+
+ /* Only process the events that are already in the queue, and
+ * not any new events that get added. Do this by counting the
+ * number of events currently in the queue
+ */
+ count = _pl_GetEventCount(self);
+ PR_ExitMonitor(self->monitor);
+
+ while (count-- > 0) {
+ PLEvent* event = PL_GetEvent(self);
+ if (event == NULL)
+ break;
+
+ PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ processing event"));
+ PL_HandleEvent(event);
+ PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ done processing event"));
+ }
+
+ PR_EnterMonitor(self->monitor);
+
+ if (self->type == EventQueueIsNative) {
+ count = _pl_GetEventCount(self);
+
+ if (count <= 0) {
+ _pl_AcknowledgeNativeNotify(self);
+ self->notified = PR_FALSE;
+ }
+ else {
+ _pl_NativeNotify(self);
+ self->notified = PR_TRUE;
+ }
+
+ }
+ self->processingEvents = PR_FALSE;
+
+ PR_ExitMonitor(self->monitor);
+}
+
+/*******************************************************************************
+ * Event Operations
+ ******************************************************************************/
+
+PR_IMPLEMENT(void)
+PL_InitEvent(PLEvent* self, void* owner,
+ PLHandleEventProc handler,
+ PLDestroyEventProc destructor)
+{
+#ifdef PL_POST_TIMINGS
+ self->postTime = PR_IntervalNow();
+#endif
+ PR_INIT_CLIST(&self->link);
+ self->handler = handler;
+ self->destructor = destructor;
+ self->owner = owner;
+ self->synchronousResult = NULL;
+ self->handled = PR_FALSE;
+ self->lock = NULL;
+ self->condVar = NULL;
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
+ self->id = 0;
+#endif
+}
+
+PR_IMPLEMENT(void*)
+PL_GetEventOwner(PLEvent* self)
+{
+ return self->owner;
+}
+
+PR_IMPLEMENT(void)
+PL_HandleEvent(PLEvent* self)
+{
+ void* result;
+ if (self == NULL)
+ return;
+
+ /* This event better not be on an event queue anymore. */
+ PR_ASSERT(PR_CLIST_IS_EMPTY(&self->link));
+
+ result = self->handler(self);
+ if (NULL != self->synchronousResult) {
+ PR_Lock(self->lock);
+ self->synchronousResult = result;
+ self->handled = PR_TRUE;
+ PR_NotifyCondVar(self->condVar);
+ PR_Unlock(self->lock);
+ }
+ else {
+ /* For asynchronous events, they're destroyed by the event-handler
+ thread. See PR_PostSynchronousEvent. */
+ PL_DestroyEvent(self);
+ }
+}
+#ifdef PL_POST_TIMINGS
+static long s_eventCount = 0;
+static long s_totalTime = 0;
+#endif
+
+PR_IMPLEMENT(void)
+PL_DestroyEvent(PLEvent* self)
+{
+ if (self == NULL)
+ return;
+
+ /* This event better not be on an event queue anymore. */
+ PR_ASSERT(PR_CLIST_IS_EMPTY(&self->link));
+
+ if(self->condVar)
+ PR_DestroyCondVar(self->condVar);
+ if(self->lock)
+ PR_DestroyLock(self->lock);
+
+#ifdef PL_POST_TIMINGS
+ s_totalTime += PR_IntervalNow() - self->postTime;
+ s_eventCount++;
+ printf("$$$ running avg (%d) \n", PR_IntervalToMilliseconds(s_totalTime/s_eventCount));
+#endif
+
+ self->destructor(self);
+}
+
+PR_IMPLEMENT(void)
+PL_DequeueEvent(PLEvent* self, PLEventQueue* queue)
+{
+ if (self == NULL)
+ return;
+
+ /* Only the owner is allowed to dequeue events because once the
+ client has put it in the queue, they have no idea whether it's
+ been processed and destroyed or not. */
+
+ PR_ASSERT(queue->handlerThread == PR_GetCurrentThread());
+
+ PR_EnterMonitor(queue->monitor);
+
+ PR_ASSERT(!PR_CLIST_IS_EMPTY(&self->link));
+
+#if 0
+ /* I do not think that we need to do this anymore.
+ if we do not acknowledge and this is the only
+ only event in the queue, any calls to process
+ the eventQ will be effective noop.
+ */
+ if (queue->type == EventQueueIsNative)
+ _pl_AcknowledgeNativeNotify(queue);
+#endif
+
+ PR_REMOVE_AND_INIT_LINK(&self->link);
+
+ PR_ExitMonitor(queue->monitor);
+}
+
+PR_IMPLEMENT(void)
+PL_FavorPerformanceHint(PRBool favorPerformanceOverEventStarvation,
+ PRUint32 starvationDelay)
+{
+#if defined(_WIN32)
+
+ _md_StarvationDelay = starvationDelay;
+
+ if (favorPerformanceOverEventStarvation) {
+ _md_PerformanceSetting++;
+ return;
+ }
+
+ _md_PerformanceSetting--;
+
+ if (_md_PerformanceSetting == 0) {
+ /* Switched from allowing event starvation to no event starvation so grab
+ the current time to determine when to actually switch to using timers
+ instead of posted WM_APP messages. */
+ _md_SwitchTime = PR_IntervalToMilliseconds(PR_IntervalNow());
+ }
+
+#endif
+}
+
+/*******************************************************************************
+ * Pure Event Queues
+ *
+ * For when you're only processing PLEvents and there is no native
+ * select, thread messages, or AppleEvents.
+ ******************************************************************************/
+
+PR_IMPLEMENT(PLEvent*)
+PL_WaitForEvent(PLEventQueue* self)
+{
+ PLEvent* event;
+ PRMonitor* mon;
+
+ if (self == NULL)
+ return NULL;
+
+ mon = self->monitor;
+ PR_EnterMonitor(mon);
+
+ while ((event = PL_GetEvent(self)) == NULL) {
+ PRStatus err;
+ PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ waiting for event"));
+ err = PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
+ if ((err == PR_FAILURE)
+ && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) break;
+ }
+
+ PR_ExitMonitor(mon);
+ return event;
+}
+
+PR_IMPLEMENT(void)
+PL_EventLoop(PLEventQueue* self)
+{
+ if (self == NULL)
+ return;
+
+ while (PR_TRUE) {
+ PLEvent* event = PL_WaitForEvent(self);
+ if (event == NULL) {
+ /* This can only happen if the current thread is interrupted */
+ return;
+ }
+
+ PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ processing event"));
+ PL_HandleEvent(event);
+ PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ done processing event"));
+ }
+}
+
+/*******************************************************************************
+ * Native Event Queues
+ *
+ * For when you need to call select, or WaitNextEvent, and yet also want
+ * to handle PLEvents.
+ ******************************************************************************/
+
+static PRStatus
+_pl_SetupNativeNotifier(PLEventQueue* self)
+{
+#if defined(VMS)
+ unsigned int status;
+ self->idFunc = 0;
+ self->idFuncClosure = 0;
+ status = LIB$GET_EF(&self->efn);
+ if (!$VMS_STATUS_SUCCESS(status))
+ return PR_FAILURE;
+ PR_LOG(event_lm, PR_LOG_DEBUG,
+ ("$$$ Allocated event flag %d", self->efn));
+ return PR_SUCCESS;
+#elif defined(XP_UNIX) && !defined(XP_MACOSX)
+ int err;
+ int flags;
+
+ self->idFunc = 0;
+ self->idFuncClosure = 0;
+
+ err = pipe(self->eventPipe);
+ if (err != 0) {
+ return PR_FAILURE;
+ }
+#ifdef VBOX
+ fcntl(self->eventPipe[0], F_SETFD, FD_CLOEXEC);
+ fcntl(self->eventPipe[1], F_SETFD, FD_CLOEXEC);
+#endif
+
+ /* make the pipe nonblocking */
+ flags = fcntl(self->eventPipe[0], F_GETFL, 0);
+ if (flags == -1) {
+ goto failed;
+ }
+ err = fcntl(self->eventPipe[0], F_SETFL, flags | O_NONBLOCK);
+ if (err == -1) {
+ goto failed;
+ }
+ flags = fcntl(self->eventPipe[1], F_GETFL, 0);
+ if (flags == -1) {
+ goto failed;
+ }
+ err = fcntl(self->eventPipe[1], F_SETFL, flags | O_NONBLOCK);
+ if (err == -1) {
+ goto failed;
+ }
+ return PR_SUCCESS;
+
+failed:
+ close(self->eventPipe[0]);
+ close(self->eventPipe[1]);
+ return PR_FAILURE;
+#elif defined(XP_BEOS)
+ /* hook up to the nsToolkit queue, however the appshell
+ * isn't necessairly started, so we might have to create
+ * the queue ourselves
+ */
+ char portname[64];
+ char semname[64];
+ PR_snprintf(portname, sizeof(portname), "event%lx",
+ (long unsigned) self->handlerThread);
+ PR_snprintf(semname, sizeof(semname), "sync%lx",
+ (long unsigned) self->handlerThread);
+
+ if((self->eventport = find_port(portname)) < 0)
+ {
+ /* create port
+ */
+ self->eventport = create_port(500, portname);
+
+ /* We don't use the sem, but it has to be there
+ */
+ create_sem(0, semname);
+ }
+
+ return PR_SUCCESS;
+#else
+ return PR_SUCCESS;
+#endif
+}
+
+static void
+_pl_CleanupNativeNotifier(PLEventQueue* self)
+{
+#if defined(VMS)
+ {
+ unsigned int status;
+ PR_LOG(event_lm, PR_LOG_DEBUG,
+ ("$$$ Freeing event flag %d", self->efn));
+ status = LIB$FREE_EF(&self->efn);
+ }
+#elif defined(XP_UNIX) && !defined(XP_MACOSX)
+ close(self->eventPipe[0]);
+ close(self->eventPipe[1]);
+#elif defined(_WIN32)
+ if (self->timerSet) {
+ KillTimer(self->eventReceiverWindow, TIMER_ID);
+ self->timerSet = PR_FALSE;
+ }
+ RemoveProp(self->eventReceiverWindow, _md_GetEventQueuePropName());
+
+ /* DestroyWindow doesn't do anything when called from a non ui thread. Since
+ * self->eventReceiverWindow was created on the ui thread, it must be destroyed
+ * on the ui thread.
+ */
+ SendMessage(self->eventReceiverWindow, WM_CLOSE, 0, 0);
+
+#elif defined(XP_OS2)
+ WinDestroyWindow(self->eventReceiverWindow);
+#elif defined(MAC_USE_CFRUNLOOPSOURCE)
+
+ CFRunLoopRemoveSource(self->mMainRunLoop, self->mRunLoopSource, kCFRunLoopCommonModes);
+ CFRunLoopRemoveSource(self->mMainRunLoop, self->mRunLoopSource, self->mRunLoopModeStr); /* vbox */
+ CFRelease(self->mRunLoopSource);
+ CFRelease(self->mMainRunLoop);
+ CFRelease(self->mRunLoopModeStr); /* vbox */
+
+#elif defined(MAC_USE_CARBON_EVENT)
+ EventComparatorUPP comparator = NewEventComparatorUPP(_md_CarbonEventComparator);
+ PR_ASSERT(comparator != NULL);
+ if (comparator) {
+ FlushSpecificEventsFromQueue(GetMainEventQueue(), comparator, self);
+ DisposeEventComparatorUPP(comparator);
+ }
+ DisposeEventHandlerUPP(self->eventHandlerUPP);
+ RemoveEventHandler(self->eventHandlerRef);
+#endif
+}
+
+#if defined(_WIN32)
+
+static PRBool _md_WasInputPending = PR_FALSE;
+static PRUint32 _md_InputTime = 0;
+static PRBool _md_WasPaintPending = PR_FALSE;
+static PRUint32 _md_PaintTime = 0;
+/* last mouse location */
+static POINT _md_LastMousePos;
+
+/*******************************************************************************
+ * Timer callback function. Timers are used on WIN32 instead of APP events
+ * when there are pending UI events because APP events can cause the GUI to lockup
+ * because posted messages are processed before other messages.
+ ******************************************************************************/
+
+static void CALLBACK _md_TimerProc( HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime )
+{
+ PREventQueue* queue = (PREventQueue *) GetProp(hwnd, _md_GetEventQueuePropName());
+ PR_ASSERT(queue != NULL);
+
+ KillTimer(hwnd, TIMER_ID);
+ queue->timerSet = PR_FALSE;
+ queue->removeMsg = PR_FALSE;
+ PL_ProcessPendingEvents( queue );
+ queue->removeMsg = PR_TRUE;
+}
+
+static PRBool _md_IsWIN9X = PR_FALSE;
+static PRBool _md_IsOSSet = PR_FALSE;
+
+static void _md_DetermineOSType()
+{
+ OSVERSIONINFO os;
+ os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ GetVersionEx(&os);
+ if (VER_PLATFORM_WIN32_WINDOWS == os.dwPlatformId) {
+ _md_IsWIN9X = PR_TRUE;
+ }
+}
+
+static PRUint32 _md_GetPaintStarvationLimit()
+{
+ if (! _md_IsOSSet) {
+ _md_DetermineOSType();
+ _md_IsOSSet = PR_TRUE;
+ }
+
+ if (_md_IsWIN9X) {
+ return WIN9X_PAINT_STARVATION_LIMIT;
+ }
+
+ return PAINT_STARVATION_LIMIT;
+}
+
+
+/*
+ * Determine if an event is being starved (i.e the starvation limit has
+ * been exceeded.
+ * Note: this function uses the current setting and updates the contents
+ * of the wasPending and lastTime arguments
+ *
+ * ispending: PR_TRUE if the event is currently pending
+ * starvationLimit: Threshold defined in milliseconds for determining when
+ * the event has been held in the queue too long
+ * wasPending: PR_TRUE if the last time _md_EventIsStarved was called
+ * the event was pending. This value is updated within
+ * this function.
+ * lastTime: Holds the last time the event was in the queue.
+ * This value is updated within this function
+ * returns: PR_TRUE if the event is starved, PR_FALSE otherwise
+ */
+
+static PRBool _md_EventIsStarved(PRBool isPending, PRUint32 starvationLimit,
+ PRBool *wasPending, PRUint32 *lastTime,
+ PRUint32 currentTime)
+{
+ if (*wasPending && isPending) {
+ /*
+ * It was pending previously and the event is still
+ * pending so check to see if the elapsed time is
+ * over the limit which indicates the event was starved
+ */
+ if ((currentTime - *lastTime) > starvationLimit) {
+ return PR_TRUE; /* pending and over the limit */
+ }
+
+ return PR_FALSE; /* pending but within the limit */
+ }
+
+ if (isPending) {
+ /*
+ * was_pending must be false so record the current time
+ * so the elapsed time can be computed the next time this
+ * function is called
+ */
+ *lastTime = currentTime;
+ *wasPending = PR_TRUE;
+ return PR_FALSE;
+ }
+
+ /* Event is no longer pending */
+ *wasPending = PR_FALSE;
+ return PR_FALSE;
+}
+
+/* Determines if the there is a pending Mouse or input event */
+
+static PRBool _md_IsInputPending(WORD qstatus)
+{
+ /* Return immediately there aren't any pending input or paints. */
+ if (qstatus == 0) {
+ return PR_FALSE;
+ }
+
+ /* Is there anything other than a QS_MOUSEMOVE pending? */
+ if ((qstatus & QS_MOUSEBUTTON) ||
+ (qstatus & QS_KEY) ||
+ (qstatus & QS_HOTKEY)) {
+ return PR_TRUE;
+ }
+
+ /*
+ * Mouse moves need extra processing to determine if the mouse
+ * pointer actually changed location because Windows automatically
+ * generates WM_MOVEMOVE events when a new window is created which
+ * we need to filter out.
+ */
+ if (qstatus & QS_MOUSEMOVE) {
+ POINT cursorPos;
+ GetCursorPos(&cursorPos);
+ if ((_md_LastMousePos.x == cursorPos.x) &&
+ (_md_LastMousePos.y == cursorPos.y)) {
+ return PR_FALSE; /* This is a fake mouse move */
+ }
+
+ /* Real mouse move */
+ _md_LastMousePos.x = cursorPos.x;
+ _md_LastMousePos.y = cursorPos.y;
+ return PR_TRUE;
+ }
+
+ return PR_FALSE;
+}
+
+static PRStatus
+_pl_NativeNotify(PLEventQueue* self)
+{
+#ifdef USE_TIMER
+ WORD qstatus;
+
+ PRUint32 now = PR_IntervalToMilliseconds(PR_IntervalNow());
+
+ /* Since calls to set the _md_PerformanceSetting can be nested
+ * only performance setting values <= 0 will potentially trigger
+ * the use of a timer.
+ */
+ if ((_md_PerformanceSetting <= 0) &&
+ ((now - _md_SwitchTime) > _md_StarvationDelay)) {
+ SetTimer(self->eventReceiverWindow, TIMER_ID, 0 ,_md_TimerProc);
+ self->timerSet = PR_TRUE;
+ _md_WasInputPending = PR_FALSE;
+ _md_WasPaintPending = PR_FALSE;
+ return PR_SUCCESS;
+ }
+
+ qstatus = HIWORD(GetQueueStatus(QS_INPUT | QS_PAINT));
+
+ /* Check for starved input */
+ if (_md_EventIsStarved( _md_IsInputPending(qstatus),
+ INPUT_STARVATION_LIMIT,
+ &_md_WasInputPending,
+ &_md_InputTime,
+ now )) {
+ /*
+ * Use a timer for notification. Timers have the lowest priority.
+ * They are not processed until all other events have been processed.
+ * This allows any starved paints and input to be processed.
+ */
+ SetTimer(self->eventReceiverWindow, TIMER_ID, 0 ,_md_TimerProc);
+ self->timerSet = PR_TRUE;
+
+ /*
+ * Clear any pending paint. _md_WasInputPending was cleared in
+ * _md_EventIsStarved.
+ */
+ _md_WasPaintPending = PR_FALSE;
+ return PR_SUCCESS;
+ }
+
+ if (_md_EventIsStarved( (qstatus & QS_PAINT),
+ _md_GetPaintStarvationLimit(),
+ &_md_WasPaintPending,
+ &_md_PaintTime,
+ now) ) {
+ /*
+ * Use a timer for notification. Timers have the lowest priority.
+ * They are not processed until all other events have been processed.
+ * This allows any starved paints and input to be processed
+ */
+ SetTimer(self->eventReceiverWindow, TIMER_ID, 0 ,_md_TimerProc);
+ self->timerSet = PR_TRUE;
+
+ /*
+ * Clear any pending input. _md_WasPaintPending was cleared in
+ * _md_EventIsStarved.
+ */
+ _md_WasInputPending = PR_FALSE;
+ return PR_SUCCESS;
+ }
+
+ /*
+ * Nothing is being starved so post a message instead of using a timer.
+ * Posted messages are processed before other messages so they have the
+ * highest priority.
+ */
+#endif
+ PostMessage( self->eventReceiverWindow, _pr_PostEventMsgId,
+ (WPARAM)0, (LPARAM)self );
+
+ return PR_SUCCESS;
+}/* --- end _pl_NativeNotify() --- */
+#endif
+
+
+#if defined(XP_OS2)
+static PRStatus
+_pl_NativeNotify(PLEventQueue* self)
+{
+ BOOL rc = WinPostMsg( self->eventReceiverWindow, _pr_PostEventMsgId,
+ 0, MPFROMP(self));
+ return (rc == TRUE) ? PR_SUCCESS : PR_FAILURE;
+}/* --- end _pl_NativeNotify() --- */
+#endif /* XP_OS2 */
+
+#if defined(VMS)
+/* Just set the event flag */
+static PRStatus
+_pl_NativeNotify(PLEventQueue* self)
+{
+ unsigned int status;
+ PR_LOG(event_lm, PR_LOG_DEBUG,
+ ("_pl_NativeNotify: self=%p efn=%d",
+ self, self->efn));
+ status = SYS$SETEF(self->efn);
+ return ($VMS_STATUS_SUCCESS(status)) ? PR_SUCCESS : PR_FAILURE;
+}/* --- end _pl_NativeNotify() --- */
+#elif defined(XP_UNIX) && !defined(XP_MACOSX)
+
+static PRStatus
+_pl_NativeNotify(PLEventQueue* self)
+{
+#define NOTIFY_TOKEN 0xFA
+ PRInt32 count;
+ unsigned char buf[] = { NOTIFY_TOKEN };
+
+# ifdef VBOX
+ /* Don't write two chars, because we'll only acknowledge one and that'll
+ cause trouble for anyone selecting/polling on the read descriptor. */
+ if (self->notified)
+ return PR_SUCCESS;
+# endif
+
+ PR_LOG(event_lm, PR_LOG_DEBUG,
+ ("_pl_NativeNotify: self=%p",
+ self));
+ count = write(self->eventPipe[1], buf, 1);
+ if (count == 1)
+ return PR_SUCCESS;
+ if (count == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
+ return PR_SUCCESS;
+ return PR_FAILURE;
+}/* --- end _pl_NativeNotify() --- */
+#endif /* defined(XP_UNIX) && !defined(XP_MACOSX) */
+
+#if defined(XP_BEOS)
+struct ThreadInterfaceData
+{
+ void *data;
+ int32 sync;
+};
+
+static PRStatus
+_pl_NativeNotify(PLEventQueue* self)
+{
+ struct ThreadInterfaceData id;
+ id.data = self;
+ id.sync = false;
+ write_port(self->eventport, 'natv', &id, sizeof(id));
+
+ return PR_SUCCESS; /* Is this correct? */
+}
+#endif /* XP_BEOS */
+
+#if defined(XP_MACOSX)
+static PRStatus
+_pl_NativeNotify(PLEventQueue* self)
+{
+#if defined(MAC_USE_CFRUNLOOPSOURCE)
+ CFRunLoopSourceSignal(self->mRunLoopSource);
+ CFRunLoopWakeUp(self->mMainRunLoop);
+#elif defined(MAC_USE_CARBON_EVENT)
+ OSErr err;
+ EventRef newEvent;
+ if (CreateEvent(NULL, kEventClassPL, kEventProcessPLEvents,
+ 0, kEventAttributeNone, &newEvent) != noErr)
+ return PR_FAILURE;
+ err = SetEventParameter(newEvent, kEventParamPLEventQueue,
+ typeUInt32, sizeof(PREventQueue*), &self);
+ if (err == noErr) {
+ err = PostEventToQueue(GetMainEventQueue(), newEvent, kEventPriorityLow);
+ ReleaseEvent(newEvent);
+ }
+ if (err != noErr)
+ return PR_FAILURE;
+#endif
+ return PR_SUCCESS;
+}
+#endif /* defined(XP_MACOSX) */
+
+static PRStatus
+_pl_AcknowledgeNativeNotify(PLEventQueue* self)
+{
+#if defined(_WIN32) || defined(XP_OS2)
+#ifdef XP_OS2
+ QMSG aMsg;
+#else
+ MSG aMsg;
+#endif
+ /*
+ * only remove msg when we've been called directly by
+ * PL_ProcessPendingEvents, not when we've been called by
+ * the window proc because the window proc will remove the
+ * msg for us.
+ */
+ if (self->removeMsg) {
+ PR_LOG(event_lm, PR_LOG_DEBUG,
+ ("_pl_AcknowledgeNativeNotify: self=%p", self));
+#ifdef XP_OS2
+ WinPeekMsg((HAB)0, &aMsg, self->eventReceiverWindow,
+ _pr_PostEventMsgId, _pr_PostEventMsgId, PM_REMOVE);
+#else
+ PeekMessage(&aMsg, self->eventReceiverWindow,
+ _pr_PostEventMsgId, _pr_PostEventMsgId, PM_REMOVE);
+ if (self->timerSet) {
+ KillTimer(self->eventReceiverWindow, TIMER_ID);
+ self->timerSet = PR_FALSE;
+ }
+#endif
+ }
+ return PR_SUCCESS;
+#elif defined(VMS)
+ PR_LOG(event_lm, PR_LOG_DEBUG,
+ ("_pl_AcknowledgeNativeNotify: self=%p efn=%d",
+ self, self->efn));
+ /*
+ ** If this is the last entry, then clear the event flag. Also make sure
+ ** the flag is cleared on any spurious wakeups.
+ */
+ sys$clref(self->efn);
+ return PR_SUCCESS;
+#elif defined(XP_UNIX) && !defined(XP_MACOSX)
+
+ PRInt32 count;
+ unsigned char c;
+ PR_LOG(event_lm, PR_LOG_DEBUG,
+ ("_pl_AcknowledgeNativeNotify: self=%p",
+ self));
+ /* consume the byte NativeNotify put in our pipe: */
+ count = read(self->eventPipe[0], &c, 1);
+ if ((count == 1) && (c == NOTIFY_TOKEN))
+ return PR_SUCCESS;
+ if ((count == -1) && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
+ return PR_SUCCESS;
+ return PR_FAILURE;
+#elif defined(MAC_USE_CFRUNLOOPSOURCE) /* vbox */
+ /* vbox */
+ CFRunLoopRunInMode(self->mRunLoopModeStr, 0.0, 1); /* vbox */
+ return PR_SUCCESS; /* vbox */
+#else
+
+ /* nothing to do on the other platforms */
+ return PR_SUCCESS;
+#endif
+}
+
+PR_IMPLEMENT(PRInt32)
+PL_GetEventQueueSelectFD(PLEventQueue* self)
+{
+ if (self == NULL)
+ return -1;
+
+#if defined(VMS)
+ return -(self->efn);
+#elif defined(XP_UNIX) && !defined(XP_MACOSX)
+ return self->eventPipe[0];
+#else
+ return -1; /* other platforms don't handle this (yet) */
+#endif
+}
+
+PR_IMPLEMENT(PRBool)
+PL_IsQueueOnCurrentThread( PLEventQueue *queue )
+{
+ PRThread *me = PR_GetCurrentThread();
+ return me == queue->handlerThread;
+}
+
+PR_EXTERN(PRBool)
+PL_IsQueueNative(PLEventQueue *queue)
+{
+ return queue->type == EventQueueIsNative ? PR_TRUE : PR_FALSE;
+}
+
+#if defined(_WIN32)
+/*
+** Global Instance handle...
+** In Win32 this is the module handle of the DLL.
+**
+*/
+static HINSTANCE _pr_hInstance;
+#endif
+
+
+#if defined(_WIN32)
+
+/*
+** Initialization routine for the DLL...
+*/
+
+BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved)
+{
+ switch (dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ _pr_hInstance = hDLL;
+ break;
+
+ case DLL_THREAD_ATTACH:
+ break;
+
+ case DLL_THREAD_DETACH:
+ break;
+
+ case DLL_PROCESS_DETACH:
+ _pr_hInstance = NULL;
+ break;
+ }
+
+ return TRUE;
+}
+#endif
+
+
+#if defined(_WIN32) || defined(XP_OS2)
+#ifdef XP_OS2
+MRESULT EXPENTRY
+_md_EventReceiverProc(HWND hwnd, ULONG uMsg, MPARAM wParam, MPARAM lParam)
+#else
+LRESULT CALLBACK
+_md_EventReceiverProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+#endif
+{
+ if (_pr_PostEventMsgId == uMsg )
+ {
+ PREventQueue *queue = (PREventQueue *)lParam;
+ queue->removeMsg = PR_FALSE;
+ PL_ProcessPendingEvents(queue);
+ queue->removeMsg = PR_TRUE;
+#ifdef XP_OS2
+ return MRFROMLONG(TRUE);
+#else
+ return TRUE;
+#endif
+ }
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+static PRBool isInitialized;
+static PRCallOnceType once;
+static PRLock *initLock;
+
+/*
+** InitWinEventLib() -- Create the Windows initialization lock
+**
+*/
+static PRStatus InitEventLib( void )
+{
+ PR_ASSERT( initLock == NULL );
+
+ initLock = PR_NewLock();
+ return initLock ? PR_SUCCESS : PR_FAILURE;
+}
+
+#endif /* Win32, OS2 */
+
+#if defined(_WIN32)
+
+/*
+** _md_CreateEventQueue() -- ModelDependent initializer
+*/
+static void _md_CreateEventQueue( PLEventQueue *eventQueue )
+{
+ WNDCLASS wc;
+
+ /*
+ ** If this is the first call to PL_InitializeEventsLib(),
+ ** make the call to InitWinEventLib() to create the initLock.
+ **
+ ** Then lock the initializer lock to insure that
+ ** we have exclusive control over the initialization sequence.
+ **
+ */
+
+
+ /* Register the windows message for XPCOM Event notification */
+ _pr_PostEventMsgId = RegisterWindowMessage("XPCOM_PostEvent");
+
+ /* Register the class for the event receiver window */
+ if (!GetClassInfo(_pr_hInstance, _pr_eventWindowClass, &wc)) {
+ wc.style = 0;
+ wc.lpfnWndProc = _md_EventReceiverProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = _pr_hInstance;
+ wc.hIcon = NULL;
+ wc.hCursor = NULL;
+ wc.hbrBackground = (HBRUSH) NULL;
+ wc.lpszMenuName = (LPCSTR) NULL;
+ wc.lpszClassName = _pr_eventWindowClass;
+ RegisterClass(&wc);
+ }
+
+ /* Create the event receiver window */
+ eventQueue->eventReceiverWindow = CreateWindow(_pr_eventWindowClass,
+ "XPCOM:EventReceiver",
+ 0, 0, 0, 10, 10,
+ NULL, NULL, _pr_hInstance,
+ NULL);
+ PR_ASSERT(eventQueue->eventReceiverWindow);
+ /* Set a property which can be used to retrieve the event queue
+ * within the _md_TimerProc callback
+ */
+ SetProp(eventQueue->eventReceiverWindow,
+ _md_GetEventQueuePropName(), (HANDLE)eventQueue);
+
+ return;
+} /* end _md_CreateEventQueue() */
+#endif /* Winxx */
+
+#if defined(XP_OS2)
+/*
+** _md_CreateEventQueue() -- ModelDependent initializer
+*/
+static void _md_CreateEventQueue( PLEventQueue *eventQueue )
+{
+ /* Must have HMQ for this & can't assume we already have appshell */
+ if( FALSE == WinQueryQueueInfo( HMQ_CURRENT, NULL, 0))
+ {
+ PPIB ppib;
+ PTIB ptib;
+ HAB hab;
+ HMQ hmq;
+
+ /* Set our app to be a PM app before attempting Win calls */
+ DosGetInfoBlocks(&ptib, &ppib);
+ ppib->pib_ultype = 3;
+
+ hab = WinInitialize(0);
+ hmq = WinCreateMsgQueue(hab, 0);
+ PR_ASSERT(hmq);
+ }
+
+ if( !_pr_PostEventMsgId)
+ {
+ WinRegisterClass( 0 /* hab_current */,
+ _pr_eventWindowClass,
+ _md_EventReceiverProc,
+ 0, 0);
+
+ _pr_PostEventMsgId = WinAddAtom( WinQuerySystemAtomTable(),
+ "XPCOM_PostEvent");
+ }
+
+ eventQueue->eventReceiverWindow = WinCreateWindow( HWND_DESKTOP,
+ _pr_eventWindowClass,
+ "", 0,
+ 0, 0, 0, 0,
+ HWND_DESKTOP,
+ HWND_TOP,
+ 0,
+ NULL,
+ NULL);
+ PR_ASSERT(eventQueue->eventReceiverWindow);
+
+ return;
+} /* end _md_CreateEventQueue() */
+#endif /* XP_OS2 */
+
+#if (defined(XP_UNIX) && !defined(XP_MACOSX)) || defined(XP_BEOS)
+/*
+** _md_CreateEventQueue() -- ModelDependent initializer
+*/
+static void _md_CreateEventQueue( PLEventQueue *eventQueue )
+{
+ /* there's really nothing special to do here,
+ ** the guts of the unix stuff is in the setupnativenotify
+ ** and related functions.
+ */
+ return;
+} /* end _md_CreateEventQueue() */
+#endif /* (defined(XP_UNIX) && !defined(XP_MACOSX)) || defined(XP_BEOS) */
+
+#if defined(MAC_USE_CFRUNLOOPSOURCE)
+static void _md_EventReceiverProc(void *info)
+{
+ PLEventQueue *queue = (PLEventQueue*)info;
+ PL_ProcessPendingEvents(queue);
+}
+
+#elif defined(MAC_USE_CARBON_EVENT)
+/*
+** _md_CreateEventQueue() -- ModelDependent initializer
+*/
+
+static pascal OSStatus _md_EventReceiverProc(EventHandlerCallRef nextHandler,
+ EventRef inEvent,
+ void* userData)
+{
+ if (GetEventClass(inEvent) == kEventClassPL &&
+ GetEventKind(inEvent) == kEventProcessPLEvents)
+ {
+ PREventQueue *queue;
+ if (GetEventParameter(inEvent, kEventParamPLEventQueue,
+ typeUInt32, NULL, sizeof(PREventQueue*), NULL,
+ &queue) == noErr)
+ {
+ PL_ProcessPendingEvents(queue);
+ return noErr;
+ }
+ }
+ return eventNotHandledErr;
+}
+
+static pascal Boolean _md_CarbonEventComparator(EventRef inEvent,
+ void *inCompareData)
+{
+ Boolean match = false;
+
+ if (GetEventClass(inEvent) == kEventClassPL &&
+ GetEventKind(inEvent) == kEventProcessPLEvents)
+ {
+ PREventQueue *queue;
+ match = ((GetEventParameter(inEvent, kEventParamPLEventQueue,
+ typeUInt32, NULL, sizeof(PREventQueue*), NULL,
+ &queue) == noErr) && (queue == inCompareData));
+ }
+ return match;
+}
+
+#endif /* defined(MAC_USE_CARBON_EVENT) */
+
+#if defined(XP_MACOSX)
+static void _md_CreateEventQueue( PLEventQueue *eventQueue )
+{
+#if defined(MAC_USE_CFRUNLOOPSOURCE)
+ CFRunLoopSourceContext sourceContext = { 0 };
+ sourceContext.version = 0;
+ sourceContext.info = (void*)eventQueue;
+ sourceContext.perform = _md_EventReceiverProc;
+
+ /* make a run loop source */
+ eventQueue->mRunLoopSource = CFRunLoopSourceCreate(kCFAllocatorDefault, 0 /* order */, &sourceContext);
+ PR_ASSERT(eventQueue->mRunLoopSource);
+
+ eventQueue->mMainRunLoop = CFRunLoopGetCurrent();
+ CFRetain(eventQueue->mMainRunLoop);
+
+ /* and add it to the run loop */
+ CFRunLoopAddSource(eventQueue->mMainRunLoop, eventQueue->mRunLoopSource, kCFRunLoopCommonModes);
+
+ /* Add it again but with a unique mode name so we can acknowledge it
+ without processing any other message sources. */
+ { /* vbox */
+ char szModeName[80]; /* vbox */
+ snprintf(szModeName, sizeof(szModeName), "VBoxXPCOMQueueMode-%p", eventQueue); /* vbox */
+ eventQueue->mRunLoopModeStr = CFStringCreateWithCString(kCFAllocatorDefault, /* vbox */
+ szModeName, kCFStringEncodingASCII); /* vbox */
+ CFRunLoopAddSource(eventQueue->mMainRunLoop, /* vbox */
+ eventQueue->mRunLoopSource, eventQueue->mRunLoopModeStr); /* vbox */
+ } /* vbox */
+
+#elif defined(MAC_USE_CARBON_EVENT)
+ eventQueue->eventHandlerUPP = NewEventHandlerUPP(_md_EventReceiverProc);
+ PR_ASSERT(eventQueue->eventHandlerUPP);
+ if (eventQueue->eventHandlerUPP)
+ {
+ EventTypeSpec eventType;
+
+ eventType.eventClass = kEventClassPL;
+ eventType.eventKind = kEventProcessPLEvents;
+
+ InstallApplicationEventHandler(eventQueue->eventHandlerUPP, 1, &eventType,
+ eventQueue, &eventQueue->eventHandlerRef);
+ PR_ASSERT(eventQueue->eventHandlerRef);
+ }
+#endif
+} /* end _md_CreateEventQueue() */
+#endif /* defined(XP_MACOSX) */
+
+/* extra functions for unix */
+
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
+
+PR_IMPLEMENT(PRInt32)
+PL_ProcessEventsBeforeID(PLEventQueue *aSelf, unsigned long aID)
+{
+ PRInt32 count = 0;
+ PRInt32 fullCount;
+
+ if (aSelf == NULL)
+ return -1;
+
+ PR_EnterMonitor(aSelf->monitor);
+
+ if (aSelf->processingEvents) {
+ PR_ExitMonitor(aSelf->monitor);
+ return 0;
+ }
+
+ aSelf->processingEvents = PR_TRUE;
+
+ /* Only process the events that are already in the queue, and
+ * not any new events that get added. Do this by counting the
+ * number of events currently in the queue
+ */
+ fullCount = _pl_GetEventCount(aSelf);
+ PR_LOG(event_lm, PR_LOG_DEBUG,
+ ("$$$ fullCount is %d id is %ld\n", fullCount, aID));
+
+ if (fullCount == 0) {
+ aSelf->processingEvents = PR_FALSE;
+ PR_ExitMonitor(aSelf->monitor);
+ return 0;
+ }
+
+ PR_ExitMonitor(aSelf->monitor);
+
+ while (fullCount-- > 0) {
+ /* peek at the next event */
+ PLEvent *event;
+ event = PR_EVENT_PTR(aSelf->queue.next);
+ if (event == NULL)
+ break;
+ PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ processing event %ld\n",
+ event->id));
+ if (event->id >= aID) {
+ PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ skipping event and breaking"));
+ break;
+ }
+
+ event = PL_GetEvent(aSelf);
+ PL_HandleEvent(event);
+ PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ done processing event"));
+ count++;
+ }
+
+ PR_EnterMonitor(aSelf->monitor);
+
+ /* if full count still had items left then there's still items left
+ in the queue. Let the native notify token stay. */
+
+ if (aSelf->type == EventQueueIsNative) {
+ fullCount = _pl_GetEventCount(aSelf);
+
+ if (fullCount <= 0) {
+ _pl_AcknowledgeNativeNotify(aSelf);
+ aSelf->notified = PR_FALSE;
+ }
+ }
+
+ aSelf->processingEvents = PR_FALSE;
+
+ PR_ExitMonitor(aSelf->monitor);
+
+ return count;
+}
+
+PR_IMPLEMENT(void)
+PL_RegisterEventIDFunc(PLEventQueue *aSelf, PLGetEventIDFunc aFunc,
+ void *aClosure)
+{
+ aSelf->idFunc = aFunc;
+ aSelf->idFuncClosure = aClosure;
+}
+
+PR_IMPLEMENT(void)
+PL_UnregisterEventIDFunc(PLEventQueue *aSelf)
+{
+ aSelf->idFunc = 0;
+ aSelf->idFuncClosure = 0;
+}
+
+#endif /* defined(XP_UNIX) && !defined(XP_MACOSX) */
+
+/* --- end plevent.c --- */
diff --git a/src/libs/xpcom18a4/xpcom/threads/plevent.h b/src/libs/xpcom18a4/xpcom/threads/plevent.h
new file mode 100644
index 00000000..5bc9c89f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/threads/plevent.h
@@ -0,0 +1,690 @@
+/* -*- 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 ***** */
+
+/**********************************************************************
+NSPL Events
+
+Defining Events
+---------------
+
+Events are essentially structures that represent argument lists for a
+function that will run on another thread. All event structures you
+define must include a PLEvent struct as their first field:
+
+ typedef struct MyEventType {
+ PLEvent e;
+ // arguments follow...
+ int x;
+ char* y;
+ } MyEventType;
+
+It is also essential that you establish a model of ownership for each
+argument passed in an event record, i.e. whether particular arguments
+will be deleted by the event destruction callback, or whether they
+only loaned to the event handler callback, and guaranteed to persist
+until the time at which the handler is called.
+
+Sending Events
+--------------
+
+Events are initialized by PL_InitEvent and can be sent via
+PL_PostEvent or PL_PostSynchronousEvent. Events can also have an
+owner. The owner of an event can revoke all the events in a given
+event-queue by calling PL_RevokeEvents. An owner might want
+to do this if, for instance, it is being destroyed, and handling the
+events after the owner's destruction would cause an error (e.g. an
+MWContext).
+
+Since the act of initializing and posting an event must be coordinated
+with it's possible revocation, it is essential that the event-queue's
+monitor be entered surrounding the code that constructs, initializes
+and posts the event:
+
+ void postMyEvent(MyOwner* owner, int x, char* y)
+ {
+ MyEventType* event;
+
+ PL_ENTER_EVENT_QUEUE_MONITOR(myQueue);
+
+ // construct
+ event = PR_NEW(MyEventType);
+ if (event == NULL) goto done;
+
+ // initialize
+ PL_InitEvent(event, owner,
+ (PLHandleEventProc)handleMyEvent,
+ (PLDestroyEventProc)destroyMyEvent);
+ event->x = x;
+ event->y = strdup(y);
+
+ // post
+ PL_PostEvent(myQueue, &event->e);
+
+ done:
+ PL_EXIT_EVENT_QUEUE_MONITOR(myQueue);
+ }
+
+If you don't call PL_InitEvent and PL_PostEvent within the
+event-queue's monitor, you'll get a big red assert.
+
+Handling Events
+---------------
+
+To handle an event you must write a callback that is passed the event
+record you defined containing the event's arguments:
+
+ void* handleMyEvent(MyEventType* event)
+ {
+ doit(event->x, event->y);
+ return NULL; // you could return a value for a sync event
+ }
+
+Similarly for the destruction callback:
+
+ void destroyMyEvent(MyEventType* event)
+ {
+ free(event->y); // created by strdup
+ free(event);
+ }
+
+Processing Events in Your Event Loop
+------------------------------------
+
+If your main loop only processes events delivered to the event queue,
+things are rather simple. You just get the next event (which may
+block), and then handle it:
+
+ while (1) {
+ event = PL_GetEvent(myQueue);
+ PL_HandleEvent(event);
+ }
+
+However, if other things must be waited on, you'll need to obtain a
+file-descriptor that represents your event queue, and hand it to select:
+
+ fd = PL_GetEventQueueSelectFD(myQueue);
+ ...add fd to select set...
+ while (select(...)) {
+ if (...fd...) {
+ PL_ProcessPendingEvents(myQueue);
+ }
+ ...
+ }
+
+Of course, with Motif and Windows it's more complicated than that, and
+on Mac it's completely different, but you get the picture.
+
+Revoking Events
+---------------
+If at any time an owner of events is about to be destroyed, you must
+take steps to ensure that no one tries to use the event queue after
+the owner is gone (or a crash may result). You can do this by either
+processing all the events in the queue before destroying the owner:
+
+ {
+ ...
+ PL_ENTER_EVENT_QUEUE_MONITOR(myQueue);
+ PL_ProcessPendingEvents(myQueue);
+ DestroyMyOwner(owner);
+ PL_EXIT_EVENT_QUEUE_MONITOR(myQueue);
+ ...
+ }
+
+or by revoking the events that are in the queue for that owner. This
+removes them from the queue and calls their destruction callback:
+
+ {
+ ...
+ PL_ENTER_EVENT_QUEUE_MONITOR(myQueue);
+ PL_RevokeEvents(myQueue, owner);
+ DestroyMyOwner(owner);
+ PL_EXIT_EVENT_QUEUE_MONITOR(myQueue);
+ ...
+ }
+
+In either case it is essential that you be in the event-queue's monitor
+to ensure that all events are removed from the queue for that owner,
+and to ensure that no more events will be delivered for that owner.
+**********************************************************************/
+
+#ifndef plevent_h___
+#define plevent_h___
+
+#include "prtypes.h"
+#include "prclist.h"
+#include "prthread.h"
+#include "prlock.h"
+#include "prcvar.h"
+#include "prmon.h"
+
+/* For HWND */
+#if defined(XP_WIN32)
+#include <windef.h>
+#elif defined(XP_OS2)
+#define INCL_DOSMISC
+#define INCL_DOSPROCESS
+#define INCL_DOSERRORS
+#include <os2.h>
+#endif
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define PL_DestroyEvent VBoxNsplPL_DestroyEvent
+#define PL_HandleEvent VBoxNsplPL_HandleEvent
+#define PL_InitEvent VBoxNsplPL_InitEvent
+#define PL_CreateEventQueue VBoxNsplPL_CreateEventQueue
+#define PL_CreateMonitoredEventQueue VBoxNsplPL_CreateMonitoredEventQueue
+#define PL_CreateNativeEventQueue VBoxNsplPL_CreateNativeEventQueue
+#define PL_DequeueEvent VBoxNsplPL_DequeueEvent
+#define PL_DestroyEventQueue VBoxNsplPL_DestroyEventQueue
+#define PL_EventAvailable VBoxNsplPL_EventAvailable
+#define PL_EventLoop VBoxNsplPL_EventLoop
+#define PL_GetEvent VBoxNsplPL_GetEvent
+#define PL_GetEventOwner VBoxNsplPL_GetEventOwner
+#define PL_GetEventQueueMonitor VBoxNsplPL_GetEventQueueMonitor
+#define PL_GetEventQueueSelectFD VBoxNsplPL_GetEventQueueSelectFD
+#define PL_MapEvents VBoxNsplPL_MapEvents
+#define PL_PostEvent VBoxNsplPL_PostEvent
+#define PL_PostSynchronousEvent VBoxNsplPL_PostSynchronousEvent
+#define PL_ProcessEventsBeforeID VBoxNsplPL_ProcessEventsBeforeID
+#define PL_ProcessPendingEvents VBoxNsplPL_ProcessPendingEvents
+#define PL_RegisterEventIDFunc VBoxNsplPL_RegisterEventIDFunc
+#define PL_RevokeEvents VBoxNsplPL_RevokeEvents
+#define PL_UnregisterEventIDFunc VBoxNsplPL_UnregisterEventIDFunc
+#define PL_WaitForEvent VBoxNsplPL_WaitForEvent
+#define PL_IsQueueNative VBoxNsplPL_IsQueueNative
+#define PL_IsQueueOnCurrentThread VBoxNsplPL_IsQueueOnCurrentThread
+#define PL_FavorPerformanceHint VBoxNsplPL_FavorPerformanceHint
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/* Typedefs */
+
+typedef struct PLEvent PLEvent;
+typedef struct PLEventQueue PLEventQueue;
+
+/*******************************************************************************
+ * Event Queue Operations
+ ******************************************************************************/
+
+/*
+** Creates a new event queue. Returns NULL on failure.
+*/
+PR_EXTERN(PLEventQueue*)
+PL_CreateEventQueue(const char* name, PRThread* handlerThread);
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PL_CreateNativeEventQueue()
+**
+** DESCRIPTION:
+** PL_CreateNativeEventQueue() creates an event queue that
+** uses platform specific notify mechanisms.
+**
+** For Unix, the platform specific notify mechanism provides
+** an FD that may be extracted using the function
+** PL_GetEventQueueSelectFD(). The FD returned may be used in
+** a select() function call.
+**
+** For Windows, the platform specific notify mechanism
+** provides an event receiver window that is called by
+** Windows to process the event using the windows message
+** pump engine.
+**
+** INPUTS:
+** name: A name, as a diagnostic aid.
+**
+** handlerThread: A pointer to the PRThread structure for
+** the thread that will "handle" events posted to this event
+** queue.
+**
+** RETURNS:
+** A pointer to a PLEventQueue structure or NULL.
+**
+*/
+PR_EXTERN(PLEventQueue *)
+ PL_CreateNativeEventQueue(
+ const char *name,
+ PRThread *handlerThread
+ );
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PL_CreateMonitoredEventQueue()
+**
+** DESCRIPTION:
+** PL_CreateMonitoredEventQueue() creates an event queue. No
+** platform specific notify mechanism is created with the
+** event queue.
+**
+** Users of this type of event queue must explicitly poll the
+** event queue to retreive and process events.
+**
+**
+** INPUTS:
+** name: A name, as a diagnostic aid.
+**
+** handlerThread: A pointer to the PRThread structure for
+** the thread that will "handle" events posted to this event
+** queue.
+**
+** RETURNS:
+** A pointer to a PLEventQueue structure or NULL.
+**
+*/
+PR_EXTERN(PLEventQueue *)
+ PL_CreateMonitoredEventQueue(
+ const char *name,
+ PRThread *handlerThread
+ );
+
+/*
+** Destroys an event queue.
+*/
+PR_EXTERN(void)
+PL_DestroyEventQueue(PLEventQueue* self);
+
+/*
+** Returns the monitor associated with an event queue. This monitor is
+** selectable. The monitor should be entered to protect against anyone
+** calling PL_RevokeEvents while the event is trying to be constructed
+** and delivered.
+*/
+PR_EXTERN(PRMonitor*)
+PL_GetEventQueueMonitor(PLEventQueue* self);
+
+#define PL_ENTER_EVENT_QUEUE_MONITOR(queue) \
+ PR_EnterMonitor(PL_GetEventQueueMonitor(queue))
+
+#define PL_EXIT_EVENT_QUEUE_MONITOR(queue) \
+ PR_ExitMonitor(PL_GetEventQueueMonitor(queue))
+
+/*
+** Posts an event to an event queue, waking up any threads waiting for an
+** event. If event is NULL, notification still occurs, but no event will
+** be available.
+**
+** Any events delivered by this routine will be destroyed by PL_HandleEvent
+** when it is called (by the event-handling thread).
+*/
+PR_EXTERN(PRStatus)
+PL_PostEvent(PLEventQueue* self, PLEvent* event);
+
+/*
+** Like PL_PostEvent, this routine posts an event to the event handling
+** thread, but does so synchronously, waiting for the result. The result
+** which is the value of the handler routine is returned.
+**
+** Any events delivered by this routine will be not be destroyed by
+** PL_HandleEvent, but instead will be destroyed just before the result is
+** returned (by the current thread).
+*/
+PR_EXTERN(void*)
+PL_PostSynchronousEvent(PLEventQueue* self, PLEvent* event);
+
+/*
+** Gets an event from an event queue. Returns NULL if no event is
+** available.
+*/
+PR_EXTERN(PLEvent*)
+PL_GetEvent(PLEventQueue* self);
+
+/*
+** Returns true if there is an event available for PL_GetEvent.
+*/
+PR_EXTERN(PRBool)
+PL_EventAvailable(PLEventQueue* self);
+
+/*
+** This is the type of the function that must be passed to PL_MapEvents
+** (see description below).
+*/
+typedef void
+(PR_CALLBACK *PLEventFunProc)(PLEvent* event, void* data, PLEventQueue* queue);
+
+/*
+** Applies a function to every event in the event queue. This can be used
+** to selectively handle, filter, or remove events. The data pointer is
+** passed to each invocation of the function fun.
+*/
+PR_EXTERN(void)
+PL_MapEvents(PLEventQueue* self, PLEventFunProc fun, void* data);
+
+/*
+** This routine walks an event queue and destroys any event whose owner is
+** the owner specified. The == operation is used to compare owners.
+*/
+PR_EXTERN(void)
+PL_RevokeEvents(PLEventQueue* self, void* owner);
+
+/*
+** This routine processes all pending events in the event queue. It can be
+** called from the thread's main event-processing loop whenever the event
+** queue's selectFD is ready (returned by PL_GetEventQueueSelectFD).
+*/
+PR_EXTERN(void)
+PL_ProcessPendingEvents(PLEventQueue* self);
+
+/*******************************************************************************
+ * Pure Event Queues
+ *
+ * For when you're only processing PLEvents and there is no native
+ * select, thread messages, or AppleEvents.
+ ******************************************************************************/
+
+/*
+** Blocks until an event can be returned from the event queue. This routine
+** may return NULL if the current thread is interrupted.
+*/
+PR_EXTERN(PLEvent*)
+PL_WaitForEvent(PLEventQueue* self);
+
+/*
+** One stop shopping if all you're going to do is process PLEvents. Just
+** call this and it loops forever processing events as they arrive. It will
+** terminate when your thread is interrupted or dies.
+*/
+PR_EXTERN(void)
+PL_EventLoop(PLEventQueue* self);
+
+/*******************************************************************************
+ * Native Event Queues
+ *
+ * For when you need to call select, or WaitNextEvent, and yet also want
+ * to handle PLEvents.
+ ******************************************************************************/
+
+/*
+** This routine allows you to grab the file descriptor associated with an
+** event queue and use it in the readFD set of select. Useful for platforms
+** that support select, and must wait on other things besides just PLEvents.
+*/
+PR_EXTERN(PRInt32)
+PL_GetEventQueueSelectFD(PLEventQueue* self);
+
+/*
+** This routine will allow you to check to see if the given eventQueue in
+** on the current thread. It will return PR_TRUE if so, else it will return
+** PR_FALSE
+*/
+PR_EXTERN(PRBool)
+ PL_IsQueueOnCurrentThread( PLEventQueue *queue );
+
+/*
+** Returns whether the queue is native (true) or monitored (false)
+*/
+PR_EXTERN(PRBool)
+PL_IsQueueNative(PLEventQueue *queue);
+
+/*******************************************************************************
+ * Event Operations
+ ******************************************************************************/
+
+/*
+** The type of an event handler function. This function is passed as an
+** initialization argument to PL_InitEvent, and called by
+** PL_HandleEvent. If the event is called synchronously, a void* result
+** may be returned (otherwise any result will be ignored).
+*/
+typedef void*
+(PR_CALLBACK *PLHandleEventProc)(PLEvent* self);
+
+/*
+** The type of an event destructor function. This function is passed as
+** an initialization argument to PL_InitEvent, and called by
+** PL_DestroyEvent.
+*/
+typedef void
+(PR_CALLBACK *PLDestroyEventProc)(PLEvent* self);
+
+/*
+** Initializes an event. Usually events are embedded in a larger event
+** structure which holds event-specific data, so this is an initializer
+** for that embedded part of the structure.
+*/
+PR_EXTERN(void)
+PL_InitEvent(PLEvent* self, void* owner,
+ PLHandleEventProc handler,
+ PLDestroyEventProc destructor);
+
+/*
+** Returns the owner of an event.
+*/
+PR_EXTERN(void*)
+PL_GetEventOwner(PLEvent* self);
+
+/*
+** Handles an event, calling the event's handler routine.
+*/
+PR_EXTERN(void)
+PL_HandleEvent(PLEvent* self);
+
+/*
+** Destroys an event, calling the event's destructor.
+*/
+PR_EXTERN(void)
+PL_DestroyEvent(PLEvent* self);
+
+/*
+** Removes an event from an event queue.
+*/
+PR_EXTERN(void)
+PL_DequeueEvent(PLEvent* self, PLEventQueue* queue);
+
+
+/*
+ * Give hint to native PL_Event notification mechanism. If the native
+ * platform needs to tradeoff performance vs. native event starvation
+ * this hint tells the native dispatch code which to favor.
+ * The default is to prevent event starvation.
+ *
+ * Calls to this function may be nested. When the number of calls that
+ * pass PR_TRUE is subtracted from the number of calls that pass PR_FALSE
+ * is greater than 0, performance is given precedence over preventing
+ * event starvation.
+ *
+ * The starvationDelay arg is only used when
+ * favorPerformanceOverEventStarvation is PR_FALSE. It is the
+ * amount of time in milliseconds to wait before the PR_FALSE actually
+ * takes effect.
+ */
+PR_EXTERN(void)
+PL_FavorPerformanceHint(PRBool favorPerformanceOverEventStarvation, PRUint32 starvationDelay);
+
+
+/*******************************************************************************
+ * Private Stuff
+ ******************************************************************************/
+
+struct PLEvent {
+ PRCList link;
+ PLHandleEventProc handler;
+ PLDestroyEventProc destructor;
+ void* owner;
+ void* synchronousResult;
+ PRLock* lock;
+ PRCondVar* condVar;
+ PRBool handled;
+#ifdef PL_POST_TIMINGS
+ PRIntervalTime postTime;
+#endif
+#ifdef XP_UNIX
+ unsigned long id;
+#endif /* XP_UNIX */
+ /* other fields follow... */
+};
+
+/******************************************************************************/
+
+/*
+** Returns the event queue associated with the main thread.
+**
+*/
+#if defined(XP_WIN) || defined(XP_OS2)
+/* -----------------------------------------------------------------------
+** FUNCTION: PL_GetNativeEventReceiverWindow()
+**
+** DESCRIPTION:
+** PL_GetNativeEventReceiverWindow() returns the windows
+** handle of the event receiver window associated with the
+** referenced PLEventQueue argument.
+**
+** INPUTS:
+** PLEventQueue pointer
+**
+** RETURNS:
+** event receiver window handle.
+**
+** RESTRICTIONS: MS-Windows ONLY.
+**
+*/
+PR_EXTERN(HWND)
+ PL_GetNativeEventReceiverWindow(
+ PLEventQueue *eqp
+ );
+#endif /* XP_WIN || XP_OS2 */
+
+#ifdef XP_UNIX
+/* -----------------------------------------------------------------------
+** FUNCTION: PL_ProcessEventsBeforeID()
+**
+** DESCRIPTION:
+**
+** PL_ProcessEventsBeforeID() will process events in a native event
+** queue that have an id that is older than the ID passed in.
+**
+** INPUTS:
+** PLEventQueue *aSelf
+** unsigned long aID
+**
+** RETURNS:
+** PRInt32 number of requests processed, -1 on error.
+**
+** RESTRICTIONS: Unix only (well, X based unix only)
+*/
+PR_EXTERN(PRInt32)
+PL_ProcessEventsBeforeID(PLEventQueue *aSelf, unsigned long aID);
+
+/* This prototype is a function that can be called when an event is
+ posted to stick an ID on it. */
+
+typedef unsigned long
+(PR_CALLBACK *PLGetEventIDFunc)(void *aClosure);
+
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PL_RegisterEventIDFunc()
+**
+** DESCRIPTION:
+**
+** This function registers a function for getting the ID on unix for
+** this event queue.
+**
+** INPUTS:
+** PLEventQueue *aSelf
+** PLGetEventIDFunc func
+** void *aClosure
+**
+** RETURNS:
+** void
+**
+** RESTRICTIONS: Unix only (well, X based unix only) */
+PR_EXTERN(void)
+PL_RegisterEventIDFunc(PLEventQueue *aSelf, PLGetEventIDFunc aFunc,
+ void *aClosure);
+
+/* -----------------------------------------------------------------------
+** FUNCTION: PL_RegisterEventIDFunc()
+**
+** DESCRIPTION:
+**
+** This function unregisters a function for getting the ID on unix for
+** this event queue.
+**
+** INPUTS:
+** PLEventQueue *aSelf
+**
+** RETURNS:
+** void
+**
+** RESTRICTIONS: Unix only (well, X based unix only) */
+PR_EXTERN(void)
+PL_UnregisterEventIDFunc(PLEventQueue *aSelf);
+
+#endif /* XP_UNIX */
+
+
+/* ----------------------------------------------------------------------- */
+
+#if defined(NO_NSPR_10_SUPPORT)
+#else
+/********* ???????????????? FIX ME ??????????????????????????? *****/
+/********************** Some old definitions *****************************/
+
+/* Re: prevent.h->plevent.h */
+#define PREvent PLEvent
+#define PREventQueue PLEventQueue
+#define PR_CreateEventQueue PL_CreateEventQueue
+#define PR_DestroyEventQueue PL_DestroyEventQueue
+#define PR_GetEventQueueMonitor PL_GetEventQueueMonitor
+#define PR_ENTER_EVENT_QUEUE_MONITOR PL_ENTER_EVENT_QUEUE_MONITOR
+#define PR_EXIT_EVENT_QUEUE_MONITOR PL_EXIT_EVENT_QUEUE_MONITOR
+#define PR_PostEvent PL_PostEvent
+#define PR_PostSynchronousEvent PL_PostSynchronousEvent
+#define PR_GetEvent PL_GetEvent
+#define PR_EventAvailable PL_EventAvailable
+#define PREventFunProc PLEventFunProc
+#define PR_MapEvents PL_MapEvents
+#define PR_RevokeEvents PL_RevokeEvents
+#define PR_ProcessPendingEvents PL_ProcessPendingEvents
+#define PR_WaitForEvent PL_WaitForEvent
+#define PR_EventLoop PL_EventLoop
+#define PR_GetEventQueueSelectFD PL_GetEventQueueSelectFD
+#define PRHandleEventProc PLHandleEventProc
+#define PRDestroyEventProc PLDestroyEventProc
+#define PR_InitEvent PL_InitEvent
+#define PR_GetEventOwner PL_GetEventOwner
+#define PR_HandleEvent PL_HandleEvent
+#define PR_DestroyEvent PL_DestroyEvent
+#define PR_DequeueEvent PL_DequeueEvent
+#define PR_GetMainEventQueue PL_GetMainEventQueue
+
+/********* ????????????? End Fix me ?????????????????????????????? *****/
+#endif /* NO_NSPR_10_SUPPORT */
+
+PR_END_EXTERN_C
+
+#endif /* plevent_h___ */
diff --git a/src/libs/xpcom18a4/xpcom/tools/.cvsignore b/src/libs/xpcom18a4/xpcom/tools/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tools/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/tools/Makefile.in b/src/libs/xpcom18a4/xpcom/tools/Makefile.in
new file mode 100644
index 00000000..be87de04
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tools/Makefile.in
@@ -0,0 +1,53 @@
+#
+# ***** 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
+DIRS = registry
+
+ifeq ($(OS_ARCH),WINNT)
+DIRS += windows
+endif
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/tools/analyze-xpcom-log.pl b/src/libs/xpcom18a4/xpcom/tools/analyze-xpcom-log.pl
new file mode 100755
index 00000000..81ccb212
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tools/analyze-xpcom-log.pl
@@ -0,0 +1,177 @@
+#!/usr/local/bin/perl -w
+
+# Perl script to analyze the xpcom output file
+#
+# To create xpcom output file :
+#
+# setenv NSPR_LOG_MODULES nsComponentManager:5
+# setenv NSPR_LOG_FILE xpcom.out
+# ./mozilla
+#
+# Also to try to convert CID -> contractID this program looks for
+# a file reg.out in the current directory. To generate this file
+#
+# $ regExport > reg.out
+#
+# Usage: analyze-xpcom-log.pl < xpcom.out
+# [does better if ./reg.out is available]
+#
+# Suresh Duddi <dpsuresh@netscape.net>
+
+
+use strict;
+
+# forward declarations
+sub getContractID($);
+sub sum($);
+
+# Configuration parameters
+# Print all ?
+my $all = 0;
+
+# hash of cid -> contractid
+my %contractid;
+my %contractid_n;
+my %failedContractid_n;
+
+# count of instances of objects created
+my (%objs, %objs_contractid, %failedObjs) = ();
+
+# dlls loaded
+my @dlls;
+
+# temporaries
+my ($cid, $n, $str);
+
+while (<>) {
+ chomp;
+
+ # dlls loaded
+ if (/loading \"(.*)\"/) {
+ push @dlls, $1;
+ next;
+ }
+
+ # FAILED ContractIDToClassID
+ if (/ContractIDToClassID\((.*)\).*\[FAILED\]/) {
+ $failedContractid_n{$1}++;
+ next;
+ }
+
+ # ContractIDToClassID
+ if (/ContractIDToClassID\((.*)\).*\{(.*)\}/) {
+ $contractid{$2} = $1;
+ $contractid_n{$2}++;
+ next;
+ }
+
+ # CreateInstance()
+ if (/CreateInstance\(\{(.*)\}\) succeeded/) {
+ $objs{$1}++;
+ next;
+ }
+
+ # CreateInstanceByContractID()
+ if (/CreateInstanceByContractID\((.*)\) succeeded/) {
+ $objs_contractid{$1}++;
+ next;
+ }
+
+ # FAILED CreateInstance()
+ if (/CreateInstance\(\{(.*)\}\) FAILED/) {
+ $failedObjs{$1}++;
+ next;
+ }
+}
+
+# if there is a file named reg.out in the current dir
+# then use that to fill in the ContractIDToClassID mapping.
+my $REG;
+open REG, "<reg.out";
+while (<REG>) {
+ chomp;
+ if (/contractID - (.*)$/) {
+ my $id = $1;
+ $cid = <REG>;
+ chomp($cid);
+ $cid =~ s/^.*\{(.*)\}.*$/$1/;
+ $contractid{$cid} = $id;
+ }
+}
+
+# print results
+# ----------------------------------------------------------------------
+
+# dlls loaded
+print "dlls loaded [", scalar @dlls, "]\n";
+print "----------------------------------------------------------------------\n";
+for ($n = 0; $n < scalar @dlls; $n++) {
+ printf "%2d. %s\n", $n+1, $dlls[$n];
+}
+print "\n";
+
+# Objects created
+print "Object creations from CID [", sum(\%objs), "]\n";
+print "----------------------------------------------------------------------\n";
+foreach $cid (sort {$objs{$b} <=> $objs{$a} } keys %objs) {
+ last if (!$all && $objs{$cid} < 50);
+ printf "%5d. %s - %s\n", $objs{$cid}, $cid, getContractID($cid);
+}
+print "\n";
+
+print "Object creations from ContractID [", sum(\%objs_contractid), "]\n";
+print "----------------------------------------------------------------------\n";
+foreach $cid (sort {$objs_contractid{$b} <=> $objs_contractid{$a} } keys %objs_contractid) {
+ last if (!$all && $objs_contractid{$cid} < 50);
+ printf "%5d. %s - %s\n", $objs_contractid{$cid}, $cid, getContractID($cid);
+}
+print "\n";
+
+# FAILED Objects created
+print "FAILED Objects creations [", sum(\%failedObjs), "]\n";
+print "----------------------------------------------------------------------\n";
+foreach $cid (sort {$failedObjs{$b} <=> $failedObjs{$a} } keys %failedObjs) {
+ last if (!$all && $failedObjs{$cid} < 50);
+ printf "%5d. %s - %s", $failedObjs{$cid}, $cid, getContractID($cid);
+}
+print "\n";
+
+# ContractIDToClassID calls
+print "ContractIDToClassID() calls [", sum(\%contractid_n),"]\n";
+print "----------------------------------------------------------------------\n";
+foreach $cid (sort {$contractid_n{$b} <=> $contractid_n{$a} } keys %contractid_n) {
+ last if (!$all && $contractid_n{$cid} < 50);
+ printf "%5d. %s - %s\n", $contractid_n{$cid}, $cid, getContractID($cid);
+}
+print "\n";
+
+
+# FAILED ContractIDToClassID calls
+print "FAILED ContractIDToClassID() calls [", sum(\%failedContractid_n), "]\n";
+print "----------------------------------------------------------------------\n";
+foreach $cid (sort {$failedContractid_n{$b} <=> $failedContractid_n{$a} } keys %failedContractid_n) {
+ last if (!$all && $failedContractid_n{$cid} < 50);
+ printf "%5d. %s\n", $failedContractid_n{$cid}, $cid;
+}
+print "\n";
+
+
+# Subroutines
+
+sub getContractID($) {
+ my $cid = shift;
+ my $ret = "";
+ $ret = $contractid{$cid} if (exists $contractid{$cid});
+ return $ret;
+}
+
+sub sum($) {
+ my $hash_ref = shift;
+ my %hash = %$hash_ref;
+ my $total = 0;
+ my $key;
+ foreach $key (keys %hash) {
+ $total += $hash{$key};
+ }
+ return $total;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tools/registry/.cvsignore b/src/libs/xpcom18a4/xpcom/tools/registry/.cvsignore
new file mode 100644
index 00000000..91acd38b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tools/registry/.cvsignore
@@ -0,0 +1,3 @@
+Makefile
+regExport
+regxpcom
diff --git a/src/libs/xpcom18a4/xpcom/tools/registry/Makefile.in b/src/libs/xpcom18a4/xpcom/tools/registry/Makefile.in
new file mode 100644
index 00000000..5c19d014
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tools/registry/Makefile.in
@@ -0,0 +1,77 @@
+#
+# ***** 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
+CPPSRCS = regxpcom.cpp
+
+DEFINES += -DXPCOM_GLUE
+
+REQUIRES = \
+ string \
+ $(NULL)
+
+LOCAL_INCLUDES = \
+ -I$(srcdir)/../../build \
+ $(NULL)
+
+SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))
+
+LIBS = \
+ $(DIST)/lib/$(LIB_PREFIX)xpcomglue.$(LIB_SUFFIX) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+# Need to link with CoreFoundation on Mac
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+LIBS += \
+ $(TK_LIBS) \
+ $(NULL)
+endif
+
+SDK_BINARY = \
+ $(SIMPLE_PROGRAMS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/tools/registry/regxpcom.cpp b/src/libs/xpcom18a4/xpcom/tools/registry/regxpcom.cpp
new file mode 100644
index 00000000..b8822b8f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tools/registry/regxpcom.cpp
@@ -0,0 +1,404 @@
+/* -*- 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>
+ * Mike Shaver <shaver@mozilla.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 ***** */
+
+#include "stdlib.h"
+#include "prenv.h"
+#include "nspr.h"
+
+#include "nsXPCOMPrivate.h" // for XPCOM_DLL defines.
+
+#include "nsXPCOMGlue.h"
+#include "nsIComponentManager.h"
+#include "nsIComponentRegistrar.h"
+#include "nsIServiceManager.h"
+#include "nsCOMPtr.h"
+#include "nsILocalFile.h"
+#include "nsEmbedString.h"
+#include "nsIDirectoryService.h"
+#include "nsDirectoryServiceDefs.h"
+
+
+static PRBool gUnreg = PR_FALSE, gQuiet = PR_FALSE;
+
+static const char* gXPCOMLocation = nsnull;
+static const char* gCompRegLocation = nsnull;
+static const char* gXPTIDatLocation = nsnull;
+static char* gPathEnvString = nsnull;
+
+class DirectoryServiceProvider : public nsIDirectoryServiceProvider
+{
+ public:
+ DirectoryServiceProvider() {}
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIDIRECTORYSERVICEPROVIDER
+
+ private:
+ ~DirectoryServiceProvider() {}
+};
+
+NS_IMPL_ISUPPORTS1(DirectoryServiceProvider, nsIDirectoryServiceProvider)
+
+NS_IMETHODIMP
+DirectoryServiceProvider::GetFile(const char *prop, PRBool *persistant, nsIFile **_retval)
+{
+ nsCOMPtr<nsILocalFile> localFile;
+ nsresult rv = NS_ERROR_FAILURE;
+
+ *_retval = nsnull;
+ *persistant = PR_TRUE;
+
+ const char* fileLocation = nsnull;
+
+ if(strcmp(prop, NS_XPCOM_CURRENT_PROCESS_DIR) == 0 && gXPCOMLocation)
+ {
+ fileLocation = gXPCOMLocation;
+ }
+ else if(strcmp(prop, NS_XPCOM_COMPONENT_REGISTRY_FILE) == 0 && gCompRegLocation)
+ {
+ fileLocation = gCompRegLocation;
+ }
+ else if(strcmp(prop, NS_XPCOM_XPTI_REGISTRY_FILE) == 0 && gXPTIDatLocation)
+ {
+ fileLocation = gXPTIDatLocation;
+ }
+ else
+ return NS_ERROR_FAILURE;
+
+ rv = NS_NewNativeLocalFile(nsEmbedCString(fileLocation), PR_TRUE, getter_AddRefs(localFile));
+ if (NS_FAILED(rv)) return rv;
+
+ return localFile->QueryInterface(NS_GET_IID(nsIFile), (void**)_retval);
+}
+
+int startup_xpcom()
+{
+ nsresult rv;
+
+ if (gXPCOMLocation) {
+ int len = strlen(gXPCOMLocation);
+ char* xpcomPath = (char*) malloc(len + sizeof(XPCOM_DLL) + sizeof(XPCOM_FILE_PATH_SEPARATOR) + 1);
+ sprintf(xpcomPath, "%s" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL, gXPCOMLocation);
+
+ rv = XPCOMGlueStartup(xpcomPath);
+
+ free(xpcomPath);
+
+ const char* path = PR_GetEnv(XPCOM_SEARCH_KEY);
+ if (!path) {
+ path = "";
+ }
+
+ if (gPathEnvString)
+ PR_smprintf_free(gPathEnvString);
+
+ gPathEnvString = PR_smprintf("%s=%s;%s",
+ XPCOM_SEARCH_KEY,
+ gXPCOMLocation,
+ path);
+
+ if (gXPCOMLocation)
+ PR_SetEnv(gPathEnvString);
+ }
+ else
+ {
+ rv = XPCOMGlueStartup(nsnull);
+ }
+
+ if (NS_FAILED(rv))
+ {
+ printf("Can not initialize XPCOM Glue\n");
+ return -1;
+ }
+
+ DirectoryServiceProvider *provider = new DirectoryServiceProvider();
+ if ( !provider )
+ {
+ NS_WARNING("GRE_Startup failed");
+ XPCOMGlueShutdown();
+ return -1;
+ }
+
+ nsCOMPtr<nsILocalFile> file;
+ if (gXPCOMLocation)
+ {
+ rv = NS_NewNativeLocalFile(nsEmbedCString(gXPCOMLocation),
+ PR_TRUE,
+ getter_AddRefs(file));
+ }
+
+ NS_ADDREF(provider);
+ rv = NS_InitXPCOM2(nsnull, file, provider);
+ NS_RELEASE(provider);
+
+ if (NS_FAILED(rv)) {
+ printf("Can not initialize XPCOM\n");
+ XPCOMGlueShutdown();
+ return -1;
+ }
+
+ return 0;
+}
+
+void shutdown_xpcom()
+{
+ nsresult rv;
+
+ rv = NS_ShutdownXPCOM(nsnull);
+
+ if (NS_FAILED(rv)) {
+ printf("Can not shutdown XPCOM cleanly\n");
+ }
+
+ rv = XPCOMGlueShutdown();
+
+ if (NS_FAILED(rv)) {
+ printf("Can not shutdown XPCOM Glue cleanly\n");
+ }
+ if (gPathEnvString)
+ PR_smprintf_free(gPathEnvString);
+}
+
+
+nsresult Register(const char *path)
+{
+ startup_xpcom();
+
+ nsresult rv;
+ nsCOMPtr<nsILocalFile> spec;
+
+ if (path) {
+ rv = NS_NewNativeLocalFile(nsEmbedCString(path),
+ PR_TRUE,
+ getter_AddRefs(spec));
+ }
+
+ nsCOMPtr<nsIComponentRegistrar> registrar;
+ rv = NS_GetComponentRegistrar(getter_AddRefs(registrar));
+ if (NS_FAILED(rv)) {
+ printf("Can not aquire component registrar\n");
+ return rv;
+ }
+
+ if (gUnreg)
+ rv = registrar->AutoUnregister(spec);
+ else
+ rv = registrar->AutoRegister(spec);
+
+ spec = 0;
+ registrar = 0;
+
+ shutdown_xpcom();
+ return rv;
+}
+
+
+void ReportSuccess(const char *file)
+{
+ if (gQuiet)
+ return;
+
+ if (gUnreg)
+ printf("Unregistration successful for %s\n", file);
+ else
+ printf("Registration successful for %s\n", file);
+}
+
+void ReportError(nsresult err, const char *file)
+{
+ if (gUnreg)
+ printf("Unregistration failed: (");
+ else
+ printf("Registration failed: (");
+
+ switch (err)
+ {
+ case NS_ERROR_FACTORY_NOT_LOADED:
+ printf("Factory not loaded");
+ break;
+ case NS_NOINTERFACE:
+ printf("No Interface");
+ break;
+ case NS_ERROR_NULL_POINTER:
+ printf("Null pointer");
+ break;
+ case NS_ERROR_OUT_OF_MEMORY:
+ printf("Out of memory");
+ break;
+ default:
+ printf("%x", (unsigned)err);
+ }
+
+ printf(") %s\n", file);
+}
+
+void printHelp()
+{
+ printf(
+"Mozilla regxpcom - a registration tool for xpcom components \n"
+" \n"
+"Usage: regxpcom [options] [file-or-directory] \n"
+" \n"
+"Options: \n"
+" -x path Specifies the location of a directory containing the \n"
+" xpcom library which will be used when registering new \n"
+" component libraries. This path will also be added to \n"
+" the \"load library\" path. If not specified, the \n"
+" current working directory will be used. \n"
+" -c path Specifies the location of the compreg.dat file. If \n"
+" not specifed, the compreg.dat file will be in its \n"
+" default location. \n"
+" -d path Specifies the location of the xpti.dat file. If not \n"
+" specifed, the xpti.dat file will be in its default \n"
+" location. \n"
+" -a Option to register all files in the default component \n"
+" directories. This is the default behavior if regxpcom \n"
+" is called without any arguments. \n"
+" -h Displays this help screen. Must be the only option \n"
+" specified. \n"
+" -u Option to uninstall the files-or-directory instead of \n"
+" registering them. \n"
+" -q Quiets some of the output of regxpcom. \n\n");
+}
+
+int ProcessArgs(int argc, char *argv[])
+{
+ int i = 1, result = 0;
+ nsresult res;
+
+ while (i < argc)
+ {
+ if (argv[i][0] == '-')
+ {
+ int j;
+ for (j = 1; argv[i][j] != '\0'; j++)
+ {
+ switch (argv[i][j])
+ {
+ case 'h':
+ printHelp();
+ return 0; // we are all done!
+
+ case 'u':
+ gUnreg = PR_TRUE;
+ break;
+
+ case 'q':
+ gQuiet = PR_TRUE;
+ break;
+
+ case 'a':
+ {
+ res = Register(nsnull);
+ if (NS_FAILED(res))
+ {
+ ReportError(res, "component directory");
+ result = -1;
+ }
+ else
+ {
+ ReportSuccess("component directory");
+ }
+ }
+ break;
+
+ case 'x':
+ gXPCOMLocation = argv[++i];
+ j = strlen(gXPCOMLocation) - 1;
+ break;
+
+ case 'c':
+ gCompRegLocation = argv[++i];
+ j = strlen(gCompRegLocation) - 1;
+ break;
+
+ case 'd':
+ gXPTIDatLocation = argv[++i];
+ j = strlen(gXPTIDatLocation) - 1;
+ break;
+
+ default:
+ printf("Unknown option '%c'\n", argv[i][j]);
+ }
+ }
+ }
+ else
+ {
+ res = Register(argv[i]);
+
+ if (NS_FAILED(res))
+ {
+ ReportError(res, argv[i]);
+ result = -1;
+ }
+ else
+ {
+ ReportSuccess(argv[i]);
+ }
+ }
+ i++;
+ }
+ return result;
+}
+
+
+int main(int argc, char *argv[])
+{
+ int ret;
+ nsresult rv;
+
+ /* With no arguments, regxpcom will autoregister */
+ if (argc <= 1)
+ {
+ startup_xpcom();
+ nsCOMPtr<nsIComponentRegistrar> registrar;
+ rv = NS_GetComponentRegistrar(getter_AddRefs(registrar));
+ if (NS_FAILED(rv)) {
+ printf("Can not aquire component registrar\n");
+ return -1;
+ }
+ rv = registrar->AutoRegister(nsnull);
+ ret = (NS_FAILED(rv)) ? -1 : 0;
+ registrar = 0;
+ shutdown_xpcom();
+ } else
+ ret = ProcessArgs(argc, argv);
+
+ return ret;
+}
diff --git a/src/libs/xpcom18a4/xpcom/tools/windows/.cvsignore b/src/libs/xpcom18a4/xpcom/tools/windows/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tools/windows/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/tools/windows/Makefile.in b/src/libs/xpcom18a4/xpcom/tools/windows/Makefile.in
new file mode 100644
index 00000000..f6ba7e69
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tools/windows/Makefile.in
@@ -0,0 +1,52 @@
+#
+# ***** 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
+
+SIMPLE_PROGRAMS = rebasedlls$(BIN_SUFFIX)
+
+CPPSRCS = rebasedlls.cpp
+
+OS_LIBS += $(call EXPAND_LIBNAME,imagehlp)
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/tools/windows/rebasedlls.cpp b/src/libs/xpcom18a4/xpcom/tools/windows/rebasedlls.cpp
new file mode 100644
index 00000000..321160e7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/tools/windows/rebasedlls.cpp
@@ -0,0 +1,104 @@
+/* -*- 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 <windows.h>
+#include <stdio.h>
+#include <imagehlp.h>
+#include <time.h>
+
+static char* gSymbolPath = NULL;
+static DWORD gBaseAddr = (DWORD) 0x60000000;
+static time_t now;
+
+static void
+ReBase(char* aDLLName)
+{
+ DWORD oldsize, oldbase, newsize;
+ DWORD newbase = gBaseAddr;
+ BOOL b = ReBaseImage(aDLLName, gSymbolPath, TRUE, FALSE, FALSE,
+ 0, &oldsize, &oldbase, &newsize, &newbase,
+ now);
+ DWORD lastError = ::GetLastError();
+ printf("%-20s %08x %08x %08x %08x",
+ aDLLName, oldbase, oldsize, newbase, newsize);
+ if (!b) {
+ printf(" (failed: error=%d/0x%x)", lastError, lastError);
+ }
+ fputs("\n", stdout);
+
+ // advance base; round size up to nearest 64k
+ newsize = ((newsize + 65535) >> 16) << 16;
+ gBaseAddr = newbase + newsize;
+}
+
+static void
+Usage()
+{
+ printf("Usage: ReBase [-libs library-path] dlls...\n");
+}
+
+int
+main(int argc, char** argv)
+{
+ now = time(0);
+ int i;
+ for (i = 1; i < argc; i++) {
+ if (argv[i][0] == '-') {
+ if (strcmp(argv[i], "-libs") == 0) {
+ if (i == argc - 1) {
+ Usage();
+ return -1;
+ }
+ gSymbolPath = argv[++i];
+ }
+ else {
+ Usage();
+ return -1;
+ }
+ }
+ else
+ break;
+ }
+
+ if (i < argc) {
+ printf("Library OldBase OldSize NewBase NewSize\n");
+ printf("------- ------- ------- ------- -------\n");
+ }
+ for (; i < argc; i++) {
+ ReBase(argv[i]);
+ }
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/typelib/.cvsignore b/src/libs/xpcom18a4/xpcom/typelib/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/typelib/Makefile.in b/src/libs/xpcom18a4/xpcom/typelib/Makefile.in
new file mode 100644
index 00000000..43d92023
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/Makefile.in
@@ -0,0 +1,49 @@
+#
+# ***** 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
+DIRS = xpt xpidl
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/.cvsignore b/src/libs/xpcom18a4/xpcom/typelib/xpidl/.cvsignore
new file mode 100644
index 00000000..8e5eac0d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/.cvsignore
@@ -0,0 +1,2 @@
+xpidl
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/Makefile.in b/src/libs/xpcom18a4/xpcom/typelib/xpidl/Makefile.in
new file mode 100644
index 00000000..ae228ef0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/Makefile.in
@@ -0,0 +1,88 @@
+#
+# The contents of this file are subject to the Netscape 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/NPL/
+#
+# 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 Netscape are
+# Copyright (C) 1998 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+PROGRAM = xpidl$(BIN_SUFFIX)
+INTERNAL_TOOLS = 1
+
+# glib and libIDL link against the non-debug msvcrt
+MOZ_NO_DEBUG_RTL=1
+
+CSRCS = \
+ xpidl.c \
+ xpidl_idl.c \
+ xpidl_util.c \
+ xpidl_header.c \
+ xpidl_typelib.c \
+ xpidl_doc.c \
+ xpidl_java.c \
+ $(NULL)
+
+SDK_BINARY = \
+ $(PROGRAM) \
+ $(NULL)
+
+ifdef CROSS_COMPILE
+HOST_PROGRAM = host_xpidl$(HOST_BIN_SUFFIX)
+HOST_CSRCS = $(CSRCS)
+endif
+
+include $(topsrcdir)/config/rules.mk
+
+CFLAGS += $(LIBIDL_CFLAGS)
+
+# Compile directly against the static lib, so we can use xpidl during the build
+# without the shared library path being set.
+ifeq (WINNT,$(OS_ARCH))
+DEFINES += -DEXPORT_XPT_API
+ifndef GNU_CC
+LDFLAGS += -SUBSYSTEM:CONSOLE -NODEFAULTLIB:MSVCRTD
+endif
+endif
+
+# Tell the $(PROGRAM) target that we need to be recompiled when libxpt changes.
+LIBS = $(DIST)/lib/$(LIB_PREFIX)xpt.$(LIB_SUFFIX) $(LIBIDL_LIBS)
+EXTRA_DEPS = $(wildcard $(DIST)/lib/$(LIB_PREFIX)xpt.*)
+
+ifdef CROSS_COMPILE
+HOST_CFLAGS += $(HOST_LIBIDL_CFLAGS)
+HOST_LIBS = $(DIST)/host/lib/libhostxpt.$(LIB_SUFFIX) $(HOST_LIBIDL_LIBS)
+HOST_EXTRA_DEPS = $(wildcard $(DIST)/host/lib/libhostxpt.*)
+
+ifdef HOST_NSPR_MDCPUCFG
+HOST_CFLAGS += -DMDCPUCFG=$(HOST_NSPR_MDCPUCFG)
+endif
+endif
+
+ifdef MACOS_SDK_DIR
+NEXT_ROOT=
+OS_LIBS := $(patsubst -L$(MACOS_SDK_DIR)/usr/lib%,,$(OS_LIBS))
+endif
+
+export::
+ @$(MAKE) libs
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/README b/src/libs/xpcom18a4/xpcom/typelib/xpidl/README
new file mode 100644
index 00000000..b7a400e0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/README
@@ -0,0 +1,16 @@
+Wed Dec 2 14:35:41 EST 1998
+
+xpidl depends on Andrew Veliath and Elliot Lee's libIDL, a part of the
+GNOME ORBit C ORB. We currently require libIDL >= 0.6.3, which in turn
+requires glib >= 1.2.0.
+
+libIDL builds for Linux and Win32 can be found, along with source
+tarballs, at http://www.rpi.edu/~veliaa/libIDL/, and Win32 users will
+need glib 1.2 and glib 1.2-dev from
+http://user.sgic.fi/~tml/gimp/win32/. Source and Linux RPMs are also
+available from ftp://ftp.mozilla.org/pub/mozilla/libraries, and Win32
+binaries are included in the wintools.zip file at
+ftp://ftp.mozilla.org/pub/mozilla/source/wintools.zip. A Mac project
+is in progress, and should be appearing shortly.
+
+glib tarballs and RPMs for Linux can be found through http://www.gtk.org.
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/compiler.rsrc b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/compiler.rsrc
new file mode 100644
index 00000000..fb06f6a3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/compiler.rsrc
Binary files differ
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/linker.rsrc b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/linker.rsrc
new file mode 100644
index 00000000..bec7c043
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/linker.rsrc
Binary files differ
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_console.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_console.c
new file mode 100644
index 00000000..ecda11e0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_console.c
@@ -0,0 +1,139 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "mac_console.h"
+
+#ifndef __CONSOLE__
+#include <console.h>
+#endif
+
+extern CWPluginContext gPluginContext;
+
+UInt32 mac_console_count = 0;
+CWMemHandle mac_console_handle = NULL;
+
+/*
+ * The following four functions provide the UI for the console package.
+ * Users wishing to replace SIOUX with their own console package need
+ * only provide the four functions below in a library.
+ */
+
+/*
+ * extern short InstallConsole(short fd);
+ *
+ * Installs the Console package, this function will be called right
+ * before any read or write to one of the standard streams.
+ *
+ * short fd: The stream which we are reading/writing to/from.
+ * returns short: 0 no error occurred, anything else error.
+ */
+
+short InstallConsole(short fd)
+{
+#pragma unused (fd)
+ mac_console_count = 0;
+ CWAllocMemHandle(gPluginContext, 8192, false, &mac_console_handle);
+ return 0;
+}
+
+/*
+ * extern void RemoveConsole(void);
+ *
+ * Removes the console package. It is called after all other streams
+ * are closed and exit functions (installed by either atexit or _atexit)
+ * have been called. Since there is no way to recover from an error,
+ * this function doesn't need to return any.
+ */
+
+void RemoveConsole(void)
+{
+ if (mac_console_handle != NULL) {
+ CWFreeMemHandle(gPluginContext, mac_console_handle);
+ mac_console_handle = NULL;
+ }
+}
+
+/*
+ * extern long WriteCharsToConsole(char *buffer, long n);
+ *
+ * Writes a stream of output to the Console window. This function is
+ * called by write.
+ *
+ * char *buffer: Pointer to the buffer to be written.
+ * long n: The length of the buffer to be written.
+ * returns short: Actual number of characters written to the stream,
+ * -1 if an error occurred.
+ */
+
+long WriteCharsToConsole(char *buffer, long n)
+{
+ long size = 0;
+ void* ptr = NULL;
+
+ if (CWGetMemHandleSize(gPluginContext, mac_console_handle, &size) == noErr) {
+ if (mac_console_count + n >= size) {
+ size += 8192;
+ if (CWResizeMemHandle(gPluginContext, mac_console_handle, size) != noErr)
+ return -1;
+ }
+ }
+
+ if (CWLockMemHandle(gPluginContext, mac_console_handle, false, &ptr) == noErr) {
+ BlockMoveData(buffer, (char *)ptr + mac_console_count, n);
+ mac_console_count += n;
+ CWUnlockMemHandle(gPluginContext, mac_console_handle);
+ }
+
+ return 0;
+}
+
+/*
+ * extern long ReadCharsFromConsole(char *buffer, long n);
+ *
+ * Reads from the Console into a buffer. This function is called by
+ * read.
+ *
+ * char *buffer: Pointer to the buffer which will recieve the input.
+ * long n: The maximum amount of characters to be read (size of
+ * buffer).
+ * returns short: Actual number of characters read from the stream,
+ * -1 if an error occurred.
+ */
+
+long ReadCharsFromConsole(char *buffer, long n)
+{
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_console.h b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_console.h
new file mode 100644
index 00000000..88809f85
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_console.h
@@ -0,0 +1,49 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ mac_console.h
+ */
+
+#pragma once
+
+#include <Files.h>
+#include <Memory.h>
+
+#include "CWPlugins.h"
+
+extern UInt32 mac_console_count;
+extern CWMemHandle mac_console_handle;
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_memory.cpp b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_memory.cpp
new file mode 100644
index 00000000..41d03d88
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_memory.cpp
@@ -0,0 +1,146 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ mac_memory.cpp
+ */
+
+#include <new.h>
+#include <stdlib.h>
+
+#include <Files.h>
+#include <Memory.h>
+
+#include "DropInCompilerLinker.h"
+#include "CompilerMapping.h"
+#include "CWPluginErrors.h"
+
+extern CWPluginContext gPluginContext;
+
+/**
+ * Note: memory allocated by these operators will automatically be freed after the
+ * current call into xpidl_compiler completes. This should be fine in most cases,
+ * as we are also having the compiler be reloaded for every request to reinitialize
+ * global data. Just be careful out there!
+ */
+
+const Boolean kTemporaryAllocation = false;
+
+void* operator new(size_t size)
+{
+ void* ptr = NULL;
+ if (CWAllocateMemory(gPluginContext, size, kTemporaryAllocation, &ptr) == cwNoErr)
+ return ptr;
+ return NULL;
+}
+
+void operator delete(void* ptr)
+{
+ if (ptr != NULL)
+ CWFreeMemory(gPluginContext, ptr, kTemporaryAllocation);
+}
+
+void* operator new[] (size_t size)
+{
+ void* ptr = NULL;
+ if (CWAllocateMemory(gPluginContext, size, kTemporaryAllocation, &ptr) == cwNoErr)
+ return ptr;
+ return NULL;
+}
+
+void operator delete[](void* ptr)
+{
+ if (ptr != NULL)
+ CWFreeMemory(gPluginContext, ptr, kTemporaryAllocation);
+}
+
+namespace std {
+
+#define TRACK_ALLOCATION
+#define kTrackedCookie 'TRKD'
+
+void* malloc(size_t size)
+{
+#if defined(TRACK_ALLOCATION)
+ OSType* ptr = (OSType*) new char[sizeof(OSType) + size];
+ if (ptr != NULL)
+ *ptr++ = kTrackedCookie;
+ return ptr;
+#else
+ return new char[size];
+#endif
+}
+
+void free(void *ptr)
+{
+#if defined(TRACK_ALLOCATION)
+ OSType* type = (OSType*)ptr;
+ if (*--type == kTrackedCookie)
+ delete[] (char*) type;
+ else
+ DebugStr("\pillegal block passed to free.");
+#else
+ delete[] (char*) ptr;
+#endif
+}
+
+void* calloc(size_t nmemb, size_t size)
+{
+ size *= nmemb;
+ void* ptr = malloc(size);
+ if (ptr != NULL) {
+ BlockZero(ptr, size);
+ }
+ return ptr;
+}
+
+void* realloc(void * ptr, size_t size)
+{
+ void* newptr = NULL;
+
+ if (size > 0)
+ newptr = malloc(size);
+
+ if (ptr != NULL && newptr != NULL)
+ BlockMoveData(ptr, newptr, size);
+
+ if (ptr != NULL)
+ free(ptr);
+
+ return newptr;
+}
+
+}
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_stdlib.cpp b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_stdlib.cpp
new file mode 100644
index 00000000..881dcb0b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_stdlib.cpp
@@ -0,0 +1,58 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ mac_stdlib.cpp
+
+ replacement functions for the CodeWarrior plugin.
+
+ by Patrick C. Beard.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <setjmp.h>
+
+// simply throw us out of here!
+
+jmp_buf exit_jump;
+int exit_status = 0;
+
+void std::exit(int status)
+{
+ exit_status = status;
+ longjmp(exit_jump, -1);
+}
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_strings.cpp b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_strings.cpp
new file mode 100644
index 00000000..37e389e5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_strings.cpp
@@ -0,0 +1,38 @@
+/*
+ mac_strings.cpp
+ */
+
+#include "mac_strings.h"
+
+#include <string.h>
+#include <Memory.h>
+#include <new>
+
+StringPtr c2p_strcpy(StringPtr pstr, const char* cstr)
+{
+ size_t len = ::strlen(cstr);
+ if (len > 255) len = 255;
+ BlockMoveData(cstr, pstr + 1, len);
+ pstr[0] = len;
+ return pstr;
+}
+
+char* p2c_strcpy(char* cstr, const StringPtr pstr)
+{
+ size_t len = pstr[0];
+ BlockMoveData(pstr + 1, cstr, len);
+ cstr[len] = '\0';
+ return cstr;
+}
+
+char* p2c_strdup(StringPtr pstr)
+{
+ size_t len = pstr[0];
+ char* cstr = new char[1 + len];
+ if (cstr != NULL) {
+ BlockMoveData(pstr + 1, cstr, len);
+ cstr[len] = '\0';
+ }
+ return cstr;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_strings.h b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_strings.h
new file mode 100644
index 00000000..44f39312
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_strings.h
@@ -0,0 +1,47 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ mac_strings.h
+ */
+
+#pragma once
+
+#include <MacTypes.h>
+
+StringPtr c2p_strcpy(StringPtr pstr, const char* cstr);
+char* p2c_strcpy(char* cstr, const StringPtr pstr);
+char* p2c_strdup(StringPtr pstr);
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl.cpp b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl.cpp
new file mode 100644
index 00000000..49f061d9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl.cpp
@@ -0,0 +1,417 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ mac_xpidl.cpp
+
+ Metrowerks Codewarrior IDL plugin.
+
+ by Patrick C. Beard.
+ */
+
+/* standard headers */
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <new.h>
+#include <setjmp.h>
+
+/* system headers */
+#include <Files.h>
+#include <Errors.h>
+#include <Strings.h>
+
+#include "FullPath.h"
+#include "MoreFilesExtras.h"
+
+/* compiler headers */
+#include "DropInCompilerLinker.h"
+#include "CompilerMapping.h"
+#include "CWPluginErrors.h"
+
+/* local headers. */
+#include "mac_xpidl.h"
+#include "mac_console.h"
+#include "mac_strings.h"
+#include "mac_xpidl_panel.h"
+
+/* prototypes of local functions */
+static CWResult Compile(CWPluginContext context);
+static CWResult Disassemble(CWPluginContext context);
+static CWResult LocateFile(CWPluginContext context, const char* filename, FSSpec& file);
+
+/* external variables */
+extern jmp_buf exit_jump;
+extern int exit_status;
+
+/* global variables */
+CWPluginContext gPluginContext;
+
+/* local variables */
+static CWFileSpec gSourceFile;
+static char* gSourcePath = NULL;
+static CWFileSpec gOutputFile;
+
+extern "C" {
+pascal short xpidl_compiler(CWPluginContext context);
+int xpidl_main(int argc, char* argv[]);
+int xptdump_main(int argc, char* argv[]);
+
+FILE * FSp_fopen(ConstFSSpecPtr spec, const char * open_mode);
+}
+
+pascal short xpidl_compiler(CWPluginContext context)
+{
+ long request;
+ if (CWGetPluginRequest(context, &request) != cwNoErr)
+ return cwErrRequestFailed;
+
+ gPluginContext = context;
+ short result = cwNoErr;
+
+ /* dispatch on compiler request */
+ switch (request) {
+ case reqInitCompiler:
+ /* compiler has just been loaded into memory */
+ break;
+
+ case reqTermCompiler:
+ /* compiler is about to be unloaded from memory */
+ break;
+
+ case reqCompile:
+ /* compile a source file */
+ result = Compile(context);
+ break;
+
+ case reqCompDisassemble:
+ /* disassemble a source file */
+ result = Disassemble(context);
+ break;
+
+ default:
+ result = cwErrRequestFailed;
+ break;
+ }
+
+ /* is this necessary? */
+ CWDonePluginRequest(context, result);
+
+ /* return result code */
+ return (result);
+}
+
+static char* full_path_to(const FSSpec& file)
+{
+ short len = 0;
+ Handle fullPath = NULL;
+ if (FSpGetFullPath(&file, &len, &fullPath) == noErr && fullPath != NULL) {
+ char* path = new char[1 + len];
+ if (path != NULL) {
+ BlockMoveData(*fullPath, path, len);
+ path[len] = '\0';
+ }
+ DisposeHandle(fullPath);
+ return path;
+ }
+ return NULL;
+}
+
+static CWResult GetSettings(CWPluginContext context, XPIDLSettings& settings)
+{
+ CWMemHandle settingsHand;
+ CWResult err = CWGetNamedPreferences(context, kXPIDLPanelName, &settingsHand);
+ if (!CWSUCCESS(err))
+ return (err);
+
+ XPIDLSettings* settingsPtr = NULL;
+ err = CWLockMemHandle(context, settingsHand, false, (void**)&settingsPtr);
+ if (!CWSUCCESS(err))
+ return (err);
+
+ settings = *settingsPtr;
+
+ err = CWUnlockMemHandle(context, settingsHand);
+ if (!CWSUCCESS(err))
+ return (err);
+
+ return noErr;
+}
+
+static CWResult Compile(CWPluginContext context)
+{
+ CWResult err = CWGetMainFileSpec(context, &gSourceFile);
+ if (!CWSUCCESS(err))
+ return (err);
+
+ long fileNum;
+ err = CWGetMainFileNumber(context, &fileNum);
+ if (!CWSUCCESS(err))
+ return (err);
+
+ // get the name of the source file to compile.
+ gSourcePath = p2c_strdup(gSourceFile.name);
+ if (gSourcePath == NULL)
+ return cwErrOutOfMemory;
+
+ // build an argument list and call the compiler.
+ XPIDLSettings settings = { kXPIDLSettingsVersion, kXPIDLModeHeader, false, false };
+ GetSettings(context, settings);
+
+#if 0
+ // if generating .xpt files, let the IDE tell us where to put the output file.
+ // otherwise, put them in the project's output directory.
+ if (settings.mode == kXPIDLModeTypelib)
+ err = CWGetSuggestedObjectFileSpec(context, fileNum, &gOutputFile);
+ else
+ err = CWGetOutputFileDirectory(gPluginContext, &gOutputFile);
+#else
+ // always generate the output file into the project target's data directory.
+ err = CWGetSuggestedObjectFileSpec(context, fileNum, &gOutputFile);
+#endif
+ if (!CWSUCCESS(err))
+ return (err);
+
+ int argc = 3;
+ char* modes[] = { "header", "java", "typelib", "doc" };
+ char* argv[] = { "xpidl", "-m", modes[settings.mode - 1], NULL, NULL, NULL, NULL, };
+ if (settings.warnings) argv[argc++] = "-w";
+ if (settings.verbose) argv[argc++] = "-v";
+ argv[argc++] = gSourcePath;
+
+ if (setjmp(exit_jump) == 0) {
+ if (xpidl_main(argc, argv) != 0)
+ err = cwErrRequestFailed;
+ } else {
+ // evidently the good old exit function got called.
+ if (exit_status != 0)
+ err = cwErrRequestFailed;
+ }
+
+ // if the compilation succeeded, tell CodeWarrior about the output file.
+ // this ensures several things: 1. if the output file is deleted by the user,
+ // then the IDE will know to recompile it, which is good for dirty builds,
+ // where the output files may be hand deleted; 2. if the user elects to remove
+ // objects, the output files are deleted. Thanks to robv@metrowerks.com for
+ // pointing this new CWPro4 API out.
+ if (err == cwNoErr) {
+ CWObjectData objectData;
+ BlockZero(&objectData, sizeof(objectData));
+
+ // for fun, show how large the output file is in the data area.
+ long dataSize, rsrcSize;
+ if (FSpGetFileSize(&gOutputFile, &dataSize, &rsrcSize) == noErr)
+ objectData.idatasize = dataSize;
+
+ // tell the IDE that this file was generated by the compiler.
+ objectData.objectfile = &gOutputFile;
+
+ err = CWStoreObjectData(context, fileNum, &objectData);
+ } else {
+ // an error occured, delete the output file, which might be a partial file.
+ if (gOutputFile.name[0] != 0) {
+ ::FSpDelete(&gOutputFile);
+ }
+ }
+
+ delete[] gSourcePath;
+ gSourcePath = NULL;
+
+ return (err);
+}
+
+static CWResult Disassemble(CWPluginContext context)
+{
+ // the disassembly code has moved to the linker.
+ return noErr;
+}
+
+static CWResult LocateFile(CWPluginContext context, const char* filename, FSSpec& file)
+{
+ /* prefill the CWFileInfo struct */
+ CWFileInfo fileinfo;
+ BlockZero(&fileinfo, sizeof(fileinfo));
+ // memset(&fileinfo, 0, sizeof(fileinfo));
+ fileinfo.fullsearch = true;
+ fileinfo.suppressload = true;
+ fileinfo.dependencyType = cwNormalDependency;
+ fileinfo.isdependentoffile = kCurrentCompiledFile;
+
+ /* locate the file name using the project's access paths */
+ CWResult err = CWFindAndLoadFile(context, filename, &fileinfo);
+ if (err == cwNoErr) {
+ file = fileinfo.filespec;
+ } else if (err == cwErrFileNotFound) {
+ char errmsg[200];
+ sprintf(errmsg, "Can't locate file \"%s\".", filename);
+ CWResult callbackResult = CWReportMessage(context, 0, errmsg, 0, messagetypeError, 0);
+ }
+
+ return (err);
+}
+
+/**
+ * Substitute for standard fopen, treats certain filenames specially,
+ * and also considers the mode argument. If a file is being opened
+ * for reading, the file is assumed to be locateable using CodeWarrior's
+ * standard access paths. If it's for writing, the file is opened in
+ * the current project's output directory.
+ */
+FILE* std::fopen(const char* filename, const char *mode)
+{
+ FSSpec filespec;
+ CWResult err = noErr;
+ do {
+ if (filename == gSourcePath || strcmp(filename, gSourcePath) == 0) {
+ // opening the main source file.
+ filespec = gSourceFile;
+ } else if (mode[0] == 'w') {
+ // if an output file, open it in the current compilation's output directory.
+ c2p_strcpy(filespec.name, filename);
+ filespec.vRefNum = gOutputFile.vRefNum;
+ filespec.parID = gOutputFile.parID;
+ c2p_strcpy(gOutputFile.name, filename);
+ } else {
+ // an input file, use CodeWarrior's search paths to find the named source file.
+ err = LocateFile(gPluginContext, filename, filespec);
+ }
+ } while (0);
+ // if all went well, we have a file to open.
+ return (err == noErr ? FSp_fopen(&filespec, mode) : NULL);
+}
+
+/**
+ * Returns the length of a file, assuming it is always located in the
+ * project's output directory.
+ */
+size_t mac_get_file_length(const char* filename)
+{
+ long dataSize= 0, rsrcSize = 0;
+ FSSpec filespec;
+ if (CWGetOutputFileDirectory(gPluginContext, &filespec) != noErr)
+ return 0;
+ c2p_strcpy(filespec.name, filename);
+ if (FSpGetFileSize(&filespec, &dataSize, &rsrcSize) != noErr)
+ return 0;
+ return dataSize;
+}
+
+void mac_warning(const char* warning_message)
+{
+ CWReportMessage(gPluginContext, 0, warning_message, 0, messagetypeWarning, 0);
+}
+
+void mac_error(const char* error_message)
+{
+ CWReportMessage(gPluginContext, 0, error_message, 0, messagetypeError, 0);
+}
+
+// plugin compiler exports.
+
+#if CW_USE_PRAGMA_EXPORT
+#pragma export on
+#endif
+
+CWPLUGIN_ENTRY(CWPlugin_GetDropInFlags)(const DropInFlags** flags, long* flagsSize)
+{
+ static const DropInFlags sFlags = {
+ kCurrentDropInFlagsVersion,
+ CWDROPINCOMPILERTYPE,
+ DROPINCOMPILERLINKERAPIVERSION,
+ (kGeneratescode | /* kCandisassemble | */ kCompMultiTargAware | kCompAlwaysReload),
+ Lang_MISC,
+ DROPINCOMPILERLINKERAPIVERSION
+ };
+
+ *flags = &sFlags;
+ *flagsSize = sizeof(sFlags);
+
+ return cwNoErr;
+}
+
+CWPLUGIN_ENTRY(CWPlugin_GetDropInName)(const char** dropinName)
+{
+ static const char* sDropInName = "xpidl";
+
+ *dropinName = sDropInName;
+
+ return cwNoErr;
+}
+
+CWPLUGIN_ENTRY(CWPlugin_GetDisplayName)(const char** displayName)
+{
+ static const char* sDisplayName = "xpidl";
+
+ *displayName = sDisplayName;
+
+ return cwNoErr;
+}
+
+CWPLUGIN_ENTRY(CWPlugin_GetPanelList)(const CWPanelList** panelList)
+{
+ static const char* sPanelName = kXPIDLPanelName;
+ static CWPanelList sPanelList = { kCurrentCWPanelListVersion, 1, &sPanelName };
+
+ *panelList = &sPanelList;
+
+ return cwNoErr;
+}
+
+CWPLUGIN_ENTRY(CWPlugin_GetTargetList)(const CWTargetList** targetList)
+{
+ static CWDataType sCPU = '****';
+ static CWDataType sOS = '****';
+ static CWTargetList sTargetList = { kCurrentCWTargetListVersion, 1, &sCPU, 1, &sOS };
+
+ *targetList = &sTargetList;
+
+ return cwNoErr;
+}
+
+CWPLUGIN_ENTRY(CWPlugin_GetDefaultMappingList)(const CWExtMapList** defaultMappingList)
+{
+ static CWExtensionMapping sExtension = { 'TEXT', ".idl", 0 };
+ static CWExtMapList sExtensionMapList = { kCurrentCWExtMapListVersion, 1, &sExtension };
+
+ *defaultMappingList = &sExtensionMapList;
+
+ return cwNoErr;
+}
+
+#if CW_USE_PRAGMA_EXPORT
+#pragma export off
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl.h b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl.h
new file mode 100644
index 00000000..bb1c5048
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl.h
@@ -0,0 +1,25 @@
+/*
+ mac_xpidl.h
+
+ prototypes for the Mac CodeWarrior plugin version of xpidl.
+
+ by Patrick C. Beard.
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _STDIO_H
+#include <stdio.h>
+#endif
+
+size_t mac_get_file_length(const char* filename);
+void mac_warning(const char* warning_message);
+void mac_error(const char* error_message);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl_panel.cpp b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl_panel.cpp
new file mode 100644
index 00000000..b046071d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl_panel.cpp
@@ -0,0 +1,695 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ mac_xpidl_panel.cpp
+ */
+
+#define CW_STRICT_DIALOGS 1
+
+/* standard headers */
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+/* system headers */
+#include <AERegistry.h>
+#include <Drag.h>
+#include <Palettes.h>
+#include <Resources.h>
+#include <Scrap.h>
+#include <TextUtils.h>
+#include <Sound.h>
+
+/* compiler headers */
+#include <DropInPanel.h>
+
+/* project headers */
+#include "mac_xpidl_panel.h"
+
+enum {
+ kFactoryPrefsID = 128,
+ kCW7ItemListID = 128,
+ kCW8ItemListID = 129,
+
+ kXPIDLModeItem = 1,
+ kXPIDLWarningsItem,
+ kXPIDLVerboseItem,
+
+ kXPTLinkerOutputItem = 4
+};
+
+
+/* local variables */
+static RgnHandle sDragRgn;
+static Boolean sHighlightOn;
+
+
+/* prototypes of local functions */
+static short InitDialog(PanelParameterBlock *pb);
+static void TermDialog(PanelParameterBlock *pb);
+static void PutData(PanelParameterBlock *pb, Handle options);
+static short GetData(PanelParameterBlock *pb, Handle options, Boolean noisy);
+static void ByteSwapData(XPIDLSettingsHandle options);
+static short Filter(PanelParameterBlock *pb, EventRecord *event, short *itemHit);
+static void ItemHit(PanelParameterBlock *pb);
+static void Validate(Handle original, Handle current, Boolean *recompile, Boolean *relink, Boolean *reset);
+static short GetPref(AEKeyword keyword, AEDesc *prefsDesc, Handle settings);
+static short SetPref(AEKeyword keyword, const AEDesc *prefsDesc, Handle settings);
+static short GetFactory(Handle settings);
+static short UpdatePref(Handle settings);
+static Boolean ComparePrefs(Handle prefsHand1, Handle prefsHand2);
+static Boolean ComparePrefs(XPIDLSettings& prefs1, XPIDLSettings& prefs2);
+static void OutlineRect(const Rect* focusRect, Boolean outlineOn);
+static OSErr DragEnter(PanelParameterBlock *pb);
+static void DragWithin(PanelParameterBlock *pb);
+static void DragExit(PanelParameterBlock *pb);
+static void DragDrop(PanelParameterBlock *pb);
+
+extern "C" {
+
+pascal short xpidl_panel(PanelParameterBlock *pb);
+
+}
+
+/*
+ * main - entry-point for Drop-In Preferences Panel
+ *
+ */
+
+pascal short xpidl_panel(PanelParameterBlock *pb)
+{
+ short result;
+
+ result = noErr;
+
+ switch (pb->request)
+ {
+ case reqInitPanel:
+ /* panel has just been loaded into memory */
+ break;
+
+ case reqTermPanel:
+ /* panel is about to be unloaded from memory */
+ break;
+
+ case reqFirstLoad:
+ /* first time panel was loaded. */
+ break;
+
+ case reqInitDialog:
+ /* hook our dialog item list into the preferences dialog */
+ result = InitDialog(pb);
+ break;
+
+ case reqTermDialog:
+ /* unhook our dialog item list from the preferences dialog */
+ TermDialog(pb);
+ break;
+
+ case reqPutData:
+ /* put the data in the given handle into our dialog items */
+ PutData(pb, pb->currentPrefs);
+ break;
+
+ case reqGetData:
+ /* fill in the given handle with our dialog items */
+ result = GetData(pb, pb->currentPrefs, true);
+ break;
+
+ case reqByteSwapData:
+ /* byte swap the data in the handle */
+ ByteSwapData((XPIDLSettingsHandle)pb->currentPrefs);
+ break;
+
+ case reqFilter:
+ /* filter an event in the dialog */
+ result = Filter(pb, pb->event, &pb->itemHit);
+ break;
+
+ case reqItemHit:
+ /* handle a hit on one of our dialog items */
+ ItemHit(pb);
+ break;
+
+ case reqDrawCustomItem:
+ /* handle a request to draw one of our user items (CW/8 and later) */
+ break;
+
+ case reqActivateItem:
+ break;
+
+ case reqDeactivateItem:
+ break;
+
+ case reqHandleKey:
+ break;
+
+ case reqHandleClick:
+ break;
+
+ case reqFindStatus:
+ break;
+
+ case reqObeyCommand:
+ break;
+
+ case reqAEGetPref:
+ /* return one item in the given handle as an Apple Event descriptor */
+ result = GetPref(pb->prefsKeyword, &pb->prefsDesc, pb->currentPrefs);
+ break;
+
+ case reqAESetPref:
+ /* change one item in the given handle according to the given Apple Event descriptor */
+ result = SetPref(pb->prefsKeyword, &pb->prefsDesc, pb->currentPrefs);
+ break;
+
+ case reqValidate:
+ /* determine if we need to reset paths, recompile, or relink */
+ Validate(pb->originalPrefs, pb->currentPrefs, &pb->recompile, &pb->relink, &pb->reset);
+ break;
+
+ case reqGetFactory:
+ /* return our factory settings */
+ result = GetFactory(pb->factoryPrefs);
+ break;
+
+ case reqUpdatePref:
+ /* update the given handle to use the current format for our prefs data */
+ result = UpdatePref(pb->currentPrefs);
+ break;
+
+ case reqDragEnter:
+ /* determine if we can accept the drag and, if so, start tracking */
+ result = DragEnter(pb);
+ break;
+
+ case reqDragWithin:
+ /* continue tracking */
+ DragWithin(pb);
+ break;
+
+ case reqDragExit:
+ /* stop tracking */
+ DragExit(pb);
+ break;
+
+ case reqDragDrop:
+ /* the user has dropped in our panel */
+ DragDrop(pb);
+ break;
+
+ default:
+ result = paramErr;
+ break;
+ }
+
+ return (result);
+}
+
+/*
+ * InitDialog - initialize Dialog Box items for this panel
+ *
+ */
+
+static short InitDialog(PanelParameterBlock *pb)
+{
+ OSErr err;
+
+ // The library function will call the IDE to append the dialog items
+ // if possible; else it will call AppendDITL itself. This way, you
+ // don't have to worry about it.
+
+ err = CWPanlAppendItems(pb, kCW8ItemListID);
+ if (err != noErr)
+ return (err);
+
+ sDragRgn = NewRgn();
+
+ return (err);
+}
+
+/*
+ * TermDialog - destroy Dialog Box items for this panel
+ *
+ */
+
+static void TermDialog(PanelParameterBlock *pb)
+{
+ DisposeRgn(sDragRgn);
+}
+
+inline Boolean hasLinkerOutput(short mode)
+{
+ return (mode == kXPIDLModeHeader || mode == kXPIDLModeTypelib);
+}
+
+/*
+ * PutData - copy the options data from the handle to the screen
+ *
+ */
+
+static void PutData(PanelParameterBlock *pb, Handle options)
+{
+ // make sure the options are the right size.
+ UpdatePref(options);
+
+ XPIDLSettings prefsData = **(XPIDLSettingsHandle) options;
+
+ CWPanlSetItemValue(pb, kXPIDLModeItem, prefsData.mode);
+ CWPanlSetItemValue(pb, kXPIDLWarningsItem, prefsData.warnings);
+ CWPanlSetItemValue(pb, kXPIDLVerboseItem, prefsData.verbose);
+
+ CWPanlEnableItem(pb, kXPTLinkerOutputItem, hasLinkerOutput(prefsData.mode));
+ CWPanlSetItemText(pb, kXPTLinkerOutputItem, prefsData.output);
+}
+
+/*
+ * GetData - copy the options data from screen to the handle
+ *
+ */
+
+static short GetData(PanelParameterBlock *pb, Handle options, Boolean noisy)
+{
+ XPIDLSettings prefsData = **(XPIDLSettingsHandle) options;
+ long mode, warnings, verbose;
+
+ CWPanlGetItemValue(pb, kXPIDLModeItem, &mode);
+ CWPanlGetItemValue(pb, kXPIDLWarningsItem, &warnings);
+ CWPanlGetItemValue(pb, kXPIDLVerboseItem, &verbose);
+
+ prefsData.mode = (short) mode;
+ prefsData.warnings = (Boolean) warnings;
+ prefsData.verbose = (Boolean) verbose;
+
+ CWPanlGetItemText(pb, kXPTLinkerOutputItem, prefsData.output, sizeof(Str32));
+
+ ** (XPIDLSettingsHandle) options = prefsData;
+
+ return (noErr);
+}
+
+static void ByteSwapShort(short* x)
+{
+ union {
+ short s;
+ char c[2];
+ } from,to;
+
+ from.s=*x;
+ to.c[0]=from.c[1];
+ to.c[1]=from.c[0];
+ *x = to.s;
+}
+
+/*
+ * ByteSwapData - byte-swap the options data
+ *
+ */
+
+static void ByteSwapData(XPIDLSettingsHandle options)
+{
+ ByteSwapShort(&(**options).version);
+ ByteSwapShort(&(**options).mode);
+}
+
+/*
+ * Filter - filter an event for the Preferences panel
+ *
+ */
+static short Filter(PanelParameterBlock *pb, EventRecord *event, short *itemHit)
+{
+#pragma unused(pb, event, itemHit)
+
+ return (noErr);
+}
+
+/*
+ * ItemHit - handle an itemHit in a Preferences panel
+ *
+ */
+
+static void ItemHit(PanelParameterBlock *pb)
+{
+ short theItem = pb->itemHit - pb->baseItems;
+ long oldValue;
+
+ switch (theItem) {
+ case kXPIDLModeItem:
+ CWPanlGetItemValue(pb, theItem, &oldValue);
+ CWPanlEnableItem(pb, kXPTLinkerOutputItem, hasLinkerOutput(oldValue));
+ break;
+
+ case kXPIDLWarningsItem:
+ case kXPIDLVerboseItem:
+ CWPanlGetItemValue(pb, theItem, &oldValue);
+ break;
+ }
+
+ GetData(pb, pb->currentPrefs, false);
+
+ pb->canRevert = !ComparePrefs(pb->originalPrefs, pb->currentPrefs);
+ pb->canFactory = !ComparePrefs(pb->factoryPrefs, pb->currentPrefs);
+}
+
+/*
+ * Validate - check if panel's changes require a recompile or relink
+ *
+ */
+
+static void Validate(Handle original, Handle current, Boolean *recompile, Boolean *relink, Boolean *reset)
+{
+#pragma unused(original, current)
+ XPIDLSettings& origSettings = **(XPIDLSettingsHandle) original;
+ XPIDLSettings& currentSettings = **(XPIDLSettingsHandle) current;
+
+ *recompile = currentSettings.mode != origSettings.mode;
+ *relink = *recompile && hasLinkerOutput(currentSettings.mode);
+ *reset = false;
+}
+
+/*
+ * GetPref - get a specified Preference setting for an AppleEvent request
+ *
+ */
+static short GetPref(AEKeyword keyword, AEDesc *prefsDesc, Handle settings)
+{
+#if 0
+ XPIDLSettings prefsData = ** (XPIDLSettingsHandle) settings;
+ DescType anEnum;
+ OSErr err;
+
+ switch (keyword) {
+ case prefsLN_GenerateSymFile:
+ err = AECreateDesc(typeBoolean, &prefsData.linksym, sizeof(Boolean), prefsDesc);
+ break;
+
+ case prefsPR_ProjectType:
+ switch (prefsData.projtype)
+ {
+ case kProjTypeApplication: anEnum = enum_Project_Application; break;
+ case kProjTypeLibrary: anEnum = enum_Project_Library; break;
+ case kProjTypeSharedLib: anEnum = enum_Project_SharedLibrary; break;
+ case kProjTypeCodeResource: anEnum = enum_Project_CodeResource; break;
+ case kProjTypeMPWTool: anEnum = enum_Project_MPWTool; break;
+ default: return (paramErr);
+ }
+ err = AECreateDesc(typeEnumeration, &anEnum, sizeof(anEnum), prefsDesc);
+ break;
+
+ case prefsPR_FileName:
+ err = AECreateDesc(typeChar, prefsData.outfile+1, StrLength(prefsData.outfile), prefsDesc);
+ break;
+
+ default:
+ err = errAECantHandleClass;
+ break;
+ }
+
+ return (err);
+#else
+ return (errAECantHandleClass);
+#endif
+}
+
+/*
+ * SetPref - set a specified Preference setting from an AppleEvent request
+ *
+ */
+
+static short SetPref(AEKeyword keyword, const AEDesc *prefsDesc, Handle settings)
+{
+#if 0
+ XPIDLSettings prefsData = ** (XPIDLSettingsHandle) settings;
+ AEDesc toDesc = { typeNull, NULL };
+ OSErr err = noErr;
+ Handle dataHand;
+ Size textLength;
+ DescType anEnum;
+
+ switch (keyword)
+ {
+ case prefsLN_GenerateSymFile:
+ if (prefsDesc->descriptorType == typeBoolean)
+ {
+ dataHand = prefsDesc->dataHandle;
+ }
+ else
+ {
+ err = AECoerceDesc(prefsDesc, typeBoolean, &toDesc);
+ if (err == noErr)
+ dataHand = toDesc.dataHandle;
+ }
+ if (err == noErr)
+ {
+ prefsData.linksym = ** (Boolean **) dataHand;
+ }
+ break;
+
+ case prefsPR_ProjectType:
+ if (prefsDesc->descriptorType != typeEnumeration)
+ {
+ err = errAETypeError;
+ break;
+ }
+
+ anEnum = ** (DescType **) prefsDesc->dataHandle;
+
+ switch (anEnum)
+ {
+ case enum_Project_Application: prefsData.projtype = kProjTypeApplication; break;
+ case enum_Project_Library: prefsData.projtype = kProjTypeLibrary; break;
+ case enum_Project_SharedLibrary: prefsData.projtype = kProjTypeSharedLib; break;
+ case enum_Project_CodeResource: prefsData.projtype = kProjTypeCodeResource; break;
+ case enum_Project_MPWTool: prefsData.projtype = kProjTypeMPWTool; break;
+ default: return (errAECoercionFail);
+ }
+ break;
+
+ case prefsPR_FileName:
+ if (prefsDesc->descriptorType == typeChar)
+ {
+ dataHand = prefsDesc->dataHandle;
+ }
+ else
+ {
+ err = AECoerceDesc(prefsDesc, typeChar, &toDesc);
+ if (err == noErr)
+ dataHand = toDesc.dataHandle;
+ }
+ if (err == noErr)
+ {
+ textLength = GetHandleSize(dataHand);
+ if (textLength > sizeof(prefsData.outfile) - 1)
+ textLength = sizeof(prefsData.outfile) - 1;
+ BlockMoveData(*dataHand, prefsData.outfile+1, textLength);
+ prefsData.outfile[0] = textLength;
+ }
+ break;
+
+ default:
+ err = errAECantHandleClass;
+ break;
+ }
+
+ if (err == noErr)
+ {
+ ** (XPIDLSettingsHandle) settings = prefsData;
+ }
+
+ AEDisposeDesc(&toDesc);
+
+ return (err);
+#else
+ return (errAECantHandleClass);
+#endif
+}
+
+/*
+ * GetFactory - retrieve factory settings
+ *
+ */
+
+static short GetFactory(Handle settings)
+{
+ Handle factory;
+ Size size;
+ OSErr err;
+
+ factory = Get1Resource('pref', kFactoryPrefsID);
+ if (factory == NULL) {
+ err = ResError();
+ if (err == noErr)
+ err = resNotFound;
+ return (err);
+ }
+
+ size = GetHandleSize(factory);
+ SetHandleSize(settings, size);
+ err = MemError();
+
+ if (err == noErr) {
+ BlockMoveData(*factory, *settings, size);
+ }
+
+ return (err);
+}
+
+/*
+ * UpdatePref - "upgrade" a pref to the current version
+ */
+static short UpdatePref(Handle settings)
+{
+ if (GetHandleSize(settings) != sizeof(XPIDLSettings))
+ GetFactory(settings);
+
+ return (noErr);
+}
+
+/*
+ * ComparePrefs
+ *
+ */
+static Boolean ComparePrefs(Handle prefsHand1, Handle prefsHand2)
+{
+ XPIDLSettings& prefs1 = **(XPIDLSettingsHandle) prefsHand1;
+ XPIDLSettings& prefs2 = **(XPIDLSettingsHandle) prefsHand2;
+
+ return ((prefs1.mode == prefs2.mode) &&
+ (prefs1.warnings == prefs2.warnings) &&
+ (prefs1.verbose == prefs2.verbose) &&
+ (EqualString(prefs1.output, prefs2.output, true, true)));
+}
+
+static Boolean ComparePrefs(XPIDLSettings& prefs1, XPIDLSettings& prefs2)
+{
+ return ((prefs1.mode == prefs2.mode) &&
+ (prefs1.warnings == prefs2.warnings) &&
+ (prefs1.verbose == prefs2.verbose) &&
+ (EqualString(prefs1.output, prefs2.output, true, true)));
+}
+
+/*
+ * OutlineRect
+ *
+ */
+static void OutlineRect(const Rect* focusRect, Boolean outlineOn)
+{
+ ColorSpec savedForeColor, backColor;
+ PenState savedPen;
+
+ GetPenState(&savedPen);
+ PenNormal();
+
+ if (!outlineOn)
+ {
+ SaveFore(&savedForeColor);
+ SaveBack(&backColor);
+ RestoreFore(&backColor);
+ }
+
+ PenSize(2, 2);
+ FrameRect(focusRect);
+
+ SetPenState(&savedPen);
+
+ if (!outlineOn)
+ {
+ RestoreFore(&savedForeColor);
+ }
+}
+
+/*
+ * DragEnter
+ *
+ */
+static OSErr DragEnter(PanelParameterBlock *pb)
+{
+#if 0
+ short theItem = pb->itemHit - pb->baseItems;
+ unsigned short itemCount;
+ Rect itemRect;
+ OSErr err;
+#endif
+
+ /* Return paramErr if the user is on a item that can't be dropped on */
+ return (paramErr);
+}
+
+/*
+ * DragWithin
+ *
+ */
+static void DragWithin(PanelParameterBlock *pb)
+{
+#pragma unused(pb)
+
+ /* there's nothing to do */
+
+/// SysBreakStr("\preqDragWithin");
+}
+
+/*
+ * DragExit
+ *
+ */
+static void DragExit(PanelParameterBlock *pb)
+{
+ OSErr err;
+
+/// SysBreakStr("\preqDragExit");
+
+ if (sHighlightOn) {
+ err = HideDragHilite(pb->dragref);
+ if (err == noErr)
+ sHighlightOn = false;
+ }
+}
+
+/*
+ * DragDrop
+ *
+ */
+static void DragDrop(PanelParameterBlock *pb)
+{
+#if 0
+ Rect itemRect;
+#endif
+
+/// SysBreakStr("\preqDragDrop");
+
+ DragExit(pb);
+}
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl_panel.h b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl_panel.h
new file mode 100644
index 00000000..582b1055
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpidl_panel.h
@@ -0,0 +1,106 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ mac_xpidl_panel.h
+ */
+
+#pragma once
+
+#ifndef __MAC_XPIDL_PANEL__
+#define __MAC_XPIDL_PANEL__
+
+#ifndef __TYPES__
+#include <Types.h>
+#endif
+
+#pragma options align=mac68k
+
+/* this is the name of the panel, as shown in the Finder */
+#define kXPIDLPanelName "xpidl Settings"
+
+/*
+ * AppleScript dictionary info. As a rule of thumb, dropin panels should use the
+ * same terminology and numeric code in their 'aete' that the IDE uses if there
+ * is already a similar item in the IDE's 'aete'. That is the case here, so we
+ * merely duplicate applicable 68K Project and 68K Linker user terms below.
+ */
+
+enum {
+/* Symbolic Name Code AETE Terminology */
+ class_XPIDL = 'XIDL',
+
+ prefsPR_ProjectType = 'PR01', /* Project Type */
+ prefsPR_FileName = 'PR02', /* File Name */
+ prefsLN_GenerateSymFile = 'LN02', /* Generate SYM File */
+
+ /* enumeration for project type */
+ enumeration_ProjectType = 'PRPT',
+ enum_Project_Application = 'PRPA', /* application */
+ enum_Project_Library = 'PRPL', /* library */
+ enum_Project_SharedLibrary = 'PRPS', /* shared library */
+ enum_Project_CodeResource = 'PRPC', /* code resource */
+ enum_Project_MPWTool = 'PRPM' /* MPW tool */
+};
+
+enum {
+ kXPIDLModeHeader = 1,
+ kXPIDLModeJava,
+ kXPIDLModeTypelib,
+ kXPIDLModeDoc
+};
+
+/* This is the structure that is manipulated by the panel. The sample
+ * compiler & linker both "know" about this structure.
+ */
+
+enum {
+ kXPIDLSettingsVersion = 0x0100
+};
+
+struct XPIDLSettings {
+ short version; /* version # of settings data */
+ short mode; /* one of kXPIDLModeHeader, ... */
+ Boolean warnings; /* generate warnings. */
+ Boolean verbose; /* verbose mode */
+ Str32Field output; /* name of the output file */
+};
+
+typedef struct XPIDLSettings XPIDLSettings, **XPIDLSettingsHandle;
+
+#pragma options align=reset
+
+#endif /* __MAC_XPIDL_PANEL__ */
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpt_linker.cpp b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpt_linker.cpp
new file mode 100644
index 00000000..fe137959
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/mac_xpt_linker.cpp
@@ -0,0 +1,546 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ mac_xpt_linker.cpp
+
+ CodeWarrior plugin linker, links together multiple .xpt files.
+
+ by Patrick C. Beard.
+ */
+
+/* standard headers */
+#include <stdio.h>
+#include <string.h>
+#include <setjmp.h>
+
+/* system headers */
+#include <Files.h>
+#include <Strings.h>
+#include <Aliases.h>
+#include <Resources.h>
+
+/* compiler headers */
+#include "DropInCompilerLinker.h"
+#include "CompilerMapping.h"
+#include "CWPluginErrors.h"
+
+/* project headers */
+#include "mac_xpidl_panel.h"
+#include "mac_console.h"
+#include "mac_strings.h"
+#include "FullPath.h"
+#include "MoreFilesExtras.h"
+
+/* use standard CodeWarrior debugger */
+#define kDebuggerCreator 'MWDB'
+
+/* prototypes of local functions */
+static CWResult Link(CWPluginContext context);
+static CWResult Disassemble(CWPluginContext context);
+static CWResult GetTargetInfo(CWPluginContext context);
+
+extern "C" {
+pascal short xpt_linker(CWPluginContext context);
+int xptlink_main(int argc, char* argv[]);
+int xptdump_main(int argc, char* argv[]);
+
+FILE * FSp_fopen(ConstFSSpecPtr spec, const char * open_mode);
+size_t mac_get_file_length(const char* filename);
+}
+
+/* external variables */
+extern jmp_buf exit_jump;
+extern int exit_status;
+
+/* global variables */
+CWPluginContext gPluginContext;
+
+/* local variables */
+static CWFileSpec gOutputDirectory;
+static CWFileSpec gObjectCodeDirectory;
+
+/*
+ * xpt_linker - main entry-point for linker plugin
+ *
+ */
+pascal short xpt_linker(CWPluginContext context)
+{
+ long request;
+ if (CWGetPluginRequest(context, &request) != cwNoErr)
+ return cwErrRequestFailed;
+
+ gPluginContext = context;
+ short result = cwNoErr;
+
+ /* dispatch on linker request */
+ switch (request) {
+ case reqInitLinker:
+ /* linker has just been loaded into memory */
+ break;
+
+ case reqTermLinker:
+ /* linker is about to be unloaded from memory */
+ break;
+
+ case reqLink:
+ /* build the final executable */
+ result = Link(context);
+ break;
+
+ case reqDisassemble:
+ /* disassemble object code for a given project file */
+ result = Disassemble(context);
+ break;
+
+ case reqTargetInfo:
+ /* return info describing target characteristics */
+ result = GetTargetInfo(context);
+ break;
+
+ default:
+ result = cwErrRequestFailed;
+ break;
+ }
+
+ result = CWDonePluginRequest(context, result);
+
+ /* return result code */
+ return result;
+}
+
+static char* full_path_to(const FSSpec& file)
+{
+ short len = 0;
+ Handle fullPath = NULL;
+ if (FSpGetFullPath(&file, &len, &fullPath) == noErr && fullPath != NULL) {
+ char* path = new char[1 + len];
+ if (path != NULL) {
+ BlockMoveData(*fullPath, path, len);
+ path[len] = '\0';
+ }
+ DisposeHandle(fullPath);
+ return path;
+ }
+ return NULL;
+}
+
+/**
+ * Provides the full path name to a given directory.
+ */
+static char* full_path_to(short vRefNum, long dirID)
+{
+ long parID;
+ if (GetParentID(vRefNum, dirID, NULL, &parID) == noErr) {
+ FSSpec dirSpec = { vRefNum, parID };
+ if (GetDirName(vRefNum, dirID, dirSpec.name) == noErr) {
+ return full_path_to(dirSpec);
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Returns the length of a file, assuming it is always located in the
+ * project's object code directory.
+ */
+size_t mac_get_file_length(const char* filename)
+{
+ FSSpec fileSpec = { gObjectCodeDirectory.vRefNum, gObjectCodeDirectory.parID };
+ c2p_strcpy(fileSpec.name, filename);
+ long dataSize, rsrcSize;
+ if (FSpGetFileSize(&fileSpec, &dataSize, &rsrcSize) != noErr)
+ dataSize = 0;
+ return dataSize;
+}
+
+/**
+ * replaces standard fopen -- opens files for writing in the project's output directory,
+ * and files for reading in the object code directory.
+ */
+FILE* std::fopen(const char* filename, const char *mode)
+{
+ CWFileSpec& fileDir = (mode[0] == 'r' ? gObjectCodeDirectory : gOutputDirectory);
+ FSSpec fileSpec = { fileDir.vRefNum, fileDir.parID };
+ c2p_strcpy(fileSpec.name, filename);
+ return FSp_fopen(&fileSpec, mode);
+}
+
+static CWResult GetSettings(CWPluginContext context, XPIDLSettings& settings)
+{
+ CWMemHandle settingsHand;
+ CWResult err = CWGetNamedPreferences(context, kXPIDLPanelName, &settingsHand);
+ if (!CWSUCCESS(err))
+ return err;
+
+ XPIDLSettings* settingsPtr = NULL;
+ err = CWLockMemHandle(context, settingsHand, false, (void**)&settingsPtr);
+ if (!CWSUCCESS(err))
+ return err;
+
+ settings = *settingsPtr;
+
+ err = CWUnlockMemHandle(context, settingsHand);
+ if (!CWSUCCESS(err))
+ return err;
+
+ return cwNoErr;
+}
+
+static CWResult LinkHeaders(CWPluginContext context, XPIDLSettings& settings)
+{
+ // find out how many files there are to link.
+ long fileCount = 0;
+ CWResult err = CWGetProjectFileCount(context, &fileCount);
+ if (err != cwNoErr || fileCount == 0)
+ return err;
+
+ // get the output directory.
+ FSSpec outputDir;
+ err = CWGetOutputFileDirectory(context, &outputDir);
+ if (!CWSUCCESS(err))
+ return err;
+
+ // enumerate all of the output header files, and make aliases to them in
+ // the output directory.
+ for (long index = 0; (err == cwNoErr) && (index < fileCount); index++) {
+ // get the name of each output file.
+ CWFileSpec outputFile;
+ err = CWGetStoredObjectFileSpec(context, index, &outputFile);
+ if (err == cwNoErr) {
+ FInfo info;
+ err = FSpGetFInfo(&outputFile, &info);
+
+ FSSpec aliasFile = { outputDir.vRefNum, outputDir.parID };
+ BlockMoveData(outputFile.name, aliasFile.name, 1 + outputFile.name[0]);
+
+ AliasHandle alias = NULL;
+ if (NewAliasMinimal(&outputFile, &alias) == noErr) {
+ // recreate the alias file from scratch.
+ FSpDelete(&aliasFile);
+ FSpCreateResFile(&aliasFile, info.fdCreator, info.fdType, smRoman);
+ short refNum = FSpOpenResFile(&aliasFile, fsRdWrPerm);
+ if (refNum != -1) {
+ UseResFile(refNum);
+ AddResource(Handle(alias), rAliasType, 0, aliasFile.name);
+ ReleaseResource(Handle(alias));
+ UpdateResFile(refNum);
+ CloseResFile(refNum);
+ }
+ // finally, mark the newly created file as an alias file.
+ FSpGetFInfo(&aliasFile, &info);
+ info.fdFlags |= kIsAlias;
+ FSpSetFInfo(&aliasFile, &info);
+ }
+ }
+ }
+
+ // create the target file in the output directory.
+ BlockMoveData(settings.output, outputDir.name, 1 + settings.output[0]);
+ FILE* outputFile = FSp_fopen(&outputDir, "w");
+ if (outputFile != NULL) fclose(outputFile);
+
+ return err;
+}
+
+static CWResult LinkTypeLib(CWPluginContext context, XPIDLSettings& settings)
+{
+ // find out how many files there are to link.
+ long fileCount = 0;
+ CWResult err = CWGetProjectFileCount(context, &fileCount);
+ if (err != cwNoErr || fileCount == 0)
+ return err;
+
+ // assemble the argument list.
+ // { "xpt_link", outputFile, inputFile1, ..., inputFileN, NULL }
+ char** argv = new char*[2 + fileCount + 1];
+ int argc = 0;
+ argv[argc++] = "xpt_link";
+
+ // get the output directory.
+ err = CWGetOutputFileDirectory(context, &gOutputDirectory);
+ if (!CWSUCCESS(err))
+ return err;
+
+ // get the object code directory.
+ err = CWGetStoredObjectFileSpec(context, 0, &gObjectCodeDirectory);
+ if (!CWSUCCESS(err))
+ return err;
+
+ // push the output file name.
+ if ((argv[argc++] = p2c_strdup(settings.output)) == NULL)
+ return cwErrOutOfMemory;
+
+ for (long index = 0; (err == cwNoErr) && (index < fileCount); index++) {
+ // get the name of each output file.
+ CWFileSpec outputFile;
+ err = CWGetStoredObjectFileSpec(context, index, &outputFile);
+ if (err == cwNoErr) {
+ if ((argv[argc++] = p2c_strdup(outputFile.name)) == NULL) {
+ err = cwErrOutOfMemory;
+ break;
+ }
+ }
+ }
+
+ if (err != cwNoErr)
+ return err;
+
+ // trap calls to exit, which longjmp back to here.
+ if (setjmp(exit_jump) == 0) {
+ if (xptlink_main(argc, argv) != 0)
+ err = cwErrRequestFailed;
+ } else {
+ // evidently the good old exit function got called.
+ if (exit_status != 0)
+ err = cwErrRequestFailed;
+ }
+
+ return err;
+}
+
+static CWResult Link(CWPluginContext context)
+{
+ // load the relevant prefs.
+ XPIDLSettings settings = { kXPIDLSettingsVersion, kXPIDLModeTypelib, false, false };
+ CWResult err = GetSettings(context, settings);
+ if (err != cwNoErr)
+ return err;
+
+ switch (settings.mode) {
+ case kXPIDLModeHeader:
+ return LinkHeaders(context, settings);
+ case kXPIDLModeTypelib:
+ return LinkTypeLib(context, settings);
+ default:
+ return cwNoErr;
+ }
+}
+
+static CWResult Disassemble(CWPluginContext context)
+{
+ CWResult err = noErr;
+
+ // cache the project's output directory.
+ err = CWGetOutputFileDirectory(gPluginContext, &gOutputDirectory);
+ if (!CWSUCCESS(err))
+ return err;
+
+ long fileNum;
+ err = CWGetMainFileNumber(context, &fileNum);
+ if (!CWSUCCESS(err))
+ return err;
+
+ // get the output file's location from the stored object data.
+ err = CWGetStoredObjectFileSpec(context, fileNum, &gObjectCodeDirectory);
+ if (!CWSUCCESS(err))
+ return err;
+
+ char* outputName = p2c_strdup(gObjectCodeDirectory.name);
+ if (outputName == NULL)
+ return cwErrOutOfMemory;
+
+ XPIDLSettings settings = { kXPIDLSettingsVersion, kXPIDLModeTypelib, false, false };
+ GetSettings(context, settings);
+
+ // build an argument list and call xpt_dump.
+ int argc = 1;
+ char* argv[] = { "xpt_dump", NULL, NULL, NULL };
+ if (settings.verbose) argv[argc++] = "-v";
+ argv[argc++] = outputName;
+
+ // trap calls to exit, which longjmp back to here.
+ if (setjmp(exit_jump) == 0) {
+ if (xptdump_main(argc, argv) != 0)
+ err = cwErrRequestFailed;
+ } else {
+ // evidently the good old exit function got called.
+ if (exit_status != 0)
+ err = cwErrRequestFailed;
+ }
+
+ delete[] outputName;
+
+ if (err == noErr) {
+ // display the disassembly in its own fresh text window.
+ CWNewTextDocumentInfo info = {
+ NULL,
+ mac_console_handle,
+ false
+ };
+ CWResizeMemHandle(context, mac_console_handle, mac_console_count);
+ err = CWCreateNewTextDocument(context, &info);
+ }
+
+ return err;
+}
+
+static CWResult GetTargetInfo(CWPluginContext context)
+{
+ CWTargetInfo targ;
+ memset(&targ, 0, sizeof(targ));
+
+ CWResult err = CWGetOutputFileDirectory(context, &targ.outfile);
+ targ.outputType = linkOutputFile;
+ targ.symfile = targ.outfile; /* location of SYM file */
+ targ.linkType = exelinkageFlat;
+ targ.targetCPU = '****';
+ targ.targetOS = '****';
+
+ // load the relevant settings.
+ XPIDLSettings settings = { kXPIDLSettingsVersion, kXPIDLModeTypelib, false, false };
+ err = GetSettings(context, settings);
+ if (err != cwNoErr)
+ return err;
+
+#if CWPLUGIN_HOST == CWPLUGIN_HOST_MACOS
+ // tell the IDE about the output file.
+ targ.outfileCreator = 'MMCH';
+ targ.outfileType = 'CWIE';
+ targ.debuggerCreator = kDebuggerCreator; /* so IDE can locate our debugger */
+
+ BlockMoveData(settings.output, targ.outfile.name, 1 + settings.output[0]);
+ targ.symfile.name[0] = 0;
+#endif
+
+#if CWPLUGIN_HOST == CWPLUGIN_HOST_WIN32
+ targ.debugHelperIsRegKey = true;
+ *(long*)targ.debugHelperName = kDebuggerCreator;
+ targ.debugHelperName[4] = 0;
+ strcat(targ.outfile.path, "\\");
+ strcat(targ.outfile.path, prefsData.outfile);
+ strcpy(targ.symfile.path, targ.outfile.path);
+ strcat(targ.symfile.path, ".SYM");
+#endif
+
+ targ.runfile = targ.outfile;
+ targ.linkAgainstFile = targ.outfile;
+
+ /* we can only run applications */
+ // targ.canRun = (prefsData.projtype == kProjTypeApplication);
+
+ /* we can only debug if we have a SYM file */
+ // targ.canDebug = prefsData.linksym;
+
+ err = CWSetTargetInfo(context, &targ);
+
+ return err;
+}
+
+#if 0
+
+#if CW_USE_PRAGMA_EXPORT
+#pragma export on
+#endif
+
+CWPLUGIN_ENTRY(CWPlugin_GetDropInFlags)(const DropInFlags** flags, long* flagsSize)
+{
+ static const DropInFlags sFlags = {
+ kCurrentDropInFlagsVersion,
+ CWDROPINLINKERTYPE,
+ DROPINCOMPILERLINKERAPIVERSION_7,
+ (linkMultiTargAware | linkAlwaysReload),
+ 0,
+ DROPINCOMPILERLINKERAPIVERSION
+ };
+
+ *flags = &sFlags;
+ *flagsSize = sizeof(sFlags);
+
+ return cwNoErr;
+}
+
+CWPLUGIN_ENTRY(CWPlugin_GetDropInName)(const char** dropinName)
+{
+ static const char* sDropInName = "xpt Linker";
+ *dropinName = sDropInName;
+ return cwNoErr;
+}
+
+CWPLUGIN_ENTRY(CWPlugin_GetDisplayName)(const char** displayName)
+{
+ static const char* sDisplayName = "xpt Linker";
+ *displayName = sDisplayName;
+ return cwNoErr;
+}
+
+CWPLUGIN_ENTRY(CWPlugin_GetPanelList)(const CWPanelList** panelList)
+{
+ // +++Turn this on when the sample panel has been converted!
+ static const char* sPanelName = kXPIDLPanelName;
+ static CWPanelList sPanelList = { kCurrentCWPanelListVersion, 1, &sPanelName };
+
+ *panelList = &sPanelList;
+
+ return cwNoErr;
+}
+
+CWPLUGIN_ENTRY(CWPlugin_GetTargetList)(const CWTargetList** targetList)
+{
+ static CWDataType sCPU = '****';
+ static CWDataType sOS = '****';
+ static CWTargetList sTargetList = { kCurrentCWTargetListVersion, 1, &sCPU, 1, &sOS };
+
+ *targetList = &sTargetList;
+
+ return cwNoErr;
+}
+
+CWPLUGIN_ENTRY(CWPlugin_GetDefaultMappingList)(const CWExtMapList** defaultMappingList)
+{
+ static CWExtensionMapping sExtension = { 'MMCH', ".xpt", 0 };
+ static CWExtMapList sExtensionMapList = { kCurrentCWExtMapListVersion, 1, &sExtension };
+
+ *defaultMappingList = &sExtensionMapList;
+
+ return cwNoErr;
+}
+
+CWPLUGIN_ENTRY (CWPlugin_GetFamilyList)(const CWFamilyList** familyList)
+{
+ static CWFamily sFamily = { 'XIDL', "xpidl Settings" };
+ static CWFamilyList sFamilyList = { kCurrentCWFamilyListVersion, 0, &sFamily };
+
+ *familyList = &sFamilyList;
+
+ return cwNoErr;
+}
+
+#if CW_USE_PRAGMA_EXPORT
+#pragma export off
+#endif
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/panel.rsrc b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/panel.rsrc
new file mode 100644
index 00000000..c5777088
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/panel.rsrc
Binary files differ
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/version.rsrc b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/version.rsrc
new file mode 100644
index 00000000..6737d356
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/macplugin/version.rsrc
Binary files differ
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.c
new file mode 100644
index 00000000..e1a7c58d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.c
@@ -0,0 +1,275 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Main xpidl program entry point.
+ */
+
+#include "xpidl.h"
+
+static ModeData modes[] = {
+ {"header", "Generate C++ header", "h", xpidl_header_dispatch},
+ {"typelib", "Generate XPConnect typelib", "xpt", xpidl_typelib_dispatch},
+ {"doc", "Generate HTML documentation", "html", xpidl_doc_dispatch},
+ {"java", "Generate Java interface", "java", xpidl_java_dispatch},
+ {0, 0, 0, 0}
+};
+
+static ModeData *
+FindMode(char *mode)
+{
+ int i;
+ for (i = 0; modes[i].mode; i++) {
+ if (!strcmp(modes[i].mode, mode))
+ return &modes[i];
+ }
+ return NULL;
+}
+
+gboolean enable_debug = FALSE;
+gboolean enable_warnings = FALSE;
+gboolean verbose_mode = FALSE;
+gboolean emit_typelib_annotations = FALSE;
+gboolean explicit_output_filename = FALSE;
+
+/* The following globals are explained in xpt_struct.h */
+PRUint8 major_version = XPT_MAJOR_VERSION;
+PRUint8 minor_version = XPT_MINOR_VERSION;
+
+static char xpidl_usage_str[] =
+"Usage: %s -m mode [-w] [-v] [-t version number]\n"
+" [-I path] [-o basename | -e filename.ext] filename.idl\n"
+" -a emit annotations to typelib\n"
+" -w turn on warnings (recommended)\n"
+" -v verbose mode (NYI)\n"
+" -t create a typelib of a specific version number\n"
+" -I add entry to start of include path for ``#include \"nsIThing.idl\"''\n"
+" -o use basename (e.g. ``/tmp/nsIThing'') for output\n"
+" -e use explicit output filename\n"
+" -m specify output mode:\n";
+
+static void
+xpidl_usage(int argc, char *argv[])
+{
+ int i;
+ fprintf(stderr, xpidl_usage_str, argv[0]);
+ for (i = 0; modes[i].mode; i++) {
+ fprintf(stderr, " %-12s %-30s (.%s)\n", modes[i].mode,
+ modes[i].modeInfo, modes[i].suffix);
+ }
+}
+
+#if defined(XP_MAC) && defined(XPIDL_PLUGIN)
+#define main xpidl_main
+int xpidl_main(int argc, char *argv[]);
+#endif
+
+int main(int argc, char *argv[])
+{
+ int i;
+ IncludePathEntry *inc, *inc_head, **inc_tail;
+ char *file_basename = NULL;
+ ModeData *mode = NULL;
+ gboolean create_old_typelib = FALSE;
+
+ /* turn this on for extra checking of our code */
+/* IDL_check_cast_enable(TRUE); */
+
+ inc_head = xpidl_malloc(sizeof *inc);
+#ifndef XP_MAC
+ inc_head->directory = ".";
+#else
+ inc_head->directory = "";
+#endif
+ inc_head->next = NULL;
+ inc_tail = &inc_head->next;
+
+ for (i = 1; i < argc; i++) {
+ if (argv[i][0] != '-')
+ break;
+ switch (argv[i][1]) {
+ case '-':
+ argc++; /* pretend we didn't see this */
+ /* fall through */
+ case 0: /* - is a legal input filename (stdin) */
+ goto done_options;
+ case 'a':
+ emit_typelib_annotations = TRUE;
+ break;
+ case 'w':
+ enable_warnings = TRUE;
+ break;
+ case 'v':
+ verbose_mode = TRUE;
+ break;
+ case 't':
+ {
+ /* Parse for "-t version number" and store it into global boolean
+ * and string variables.
+ */
+ const gchar* typelib_version_string = NULL;
+
+ /*
+ * If -t is the last argument on the command line, we have a problem
+ */
+
+ if (i + 1 == argc) {
+ fprintf(stderr, "ERROR: missing version number after -t\n");
+ xpidl_usage(argc, argv);
+ return 1;
+ }
+
+ /* Do not allow more than one "-t" definition */
+ if (create_old_typelib) {
+ fprintf(stderr,
+ "ERROR: -t argument used twice. "
+ "Cannot specify more than one version\n");
+ xpidl_usage(argc, argv);
+ return 1;
+ }
+
+ /*
+ * Assume that the argument after "-t" is the version number string
+ * and search for it in our internal list of acceptable version
+ * numbers.
+ */
+ switch (XPT_ParseVersionString(argv[++i], &major_version,
+ &minor_version)) {
+ case XPT_VERSION_CURRENT:
+ break;
+ case XPT_VERSION_OLD:
+ create_old_typelib = TRUE;
+ break;
+ case XPT_VERSION_UNSUPPORTED:
+ fprintf(stderr, "ERROR: version \"%s\" not supported.\n",
+ argv[i]);
+ xpidl_usage(argc, argv);
+ return 1;
+ case XPT_VERSION_UNKNOWN:
+ default:
+ fprintf(stderr, "ERROR: version \"%s\" not recognised.\n",
+ argv[i]);
+ xpidl_usage(argc, argv);
+ return 1;
+ }
+ break;
+ }
+ case 'I':
+ if (argv[i][2] == '\0' && i == argc) {
+ fputs("ERROR: missing path after -I\n", stderr);
+ xpidl_usage(argc, argv);
+ return 1;
+ }
+ inc = xpidl_malloc(sizeof *inc);
+ if (argv[i][2] == '\0') {
+ /* is it the -I foo form? */
+ inc->directory = argv[++i];
+ } else {
+ /* must be the -Ifoo form. Don't preincrement i. */
+ inc->directory = argv[i] + 2;
+ }
+#ifdef DEBUG_shaver_includes
+ fprintf(stderr, "adding %s to include path\n", inc->directory);
+#endif
+ inc->next = NULL;
+ *inc_tail = inc;
+ inc_tail = &inc->next;
+ break;
+ case 'o':
+ if (i == argc) {
+ fprintf(stderr, "ERROR: missing basename after -o\n");
+ xpidl_usage(argc, argv);
+ return 1;
+ }
+ file_basename = argv[++i];
+ explicit_output_filename = FALSE;
+ break;
+ case 'e':
+ if (i == argc) {
+ fprintf(stderr, "ERROR: missing basename after -e\n");
+ xpidl_usage(argc, argv);
+ return 1;
+ }
+ file_basename = argv[++i];
+ explicit_output_filename = TRUE;
+ break;
+ case 'm':
+ if (i + 1 == argc) {
+ fprintf(stderr, "ERROR: missing modename after -m\n");
+ xpidl_usage(argc, argv);
+ return 1;
+ }
+ if (mode) {
+ fprintf(stderr,
+ "ERROR: must specify exactly one mode "
+ "(first \"%s\", now \"%s\")\n", mode->mode,
+ argv[i + 1]);
+ xpidl_usage(argc, argv);
+ return 1;
+ }
+ mode = FindMode(argv[++i]);
+ if (!mode) {
+ fprintf(stderr, "ERROR: unknown mode \"%s\"\n", argv[i]);
+ xpidl_usage(argc, argv);
+ return 1;
+ }
+ break;
+ default:
+ fprintf(stderr, "unknown option %s\n", argv[i]);
+ xpidl_usage(argc, argv);
+ return 1;
+ }
+ }
+ done_options:
+ if (!mode) {
+ fprintf(stderr, "ERROR: must specify output mode\n");
+ xpidl_usage(argc, argv);
+ return 1;
+ }
+ if (argc != i + 1) {
+ fprintf(stderr, "ERROR: extra arguments after input file\n");
+ }
+
+ /*
+ * Don't try to process multiple files, given that we don't handle -o
+ * multiply.
+ */
+ if (xpidl_process_idl(argv[i], inc_head, file_basename, mode))
+ return 0;
+
+ return 1;
+}
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.h b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.h
new file mode 100644
index 00000000..857bfdf8
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl.h
@@ -0,0 +1,278 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Intramodule declarations.
+ */
+
+#ifndef __xpidl_h
+#define __xpidl_h
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <string.h> /* After glib.h to avoid warnings about shadowing 'index'. */
+
+#ifndef XP_MAC
+#include <libIDL/IDL.h>
+#else
+#include <IDL.h>
+#endif
+
+#include <xpt_struct.h>
+
+/*
+ * IDL_tree_warning bombs on libIDL version 6.5, and I don't want to not write
+ * warnings... so I define a versioned one here. Thanks to Mike Shaver for the
+ * this solution, which allows us to pass through varargs calls.
+ */
+#if !(LIBIDL_MAJOR_VERSION == 0 && LIBIDL_MINOR_VERSION == 6 && \
+ LIBIDL_MICRO_VERSION == 5) && !defined(DEBUG_shaver)
+/*
+ * This turns a varargs call to XPIDL_WARNING directly into a varargs
+ * call to IDL_tree_warning or xpidl_tree_warning as appropriate. The
+ * only tricky bit is that you must call XPIDL_WARNING with extra
+ * parens, e.g. XPIDL_WARNING((foo, bar, "sil"))
+ *
+ * Probably best removed when we leave 6.5. */
+#define XPIDL_WARNING(x) IDL_tree_warning x
+#else
+extern void xpidl_tree_warning(IDL_tree p, int level, const char *fmt, ...);
+#define XPIDL_WARNING(x) xpidl_tree_warning x
+#endif
+
+/*
+ * Internal operation flags.
+ */
+extern gboolean enable_debug;
+extern gboolean enable_warnings;
+extern gboolean verbose_mode;
+extern gboolean emit_typelib_annotations;
+extern gboolean explicit_output_filename;
+
+extern PRUint8 major_version;
+extern PRUint8 minor_version;
+
+typedef struct TreeState TreeState;
+
+/*
+ * A function to handle an IDL_tree type.
+ */
+typedef gboolean (*nodeHandler)(TreeState *);
+
+/*
+ * Struct containing functions to define the behavior of a given output mode.
+ */
+typedef struct backend {
+ nodeHandler *dispatch_table; /* nodeHandlers table, indexed by node type. */
+ nodeHandler emit_prolog; /* called at beginning of output generation. */
+ nodeHandler emit_epilog; /* called at end. */
+} backend;
+
+/* Function that produces a struct of output-generation functions */
+typedef backend *(*backendFactory)();
+
+extern backend *xpidl_header_dispatch(void);
+extern backend *xpidl_typelib_dispatch(void);
+extern backend *xpidl_doc_dispatch(void);
+extern backend *xpidl_java_dispatch(void);
+
+typedef struct ModeData {
+ char *mode;
+ char *modeInfo;
+ char *suffix;
+ backendFactory factory;
+} ModeData;
+
+typedef struct IncludePathEntry {
+ char *directory;
+ struct IncludePathEntry *next;
+} IncludePathEntry;
+
+struct TreeState {
+ FILE *file;
+ /* Maybe supplied by -o. Not related to (g_)basename from string.h or glib */
+ char *basename;
+ IDL_ns ns;
+ IDL_tree tree;
+ GSList *base_includes;
+ nodeHandler *dispatch;
+ void *priv; /* mode-private data */
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ char *real_outname;
+#endif
+
+};
+
+/*
+ * Process an IDL file, generating InterfaceInfo, documentation and headers as
+ * appropriate.
+ */
+int
+xpidl_process_idl(char *filename, IncludePathEntry *include_path,
+ char *file_basename, ModeData *mode);
+
+/*
+ * Iterate over an IDLN_LIST -- why is this not part of libIDL?
+ */
+void
+xpidl_list_foreach(IDL_tree p, IDL_tree_func foreach, gpointer user_data);
+
+/*
+ * Wrapper whines to stderr then exits after null return from malloc or strdup.
+ */
+void *
+xpidl_malloc(size_t nbytes);
+
+char *
+xpidl_strdup(const char *s);
+
+/*
+ * Return a newly allocated string to the start of the base filename of path.
+ * Free with g_free().
+ */
+char *
+xpidl_basename(const char * path);
+
+/*
+ * Process an XPIDL node and its kids, if any.
+ */
+gboolean
+xpidl_process_node(TreeState *state);
+
+/*
+ * Write a newline folllowed by an indented, one-line comment containing IDL
+ * source decompiled from state->tree.
+ */
+void
+xpidl_write_comment(TreeState *state, int indent);
+
+
+
+/*
+ * Functions for parsing and printing UUIDs.
+ */
+
+/*
+ * How large should the buffer supplied to xpidl_sprint_IID be?
+ */
+#define UUID_LENGTH 37
+
+/*
+ * Print an iid to into a supplied buffer; the buffer should be at least
+ * UUID_LENGTH bytes.
+ */
+gboolean
+xpidl_sprint_iid(nsID *iid, char iidbuf[]);
+
+/*
+ * Parse a uuid string into an nsID struct. We cannot link against libxpcom,
+ * so we re-implement nsID::Parse here.
+ */
+gboolean
+xpidl_parse_iid(nsID *id, const char *str);
+
+
+/* Try to common a little node-handling stuff. */
+
+/* is this node from an aggregate type (interface)? */
+#define UP_IS_AGGREGATE(node) \
+ (IDL_NODE_UP(node) && \
+ (IDL_NODE_TYPE(IDL_NODE_UP(node)) == IDLN_INTERFACE || \
+ IDL_NODE_TYPE(IDL_NODE_UP(node)) == IDLN_FORWARD_DCL))
+
+#define UP_IS_NATIVE(node) \
+ (IDL_NODE_UP(node) && \
+ IDL_NODE_TYPE(IDL_NODE_UP(node)) == IDLN_NATIVE)
+
+/* is this type output in the form "<foo> *"? */
+#define STARRED_TYPE(node) (IDL_NODE_TYPE(node) == IDLN_TYPE_STRING || \
+ IDL_NODE_TYPE(node) == IDLN_TYPE_WIDE_STRING || \
+ (IDL_NODE_TYPE(node) == IDLN_IDENT && \
+ UP_IS_AGGREGATE(node)))
+
+#define DIPPER_TYPE(node) \
+ (NULL != IDL_tree_property_get(node, "domstring") || \
+ NULL != IDL_tree_property_get(node, "utf8string") || \
+ NULL != IDL_tree_property_get(node, "cstring") || \
+ NULL != IDL_tree_property_get(node, "astring"))
+
+/*
+ * Find the underlying type of an identifier typedef. Returns NULL
+ * (and doesn't complain) on failure.
+ */
+IDL_tree /* IDL_TYPE_DCL */
+find_underlying_type(IDL_tree typedef_ident);
+
+/*
+ * Check that const declarations match their stated sign and are of the
+ * appropriate types.
+ */
+gboolean
+verify_const_declaration(IDL_tree const_tree);
+
+/*
+ * Check that scriptable attributes in scriptable interfaces actually are.
+ */
+gboolean
+verify_attribute_declaration(IDL_tree method_tree);
+
+/*
+ * Perform various validation checks on methods.
+ */
+gboolean
+verify_method_declaration(IDL_tree method_tree);
+
+/*
+ * Verifies the interface declaration
+ */
+gboolean
+verify_interface_declaration(IDL_tree method_tree);
+
+/*
+ * Verify that a native declaration has an associated C++ expression, i.e. that
+ * it's of the form native <idl-name>(<c++-name>)
+ */
+gboolean
+check_native(TreeState *state);
+
+void
+printlist(FILE *outfile, GSList *slist);
+
+#endif /* __xpidl_h */
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_doc.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_doc.c
new file mode 100644
index 00000000..d560e407
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_doc.c
@@ -0,0 +1,312 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "xpidl.h"
+
+/*
+ * Generates documentation from javadoc-style comments in XPIDL files.
+ */
+
+static gboolean
+doc_prolog(TreeState *state)
+{
+ fprintf(state->file, "<html>\n");
+ fprintf(state->file, "<head>\n");
+
+ fprintf(state->file,
+ "<!-- this file is generated from %s.idl -->\n",
+ state->basename);
+ fprintf(state->file, "<title>documentation for %s.idl interfaces</title>\n",
+ state->basename);
+ fprintf(state->file, "</head>\n\n");
+ fprintf(state->file, "<body>\n");
+
+ return TRUE;
+}
+
+static gboolean
+doc_epilog(TreeState *state)
+{
+ fprintf(state->file, "</body>\n");
+ fprintf(state->file, "</html>\n");
+
+ return TRUE;
+}
+
+
+static gboolean
+doc_list(TreeState *state)
+{
+ IDL_tree iter;
+ for (iter = state->tree; iter; iter = IDL_LIST(iter).next) {
+ state->tree = IDL_LIST(iter).data;
+ if (!xpidl_process_node(state))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+print_list(FILE *outfile, IDL_tree list)
+{
+ if (list == NULL)
+ return TRUE;
+
+ fprintf(outfile, "<ul>\n");
+ while (list != NULL) {
+ fprintf(outfile, " <li>%s\n",
+ IDL_IDENT(IDL_LIST(list).data).str);
+ list = IDL_LIST(list).next;
+ }
+ fprintf(outfile, "</ul>\n");
+ return TRUE;
+}
+
+static gboolean
+doc_interface(TreeState *state)
+{
+ IDL_tree iface = state->tree;
+ IDL_tree iter;
+ IDL_tree orig;
+ char *classname = IDL_IDENT(IDL_INTERFACE(iface).ident).str;
+ GSList *doc_comments = IDL_IDENT(IDL_INTERFACE(iface).ident).comments;
+
+ fprintf(state->file, "interface %s<br>\n", classname);
+
+ /* Much more could happen at this step. */
+ /*
+ * If parsing doc comments, you might need to take some care with line
+ * endings, as the xpidl frontend will return comments containing of /r,
+ * /n, /r/n depending on the platform. It's best to leave out platform
+ * #defines and just treat them all as equivalent.
+ */
+ if (doc_comments != NULL) {
+ fprintf(state->file, "doc comments:<br>\n");
+ fprintf(state->file, "<pre>\n");
+ printlist(state->file, doc_comments);
+ fprintf(state->file, "</pre>\n");
+ fprintf(state->file, "<br>\n");
+ }
+
+ /* inherits from */
+ /*
+ * Note that we accept multiple inheritance here (for e.g. gnome idl)
+ * even though the header backend (specific to mozilla idl) rejects it.
+ */
+ if ((iter = IDL_INTERFACE(iface).inheritance_spec)) {
+ fprintf(state->file, "%s inherits from:<br>\n", classname);
+ print_list(state->file, iter);
+ fprintf(state->file, "<br>\n");
+ }
+
+ /*
+ * Call xpidl_process_node to recur through list of declarations in
+ * interface body; another option would be to explicitly iterate through
+ * the list. xpidl_process_node currently requires twiddling the state to
+ * get the right node; I'll fix that soon to just take the node. Makes it
+ * easier to follow what's going on, I think...
+ */
+ orig = state->tree;
+ state->tree = IDL_INTERFACE(iface).body;
+ if (state->tree && !xpidl_process_node(state))
+ return FALSE;
+ state->tree = orig;
+
+ return TRUE;
+}
+
+/*
+ * Copied from xpidl_header.c. You'll probably want to change it; if you can
+ * use it verbatim or abstract it, we could move it to xpidl_util.c and share
+ * it from there.
+ */
+static gboolean
+write_type(IDL_tree type_tree, FILE *outfile)
+{
+ if (!type_tree) {
+ fputs("void", outfile);
+ return TRUE;
+ }
+
+ switch (IDL_NODE_TYPE(type_tree)) {
+ case IDLN_TYPE_INTEGER: {
+ gboolean sign = IDL_TYPE_INTEGER(type_tree).f_signed;
+ switch (IDL_TYPE_INTEGER(type_tree).f_type) {
+ case IDL_INTEGER_TYPE_SHORT:
+ fputs(sign ? "PRInt16" : "PRUint16", outfile);
+ break;
+ case IDL_INTEGER_TYPE_LONG:
+ fputs(sign ? "PRInt32" : "PRUint32", outfile);
+ break;
+ case IDL_INTEGER_TYPE_LONGLONG:
+ fputs(sign ? "PRInt64" : "PRUint64", outfile);
+ break;
+ default:
+ g_error("Unknown integer type %d\n",
+ IDL_TYPE_INTEGER(type_tree).f_type);
+ return FALSE;
+ }
+ break;
+ }
+ case IDLN_TYPE_CHAR:
+ fputs("char", outfile);
+ break;
+ case IDLN_TYPE_WIDE_CHAR:
+ fputs("PRUnichar", outfile); /* wchar_t? */
+ break;
+ case IDLN_TYPE_WIDE_STRING:
+ fputs("PRUnichar *", outfile);
+ break;
+ case IDLN_TYPE_STRING:
+ fputs("char *", outfile);
+ break;
+ case IDLN_TYPE_BOOLEAN:
+ fputs("PRBool", outfile);
+ break;
+ case IDLN_TYPE_OCTET:
+ fputs("PRUint8", outfile);
+ break;
+ case IDLN_TYPE_FLOAT:
+ switch (IDL_TYPE_FLOAT(type_tree).f_type) {
+ case IDL_FLOAT_TYPE_FLOAT:
+ fputs("float", outfile);
+ break;
+ case IDL_FLOAT_TYPE_DOUBLE:
+ fputs("double", outfile);
+ break;
+ /* XXX 'long double' just ignored, or what? */
+ default:
+ fprintf(outfile, "unknown_type_%d", IDL_NODE_TYPE(type_tree));
+ break;
+ }
+ break;
+ case IDLN_IDENT:
+ if (UP_IS_NATIVE(type_tree)) {
+ fputs(IDL_NATIVE(IDL_NODE_UP(type_tree)).user_type, outfile);
+ if (IDL_tree_property_get(type_tree, "ptr")) {
+ fputs(" *", outfile);
+ } else if (IDL_tree_property_get(type_tree, "ref")) {
+ fputs(" &", outfile);
+ }
+ } else {
+ fputs(IDL_IDENT(type_tree).str, outfile);
+ }
+ if (UP_IS_AGGREGATE(type_tree))
+ fputs(" *", outfile);
+ break;
+ default:
+ fprintf(outfile, "unknown_type_%d", IDL_NODE_TYPE(type_tree));
+ break;
+ }
+ return TRUE;
+}
+
+/* handle ATTR_DCL (attribute declaration) nodes */
+static gboolean
+doc_attribute_declaration(TreeState *state)
+{
+ IDL_tree attr = state->tree;
+
+ if (!verify_attribute_declaration(attr))
+ return FALSE;
+ /*
+ * Attribute idents can also take doc comments. They're ignored here;
+ * should they be?
+ */
+
+ if (IDL_ATTR_DCL(attr).f_readonly)
+ fprintf(state->file, "readonly ");
+
+ fprintf(state->file, "attribute ");
+
+ if (!write_type(IDL_ATTR_DCL(attr).param_type_spec, state->file))
+ return FALSE;
+
+ fprintf(state->file, "\n");
+ print_list(state->file, IDL_ATTR_DCL(attr).simple_declarations);
+ fprintf(state->file, "<br>\n");
+
+ return TRUE;
+}
+
+/* handle OP_DCL (method declaration) nodes */
+static gboolean
+doc_method_declaration(TreeState *state)
+{
+ /*
+ * Doc comment for attributes also applies here.
+ */
+
+ /*
+ * Look at 'write_method_signature' in xpidl_header.c for an example of how
+ * to navigate parse trees for methods. For here, I just print the method
+ * name.
+ */
+
+ fprintf(state->file,
+ "method %s<br>\n",
+ IDL_IDENT(IDL_OP_DCL(state->tree).ident).str);
+
+ return TRUE;
+}
+
+backend *
+xpidl_doc_dispatch(void)
+{
+ static backend result;
+ static nodeHandler table[IDLN_LAST];
+ static gboolean initialized = FALSE;
+
+ result.emit_prolog = doc_prolog;
+ result.emit_epilog = doc_epilog;
+
+ if (!initialized) {
+ /* Initialize non-NULL elements */
+
+ /* I just handle a few... many still to be filled in! */
+
+ table[IDLN_LIST] = doc_list;
+ table[IDLN_INTERFACE] = doc_interface;
+ table[IDLN_ATTR_DCL] = doc_attribute_declaration;
+ table[IDLN_OP_DCL] = doc_method_declaration;
+
+ initialized = TRUE;
+ }
+
+ result.dispatch_table = table;
+ return &result;
+}
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_header.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_header.c
new file mode 100644
index 00000000..f4fe9d5b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_header.c
@@ -0,0 +1,1196 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Generate XPCOM headers from XPIDL.
+ */
+
+#include "xpidl.h"
+#include <ctype.h>
+
+#define AS_DECL 0
+#define AS_CALL 1
+#define AS_IMPL 2
+
+static gboolean write_method_signature(IDL_tree method_tree, FILE *outfile,
+ int mode, const char *className);
+static gboolean write_attr_accessor(IDL_tree attr_tree, FILE * outfile,
+ gboolean getter,
+ int mode, const char *className);
+
+static void
+write_indent(FILE *outfile) {
+ fputs(" ", outfile);
+}
+
+static gboolean
+header_prolog(TreeState *state)
+{
+ char *define = xpidl_basename(state->basename);
+ fprintf(state->file, "/*\n * DO NOT EDIT. THIS FILE IS GENERATED FROM"
+ " %s.idl\n */\n", state->basename);
+ fprintf(state->file,
+ "\n#ifndef __gen_%s_h__\n"
+ "#define __gen_%s_h__\n",
+ define, define);
+ g_free(define);
+ if (state->base_includes != NULL) {
+ guint len = g_slist_length(state->base_includes);
+ guint i;
+
+ fputc('\n', state->file);
+ for (i = 0; i < len; i++) {
+ char *ident, *dot;
+
+ ident = (char *)g_slist_nth_data(state->base_includes, i);
+
+ /* suppress any trailing .extension */
+
+ /* XXX use g_basename instead ? ? */
+
+ dot = strrchr(ident, '.');
+ if (dot != NULL)
+ *dot = '\0';
+
+
+ /* begin include guard */
+ fprintf(state->file,
+ "\n#ifndef __gen_%s_h__\n",
+ ident);
+
+ fprintf(state->file, "#include \"%s.h\"\n",
+ (char *)g_slist_nth_data(state->base_includes, i));
+
+ fprintf(state->file, "#endif\n");
+
+ }
+ if (i > 0)
+ fputc('\n', state->file);
+ }
+ /*
+ * Support IDL files that don't include a root IDL file that defines
+ * NS_NO_VTABLE.
+ */
+ fprintf(state->file,
+ "/* For IDL files that don't want to include root IDL files. */\n"
+ "#ifndef NS_NO_VTABLE\n"
+ "#define NS_NO_VTABLE\n"
+ "#endif\n");
+
+ return TRUE;
+}
+
+static gboolean
+header_epilog(TreeState *state)
+{
+ char *define = xpidl_basename(state->basename);
+ fprintf(state->file, "\n#endif /* __gen_%s_h__ */\n", define);
+ g_free(define);
+ return TRUE;
+}
+
+static void
+write_classname_iid_define(FILE *file, const char *className)
+{
+ const char *iidName;
+ if (className[0] == 'n' && className[1] == 's') {
+ /* backcompat naming styles */
+ fputs("NS_", file);
+ iidName = className + 2;
+ } else {
+ iidName = className;
+ }
+ while (*iidName)
+ fputc(toupper(*iidName++), file);
+ fputs("_IID", file);
+}
+
+static gboolean
+interface(TreeState *state)
+{
+ IDL_tree iface = state->tree, iter, orig;
+ char *className = IDL_IDENT(IDL_INTERFACE(iface).ident).str;
+ char *classNameUpper = NULL;
+ char *classNameImpl = NULL;
+ char *cp;
+ gboolean ok = TRUE;
+ gboolean keepvtable;
+ const char *iid;
+ const char *name_space;
+ struct nsID id;
+ char iid_parsed[UUID_LENGTH];
+ GSList *doc_comments = IDL_IDENT(IDL_INTERFACE(iface).ident).comments;
+
+ if (!verify_interface_declaration(iface))
+ return FALSE;
+
+#define FAIL do {ok = FALSE; goto out;} while(0)
+
+ fprintf(state->file, "\n/* starting interface: %s */\n",
+ className);
+
+ name_space = IDL_tree_property_get(IDL_INTERFACE(iface).ident, "namespace");
+ if (name_space) {
+ fprintf(state->file, "/* namespace: %s */\n",
+ name_space);
+ fprintf(state->file, "/* fully qualified name: %s.%s */\n",
+ name_space,className);
+ }
+
+ iid = IDL_tree_property_get(IDL_INTERFACE(iface).ident, "uuid");
+ if (iid) {
+ /* Redundant, but a better error than 'cannot parse.' */
+ if (strlen(iid) != 36) {
+ IDL_tree_error(state->tree, "IID %s is the wrong length\n", iid);
+ FAIL;
+ }
+
+ /*
+ * Parse uuid and then output resulting nsID to string, to validate
+ * uuid and normalize resulting .h files.
+ */
+ if (!xpidl_parse_iid(&id, iid)) {
+ IDL_tree_error(state->tree, "cannot parse IID %s\n", iid);
+ FAIL;
+ }
+ if (!xpidl_sprint_iid(&id, iid_parsed)) {
+ IDL_tree_error(state->tree, "error formatting IID %s\n", iid);
+ FAIL;
+ }
+
+ /* #define NS_ISUPPORTS_IID_STR "00000000-0000-0000-c000-000000000046" */
+ fputs("#define ", state->file);
+ write_classname_iid_define(state->file, className);
+ fprintf(state->file, "_STR \"%s\"\n", iid_parsed);
+ fputc('\n', state->file);
+
+ /* #define NS_ISUPPORTS_IID { {0x00000000 .... 0x46 }} */
+ fprintf(state->file, "#define ");
+ write_classname_iid_define(state->file, className);
+ fprintf(state->file, " \\\n"
+ " {0x%.8x, 0x%.4x, 0x%.4x, \\\n"
+ " { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, "
+ "0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }}\n",
+ id.m0, id.m1, id.m2,
+ id.m3[0], id.m3[1], id.m3[2], id.m3[3],
+ id.m3[4], id.m3[5], id.m3[6], id.m3[7]);
+ fputc('\n', state->file);
+ } else {
+ IDL_tree_error(state->tree, "interface %s lacks a uuid attribute\n",
+ className);
+ FAIL;
+ }
+
+ if (doc_comments != NULL)
+ printlist(state->file, doc_comments);
+
+ /*
+ * NS_NO_VTABLE is defined in nsISupportsUtils.h, and defined on windows
+ * to __declspec(novtable) on windows. This optimization is safe
+ * whenever the constructor calls no virtual methods. Writing in IDL
+ * almost guarantees this, except for the case when a %{C++ block occurs in
+ * the interface. We detect that case, and emit a macro call that disables
+ * the optimization.
+ */
+ keepvtable = FALSE;
+ for (iter = IDL_INTERFACE(state->tree).body;
+ iter != NULL;
+ iter = IDL_LIST(iter).next)
+ {
+ IDL_tree data = IDL_LIST(iter).data;
+ if (IDL_NODE_TYPE(data) == IDLN_CODEFRAG)
+ keepvtable = TRUE;
+ }
+
+ /* The interface declaration itself. */
+ fprintf(state->file,
+ "class %s%s",
+ (keepvtable ? "" : "NS_NO_VTABLE "), className);
+
+ if ((iter = IDL_INTERFACE(iface).inheritance_spec)) {
+ fputs(" : ", state->file);
+ if (IDL_LIST(iter).next != NULL) {
+ IDL_tree_error(iter,
+ "multiple inheritance is not supported by xpidl");
+ FAIL;
+ }
+ fprintf(state->file, "public %s", IDL_IDENT(IDL_LIST(iter).data).str);
+ }
+ fputs(" {\n"
+ " public: \n\n", state->file);
+ if (iid) {
+ fputs(" NS_DEFINE_STATIC_IID_ACCESSOR(", state->file);
+ write_classname_iid_define(state->file, className);
+ fputs(")\n\n", state->file);
+ }
+
+ orig = state->tree; /* It would be nice to remove this state-twiddling. */
+
+ state->tree = IDL_INTERFACE(iface).body;
+
+ if (state->tree && !xpidl_process_node(state))
+ FAIL;
+
+ fputs("};\n", state->file);
+ fputc('\n', state->file);
+
+ /*
+ * #define NS_DECL_NSIFOO - create method prototypes that can be used in
+ * class definitions that support this interface.
+ *
+ * Walk the tree explicitly to prototype a reworking of xpidl to get rid of
+ * the callback mechanism.
+ */
+ state->tree = orig;
+ fputs("/* Use this macro when declaring classes that implement this "
+ "interface. */\n", state->file);
+ fputs("#define NS_DECL_", state->file);
+ classNameUpper = xpidl_strdup(className);
+ for (cp = classNameUpper; *cp != '\0'; cp++)
+ *cp = toupper(*cp);
+ fprintf(state->file, "%s \\\n", classNameUpper);
+ if (IDL_INTERFACE(state->tree).body == NULL) {
+ write_indent(state->file);
+ fputs("/* no methods! */\n", state->file);
+ }
+
+ for (iter = IDL_INTERFACE(state->tree).body;
+ iter != NULL;
+ iter = IDL_LIST(iter).next)
+ {
+ IDL_tree data = IDL_LIST(iter).data;
+
+ switch(IDL_NODE_TYPE(data)) {
+ case IDLN_OP_DCL:
+ write_indent(state->file);
+ write_method_signature(data, state->file, AS_DECL, NULL);
+ break;
+
+ case IDLN_ATTR_DCL:
+ write_indent(state->file);
+ if (!write_attr_accessor(data, state->file, TRUE, AS_DECL, NULL))
+ FAIL;
+ if (!IDL_ATTR_DCL(data).f_readonly) {
+ fputs("; \\\n", state->file); /* Terminate the previous one. */
+ write_indent(state->file);
+ if (!write_attr_accessor(data, state->file,
+ FALSE, AS_DECL, NULL))
+ FAIL;
+ /* '; \n' at end will clean up. */
+ }
+ break;
+
+ case IDLN_CONST_DCL:
+ /* ignore it here; it doesn't contribute to the macro. */
+ continue;
+
+ case IDLN_CODEFRAG:
+ XPIDL_WARNING((iter, IDL_WARNING1,
+ "%%{ .. %%} code fragment within interface "
+ "ignored when generating NS_DECL_%s macro; "
+ "if the code fragment contains method "
+ "declarations, the macro probably isn't "
+ "complete.", classNameUpper));
+ continue;
+
+ default:
+ IDL_tree_error(iter,
+ "unexpected node type %d! "
+ "Please file a bug against the xpidl component.",
+ IDL_NODE_TYPE(data));
+ FAIL;
+ }
+
+ if (IDL_LIST(iter).next != NULL) {
+ fprintf(state->file, "; \\\n");
+ } else {
+ fprintf(state->file, "; \n");
+ }
+ }
+ fputc('\n', state->file);
+
+ /* XXX abstract above and below into one function? */
+ /*
+ * #define NS_FORWARD_NSIFOO - create forwarding methods that can delegate
+ * behavior from in implementation to another object. As generated by
+ * idlc.
+ */
+ fprintf(state->file,
+ "/* Use this macro to declare functions that forward the "
+ "behavior of this interface to another object. */\n"
+ "#define NS_FORWARD_%s(_to) \\\n",
+ classNameUpper);
+ if (IDL_INTERFACE(state->tree).body == NULL) {
+ write_indent(state->file);
+ fputs("/* no methods! */\n", state->file);
+ }
+
+ for (iter = IDL_INTERFACE(state->tree).body;
+ iter != NULL;
+ iter = IDL_LIST(iter).next)
+ {
+ IDL_tree data = IDL_LIST(iter).data;
+
+ switch(IDL_NODE_TYPE(data)) {
+ case IDLN_OP_DCL:
+ write_indent(state->file);
+ write_method_signature(data, state->file, AS_DECL, NULL);
+ fputs(" { return _to ", state->file);
+ write_method_signature(data, state->file, AS_CALL, NULL);
+ break;
+
+ case IDLN_ATTR_DCL:
+ write_indent(state->file);
+ if (!write_attr_accessor(data, state->file, TRUE, AS_DECL, NULL))
+ FAIL;
+ fputs(" { return _to ", state->file);
+ if (!write_attr_accessor(data, state->file, TRUE, AS_CALL, NULL))
+ FAIL;
+ if (!IDL_ATTR_DCL(data).f_readonly) {
+ fputs("; } \\\n", state->file); /* Terminate the previous one. */
+ write_indent(state->file);
+ if (!write_attr_accessor(data, state->file,
+ FALSE, AS_DECL, NULL))
+ FAIL;
+ fputs(" { return _to ", state->file);
+ if (!write_attr_accessor(data, state->file,
+ FALSE, AS_CALL, NULL))
+ FAIL;
+ /* '; } \n' at end will clean up. */
+ }
+ break;
+
+ case IDLN_CONST_DCL:
+ case IDLN_CODEFRAG:
+ continue;
+
+ default:
+ FAIL;
+ }
+
+ if (IDL_LIST(iter).next != NULL) {
+ fprintf(state->file, "; } \\\n");
+ } else {
+ fprintf(state->file, "; } \n");
+ }
+ }
+ fputc('\n', state->file);
+
+
+ /* XXX abstract above and below into one function? */
+ /*
+ * #define NS_FORWARD_SAFE_NSIFOO - create forwarding methods that can delegate
+ * behavior from in implementation to another object. As generated by
+ * idlc.
+ */
+ fprintf(state->file,
+ "/* Use this macro to declare functions that forward the "
+ "behavior of this interface to another object in a safe way. */\n"
+ "#define NS_FORWARD_SAFE_%s(_to) \\\n",
+ classNameUpper);
+ if (IDL_INTERFACE(state->tree).body == NULL) {
+ write_indent(state->file);
+ fputs("/* no methods! */\n", state->file);
+ }
+
+ for (iter = IDL_INTERFACE(state->tree).body;
+ iter != NULL;
+ iter = IDL_LIST(iter).next)
+ {
+ IDL_tree data = IDL_LIST(iter).data;
+
+ switch(IDL_NODE_TYPE(data)) {
+ case IDLN_OP_DCL:
+ write_indent(state->file);
+ write_method_signature(data, state->file, AS_DECL, NULL);
+ fputs(" { return !_to ? NS_ERROR_NULL_POINTER : _to->", state->file);
+ write_method_signature(data, state->file, AS_CALL, NULL);
+ break;
+
+ case IDLN_ATTR_DCL:
+ write_indent(state->file);
+ if (!write_attr_accessor(data, state->file, TRUE, AS_DECL, NULL))
+ FAIL;
+ fputs(" { return !_to ? NS_ERROR_NULL_POINTER : _to->", state->file);
+ if (!write_attr_accessor(data, state->file, TRUE, AS_CALL, NULL))
+ FAIL;
+ if (!IDL_ATTR_DCL(data).f_readonly) {
+ fputs("; } \\\n", state->file); /* Terminate the previous one. */
+ write_indent(state->file);
+ if (!write_attr_accessor(data, state->file,
+ FALSE, AS_DECL, NULL))
+ FAIL;
+ fputs(" { return !_to ? NS_ERROR_NULL_POINTER : _to->", state->file);
+ if (!write_attr_accessor(data, state->file,
+ FALSE, AS_CALL, NULL))
+ FAIL;
+ /* '; } \n' at end will clean up. */
+ }
+ break;
+
+ case IDLN_CONST_DCL:
+ case IDLN_CODEFRAG:
+ continue;
+
+ default:
+ FAIL;
+ }
+
+ if (IDL_LIST(iter).next != NULL) {
+ fprintf(state->file, "; } \\\n");
+ } else {
+ fprintf(state->file, "; } \n");
+ }
+ }
+ fputc('\n', state->file);
+
+ /*
+ * Build a sample implementation template.
+ */
+ if (strlen(className) >= 3 && className[2] == 'I') {
+ classNameImpl = xpidl_strdup(className);
+ if (!classNameImpl)
+ FAIL;
+ memmove(&classNameImpl[2], &classNameImpl[3], strlen(classNameImpl) - 2);
+ } else {
+ classNameImpl = xpidl_strdup("_MYCLASS_");
+ if (!classNameImpl)
+ FAIL;
+ }
+
+ fputs("#if 0\n"
+ "/* Use the code below as a template for the "
+ "implementation class for this interface. */\n"
+ "\n"
+ "/* Header file */"
+ "\n",
+ state->file);
+ fprintf(state->file, "class %s : public %s\n", classNameImpl, className);
+ fputs("{\n"
+ "public:\n", state->file);
+ write_indent(state->file);
+ fputs("NS_DECL_ISUPPORTS\n", state->file);
+ write_indent(state->file);
+ fprintf(state->file, "NS_DECL_%s\n", classNameUpper);
+ fputs("\n", state->file);
+ write_indent(state->file);
+ fprintf(state->file, "%s();\n", classNameImpl);
+ fputs("\n"
+ "private:\n", state->file);
+ write_indent(state->file);
+ fprintf(state->file, "~%s();\n", classNameImpl);
+ fputs("\n"
+ "protected:\n", state->file);
+ write_indent(state->file);
+ fputs("/* additional members */\n", state->file);
+ fputs("};\n\n", state->file);
+
+ fputs("/* Implementation file */\n", state->file);
+
+ fprintf(state->file,
+ "NS_IMPL_ISUPPORTS1(%s, %s)\n", classNameImpl, className);
+ fputs("\n", state->file);
+
+ fprintf(state->file, "%s::%s()\n", classNameImpl, classNameImpl);
+ fputs("{\n", state->file);
+ write_indent(state->file);
+ fputs("/* member initializers and constructor code */\n", state->file);
+ fputs("}\n\n", state->file);
+
+ fprintf(state->file, "%s::~%s()\n", classNameImpl, classNameImpl);
+ fputs("{\n", state->file);
+ write_indent(state->file);
+ fputs("/* destructor code */\n", state->file);
+ fputs("}\n\n", state->file);
+
+ for (iter = IDL_INTERFACE(state->tree).body;
+ iter != NULL;
+ iter = IDL_LIST(iter).next)
+ {
+ IDL_tree data = IDL_LIST(iter).data;
+
+ switch(IDL_NODE_TYPE(data)) {
+ case IDLN_OP_DCL:
+ /* It would be nice to remove this state-twiddling. */
+ orig = state->tree;
+ state->tree = data;
+ xpidl_write_comment(state, 0);
+ state->tree = orig;
+
+ write_method_signature(data, state->file, AS_IMPL, classNameImpl);
+ fputs("\n{\n", state->file);
+ write_indent(state->file);
+ write_indent(state->file);
+ fputs("return NS_ERROR_NOT_IMPLEMENTED;\n"
+ "}\n"
+ "\n", state->file);
+ break;
+
+ case IDLN_ATTR_DCL:
+ /* It would be nice to remove this state-twiddling. */
+ orig = state->tree;
+ state->tree = data;
+ xpidl_write_comment(state, 0);
+ state->tree = orig;
+
+ if (!write_attr_accessor(data, state->file, TRUE,
+ AS_IMPL, classNameImpl))
+ FAIL;
+ fputs("\n{\n", state->file);
+ write_indent(state->file);
+ write_indent(state->file);
+ fputs("return NS_ERROR_NOT_IMPLEMENTED;\n"
+ "}\n", state->file);
+
+ if (!IDL_ATTR_DCL(data).f_readonly) {
+ if (!write_attr_accessor(data, state->file, FALSE,
+ AS_IMPL, classNameImpl))
+ FAIL;
+ fputs("\n{\n", state->file);
+ write_indent(state->file);
+ write_indent(state->file);
+ fputs("return NS_ERROR_NOT_IMPLEMENTED;\n"
+ "}\n", state->file);
+ }
+ fputs("\n", state->file);
+ break;
+
+ case IDLN_CONST_DCL:
+ case IDLN_CODEFRAG:
+ continue;
+
+ default:
+ FAIL;
+ }
+ }
+
+ fputs("/* End of implementation class template. */\n"
+ "#endif\n"
+ "\n", state->file);
+
+#undef FAIL
+
+out:
+ if (classNameUpper)
+ free(classNameUpper);
+ if (classNameImpl)
+ free(classNameImpl);
+ return ok;
+}
+
+static gboolean
+list(TreeState *state)
+{
+ IDL_tree iter;
+ for (iter = state->tree; iter; iter = IDL_LIST(iter).next) {
+ state->tree = IDL_LIST(iter).data;
+ if (!xpidl_process_node(state))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+write_type(IDL_tree type_tree, gboolean is_out, FILE *outfile)
+{
+ if (!type_tree) {
+ fputs("void", outfile);
+ return TRUE;
+ }
+
+ switch (IDL_NODE_TYPE(type_tree)) {
+ case IDLN_TYPE_INTEGER: {
+ gboolean sign = IDL_TYPE_INTEGER(type_tree).f_signed;
+ switch (IDL_TYPE_INTEGER(type_tree).f_type) {
+ case IDL_INTEGER_TYPE_SHORT:
+ fputs(sign ? "PRInt16" : "PRUint16", outfile);
+ break;
+ case IDL_INTEGER_TYPE_LONG:
+ fputs(sign ? "PRInt32" : "PRUint32", outfile);
+ break;
+ case IDL_INTEGER_TYPE_LONGLONG:
+ fputs(sign ? "PRInt64" : "PRUint64", outfile);
+ break;
+ default:
+ g_error("Unknown integer type %d\n",
+ IDL_TYPE_INTEGER(type_tree).f_type);
+ return FALSE;
+ }
+ break;
+ }
+ case IDLN_TYPE_CHAR:
+ fputs("char", outfile);
+ break;
+ case IDLN_TYPE_WIDE_CHAR:
+ fputs("PRUnichar", outfile); /* wchar_t? */
+ break;
+ case IDLN_TYPE_WIDE_STRING:
+ fputs("PRUnichar *", outfile);
+ break;
+ case IDLN_TYPE_STRING:
+ fputs("char *", outfile);
+ break;
+ case IDLN_TYPE_BOOLEAN:
+ fputs("PRBool", outfile);
+ break;
+ case IDLN_TYPE_OCTET:
+ fputs("PRUint8", outfile);
+ break;
+ case IDLN_TYPE_FLOAT:
+ switch (IDL_TYPE_FLOAT(type_tree).f_type) {
+ case IDL_FLOAT_TYPE_FLOAT:
+ fputs("float", outfile);
+ break;
+ case IDL_FLOAT_TYPE_DOUBLE:
+ fputs("double", outfile);
+ break;
+ /* XXX 'long double' just ignored, or what? */
+ default:
+ fprintf(outfile, "unknown_type_%d", IDL_NODE_TYPE(type_tree));
+ break;
+ }
+ break;
+ case IDLN_IDENT:
+ if (UP_IS_NATIVE(type_tree)) {
+ if (IDL_tree_property_get(type_tree, "domstring") ||
+ IDL_tree_property_get(type_tree, "astring")) {
+ fputs("nsAString", outfile);
+ } else if (IDL_tree_property_get(type_tree, "utf8string")) {
+ fputs("nsACString", outfile);
+ } else if (IDL_tree_property_get(type_tree, "cstring")) {
+ fputs("nsACString", outfile);
+ } else {
+ fputs(IDL_NATIVE(IDL_NODE_UP(type_tree)).user_type, outfile);
+ }
+ if (IDL_tree_property_get(type_tree, "ptr")) {
+ fputs(" *", outfile);
+ } else if (IDL_tree_property_get(type_tree, "ref")) {
+ fputs(" &", outfile);
+ }
+ } else {
+ fputs(IDL_IDENT(type_tree).str, outfile);
+ }
+ if (UP_IS_AGGREGATE(type_tree))
+ fputs(" *", outfile);
+ break;
+ default:
+ fprintf(outfile, "unknown_type_%d", IDL_NODE_TYPE(type_tree));
+ break;
+ }
+ return TRUE;
+}
+
+/*
+ * An attribute declaration looks like:
+ *
+ * [ IDL_ATTR_DCL]
+ * - param_type_spec [IDL_TYPE_* or NULL for void]
+ * - simple_declarations [IDL_LIST]
+ * - data [IDL_IDENT]
+ * - next [IDL_LIST or NULL if no more idents]
+ * - data [IDL_IDENT]
+ */
+
+#define ATTR_IDENT(tree) (IDL_IDENT(IDL_LIST(IDL_ATTR_DCL(tree).simple_declarations).data))
+#define ATTR_TYPE_DECL(tree) (IDL_ATTR_DCL(tree).param_type_spec)
+#define ATTR_TYPE(tree) (IDL_NODE_TYPE(ATTR_TYPE_DECL(tree)))
+
+/*
+ * AS_DECL writes 'NS_IMETHOD foo(string bar, long sil)'
+ * AS_IMPL writes 'NS_IMETHODIMP className::foo(string bar, long sil)'
+ * AS_CALL writes 'foo(bar, sil)'
+ */
+static gboolean
+write_attr_accessor(IDL_tree attr_tree, FILE * outfile,
+ gboolean getter, int mode, const char *className)
+{
+ char *attrname = ATTR_IDENT(attr_tree).str;
+
+ if (mode == AS_DECL) {
+ fputs("NS_IMETHOD ", outfile);
+ } else if (mode == AS_IMPL) {
+ fprintf(outfile, "NS_IMETHODIMP %s::", className);
+ }
+ fprintf(outfile, "%cet%c%s(",
+ getter ? 'G' : 'S',
+ toupper(*attrname), attrname + 1);
+ if (mode == AS_DECL || mode == AS_IMPL) {
+ /* Setters for string, wstring, nsid, domstring, utf8string,
+ * cstring and astring get const.
+ */
+ if (!getter &&
+ (IDL_NODE_TYPE(ATTR_TYPE_DECL(attr_tree)) == IDLN_TYPE_STRING ||
+ IDL_NODE_TYPE(ATTR_TYPE_DECL(attr_tree)) == IDLN_TYPE_WIDE_STRING ||
+ IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "nsid") ||
+ IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "domstring") ||
+ IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "utf8string") ||
+ IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "cstring") ||
+ IDL_tree_property_get(ATTR_TYPE_DECL(attr_tree), "astring")))
+ {
+ fputs("const ", outfile);
+ }
+
+ if (!write_type(ATTR_TYPE_DECL(attr_tree), getter, outfile))
+ return FALSE;
+ fprintf(outfile, "%s%s",
+ (STARRED_TYPE(attr_tree) ? "" : " "),
+ (getter && !DIPPER_TYPE(ATTR_TYPE_DECL(attr_tree)))? "*" : "");
+ }
+ fprintf(outfile, "a%c%s)", toupper(attrname[0]), attrname + 1);
+ return TRUE;
+}
+
+static gboolean
+attr_dcl(TreeState *state)
+{
+ GSList *doc_comments;
+
+ if (!verify_attribute_declaration(state->tree))
+ return FALSE;
+
+ doc_comments =
+ IDL_IDENT(IDL_LIST(IDL_ATTR_DCL
+ (state->tree).simple_declarations).data).comments;
+
+ if (doc_comments != NULL) {
+ write_indent(state->file);
+ printlist(state->file, doc_comments);
+ }
+
+ /*
+ * XXX lists of attributes with the same type, e.g.
+ * attribute string foo, bar sil;
+ * are legal IDL... but we don't do anything with 'em.
+ */
+ if (IDL_LIST(IDL_ATTR_DCL(state->tree).simple_declarations).next != NULL) {
+ XPIDL_WARNING((state->tree, IDL_WARNING1,
+ "multiple attributes in a single declaration aren't "
+ "currently supported by xpidl"));
+ }
+
+ xpidl_write_comment(state, 2);
+
+ write_indent(state->file);
+ if (!write_attr_accessor(state->tree, state->file, TRUE, AS_DECL, NULL))
+ return FALSE;
+ fputs(" = 0;\n", state->file);
+
+ if (!IDL_ATTR_DCL(state->tree).f_readonly) {
+ write_indent(state->file);
+ if (!write_attr_accessor(state->tree, state->file, FALSE, AS_DECL, NULL))
+ return FALSE;
+ fputs(" = 0;\n", state->file);
+ }
+ fputc('\n', state->file);
+
+ return TRUE;
+}
+
+static gboolean
+do_enum(TreeState *state)
+{
+ IDL_tree_error(state->tree, "enums not supported, "
+ "see http://bugzilla.mozilla.org/show_bug.cgi?id=8781");
+ return FALSE;
+}
+
+static gboolean
+do_const_dcl(TreeState *state)
+{
+ struct _IDL_CONST_DCL *dcl = &IDL_CONST_DCL(state->tree);
+ const char *name = IDL_IDENT(dcl->ident).str;
+ gboolean is_signed;
+ GSList *doc_comments = IDL_IDENT(dcl->ident).comments;
+ IDL_tree real_type;
+ const char *const_format;
+
+ if (!verify_const_declaration(state->tree))
+ return FALSE;
+
+ if (doc_comments != NULL) {
+ write_indent(state->file);
+ printlist(state->file, doc_comments);
+ }
+
+ /* Could be a typedef; try to map it to the real type. */
+ real_type = find_underlying_type(dcl->const_type);
+ real_type = real_type ? real_type : dcl->const_type;
+ is_signed = IDL_TYPE_INTEGER(real_type).f_signed;
+
+ const_format = is_signed ? "%" IDL_LL "d" : "%" IDL_LL "uU";
+ write_indent(state->file);
+ fprintf(state->file, "enum { %s = ", name);
+ fprintf(state->file, const_format, IDL_INTEGER(dcl->const_exp).value);
+ fprintf(state->file, " };\n\n");
+
+ return TRUE;
+}
+
+static gboolean
+do_typedef(TreeState *state)
+{
+ IDL_tree type = IDL_TYPE_DCL(state->tree).type_spec;
+ IDL_tree dcls = IDL_TYPE_DCL(state->tree).dcls;
+ IDL_tree complex;
+ GSList *doc_comments;
+
+ if (IDL_NODE_TYPE(type) == IDLN_TYPE_SEQUENCE) {
+ XPIDL_WARNING((state->tree, IDL_WARNING1,
+ "sequences not supported, ignored"));
+ } else {
+ if (IDL_NODE_TYPE(complex = IDL_LIST(dcls).data) == IDLN_TYPE_ARRAY) {
+ IDL_tree dim = IDL_TYPE_ARRAY(complex).size_list;
+ doc_comments = IDL_IDENT(IDL_TYPE_ARRAY(complex).ident).comments;
+
+ if (doc_comments != NULL)
+ printlist(state->file, doc_comments);
+
+ fputs("typedef ", state->file);
+ if (!write_type(type, FALSE, state->file))
+ return FALSE;
+ fputs(" ", state->file);
+
+ fprintf(state->file, "%s",
+ IDL_IDENT(IDL_TYPE_ARRAY(complex).ident).str);
+ do {
+ fputc('[', state->file);
+ if (IDL_LIST(dim).data) {
+ fprintf(state->file, "%ld",
+ (long)IDL_INTEGER(IDL_LIST(dim).data).value);
+ }
+ fputc(']', state->file);
+ } while ((dim = IDL_LIST(dim).next) != NULL);
+ } else {
+ doc_comments = IDL_IDENT(IDL_LIST(dcls).data).comments;
+
+ if (doc_comments != NULL)
+ printlist(state->file, doc_comments);
+
+ fputs("typedef ", state->file);
+ if (!write_type(type, FALSE, state->file))
+ return FALSE;
+ fputs(" ", state->file);
+ fputs(IDL_IDENT(IDL_LIST(dcls).data).str, state->file);
+ }
+ fputs(";\n\n", state->file);
+ }
+ return TRUE;
+}
+
+/*
+ * param generation:
+ * in string foo --> nsString *foo
+ * out string foo --> nsString **foo;
+ * inout string foo --> nsString **foo;
+ */
+
+/* If notype is true, just write the param name. */
+static gboolean
+write_param(IDL_tree param_tree, FILE *outfile)
+{
+ IDL_tree param_type_spec = IDL_PARAM_DCL(param_tree).param_type_spec;
+ gboolean is_in = IDL_PARAM_DCL(param_tree).attr == IDL_PARAM_IN;
+ /* in string, wstring, nsid, domstring, utf8string, cstring and
+ * astring any explicitly marked [const] are const
+ */
+
+ if (is_in &&
+ (IDL_NODE_TYPE(param_type_spec) == IDLN_TYPE_STRING ||
+ IDL_NODE_TYPE(param_type_spec) == IDLN_TYPE_WIDE_STRING ||
+ IDL_tree_property_get(IDL_PARAM_DCL(param_tree).simple_declarator,
+ "const") ||
+ IDL_tree_property_get(param_type_spec, "nsid") ||
+ IDL_tree_property_get(param_type_spec, "domstring") ||
+ IDL_tree_property_get(param_type_spec, "utf8string") ||
+ IDL_tree_property_get(param_type_spec, "cstring") ||
+ IDL_tree_property_get(param_type_spec, "astring"))) {
+ fputs("const ", outfile);
+ }
+ else if (IDL_PARAM_DCL(param_tree).attr == IDL_PARAM_OUT &&
+ IDL_tree_property_get(IDL_PARAM_DCL(param_tree).simple_declarator,
+ "shared")) {
+ fputs("const ", outfile);
+ }
+
+ if (!write_type(param_type_spec, !is_in, outfile))
+ return FALSE;
+
+ /* unless the type ended in a *, add a space */
+ if (!STARRED_TYPE(param_type_spec))
+ fputc(' ', outfile);
+
+ /* out and inout params get a bonus '*' (unless this is type that has a
+ * 'dipper' class that is passed in to receive 'out' data)
+ */
+ if (IDL_PARAM_DCL(param_tree).attr != IDL_PARAM_IN &&
+ !DIPPER_TYPE(param_type_spec)) {
+ fputc('*', outfile);
+ }
+ /* arrays get a bonus * too */
+ /* XXX Should this be a leading '*' or a trailing "[]" ?*/
+ if (IDL_tree_property_get(IDL_PARAM_DCL(param_tree).simple_declarator,
+ "array"))
+ fputc('*', outfile);
+
+ fputs(IDL_IDENT(IDL_PARAM_DCL(param_tree).simple_declarator).str, outfile);
+
+ return TRUE;
+}
+
+/*
+ * A forward declaration, usually an interface.
+ */
+static gboolean
+forward_dcl(TreeState *state)
+{
+ IDL_tree iface = state->tree;
+ const char *className = IDL_IDENT(IDL_FORWARD_DCL(iface).ident).str;
+
+ if (!className)
+ return FALSE;
+
+ fprintf(state->file, "class %s; /* forward declaration */\n\n", className);
+ return TRUE;
+}
+
+/*
+ * Shared between the interface class declaration and the NS_DECL_IFOO macro
+ * provided to aid declaration of implementation classes.
+ * mode...
+ * AS_DECL writes 'NS_IMETHOD foo(string bar, long sil)'
+ * AS_IMPL writes 'NS_IMETHODIMP className::foo(string bar, long sil)'
+ * AS_CALL writes 'foo(bar, sil)'
+ */
+static gboolean
+write_method_signature(IDL_tree method_tree, FILE *outfile, int mode,
+ const char *className)
+{
+ struct _IDL_OP_DCL *op = &IDL_OP_DCL(method_tree);
+ gboolean no_generated_args = TRUE;
+ gboolean op_notxpcom =
+ (IDL_tree_property_get(op->ident, "notxpcom") != NULL);
+ const char *name;
+ IDL_tree iter;
+
+ if (mode == AS_DECL) {
+ if (op_notxpcom) {
+ fputs("NS_IMETHOD_(", outfile);
+ if (!write_type(op->op_type_spec, FALSE, outfile))
+ return FALSE;
+ fputc(')', outfile);
+ } else {
+ fputs("NS_IMETHOD", outfile);
+ }
+ fputc(' ', outfile);
+ }
+ else if (mode == AS_IMPL) {
+ if (op_notxpcom) {
+ fputs("NS_IMETHODIMP_(", outfile);
+ if (!write_type(op->op_type_spec, FALSE, outfile))
+ return FALSE;
+ fputc(')', outfile);
+ } else {
+ fputs("NS_IMETHODIMP", outfile);
+ }
+ fputc(' ', outfile);
+ }
+ name = IDL_IDENT(op->ident).str;
+ if (mode == AS_IMPL) {
+ fprintf(outfile, "%s::%c%s(", className, toupper(*name), name + 1);
+ } else {
+ fprintf(outfile, "%c%s(", toupper(*name), name + 1);
+ }
+ for (iter = op->parameter_dcls; iter; iter = IDL_LIST(iter).next) {
+ if (mode == AS_DECL || mode == AS_IMPL) {
+ if (!write_param(IDL_LIST(iter).data, outfile))
+ return FALSE;
+ } else {
+ fputs(IDL_IDENT(IDL_PARAM_DCL(IDL_LIST(iter).data)
+ .simple_declarator).str,
+ outfile);
+ }
+ if ((IDL_LIST(iter).next ||
+ (!op_notxpcom && op->op_type_spec) || op->f_varargs))
+ fputs(", ", outfile);
+ no_generated_args = FALSE;
+ }
+
+ /* make IDL return value into trailing out argument */
+ if (op->op_type_spec && !op_notxpcom) {
+ IDL_tree fake_param = IDL_param_dcl_new(IDL_PARAM_OUT,
+ op->op_type_spec,
+ IDL_ident_new("_retval"));
+ if (!fake_param)
+ return FALSE;
+ if (mode == AS_DECL || mode == AS_IMPL) {
+ if (!write_param(fake_param, outfile))
+ return FALSE;
+ } else {
+ fputs("_retval", outfile);
+ }
+ if (op->f_varargs)
+ fputs(", ", outfile);
+ no_generated_args = FALSE;
+ }
+
+ /* varargs go last */
+ if (op->f_varargs) {
+ if (mode == AS_DECL || mode == AS_IMPL) {
+ fputs("nsVarArgs *", outfile);
+ }
+ fputs("_varargs", outfile);
+ no_generated_args = FALSE;
+ }
+
+ /*
+ * If generated method has no arguments, output 'void' to avoid C legacy
+ * behavior of disabling type checking.
+ */
+ if (no_generated_args && mode == AS_DECL) {
+ fputs("void", outfile);
+ }
+
+ fputc(')', outfile);
+
+ return TRUE;
+}
+
+/*
+ * A method is an `operation', therefore a method decl is an `op dcl'.
+ * I blame Elliot.
+ */
+static gboolean
+op_dcl(TreeState *state)
+{
+ GSList *doc_comments = IDL_IDENT(IDL_OP_DCL(state->tree).ident).comments;
+
+ /*
+ * Verify that e.g. non-scriptable methods in [scriptable] interfaces
+ * are declared so. Do this in a separate verification pass?
+ */
+ if (!verify_method_declaration(state->tree))
+ return FALSE;
+
+ if (doc_comments != NULL) {
+ write_indent(state->file);
+ printlist(state->file, doc_comments);
+ }
+ xpidl_write_comment(state, 2);
+
+ write_indent(state->file);
+ if (!write_method_signature(state->tree, state->file, AS_DECL, NULL))
+ return FALSE;
+ fputs(" = 0;\n\n", state->file);
+
+ return TRUE;
+}
+
+static void
+write_codefrag_line(gpointer data, gpointer user_data)
+{
+ TreeState *state = (TreeState *)user_data;
+ const char *line = (const char *)data;
+ fputs(line, state->file);
+ fputc('\n', state->file);
+}
+
+static gboolean
+codefrag(TreeState *state)
+{
+ const char *desc = IDL_CODEFRAG(state->tree).desc;
+ GSList *lines = IDL_CODEFRAG(state->tree).lines;
+ guint fragment_length;
+
+ if (strcmp(desc, "C++") && /* libIDL bug? */ strcmp(desc, "C++\r")) {
+ XPIDL_WARNING((state->tree, IDL_WARNING1,
+ "ignoring '%%{%s' escape. "
+ "(Use '%%{C++' to escape verbatim C++ code.)", desc));
+
+ return TRUE;
+ }
+
+ /*
+ * Emit #file directive to point debuggers back to the original .idl file
+ * for the duration of the code fragment. We look at internal IDL node
+ * properties _file, _line to do this; hopefully they won't change.
+ *
+ * _line seems to refer to the line immediately after the closing %}, so
+ * we backtrack to get the proper line for the beginning of the block.
+ */
+ /*
+ * Looks like getting this right means maintaining an accurate line
+ * count of everything generated, so we can set the file back to the
+ * correct line in the generated file afterwards. Skipping for now...
+ */
+
+ fragment_length = g_slist_length(lines);
+/* fprintf(state->file, "#line %d \"%s\"\n", */
+/* state->tree->_line - fragment_length - 1, */
+/* state->tree->_file); */
+
+ g_slist_foreach(lines, write_codefrag_line, (gpointer)state);
+
+ return TRUE;
+}
+
+backend *
+xpidl_header_dispatch(void)
+{
+ static backend result;
+ static nodeHandler table[IDLN_LAST];
+ static gboolean initialized = FALSE;
+
+ result.emit_prolog = header_prolog;
+ result.emit_epilog = header_epilog;
+
+ if (!initialized) {
+ table[IDLN_LIST] = list;
+ table[IDLN_ATTR_DCL] = attr_dcl;
+ table[IDLN_OP_DCL] = op_dcl;
+ table[IDLN_FORWARD_DCL] = forward_dcl;
+ table[IDLN_TYPE_ENUM] = do_enum;
+ table[IDLN_INTERFACE] = interface;
+ table[IDLN_CODEFRAG] = codefrag;
+ table[IDLN_TYPE_DCL] = do_typedef;
+ table[IDLN_CONST_DCL] = do_const_dcl;
+ table[IDLN_NATIVE] = check_native;
+ initialized = TRUE;
+ }
+
+ result.dispatch_table = table;
+ return &result;
+}
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_idl.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_idl.c
new file mode 100644
index 00000000..175f379a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_idl.c
@@ -0,0 +1,836 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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):
+ * Michael Ang <mang@subcarrier.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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Common IDL-processing code.
+ */
+
+#include "xpidl.h"
+
+#ifdef XP_MAC
+#include <stat.h>
+#endif
+
+static gboolean parsed_empty_file;
+
+/*
+ * The bulk of the generation happens here.
+ */
+gboolean
+xpidl_process_node(TreeState *state)
+{
+ gint type;
+ nodeHandler *dispatch, handler;
+
+ XPT_ASSERT(state->tree);
+ type = IDL_NODE_TYPE(state->tree);
+
+ if ((dispatch = state->dispatch) && (handler = dispatch[type]))
+ return handler(state);
+ return TRUE;
+}
+
+#if defined(XP_MAC) && defined(XPIDL_PLUGIN)
+extern void mac_warning(const char* warning_message);
+#endif
+
+static int
+msg_callback(int level, int num, int line, const char *file,
+ const char *message)
+{
+ char *warning_message;
+
+ /*
+ * Egregious hack to permit empty files.
+ * XXX libIDL needs an API to detect this case robustly.
+ */
+ if (0 == strcmp(message, "File empty after optimization")) {
+ parsed_empty_file = TRUE;
+ return 1;
+ }
+
+ if (!file)
+ file = "<unknown file>";
+ warning_message = g_strdup_printf("%s:%d: %s\n", file, line, message);
+
+#if defined(XP_MAC) && defined(XPIDL_PLUGIN)
+ mac_warning(warning_message);
+#else
+ fputs(warning_message, stderr);
+#endif
+
+ g_free(warning_message);
+ return 1;
+}
+
+/*
+ * To keep track of the state associated with a given input file. The 'next'
+ * field lets us maintain a stack of input files.
+ */
+typedef struct input_data {
+ char *filename; /* where did I come from? */
+ unsigned int lineno; /* last lineno processed */
+ char *buf; /* contents of file */
+ char *point; /* next char to feed to libIDL */
+ char *max; /* 1 past last char in buf */
+ struct input_data *next; /* file from which we were included */
+} input_data;
+
+/*
+ * Passed to us by libIDL. Holds global information and the current stack of
+ * include files.
+ */
+typedef struct input_callback_state {
+ struct input_data *input_stack; /* linked list of input_data */
+ GHashTable *already_included; /* to prevent redundant includes */
+ IncludePathEntry *include_path; /* search path for included files */
+ GSList *base_includes; /* to accumulate #includes from *first* file;
+ * for passing thru TreeState to
+ * xpidl_header backend. */
+} input_callback_state;
+
+static FILE *
+fopen_from_includes(const char *filename, const char *mode,
+ IncludePathEntry *include_path)
+{
+ IncludePathEntry *current_path = include_path;
+ char *pathname;
+ FILE *inputfile;
+ if (!strcmp(filename, "-"))
+ return stdin;
+
+ if (filename[0] != '/') {
+ while (current_path) {
+ pathname = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
+ current_path->directory, filename);
+ if (!pathname)
+ return NULL;
+ inputfile = fopen(pathname, mode);
+ g_free(pathname);
+ if (inputfile)
+ return inputfile;
+ current_path = current_path->next;
+ }
+ } else {
+ inputfile = fopen(filename, mode);
+ if (inputfile)
+ return inputfile;
+ }
+ return NULL;
+}
+
+#if defined(XP_MAC) && defined(XPIDL_PLUGIN)
+extern FILE* mac_fopen(const char* filename, const char *mode);
+#endif
+
+static input_data *
+new_input_data(const char *filename, IncludePathEntry *include_path)
+{
+ input_data *new_data;
+ FILE *inputfile;
+ char *buffer = NULL;
+ size_t offset = 0;
+ size_t buffer_size;
+#ifdef XP_MAC
+ size_t i;
+#endif
+
+#if defined(XP_MAC) && defined(XPIDL_PLUGIN)
+ /* on Mac, fopen knows how to find files. */
+ inputfile = fopen(filename, "r");
+#elif defined(XP_OS2) || defined(XP_WIN32)
+ /*
+ * if filename is fully qualified (starts with driver letter), then
+ * just call fopen(); else, go with fopen_from_includes()
+ */
+ if( filename[1] == ':' )
+ inputfile = fopen(filename, "r");
+ else
+ inputfile = fopen_from_includes(filename, "r", include_path);
+#else
+ inputfile = fopen_from_includes(filename, "r", include_path);
+#endif
+
+ if (!inputfile)
+ return NULL;
+
+#ifdef XP_MAC
+ {
+ struct stat input_stat;
+ if (fstat(fileno(inputfile), &input_stat))
+ return NULL;
+ buffer = malloc(input_stat.st_size + 1);
+ if (!buffer)
+ return NULL;
+ offset = fread(buffer, 1, input_stat.st_size, inputfile);
+ if (ferror(inputfile))
+ return NULL;
+ }
+#else
+ /*
+ * Rather than try to keep track of many different varieties of state
+ * around the boundaries of a circular buffer, we just read in the entire
+ * file.
+ *
+ * We iteratively grow the buffer here; an alternative would be to use
+ * stat to find the exact buffer size we need, as xpt_dump does.
+ */
+ for (buffer_size = 8191; ; buffer_size *= 2) {
+ size_t just_read;
+ buffer = realloc(buffer, buffer_size + 1); /* +1 for trailing nul */
+ just_read = fread(buffer + offset, 1, buffer_size - offset, inputfile);
+ if (ferror(inputfile))
+ return NULL;
+
+ if (just_read < buffer_size - offset || just_read == 0) {
+ /* Done reading. */
+ offset += just_read;
+ break;
+ }
+ offset += just_read;
+ }
+#endif
+
+ fclose(inputfile);
+
+#ifdef XP_MAC
+ /*
+ * libIDL doesn't speak '\r' properly - always make sure lines end with
+ * '\n'.
+ */
+ for (i = 0; i < offset; i++) {
+ if (buffer[i] == '\r')
+ buffer[i] = '\n';
+ }
+#endif
+
+ new_data = xpidl_malloc(sizeof (struct input_data));
+ new_data->point = new_data->buf = buffer;
+ new_data->max = buffer + offset;
+ *new_data->max = '\0';
+ new_data->filename = xpidl_strdup(filename);
+ /* libIDL expects the line number to be that of the *next* line */
+ new_data->lineno = 2;
+ new_data->next = NULL;
+
+ return new_data;
+}
+
+/* process pending raw section */
+static int
+NextIsRaw(input_data *data, char **startp, int *lenp)
+{
+ char *end, *start;
+
+ /*
+ * XXXmccabe still needed: an in_raw flag to handle the case where we're in
+ * a raw block, but haven't managed to copy it all to xpidl. This will
+ * happen when we have a raw block larger than
+ * IDL_input_data->fill.max_size (currently 8192.)
+ */
+ if (!(data->point[0] == '%' && data->point[1] == '{'))
+ return 0;
+
+ start = *startp = data->point;
+
+ end = NULL;
+ while (start < data->max && (end = strstr(start, "%}"))) {
+ if (end[-1] == '\r' ||
+ end[-1] == '\n')
+ break;
+ start = end + 1;
+ }
+
+ if (end && start < data->max) {
+ *lenp = end - data->point + 2;
+ return 1;
+ } else {
+ const char *filename;
+ int lineno;
+
+ IDL_file_get(&filename, &lineno);
+ msg_callback(IDL_ERROR, 0, lineno, filename,
+ "unterminated %{ block");
+ return -1;
+ }
+}
+
+/* process pending comment */
+static int
+NextIsComment(input_data *data, char **startp, int *lenp)
+{
+ char *end;
+
+ if (!(data->point[0] == '/' && data->point[1] == '*'))
+ return 0;
+
+ end = strstr(data->point, "*/");
+ *lenp = 0;
+ if (end) {
+ int skippedLines = 0;
+ char *tempPoint;
+
+ /* get current lineno */
+ IDL_file_get(NULL,(int *)&data->lineno);
+
+ /* get line count */
+ for (tempPoint = data->point; tempPoint < end; tempPoint++) {
+ if (*tempPoint == '\n')
+ skippedLines++;
+ }
+
+ data->lineno += skippedLines;
+ IDL_file_set(data->filename, (int)data->lineno);
+
+ *startp = end + 2;
+
+ /* If it's a ** comment, tell libIDL about it. */
+ if (data->point[2] == '*') {
+ /* hack termination. +2 to get past '*' '/' */
+ char t = *(end + 2);
+ *(end + 2) = '\0';
+ IDL_queue_new_ident_comment(data->point);
+ *(end + 2) = t;
+ }
+
+ data->point = *startp; /* XXXmccabe move this out of function? */
+ return 1;
+ } else {
+ const char *filename;
+ int lineno;
+
+ IDL_file_get(&filename, &lineno);
+ msg_callback(IDL_ERROR, 0, lineno, filename,
+ "unterminated comment");
+ return -1;
+ }
+}
+
+static int
+NextIsInclude(input_callback_state *callback_state, char **startp,
+ int *lenp)
+{
+ input_data *data = callback_state->input_stack;
+ input_data *new_data;
+ char *filename, *end;
+ const char *scratch;
+
+ /* process the #include that we're in now */
+ if (strncmp(data->point, "#include \"", 10)) {
+ return 0;
+ }
+
+ filename = data->point + 10; /* skip #include " */
+ XPT_ASSERT(filename < data->max);
+ end = filename;
+ while (end < data->max) {
+ if (*end == '\"' || *end == '\n' || *end == '\r')
+ break;
+ end++;
+ }
+
+ if (*end != '\"') {
+ /*
+ * Didn't find end of include file. Scan 'til next whitespace to find
+ * some reasonable approximation of the filename, and use it to report
+ * an error.
+ */
+
+ end = filename;
+ while (end < data->max) {
+ if (*end == ' ' || *end == '\n' || *end == '\r' || *end == '\t')
+ break;
+ end++;
+ }
+ *end = '\0';
+
+ /* make sure we have accurate line info */
+ IDL_file_get(&scratch, (int *)&data->lineno);
+ fprintf(stderr,
+ "%s:%u: didn't find end of quoted include name \"%s\n",
+ scratch, data->lineno, filename);
+ return -1;
+ }
+
+ *end = '\0';
+ *startp = end + 1;
+
+ if (data->next == NULL) {
+ /*
+ * If we're in the initial file, add this filename to the list
+ * of filenames to be turned into #include "filename.h"
+ * directives in xpidl_header.c. We do it here rather than in the
+ * block below so it still gets added to the list even if it's
+ * already been recursively included from some other file.
+ */
+ char *filename_cp = xpidl_strdup(filename);
+
+ /* note that g_slist_append accepts and likes null as list-start. */
+ callback_state->base_includes =
+ g_slist_append(callback_state->base_includes, filename_cp);
+ }
+
+ /* store offset for when we pop, or if we skip this one */
+ data->point = *startp;
+
+ if (!g_hash_table_lookup(callback_state->already_included, filename)) {
+ filename = xpidl_strdup(filename);
+ g_hash_table_insert(callback_state->already_included,
+ filename, (void *)TRUE);
+ new_data = new_input_data(filename, callback_state->include_path);
+ if (!new_data) {
+ char *error_message;
+ IDL_file_get(&scratch, (int *)&data->lineno);
+ error_message =
+ g_strdup_printf("can't open included file %s for reading\n",
+ filename);
+ msg_callback(IDL_ERROR, 0,
+ data->lineno, scratch, error_message);
+ g_free(error_message);
+ return -1;
+ }
+
+ new_data->next = data;
+ /* tell libIDL to exclude this IDL from the toplevel tree */
+ IDL_inhibit_push();
+ IDL_file_get(&scratch, (int *)&data->lineno);
+ callback_state->input_stack = new_data;
+ IDL_file_set(new_data->filename, (int)new_data->lineno);
+ }
+
+ *lenp = 0; /* this is magic, see the comment below */
+ return 1;
+}
+
+static void
+FindSpecial(input_data *data, char **startp, int *lenp)
+{
+ char *point = data->point;
+
+ /* magic sequences are:
+ * "%{" raw block
+ * "/\*" comment
+ * "#include \"" include
+ * The first and last want a newline [\r\n] before, or the start of the
+ * file.
+ */
+
+#define LINE_START(data, point) (point == data->buf || \
+ (point > data->point && \
+ (point[-1] == '\r' || point[-1] == '\n')))
+
+ while (point < data->max) {
+ if (point[0] == '/' && point[1] == '*')
+ break;
+ if (LINE_START(data, point)) {
+ if (point[0] == '%' && point[1] == '{')
+ break;
+ if (point[0] == '#' && !strncmp(point + 1, "include \"", 9))
+ break;
+ }
+ point++;
+ }
+
+#undef LINE_START
+
+ *startp = data->point;
+ *lenp = point - data->point;
+}
+
+/* set this with a debugger to see exactly what libIDL sees */
+static FILE *tracefile;
+
+static int
+input_callback(IDL_input_reason reason, union IDL_input_data *cb_data,
+ gpointer user_data)
+{
+ input_callback_state *callback_state = user_data;
+ input_data *data = callback_state->input_stack;
+ input_data *new_data = NULL;
+ unsigned int len, copy;
+ int rv;
+ char *start;
+
+ switch(reason) {
+ case IDL_INPUT_REASON_INIT:
+ if (data == NULL || data->next == NULL) {
+ /*
+ * This is the first file being processed. As it's the target
+ * file, we only look for it in the first entry in the include
+ * path, which we assume to be the current directory.
+ */
+
+ /* XXXmccabe proper assumption? Do we handle files in other
+ directories? */
+
+ IncludePathEntry first_entry;
+
+ first_entry.directory = callback_state->include_path->directory;
+ first_entry.next = NULL;
+
+ new_data = new_input_data(cb_data->init.filename,
+ &first_entry);
+ } else {
+ new_data = new_input_data(cb_data->init.filename,
+ callback_state->include_path);
+ }
+
+ if (!new_data)
+ return -1;
+
+ IDL_file_set(new_data->filename, (int)new_data->lineno);
+ callback_state->input_stack = new_data;
+ return 0;
+
+ case IDL_INPUT_REASON_FILL:
+ start = NULL;
+ len = 0;
+
+ while (data->point >= data->max) {
+ if (!data->next)
+ return 0;
+
+ /* Current file is done; revert to including file */
+ callback_state->input_stack = data->next;
+ free(data->filename);
+ free(data->buf);
+ free(data);
+ data = callback_state->input_stack;
+
+ IDL_file_set(data->filename, (int)data->lineno);
+ IDL_inhibit_pop();
+ }
+
+ /*
+ * Now we scan for sequences which require special attention:
+ * \n#include begins an include statement
+ * \n%{ begins a raw-source block
+ * /\* begins a comment
+ *
+ * We used to be fancier here, so make sure that we sent the most
+ * data possible at any given time. To that end, we skipped over
+ * \n%{ raw \n%} blocks and then _continued_ the search for special
+ * sequences like \n#include or /\* comments .
+ *
+ * It was really ugly, though -- liberal use of goto! lots of implicit
+ * state! what fun! -- so now we just do this:
+ *
+ * if (special at start) {
+ * process that special -
+ * - raw: send it to libIDL, and don't look inside for specials
+ * - comments: adjust point and start over
+ * - includes: push new input_data struct for included file, and
+ * start over
+ * } else {
+ * scan for next special
+ * send data up to that special to libIDL
+ * }
+ *
+ * If len is set to zero, it is a sentinel value indicating we a comment
+ * or include was found, and parsing should start over.
+ *
+ * XXX const string foo = "/\*" will just screw us horribly.
+ * Hm but. We could treat strings as we treat raw blocks, eh?
+ */
+
+ /*
+ * Order is important, so that you can have /\* comments and
+ * #includes within raw sections, and so that you can comment out
+ * #includes.
+ */
+ rv = NextIsRaw(data, &start, (int *)&len);
+ if (rv == -1) return -1;
+ if (!rv) {
+ /*
+ * When NextIsComment succeeds, it returns a 0 len (requesting a
+ * restart) and adjusts data->point to pick up after the comment.
+ */
+ rv = NextIsComment(data, &start, (int *)&len);
+ if (rv == -1) return -1;
+ if (!rv) {
+ /*
+ * NextIsInclude might push a new input_data struct; if so, it
+ * will return a 0 len, letting the callback pick up the new
+ * file the next time around.
+ */
+ rv = NextIsInclude(callback_state, &start, (int *)&len);
+ if (rv == -1) return -1;
+ if (!rv)
+ FindSpecial(data, &start, (int *)&len);
+ }
+ }
+
+ if (len == 0) {
+ /*
+ * len == 0 is a sentinel value that means we found a comment or
+ * include. If we found a comment, point has been adjusted to
+ * point past the comment. If we found an include, a new input_data
+ * has been pushed. In both cases, calling the input_callback again
+ * will pick up the new state.
+ */
+ return input_callback(reason, cb_data, user_data);
+ }
+
+ copy = MIN(len, (unsigned int) cb_data->fill.max_size);
+ memcpy(cb_data->fill.buffer, start, copy);
+ data->point = start + copy;
+
+ if (tracefile)
+ fwrite(cb_data->fill.buffer, copy, 1, tracefile);
+
+ return copy;
+
+ case IDL_INPUT_REASON_ABORT:
+ case IDL_INPUT_REASON_FINISH:
+ while (data != NULL) {
+ input_data *next;
+
+ next = data->next;
+ free(data->filename);
+ free(data->buf);
+ free(data);
+ data = next;
+ }
+ return 0;
+
+ default:
+ g_error("unknown input reason %d!", reason);
+ return -1;
+ }
+}
+
+static void
+free_ghash_key(gpointer key, gpointer value, gpointer user_data)
+{
+ /* We're only storing TRUE in the value... */
+ free(key);
+}
+
+static void
+free_gslist_data(gpointer data, gpointer user_data)
+{
+ free(data);
+}
+
+/* Pick up unlink. */
+#ifdef XP_UNIX
+#include <unistd.h>
+#elif XP_WIN
+/* We get it from stdio.h. */
+#endif
+
+int
+xpidl_process_idl(char *filename, IncludePathEntry *include_path,
+ char *file_basename, ModeData *mode)
+{
+ char *tmp, *outname, *real_outname = NULL;
+ IDL_tree top;
+ TreeState state;
+ int rv;
+ input_callback_state callback_state;
+ gboolean ok = TRUE;
+ backend *emitter;
+
+ callback_state.input_stack = NULL;
+ callback_state.base_includes = NULL;
+ callback_state.include_path = include_path;
+ callback_state.already_included = g_hash_table_new(g_str_hash, g_str_equal);
+
+ if (!callback_state.already_included) {
+ fprintf(stderr, "failed to create hashtable. out of memory?\n");
+ return 0;
+ }
+
+ state.basename = xpidl_strdup(filename);
+
+ /* if basename has an .extension, truncate it. */
+ tmp = strrchr(state.basename, '.');
+ if (tmp)
+ *tmp = '\0';
+
+ if (!file_basename)
+ outname = xpidl_strdup(state.basename);
+ else
+ outname = xpidl_strdup(file_basename);
+
+ /* so we don't include it again! */
+ g_hash_table_insert(callback_state.already_included,
+ xpidl_strdup(filename), (void *)TRUE);
+
+ parsed_empty_file = FALSE;
+
+ rv = IDL_parse_filename_with_input(filename, input_callback, &callback_state,
+ msg_callback, &top,
+ &state.ns,
+ IDLF_IGNORE_FORWARDS |
+ IDLF_XPIDL,
+ enable_warnings ? IDL_WARNING1 :
+ IDL_ERROR);
+ if (parsed_empty_file) {
+ /*
+ * If we've detected (via hack in msg_callback) that libIDL returned
+ * failure because it found a file with no IDL, set the parse tree to
+ * null and proceed. Allowing this is useful to permit .idl files that
+ * collect #includes.
+ */
+ top = NULL;
+ state.ns = NULL;
+ } else if (rv != IDL_SUCCESS) {
+ if (rv == -1) {
+ g_warning("Parse of %s failed: %s", filename, g_strerror(errno));
+ } else {
+ g_warning("Parse of %s failed", filename);
+ }
+ return 0;
+ }
+
+ state.basename = xpidl_strdup(filename);
+ tmp = strrchr(state.basename, '.');
+ if (tmp)
+ *tmp = '\0';
+
+ /* so xpidl_header.c can use it to generate a list of #include directives */
+ state.base_includes = callback_state.base_includes;
+
+ emitter = mode->factory();
+ state.dispatch = emitter->dispatch_table;
+
+ if (strcmp(outname, "-")) {
+ const char *fopen_mode;
+ char *out_basename;
+
+ /* explicit_output_filename can't be true without a filename */
+ if (explicit_output_filename) {
+ real_outname = g_strdup(outname);
+ } else {
+/*
+ *This combination seems a little strange, what about OS/2?
+ * Assume it's some build issue
+ */
+#if defined(XP_UNIX) || defined(XP_WIN)
+ if (!file_basename) {
+ out_basename = xpidl_basename(outname);
+ } else {
+ out_basename = outname;
+ }
+#else
+ out_basename = outname;
+#endif
+ real_outname = g_strdup_printf("%s.%s", out_basename, mode->suffix);
+ if (out_basename != outname)
+ g_free(out_basename);
+ }
+
+ /* Use binary write for typelib mode */
+ fopen_mode = (strcmp(mode->mode, "typelib")) ? "w" : "wb";
+ state.file = fopen(real_outname, fopen_mode);
+ if (!state.file) {
+ perror("error opening output file");
+ return 0;
+ }
+ } else {
+ state.file = stdout;
+ }
+ state.tree = top;
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ state.real_outname = real_outname;
+#endif
+
+ if (emitter->emit_prolog)
+ emitter->emit_prolog(&state);
+ if (state.tree) /* Only if we have a tree to process. */
+ ok = xpidl_process_node(&state);
+ if (emitter->emit_epilog)
+ emitter->emit_epilog(&state);
+
+ if (state.file != stdout)
+ fclose(state.file);
+ free(state.basename);
+ free(outname);
+ g_hash_table_foreach(callback_state.already_included, free_ghash_key, NULL);
+ g_hash_table_destroy(callback_state.already_included);
+ g_slist_foreach(callback_state.base_includes, free_gslist_data, NULL);
+
+ if (state.ns)
+ IDL_ns_free(state.ns);
+ if (top)
+ IDL_tree_free(top);
+
+ if (real_outname != NULL) {
+ /*
+ * Delete partial output file on failure. (Mac does this in the plugin
+ * driver code, if the compiler returns failure.)
+ */
+#if defined(XP_UNIX) || defined(XP_WIN)
+ if (!ok)
+ unlink(real_outname);
+#endif
+ g_free(real_outname);
+ }
+
+ return ok;
+}
+
+/*
+ * Our own version of IDL_tree_warning, which we use when IDL_tree_warning
+ * would crash on us.
+ */
+void
+xpidl_tree_warning(IDL_tree p, int level, const char *fmt, ...)
+{
+ va_list ap;
+ char *msg, *file;
+ int lineno;
+
+ /* XXX need to check against __IDL_max_msg_level, no accessor */
+ va_start(ap, fmt);
+ msg = g_strdup_vprintf(fmt, ap);
+
+ if (p) {
+ file = p->_file;
+ lineno = p->_line;
+ } else {
+ file = NULL;
+ lineno = 0;
+ }
+
+ /* call our message callback, like IDL_tree_warning would */
+ msg_callback(level, 0, lineno, file, msg);
+ g_free(msg);
+ va_end(ap);
+}
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_java.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_java.c
new file mode 100644
index 00000000..4f708027
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_java.c
@@ -0,0 +1,1053 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 Sun Microsystems,
+ * Inc. Portions created by Sun are
+ * Copyright (C) 1999 Sun Microsystems, Inc. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ * Michael Allen (michael.allen@sun.com)
+ * Frank Mitchell (frank.mitchell@sun.com)
+ */
+
+/*
+ * Generate Java interfaces from XPIDL.
+ */
+
+#include "xpidl.h"
+#include <ctype.h>
+#include <glib.h>
+
+
+struct java_priv_data {
+ GHashTable *typedefTable;
+};
+
+#define TYPEDEFS(state) (((struct java_priv_data *)state->priv)->typedefTable)
+
+static gboolean
+write_classname_iid_define(FILE *file, const char *className)
+{
+ const char *iidName;
+ if (className[0] == 'n' && className[1] == 's') {
+ /* backcompat naming styles */
+ fputs("NS_", file);
+ iidName = className + 2;
+ } else {
+ iidName = className;
+ }
+
+ while (*iidName) {
+ fputc(toupper(*iidName++), file);
+ }
+
+ fputs("_IID", file);
+ return TRUE;
+}
+
+static gboolean
+java_prolog(TreeState *state)
+{
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ const char *basename;
+ const char *ext;
+#endif
+
+ state->priv = calloc(1, sizeof(struct java_priv_data));
+ if (!state->priv)
+ return FALSE;
+ TYPEDEFS(state) = 0;
+ TYPEDEFS(state) = g_hash_table_new(g_str_hash, g_str_equal);
+ if (!TYPEDEFS(state)) {
+ /* XXX report error */
+ free(state->priv);
+ return FALSE;
+ }
+
+ /*
+ * First pass
+ */
+
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ basename = xpidl_basename(state->real_outname ? state->real_outname : state->basename);
+ ext = strrchr(basename, '.');
+ if (!ext)
+ ext = strchr(basename, '\0');
+ fprintf(state->file,
+ "/**\n"
+ " * NOTE: THIS IS A GENERATED FILE. PLEASE CONSULT THE ORIGINAL IDL FILE\n"
+ " * FOR THE FULL DOCUMENTATION AND LICENSE.\n"
+ " *\n"
+ " * @see <a href=\"http://lxr.mozilla.org/mozilla/search?string=interface+%.*s\">\n"
+ " **/\n"
+ "\n"
+ "package org.mozilla.interfaces;\n\n"
+ "import java.math.BigInteger;\n\n"
+ "\n"
+ , ext - basename >= 19 ? 19 : (int)(ext - basename), basename);
+ g_free(basename);
+#else
+ fputs("/*\n * ************* DO NOT EDIT THIS FILE ***********\n",
+ state->file);
+
+ fprintf(state->file,
+ " *\n * This file was automatically generated from %s.idl.\n",
+ state->basename);
+
+ fputs(" */\n\n", state->file);
+#endif
+
+ return TRUE;
+}
+
+static gboolean
+java_epilog(TreeState *state)
+{
+ /* points to other elements of the tree, so just destroy the table */
+ g_hash_table_destroy(TYPEDEFS(state));
+ free(state->priv);
+ state->priv = NULL;
+
+#ifndef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ /*
+ * Last pass
+ */
+
+ fprintf(state->file, "\n/*\n * end\n */\n");
+#endif
+
+ return TRUE;
+}
+
+static gboolean
+forward_declaration(TreeState *state)
+{
+ /*
+ * Java doesn't need forward declarations unless the declared
+ * class resides in a different package.
+ */
+#if 0
+ IDL_tree iface = state->tree;
+ const char *className = IDL_IDENT(IDL_FORWARD_DCL(iface).ident).str;
+ const char *pkgName = "org.mozilla.xpcom";
+ if (!className)
+ return FALSE;
+ /* XXX: Get package name and compare */
+ fprintf(state->file, "import %s.%s;\n", pkgName, className);
+#endif
+ return TRUE;
+}
+
+
+static gboolean
+interface_declaration(TreeState *state)
+{
+ IDL_tree interface = state->tree;
+ IDL_tree iterator = NULL;
+ char *interface_name = IDL_IDENT(IDL_INTERFACE(interface).ident).str;
+ const char *iid = NULL;
+
+ if (!verify_interface_declaration(interface))
+ return FALSE;
+#ifndef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ /*
+ * Write out JavaDoc comment
+ */
+
+ fprintf(state->file, "\n/**\n * Interface %s\n", interface_name);
+#endif
+
+#ifndef LIBIDL_MAJOR_VERSION
+ iid = IDL_tree_property_get(interface, "uuid");
+#else
+ iid = IDL_tree_property_get(IDL_INTERFACE(interface).ident, "uuid");
+#endif
+
+#ifndef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ if (iid != NULL) {
+ fprintf(state->file, " *\n * IID: 0x%s\n */\n\n", iid);
+ } else {
+ fputs(" */\n\n", state->file);
+ }
+#endif
+
+ /*
+ * Write "public interface <foo>"
+ */
+
+ fprintf(state->file, "public interface %s ", interface_name);
+
+ /*
+ * Check for inheritence, and iterator over the inherited names,
+ * if any.
+ */
+
+ if ((iterator = IDL_INTERFACE(interface).inheritance_spec)) {
+ fputs("extends ", state->file);
+
+ do {
+
+ fprintf(state->file, "%s",
+ IDL_IDENT(IDL_LIST(iterator).data).str);
+
+ if (IDL_LIST(iterator).next) {
+ fputs(", ", state->file);
+ }
+ } while ((iterator = IDL_LIST(iterator).next));
+
+ }
+
+ fputs("\n{\n", state->file);
+
+ if (iid) {
+ /*
+ * Write interface constants for IID
+ */
+
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ fputs(" public static final String ", state->file);
+#else
+ fputs(" public static final String ", state->file);
+#endif
+
+ /* XXX s.b just "IID" ? */
+ if (!write_classname_iid_define(state->file, interface_name)) {
+ return FALSE;
+ }
+
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ fputs(" =\n \"{", state->file);
+ while (*iid) {
+ fputc(tolower(*iid++), state->file);
+ }
+ fputs("}\";\n", state->file);
+
+#else
+ fprintf(state->file, "_STRING =\n \"%s\";\n\n", iid);
+
+ fputs(" public static final nsID ", state->file);
+
+ /* XXX s.b just "IID" ? */
+ if (!write_classname_iid_define(state->file, interface_name)) {
+ return FALSE;
+ }
+
+ fprintf(state->file, " =\n new nsID(\"%s\");\n\n", iid);
+#endif
+ }
+
+ /*
+ * Advance the state of the tree, go on to process more
+ */
+
+ state->tree = IDL_INTERFACE(interface).body;
+
+ if (state->tree && !xpidl_process_node(state)) {
+ return FALSE;
+ }
+
+
+ fputs("\n}\n", state->file);
+
+ return TRUE;
+}
+
+static gboolean
+process_list(TreeState *state)
+{
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ /* To make the diffing simple, group the constants, methods and attributes. */
+ IDL_tree list = state->tree;
+ IDL_tree iter;
+ for (iter = list; iter; iter = IDL_LIST(iter).next) {
+ if (IDL_NODE_TYPE(IDL_LIST(iter).data) == IDLN_CONST_DCL) {
+ state->tree = IDL_LIST(iter).data;
+ if (!xpidl_process_node(state))
+ return FALSE;
+ }
+ }
+ for (iter = list; iter; iter = IDL_LIST(iter).next) {
+ if (IDL_NODE_TYPE(IDL_LIST(iter).data) == IDLN_ATTR_DCL) {
+ state->tree = IDL_LIST(iter).data;
+ if (!xpidl_process_node(state))
+ return FALSE;
+ }
+ }
+ for (iter = list; iter; iter = IDL_LIST(iter).next) {
+ if (IDL_NODE_TYPE(IDL_LIST(iter).data) == IDLN_OP_DCL) {
+ state->tree = IDL_LIST(iter).data;
+ if (!xpidl_process_node(state))
+ return FALSE;
+ }
+ }
+ for (iter = list; iter; iter = IDL_LIST(iter).next) {
+ if ( IDL_NODE_TYPE(IDL_LIST(iter).data) != IDLN_CONST_DCL
+ && IDL_NODE_TYPE(IDL_LIST(iter).data) != IDLN_OP_DCL
+ && IDL_NODE_TYPE(IDL_LIST(iter).data) != IDLN_ATTR_DCL ) {
+ state->tree = IDL_LIST(iter).data;
+ if (!xpidl_process_node(state))
+ return FALSE;
+ }
+ }
+
+#else
+ IDL_tree iter;
+ for (iter = state->tree; iter; iter = IDL_LIST(iter).next) {
+ state->tree = IDL_LIST(iter).data;
+ if (!xpidl_process_node(state))
+ return FALSE;
+ }
+#endif
+ return TRUE;
+}
+
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+static gboolean
+interface_declaration_wrapper(TreeState *state)
+{
+ IDL_tree interface = state->tree;
+ char *interface_name = IDL_IDENT(IDL_INTERFACE(interface).ident).str;
+ FILE *org_file = state->file;
+ char *org_name = state->real_outname;
+ void *org_priv = state->priv;
+ gboolean rc;
+
+ /*
+ * Skip non-scriptable interfaces.
+ */
+ if ( !IDL_tree_property_get(IDL_INTERFACE(interface).ident, "scriptable")
+ && strcmp(interface_name, "nsIAppShell") )
+ return TRUE;
+
+ /*
+ * GROSS HACK: If the interface isn't the same as the file name,
+ * temporarily switch output file.
+ */
+ if (state->real_outname) {
+ const char *basename = xpidl_basename(state->real_outname);
+ const char *ext = strrchr(basename, '.');
+ if ( ext
+ && !strcmp(ext, ".java")
+ && ( strncmp(interface_name, basename, ext - basename)
+ || interface_name[ext - basename] != '.') ) {
+ size_t needed = strlen(state->real_outname) + strlen(interface_name) + strlen(".java") + 4;
+ char *tmp = malloc(needed);
+ if (basename != state->real_outname)
+ sprintf(tmp,"%.*s/%s.java", (int)(basename - state->real_outname - 1), state->real_outname, interface_name);
+ else
+ sprintf(tmp,"%s.java", interface_name);
+ state->file = fopen(tmp, "w");
+ if (!state->file) {
+ perror("error opening output file");
+ state->file = org_file;
+ free(tmp);
+ return FALSE;
+ }
+ state->real_outname = tmp;
+ java_prolog(state);
+ }
+ g_free(basename);
+ }
+
+ rc = interface_declaration(state);
+
+ if (state->file != org_file) {
+ java_epilog(state);
+ fclose(state->file);
+ free(state->real_outname);
+ state->file = org_file;
+ state->real_outname = org_name;
+ state->priv = org_priv;
+ }
+ return rc;
+}
+#endif /* VBOX_XPIDL_EMULATE_GENJIFACES */
+
+static gboolean
+xpcom_to_java_type (TreeState *state)
+{
+ if (!state->tree) {
+ fputs("Object", state->file);
+ return TRUE;
+ }
+
+ switch(IDL_NODE_TYPE(state->tree)) {
+
+ case IDLN_TYPE_INTEGER: {
+
+ switch(IDL_TYPE_INTEGER(state->tree).f_type) {
+
+ case IDL_INTEGER_TYPE_SHORT:
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ if (IDL_TYPE_INTEGER(state->tree).f_signed)
+ fputs("short", state->file);
+ else
+ fputs("int", state->file);
+#else
+ fputs("short", state->file);
+#endif
+ break;
+
+ case IDL_INTEGER_TYPE_LONG:
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ if (IDL_TYPE_INTEGER(state->tree).f_signed)
+ fputs("int", state->file);
+ else
+ fputs("long", state->file);
+#else
+ fputs("int", state->file);
+#endif
+ break;
+
+ case IDL_INTEGER_TYPE_LONGLONG:
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ if (IDL_TYPE_INTEGER(state->tree).f_signed)
+ fputs("long", state->file);
+ else
+ fputs("double", state->file);
+#else
+ fputs("long", state->file);
+#endif
+ break;
+
+ default:
+ g_error(" Unknown integer type: %d\n",
+ IDL_TYPE_INTEGER(state->tree).f_type);
+ return FALSE;
+
+ }
+
+ break;
+ }
+
+ case IDLN_TYPE_CHAR:
+ case IDLN_TYPE_WIDE_CHAR:
+ fputs("char", state->file);
+ break;
+
+ case IDLN_TYPE_WIDE_STRING:
+ case IDLN_TYPE_STRING:
+ fputs("String", state->file);
+ break;
+
+ case IDLN_TYPE_BOOLEAN:
+ fputs("boolean", state->file);
+ break;
+
+ case IDLN_TYPE_OCTET:
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ fputs("short", state->file);
+#else
+ fputs("byte", state->file);
+#endif
+ break;
+
+ case IDLN_TYPE_FLOAT:
+ switch(IDL_TYPE_FLOAT(state->tree).f_type) {
+
+ case IDL_FLOAT_TYPE_FLOAT:
+ fputs("float", state->file);
+ break;
+
+ case IDL_FLOAT_TYPE_DOUBLE:
+ fputs("double", state->file);
+ break;
+
+ default:
+ g_error(" Unknown floating point typ: %d\n",
+ IDL_NODE_TYPE(state->tree));
+ break;
+ }
+ break;
+
+
+ case IDLN_IDENT:
+ if (IDL_NODE_UP(state->tree) &&
+ IDL_NODE_TYPE(IDL_NODE_UP(state->tree)) == IDLN_NATIVE) {
+ const char *user_type = IDL_NATIVE(IDL_NODE_UP(state->tree)).user_type;
+ if (strcmp(user_type, "void") == 0) {
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ fputs("nsISupports", state->file);
+#else
+ fputs("Object", state->file);
+#endif
+ }
+ else if (strcmp(user_type, "nsID") == 0 ||
+ strcmp(user_type, "nsIID") == 0 ||
+ strcmp(user_type, "nsCID") == 0) {
+ /* XXX: s.b test for "iid" attribute */
+ /* XXX: special class for nsIDs */
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ fputs("String", state->file);
+#else
+ fputs("nsID", state->file);
+#endif
+ }
+ else {
+ /* XXX: special class for opaque types */
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ fputs("String", state->file);
+#else
+ fputs("OpaqueValue", state->file);
+#endif
+ }
+ } else {
+ const char *ident_str = IDL_IDENT(state->tree).str;
+
+ /* XXX: big kludge; s.b. way to match to typedefs */
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ if (strcmp(ident_str, "PRInt8") == 0) {
+ fputs("byte", state->file);
+ }
+ else if (strcmp(ident_str, "PRInt16") == 0 ||
+ strcmp(ident_str, "PRUint8") == 0) {
+ fputs("short", state->file);
+ }
+ else if (strcmp(ident_str, "PRInt32") == 0 ||
+ strcmp(ident_str, "PRUint16") == 0) {
+ fputs("int", state->file);
+ }
+ else if (strcmp(ident_str, "PRInt64") == 0 ||
+ strcmp(ident_str, "PRUint32") == 0 ||
+ strcmp(ident_str, "PRThreadPriority") == 0 ||
+ strcmp(ident_str, "PRThreadScope") == 0 ||
+ strcmp(ident_str, "PRThreadState") == 0) {
+ fputs("long", state->file);
+ }
+ else if (strcmp(ident_str, "PRUint64") == 0) {
+ fputs("double", state->file);
+ }
+#else
+ if (strcmp(ident_str, "PRInt8") == 0 ||
+ strcmp(ident_str, "PRUint8") == 0) {
+ fputs("byte", state->file);
+ }
+ else if (strcmp(ident_str, "PRInt16") == 0 ||
+ strcmp(ident_str, "PRUint16") == 0) {
+ fputs("short", state->file);
+ }
+ else if (strcmp(ident_str, "PRInt32") == 0 ||
+ strcmp(ident_str, "PRUint32") == 0) {
+ fputs("int", state->file);
+ }
+ else if (strcmp(ident_str, "PRInt64") == 0 ||
+ strcmp(ident_str, "PRUint64") == 0) {
+ fputs("long", state->file);
+ }
+#endif
+ else if (strcmp(ident_str, "PRBool") == 0) {
+ fputs("boolean", state->file);
+ }
+ else if (strcmp(ident_str, "nsrefcnt") == 0) {
+ fputs("int", state->file);
+ }
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ /* XXX: Use find_underlying_type instead? */
+ else if ( strcmp(ident_str, "nsresult") == 0
+ || strcmp(ident_str, "size_t") == 0) {
+ fputs("long", state->file);
+ }
+ else if ( strcmp(ident_str, "PRTime") == 0) {
+ fputs("double", state->file);
+ }
+ /* In Javaconnect, we handle weak references internally; no need for the
+ |nsIWeakReference| interface. So just return |nsISupports|. */
+ else if (strcmp(ident_str, "nsIWeakReference") == 0) {
+ fputs("nsISupports", state->file);
+ }
+#endif
+ else {
+ IDL_tree real_type =
+ g_hash_table_lookup(TYPEDEFS(state), ident_str);
+
+ if (real_type) {
+ IDL_tree orig_tree = state->tree;
+
+ state->tree = real_type;
+ xpcom_to_java_type(state);
+
+ state->tree = orig_tree;
+ }
+ else {
+ fputs(ident_str, state->file);
+ }
+ }
+ }
+
+ break;
+
+ case IDLN_TYPE_ENUM:
+ case IDLN_TYPE_OBJECT:
+ default:
+ g_error(" Unknown type: %d\n",
+ IDL_TYPE_FLOAT(state->tree).f_type);
+ break;
+ }
+
+ return TRUE;
+
+}
+
+static gboolean
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+xpcom_to_java_param(TreeState *state, unsigned nparam)
+#else
+xpcom_to_java_param(TreeState *state)
+#endif
+{
+ IDL_tree param = state->tree;
+ state->tree = IDL_PARAM_DCL(param).param_type_spec;
+
+ /*
+ * Put in type of parameter
+ */
+
+ if (!xpcom_to_java_type(state)) {
+ return FALSE;
+ }
+
+ /*
+ * If the parameter is out or inout, make it a Java array of the
+ * appropriate type
+ */
+
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ /* XXX: Causes nsILineInputStream::readLine(String[] arg1) where genjifaces drops the []. */
+#endif
+ if (IDL_PARAM_DCL(param).attr != IDL_PARAM_IN) {
+ fputs("[]", state->file);
+ }
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ /*XXX: nsIConsoleService::getMessageArray ends up with [][] arg1... */
+ /*else*/ if (IDL_tree_property_get(IDL_PARAM_DCL(param).simple_declarator, "array")) {
+ fputs("[]", state->file);
+ }
+#endif
+
+ /*
+ * Put in name of parameter
+ */
+
+ fputc(' ', state->file);
+
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ fprintf(state->file, "arg%u", nparam+1);
+#else
+ fputs(IDL_IDENT(IDL_PARAM_DCL(param).simple_declarator).str, state->file);
+#endif
+
+ return TRUE;
+}
+
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+static gboolean is_java_keyword(char ch0, const char *name)
+{
+ static const char * const kJavaKeywords[] = {
+ "abstract", "default", "if" , "private" , "this" ,
+ "boolean" , "do" , "implements", "protected" , "throw" ,
+ "break" , "double" , "import", "public" , "throws" ,
+ "byte" , "else" , "instanceof", "return" , "transient",
+ "case" , "extends", "int" , "short" , "try" ,
+ "catch" , "final" , "interface" , "static" , "void" ,
+ "char" , "finally", "long" , "strictfp" , "volatile" ,
+ "class" , "float" , "native" , "super" , "while" ,
+ "const" , "for" , "new" , "switch" ,
+ "continue", "goto" , "package" , "synchronized",
+ "assert" , /* added in Java 1.4 */
+ "enum" , /* added in Java 5.0 */
+ "clone" , /* clone is a member function of java.lang.Object */
+ "finalize" /* finalize is a member function of java.lang.Object */
+ };
+ unsigned i;
+ for (i = 0; i < sizeof(kJavaKeywords) / sizeof(kJavaKeywords[0]); i++) {
+ if (kJavaKeywords[i][0] == ch0 && !strcmp(&kJavaKeywords[i][1], &name[1])) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+#endif
+
+static gboolean
+type_declaration(TreeState *state)
+{
+ /*
+ * Unlike C, Java has no type declaration directive.
+ * Instead, we record the mapping, and look up the actual type
+ * when needed.
+ */
+ IDL_tree type = IDL_TYPE_DCL(state->tree).type_spec;
+ IDL_tree dcls = IDL_TYPE_DCL(state->tree).dcls;
+
+ /* XXX: check for illegal types */
+
+ g_hash_table_insert(TYPEDEFS(state),
+ IDL_IDENT(IDL_LIST(dcls).data).str,
+ type);
+
+ return TRUE;
+}
+
+static gboolean
+method_declaration(TreeState *state)
+{
+ /* IDL_tree method_tree = state->tree; */
+ struct _IDL_OP_DCL *method = &IDL_OP_DCL(state->tree);
+ gboolean method_notxpcom =
+ (IDL_tree_property_get(method->ident, "notxpcom") != NULL);
+ gboolean method_noscript =
+ (IDL_tree_property_get(method->ident, "noscript") != NULL);
+ IDL_tree iterator = NULL;
+ IDL_tree retval_param = NULL;
+ const char *method_name = IDL_IDENT(method->ident).str;
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ unsigned nparam = 0;
+#endif
+
+ if (!verify_method_declaration(state->tree))
+ return FALSE;
+
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ /*
+ * Skip most (todo) non-scriptable and not-xpcom methods.
+ */
+ if (method_noscript || method_notxpcom) {
+ return TRUE;
+ }
+#endif
+
+ fputc('\n', state->file);
+#ifndef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ xpidl_write_comment(state, 4);
+#endif
+
+ /*
+ * Write beginning of method declaration
+ */
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ fputs(" ", state->file);
+#else
+ fputs(" ", state->file);
+#endif
+ if (!method_noscript) {
+ /* Nonscriptable methods become package-protected */
+ fputs("public ", state->file);
+ }
+
+ /*
+ * Write return type
+ * Unlike C++ headers, Java interfaces return the declared
+ * return value; an exception indicates XPCOM method failure.
+ */
+ if (method_notxpcom || method->op_type_spec) {
+ state->tree = method->op_type_spec;
+ if (!xpcom_to_java_type(state)) {
+ return FALSE;
+ }
+ } else {
+ /* Check for retval attribute */
+ for (iterator = method->parameter_dcls; iterator != NULL;
+ iterator = IDL_LIST(iterator).next) {
+
+ IDL_tree original_tree = state->tree;
+
+ state->tree = IDL_LIST(iterator).data;
+
+ if (IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator,
+ "retval")) {
+ retval_param = iterator;
+
+ state->tree = IDL_PARAM_DCL(state->tree).param_type_spec;
+
+ /*
+ * Put in type of parameter
+ */
+
+ if (!xpcom_to_java_type(state)) {
+ return FALSE;
+ }
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ if (IDL_tree_property_get(IDL_PARAM_DCL(IDL_LIST(iterator).data).simple_declarator, "array")) {
+ fputs("[]", state->file);
+ }
+#endif
+ }
+
+ state->tree = original_tree;
+ }
+
+ if (retval_param == NULL) {
+ fputs("void", state->file);
+ }
+ }
+
+ /*
+ * Write method name
+ */
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ if (is_java_keyword(tolower(method_name[0]), method_name)) {
+ fprintf(state->file, " %c%s_(", tolower(method_name[0]), method_name + 1);
+ } else {
+ fprintf(state->file, " %c%s(", tolower(method_name[0]), method_name + 1);
+ }
+#else
+ fprintf(state->file, " %c%s(", tolower(method_name[0]), method_name + 1);
+#endif
+
+ /*
+ * Write parameters
+ */
+ for (iterator = method->parameter_dcls; iterator != NULL;
+ iterator = IDL_LIST(iterator).next) {
+
+ /* Skip "retval" */
+ if (iterator == retval_param) {
+ continue;
+ }
+
+ if (iterator != method->parameter_dcls) {
+ fputs(", ", state->file);
+ }
+
+ state->tree = IDL_LIST(iterator).data;
+
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ if (!xpcom_to_java_param(state, nparam++)) {
+#else
+ if (!xpcom_to_java_param(state)) {
+#endif
+ return FALSE;
+ }
+ }
+
+ fputs(")", state->file);
+
+ if (method->raises_expr) {
+ IDL_tree iter = method->raises_expr;
+ IDL_tree dataNode = IDL_LIST(iter).data;
+
+ fputs(" throws ", state->file);
+ fputs(IDL_IDENT(dataNode).str, state->file);
+ iter = IDL_LIST(iter).next;
+
+ while (iter) {
+ dataNode = IDL_LIST(iter).data;
+ fprintf(state->file, ", %s", IDL_IDENT(dataNode).str);
+ iter = IDL_LIST(iter).next;
+ }
+ }
+
+ fputs(";\n", state->file);
+
+ return TRUE;
+
+}
+
+
+static gboolean
+constant_declaration(TreeState *state)
+{
+ struct _IDL_CONST_DCL *declaration = &IDL_CONST_DCL(state->tree);
+ const char *name = IDL_IDENT(declaration->ident).str;
+ IDL_tree real_type;
+
+ if (!verify_const_declaration(state->tree))
+ return FALSE;
+
+ /* Could be a typedef; try to map it to the real type. */
+ real_type = find_underlying_type(declaration->const_type);
+ real_type = real_type ? real_type : declaration->const_type;
+
+ fputc('\n', state->file);
+#ifndef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ xpidl_write_comment(state, 4);
+#endif
+
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+# ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ fputs(" public static final ", state->file);
+# else
+ fputs(" public static final ", state->file);
+# endif
+ if (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG) {
+ if (IDL_TYPE_INTEGER(real_type).f_signed)
+ fprintf(state->file, "int %s = %" IDL_LL "d;\n", name, IDL_INTEGER(declaration->const_exp).value);
+ else
+ fprintf(state->file, "long %s = %" IDL_LL "uL;\n", name, IDL_INTEGER(declaration->const_exp).value);
+ } else {
+ if (IDL_TYPE_INTEGER(real_type).f_signed)
+ fprintf(state->file, "short %s = %" IDL_LL "d;\n", name, IDL_INTEGER(declaration->const_exp).value);
+ else
+ fprintf(state->file, "int %s = %" IDL_LL "u;\n", name, IDL_INTEGER(declaration->const_exp).value);
+ }
+#else /* !VBOX_XPIDL_EMULATE_GENJIFACES */
+ fprintf(state->file, " public static final %s %s = %d;\n",
+ (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG
+ ? "long" : "short"),
+ name, (int) IDL_INTEGER(declaration->const_exp).value);
+#endif /* !VBOX_XPIDL_EMULATE_GENJIFACES */
+
+ return TRUE;
+
+}
+
+#define ATTR_IDENT(tree) (IDL_IDENT(IDL_LIST(IDL_ATTR_DCL((tree)).simple_declarations).data))
+#define ATTR_PROPS(tree) (IDL_LIST(IDL_ATTR_DCL((tree)).simple_declarations).data)
+#define ATTR_TYPE_DECL(tree) (IDL_ATTR_DCL((tree)).param_type_spec)
+
+
+static gboolean
+attribute_declaration(TreeState *state)
+{
+ gboolean read_only = IDL_ATTR_DCL(state->tree).f_readonly;
+ char *attribute_name = ATTR_IDENT(state->tree).str;
+
+ gboolean method_noscript =
+ (IDL_tree_property_get(ATTR_PROPS(state->tree), "noscript") != NULL);
+
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ /*
+ * Skip most non-scriptable attributes.
+ */
+ if (method_noscript) {
+ return TRUE;
+ }
+#endif
+
+#if 0
+ /*
+ * Disabled here because I can't verify this check against possible
+ * users of the java xpidl backend.
+ */
+ if (!verify_attribute_declaration(state->tree))
+ return FALSE;
+#endif
+
+ /* Comment */
+ fputc('\n', state->file);
+#ifndef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ xpidl_write_comment(state, 4);
+#endif
+
+ state->tree = ATTR_TYPE_DECL(state->tree);
+
+ /*
+ * Write access permission ("public" unless nonscriptable)
+ */
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ fputs(" ", state->file);
+#else
+ fputs(" ", state->file);
+#endif
+ if (!method_noscript) {
+ fputs("public ", state->file);
+ }
+
+ /*
+ * Write the proper Java return value for the get operation
+ */
+ if (!xpcom_to_java_type(state)) {
+ return FALSE;
+ }
+
+ /*
+ * Write the name of the accessor ("get") method.
+ */
+ fprintf(state->file, " get%c%s();\n",
+ toupper(attribute_name[0]), attribute_name + 1);
+
+
+ if (!read_only) {
+ /* Nonscriptable methods become package-protected */
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ fputs("\n ", state->file);
+#else
+ fputs(" ", state->file);
+#endif
+ if (!method_noscript) {
+ fputs("public ", state->file);
+ }
+
+ /*
+ * Write attribute access method name and return type
+ */
+ fprintf(state->file, "void set%c%s(",
+ toupper(attribute_name[0]),
+ attribute_name+1);
+
+ /*
+ * Write the proper Java type for the set operation
+ */
+ if (!xpcom_to_java_type(state)) {
+ return FALSE;
+ }
+
+ /*
+ * Write the name of the formal parameter.
+ */
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES_DIFF
+ fputs(" arg1);\n", state->file);
+#else
+ fputs(" value);\n", state->file);
+#endif
+ }
+
+ return TRUE;
+}
+
+
+static gboolean
+enum_declaration(TreeState *state)
+{
+ XPIDL_WARNING((state->tree, IDL_WARNING1,
+ "enums not supported, enum \'%s\' ignored",
+ IDL_IDENT(IDL_TYPE_ENUM(state->tree).ident).str));
+ return TRUE;
+}
+
+backend *
+xpidl_java_dispatch(void)
+{
+ static backend result;
+ static nodeHandler table[IDLN_LAST];
+ static gboolean initialized = FALSE;
+
+ result.emit_prolog = java_prolog;
+ result.emit_epilog = java_epilog;
+
+ if (!initialized) {
+#ifdef VBOX_XPIDL_EMULATE_GENJIFACES
+ table[IDLN_INTERFACE] = interface_declaration_wrapper;
+#else
+ table[IDLN_INTERFACE] = interface_declaration;
+#endif
+ table[IDLN_LIST] = process_list;
+
+ table[IDLN_OP_DCL] = method_declaration;
+ table[IDLN_ATTR_DCL] = attribute_declaration;
+ table[IDLN_CONST_DCL] = constant_declaration;
+
+ table[IDLN_TYPE_DCL] = type_declaration;
+ table[IDLN_FORWARD_DCL] = forward_declaration;
+
+ table[IDLN_TYPE_ENUM] = enum_declaration;
+
+ initialized = TRUE;
+ }
+
+ result.dispatch_table = table;
+ return &result;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_typelib.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_typelib.c
new file mode 100644
index 00000000..f2daae0d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_typelib.c
@@ -0,0 +1,1237 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Generate typelib files for use with InterfaceInfo.
+ * http://www.mozilla.org/scriptable/typelib_file.html
+ */
+
+#include "xpidl.h"
+#include <xpt_xdr.h>
+#include <xpt_struct.h>
+#include <time.h> /* XXX XP? */
+
+struct priv_data {
+ XPTHeader *header;
+ uint16 ifaces;
+ GHashTable *interface_map;
+ XPTInterfaceDescriptor *current;
+ XPTArena *arena;
+ uint16 next_method;
+ uint16 next_const;
+ uint16 next_type; /* used for 'additional_types' for idl arrays */
+};
+
+#define HEADER(state) (((struct priv_data *)state->priv)->header)
+#define IFACES(state) (((struct priv_data *)state->priv)->ifaces)
+#define IFACE_MAP(state) (((struct priv_data *)state->priv)->interface_map)
+#define CURRENT(state) (((struct priv_data *)state->priv)->current)
+#define ARENA(state) (((struct priv_data *)state->priv)->arena)
+#define NEXT_METH(state) (((struct priv_data *)state->priv)->next_method)
+#define NEXT_CONST(state) (((struct priv_data *)state->priv)->next_const)
+#define NEXT_TYPE(state) (((struct priv_data *)state->priv)->next_type)
+
+#ifdef DEBUG_shaver
+/* #define DEBUG_shaver_sort */
+#endif
+
+typedef struct {
+ char *full_name;
+ char *name;
+ char *name_space;
+ char *iid;
+ gboolean is_forward_dcl;
+} NewInterfaceHolder;
+
+static NewInterfaceHolder*
+CreateNewInterfaceHolder(char *name, char *name_space, char *iid,
+ gboolean is_forward_dcl)
+{
+ NewInterfaceHolder *holder = calloc(1, sizeof(NewInterfaceHolder));
+ if (holder) {
+ holder->is_forward_dcl = is_forward_dcl;
+ if (name)
+ holder->name = xpidl_strdup(name);
+ if (name_space)
+ holder->name_space = xpidl_strdup(name_space);
+ if (holder->name && holder->name_space) {
+ holder->full_name = calloc(1, strlen(holder->name) +
+ strlen(holder->name_space) + 2);
+ }
+ if (holder->full_name) {
+ strcpy(holder->full_name, holder->name_space);
+ strcat(holder->full_name, ".");
+ strcat(holder->full_name, holder->name);
+ }
+ else
+ holder->full_name = holder->name;
+ if (iid)
+ holder->iid = xpidl_strdup(iid);
+ }
+ return holder;
+}
+
+static void
+DeleteNewInterfaceHolder(NewInterfaceHolder *holder)
+{
+ if (holder) {
+ if (holder->full_name && holder->full_name != holder->name)
+ free(holder->full_name);
+ if (holder->name)
+ free(holder->name);
+ if (holder->name_space)
+ free(holder->name_space);
+ if (holder->iid)
+ free(holder->iid);
+ free(holder);
+ }
+}
+
+/*
+ * If p is an ident for an interface, and we don't have an entry in the
+ * interface map yet, add one.
+ */
+static gboolean
+add_interface_maybe(IDL_tree_func_data *tfd, gpointer user_data)
+{
+ TreeState *state = user_data;
+ IDL_tree up;
+ if (IDL_NODE_TYPE(tfd->tree) == IDLN_IDENT) {
+ IDL_tree_type node_type = IDL_NODE_TYPE((up = IDL_NODE_UP(tfd->tree)));
+ if (node_type == IDLN_INTERFACE || node_type == IDLN_FORWARD_DCL) {
+
+ /* We only want to add a new entry if there is no entry by this
+ * name or if the previously found entry was just a forward
+ * declaration and the new entry is not.
+ */
+
+ char *iface = IDL_IDENT(tfd->tree).str;
+ NewInterfaceHolder *old_holder = (NewInterfaceHolder *)
+ g_hash_table_lookup(IFACE_MAP(state), iface);
+ if (old_holder && old_holder->is_forward_dcl &&
+ node_type != IDLN_FORWARD_DCL)
+ {
+ g_hash_table_remove(IFACE_MAP(state), iface);
+ DeleteNewInterfaceHolder(old_holder);
+ old_holder = NULL;
+ }
+ if (!old_holder) {
+ /* XXX should we parse here and store a struct nsID *? */
+ char *iid = (char *)IDL_tree_property_get(tfd->tree, "uuid");
+ char *name_space = (char *)
+ IDL_tree_property_get(tfd->tree, "namespace");
+ NewInterfaceHolder *holder =
+ CreateNewInterfaceHolder(iface, name_space, iid,
+ (gboolean) node_type == IDLN_FORWARD_DCL);
+ if (!holder)
+ return FALSE;
+ g_hash_table_insert(IFACE_MAP(state),
+ holder->full_name, holder);
+ IFACES(state)++;
+#ifdef DEBUG_shaver_ifaces
+ fprintf(stderr, "adding interface #%d: %s/%s\n", IFACES(state),
+ iface, iid[0] ? iid : "<unresolved>");
+#endif
+ }
+ } else {
+#ifdef DEBUG_shaver_ifaces
+ fprintf(stderr, "ident %s isn't an interface (%s)\n",
+ IDL_IDENT(tfd->tree).str, IDL_NODE_TYPE_NAME(up));
+#endif
+ }
+ }
+
+ return TRUE;
+}
+
+/* Find all the interfaces referenced in the tree (uses add_interface_maybe) */
+static gboolean
+find_interfaces(IDL_tree_func_data *tfd, gpointer user_data)
+{
+ IDL_tree node = NULL;
+
+ switch (IDL_NODE_TYPE(tfd->tree)) {
+ case IDLN_ATTR_DCL:
+ node = IDL_ATTR_DCL(tfd->tree).param_type_spec;
+ break;
+ case IDLN_OP_DCL:
+ IDL_tree_walk_in_order(IDL_OP_DCL(tfd->tree).parameter_dcls, find_interfaces,
+ user_data);
+ node = IDL_OP_DCL(tfd->tree).op_type_spec;
+ break;
+ case IDLN_PARAM_DCL:
+ node = IDL_PARAM_DCL(tfd->tree).param_type_spec;
+ break;
+ case IDLN_INTERFACE:
+ node = IDL_INTERFACE(tfd->tree).inheritance_spec;
+ if (node)
+ xpidl_list_foreach(node, add_interface_maybe, user_data);
+ node = IDL_INTERFACE(tfd->tree).ident;
+ break;
+ case IDLN_FORWARD_DCL:
+ node = IDL_FORWARD_DCL(tfd->tree).ident;
+ break;
+ default:
+ node = NULL;
+ }
+
+ if (node && IDL_NODE_TYPE(node) == IDLN_IDENT) {
+ IDL_tree_func_data new_tfd;
+ new_tfd.tree = node;
+ add_interface_maybe(&new_tfd, user_data);
+ }
+
+ return TRUE;
+}
+
+#ifdef DEBUG_shaver
+/* for calling from gdb */
+static void
+print_IID(struct nsID *iid, FILE *file)
+{
+ char iid_buf[UUID_LENGTH];
+
+ xpidl_sprint_iid(iid, iid_buf);
+ fprintf(file, "%s\n", iid_buf);
+}
+#endif
+
+/* fill the interface_directory IDE table from the interface_map */
+static gboolean
+fill_ide_table(gpointer key, gpointer value, gpointer user_data)
+{
+ TreeState *state = user_data;
+ NewInterfaceHolder *holder = (NewInterfaceHolder *) value;
+ struct nsID id;
+ XPTInterfaceDirectoryEntry *ide;
+
+ XPT_ASSERT(holder);
+
+#ifdef DEBUG_shaver_ifaces
+ fprintf(stderr, "filling %s\n", holder->full_name);
+#endif
+
+ if (holder->iid) {
+ if (strlen(holder->iid) != 36) {
+ IDL_tree_error(state->tree, "IID %s is the wrong length\n",
+ holder->iid);
+ return FALSE;
+ }
+ if (!xpidl_parse_iid(&id, holder->iid)) {
+ IDL_tree_error(state->tree, "cannot parse IID %s\n", holder->iid);
+ return FALSE;
+ }
+ } else {
+ memset(&id, 0, sizeof(id));
+ }
+
+ ide = &(HEADER(state)->interface_directory[IFACES(state)]);
+ if (!XPT_FillInterfaceDirectoryEntry(ARENA(state), ide, &id, holder->name,
+ holder->name_space, NULL)) {
+ IDL_tree_error(state->tree, "INTERNAL: XPT_FillIDE failed for %s\n",
+ holder->full_name);
+ return FALSE;
+ }
+
+ IFACES(state)++;
+ DeleteNewInterfaceHolder(holder);
+ return TRUE;
+}
+
+static int
+compare_IDEs(const void *ap, const void *bp)
+{
+ const XPTInterfaceDirectoryEntry *a = ap, *b = bp;
+ const nsID *aid = &a->iid, *bid = &b->iid;
+ const char *ans, *bns;
+
+ int i;
+#define COMPARE(field) if (aid->field > bid->field) return 1; \
+ if (bid->field > aid->field) return -1;
+ COMPARE(m0);
+ COMPARE(m1);
+ COMPARE(m2);
+ for (i = 0; i < 8; i++) {
+ COMPARE(m3[i]);
+ }
+
+ /* defend against NULL name_space by using empty string. */
+ ans = a->name_space ? a->name_space : "";
+ bns = b->name_space ? b->name_space : "";
+
+ if (a->name_space && b->name_space) {
+ if ((i = strcmp(a->name_space, b->name_space)))
+ return i;
+ } else {
+ if (a->name_space || b->name_space) {
+ if (a->name_space)
+ return -1;
+ return 1;
+ }
+ }
+ /* these had better not be NULL... */
+ return strcmp(a->name, b->name);
+#undef COMPARE
+}
+
+/* sort the IDE block as per the typelib spec: IID order, unresolved first */
+static void
+sort_ide_block(TreeState *state)
+{
+ XPTInterfaceDirectoryEntry *ide;
+ int i;
+
+ /* boy, I sure hope qsort works correctly everywhere */
+#ifdef DEBUG_shaver_sort
+ fputs("before sort:\n", stderr);
+ for (i = 0; i < IFACES(state); i++) {
+ fputs(" ", stderr);
+ print_IID(&HEADER(state)->interface_directory[i].iid, stderr);
+ fputc('\n', stderr);
+ }
+#endif
+ qsort(HEADER(state)->interface_directory, IFACES(state),
+ sizeof(*ide), compare_IDEs);
+#ifdef DEBUG_shaver_sort
+ fputs("after sort:\n", stderr);
+ for (i = 0; i < IFACES(state); i++) {
+ fputs(" ", stderr);
+ print_IID(&HEADER(state)->interface_directory[i].iid, stderr);
+ fputc('\n', stderr);
+ }
+#endif
+
+ for (i = 0; i < IFACES(state); i++) {
+ ide = HEADER(state)->interface_directory + i;
+ g_hash_table_insert(IFACE_MAP(state), ide->name, (void *)(i + 1));
+ }
+
+ return;
+}
+
+static gboolean
+typelib_list(TreeState *state)
+{
+ IDL_tree iter;
+ for (iter = state->tree; iter; iter = IDL_LIST(iter).next) {
+ state->tree = IDL_LIST(iter).data;
+ if (!xpidl_process_node(state))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+typelib_prolog(TreeState *state)
+{
+ state->priv = calloc(1, sizeof(struct priv_data));
+ if (!state->priv)
+ return FALSE;
+ IFACES(state) = 0;
+ IFACE_MAP(state) = g_hash_table_new(g_str_hash, g_str_equal);
+ if (!IFACE_MAP(state)) {
+ /* XXX report error */
+ free(state->priv);
+ return FALSE;
+ }
+ /* find all interfaces, top-level and referenced by others */
+ IDL_tree_walk_in_order(state->tree, find_interfaces, state);
+ ARENA(state) = XPT_NewArena(1024, sizeof(double), "main xpidl arena");
+ HEADER(state) = XPT_NewHeader(ARENA(state), IFACES(state),
+ major_version, minor_version);
+
+ /* fill IDEs from hash table */
+ IFACES(state) = 0;
+ g_hash_table_foreach_remove(IFACE_MAP(state), fill_ide_table, state);
+
+ /* if any are left then we must have failed in fill_ide_table */
+ if (g_hash_table_size(IFACE_MAP(state)))
+ return FALSE;
+
+ /* sort the IDEs by IID order and store indices in the interface map */
+ sort_ide_block(state);
+
+ return TRUE;
+}
+
+static gboolean
+typelib_epilog(TreeState *state)
+{
+ XPTState *xstate = XPT_NewXDRState(XPT_ENCODE, NULL, 0);
+ XPTCursor curs, *cursor = &curs;
+ PRUint32 i, len, header_sz;
+ PRUint32 oldOffset;
+ PRUint32 newOffset;
+ char *data;
+
+ /* Write any annotations */
+ if (emit_typelib_annotations) {
+ PRUint32 annotation_len, written_so_far;
+ char *annotate_val, *timestr;
+ time_t now;
+ static char *annotation_format =
+ "Created from %s.idl\nCreation date: %sInterfaces:";
+
+ /* fill in the annotations, listing resolved interfaces in order */
+
+ (void)time(&now);
+ timestr = ctime(&now);
+
+ /* Avoid dependence on nspr; no PR_smprintf and friends. */
+
+ /* How large should the annotation string be? */
+ annotation_len = strlen(annotation_format) + strlen(state->basename) +
+ strlen(timestr);
+#ifdef VBOX
+ /* note that '%s' is contained two times in annotation_format and both
+ * format specifiers are replaced by a string. So in fact we reserve 4
+ * bytes minus one byte (for the terminating '\0') more than necessary. */
+#endif
+ for (i = 0; i < HEADER(state)->num_interfaces; i++) {
+ XPTInterfaceDirectoryEntry *ide;
+ ide = &HEADER(state)->interface_directory[i];
+ if (ide->interface_descriptor) {
+ annotation_len += strlen(ide->name) + 1;
+ }
+ }
+
+ annotate_val = (char *) malloc(annotation_len);
+ written_so_far = sprintf(annotate_val, annotation_format,
+ state->basename, timestr);
+
+ for (i = 0; i < HEADER(state)->num_interfaces; i++) {
+ XPTInterfaceDirectoryEntry *ide;
+ ide = &HEADER(state)->interface_directory[i];
+ if (ide->interface_descriptor) {
+ written_so_far += sprintf(annotate_val + written_so_far, " %s",
+ ide->name);
+ }
+ }
+
+ HEADER(state)->annotations =
+ XPT_NewAnnotation(ARENA(state),
+ XPT_ANN_LAST | XPT_ANN_PRIVATE,
+ XPT_NewStringZ(ARENA(state), "xpidl 0.99.9"),
+ XPT_NewStringZ(ARENA(state), annotate_val));
+ free(annotate_val);
+ } else {
+ HEADER(state)->annotations =
+ XPT_NewAnnotation(ARENA(state), XPT_ANN_LAST, NULL, NULL);
+ }
+
+ if (!HEADER(state)->annotations) {
+ /* XXX report out of memory error */
+ return FALSE;
+ }
+
+ /* Write the typelib */
+ header_sz = XPT_SizeOfHeaderBlock(HEADER(state));
+
+ if (!xstate ||
+ !XPT_MakeCursor(xstate, XPT_HEADER, header_sz, cursor))
+ goto destroy_header;
+ oldOffset = cursor->offset;
+ if (!XPT_DoHeader(ARENA(state), cursor, &HEADER(state)))
+ goto destroy;
+ newOffset = cursor->offset;
+ XPT_GetXDRDataLength(xstate, XPT_HEADER, &len);
+ HEADER(state)->file_length = len;
+ XPT_GetXDRDataLength(xstate, XPT_DATA, &len);
+ HEADER(state)->file_length += len;
+ XPT_SeekTo(cursor, oldOffset);
+ if (!XPT_DoHeaderPrologue(ARENA(state), cursor, &HEADER(state), NULL))
+ goto destroy;
+ XPT_SeekTo(cursor, newOffset);
+ XPT_GetXDRData(xstate, XPT_HEADER, &data, &len);
+ fwrite(data, len, 1, state->file);
+ XPT_GetXDRData(xstate, XPT_DATA, &data, &len);
+ fwrite(data, len, 1, state->file);
+
+ destroy:
+ XPT_DestroyXDRState(xstate);
+ destroy_header:
+ /* XXX XPT_DestroyHeader(HEADER(state)) */
+
+ XPT_FreeHeader(ARENA(state), HEADER(state));
+ XPT_DestroyArena(ARENA(state));
+
+ /* XXX should destroy priv_data here */
+
+ return TRUE;
+}
+
+static XPTInterfaceDirectoryEntry *
+FindInterfaceByName(XPTInterfaceDirectoryEntry *ides, uint16 num_interfaces,
+ const char *name)
+{
+ uint16 i;
+ for (i = 0; i < num_interfaces; i++) {
+ if (!strcmp(ides[i].name, name))
+ return &ides[i];
+ }
+ return NULL;
+}
+
+static gboolean
+typelib_interface(TreeState *state)
+{
+ IDL_tree iface = state->tree, iter;
+ char *name = IDL_IDENT(IDL_INTERFACE(iface).ident).str;
+ XPTInterfaceDirectoryEntry *ide;
+ XPTInterfaceDescriptor *id;
+ uint16 parent_id = 0;
+ PRUint8 interface_flags = 0;
+
+ if (!verify_interface_declaration(iface))
+ return FALSE;
+
+ if (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable"))
+ interface_flags |= XPT_ID_SCRIPTABLE;
+
+ if (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "function"))
+ interface_flags |= XPT_ID_FUNCTION;
+
+ ide = FindInterfaceByName(HEADER(state)->interface_directory,
+ HEADER(state)->num_interfaces, name);
+ if (!ide) {
+ IDL_tree_error(iface, "ERROR: didn't find interface %s in "
+ "IDE block. Giving up.\n", name);
+ return FALSE;
+ }
+
+ if ((iter = IDL_INTERFACE(iface).inheritance_spec)) {
+ char *parent;
+ if (IDL_LIST(iter).next) {
+ IDL_tree_error(iface,
+ "ERROR: more than one parent interface for %s\n",
+ name);
+ return FALSE;
+ }
+ parent = IDL_IDENT(IDL_LIST(iter).data).str;
+ parent_id = (uint16)(uint32)g_hash_table_lookup(IFACE_MAP(state),
+ parent);
+ if (!parent_id) {
+ IDL_tree_error(iface,
+ "ERROR: no index found for %s. Giving up.\n",
+ parent);
+ return FALSE;
+ }
+ }
+
+ id = XPT_NewInterfaceDescriptor(ARENA(state), parent_id, 0, 0,
+ interface_flags);
+ if (!id)
+ return FALSE;
+
+ CURRENT(state) = ide->interface_descriptor = id;
+#ifdef DEBUG_shaver_ifaces
+ fprintf(stderr, "DBG: starting interface %s @ %p\n", name, id);
+#endif
+
+ NEXT_METH(state) = 0;
+ NEXT_CONST(state) = 0;
+ NEXT_TYPE(state) = 0;
+
+ state->tree = IDL_INTERFACE(iface).body;
+ if (state->tree && !xpidl_process_node(state))
+ return FALSE;
+#ifdef DEBUG_shaver_ifaces
+ fprintf(stderr, "DBG: ending interface %s\n", name);
+#endif
+ return TRUE;
+}
+
+static gboolean
+find_arg_with_name(TreeState *state, const char *name, int16 *argnum)
+{
+ int16 count;
+ IDL_tree params;
+
+ XPT_ASSERT(state);
+ XPT_ASSERT(name);
+ XPT_ASSERT(argnum);
+
+ params = IDL_OP_DCL(IDL_NODE_UP(IDL_NODE_UP(state->tree))).parameter_dcls;
+ for (count = 0;
+ params != NULL && IDL_LIST(params).data != NULL;
+ params = IDL_LIST(params).next, count++)
+ {
+ const char *cur_name = IDL_IDENT(
+ IDL_PARAM_DCL(IDL_LIST(params).data).simple_declarator).str;
+ if (!strcmp(cur_name, name)) {
+ /* XXX ought to verify that this is the right type here */
+ /* XXX for iid_is this must be an iid */
+ /* XXX for size_is and length_is this must be a uint32 */
+ *argnum = count;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/* return value is for success or failure */
+static gboolean
+get_size_and_length(TreeState *state, IDL_tree type,
+ int16 *size_is_argnum, int16 *length_is_argnum,
+ gboolean *has_size_is, gboolean *has_length_is)
+{
+ *has_size_is = FALSE;
+ *has_length_is = FALSE;
+
+ if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) {
+ IDL_tree sd = IDL_PARAM_DCL(state->tree).simple_declarator;
+ const char *size_is;
+ const char *length_is;
+
+ /* only if size_is is found does any of this matter */
+ size_is = IDL_tree_property_get(sd, "size_is");
+ if (!size_is)
+ return TRUE;
+
+ if (!find_arg_with_name(state, size_is, size_is_argnum)) {
+ IDL_tree_error(state->tree, "can't find matching argument for "
+ "[size_is(%s)]\n", size_is);
+ return FALSE;
+ }
+ *has_size_is = TRUE;
+
+ /* length_is is optional */
+ length_is = IDL_tree_property_get(sd, "length_is");
+ if (length_is) {
+ *has_length_is = TRUE;
+ if (!find_arg_with_name(state, length_is, length_is_argnum)) {
+ IDL_tree_error(state->tree, "can't find matching argument for "
+ "[length_is(%s)]\n", length_is);
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+static gboolean
+fill_td_from_type(TreeState *state, XPTTypeDescriptor *td, IDL_tree type)
+{
+ IDL_tree up;
+ int16 size_is_argnum;
+ int16 length_is_argnum;
+ gboolean has_size_is;
+ gboolean has_length_is;
+ gboolean is_array = FALSE;
+
+ if (type) {
+
+ /* deal with array */
+
+ if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) {
+ IDL_tree sd = IDL_PARAM_DCL(state->tree).simple_declarator;
+ if (IDL_tree_property_get(sd, "array")) {
+
+ is_array = TRUE;
+
+ /* size_is is required! */
+ if (!get_size_and_length(state, type,
+ &size_is_argnum, &length_is_argnum,
+ &has_size_is, &has_length_is)) {
+ /* error was reported by helper function */
+ return FALSE;
+ }
+
+ if (!has_size_is) {
+ IDL_tree_error(state->tree, "[array] requires [size_is()]\n");
+ return FALSE;
+ }
+
+ td->prefix.flags = TD_ARRAY | XPT_TDP_POINTER;
+ td->argnum = size_is_argnum;
+
+ if (has_length_is)
+ td->argnum2 = length_is_argnum;
+ else
+ td->argnum2 = size_is_argnum;
+
+ /*
+ * XXX - NOTE - this will be broken for multidimensional
+ * arrays because of the realloc XPT_InterfaceDescriptorAddTypes
+ * uses. The underlying 'td' can change as we recurse in to get
+ * additional dimensions. Luckily, we don't yet support more
+ * than on dimension in the arrays
+ */
+ /* setup the additional_type */
+ if (!XPT_InterfaceDescriptorAddTypes(ARENA(state),
+ CURRENT(state), 1)) {
+ g_error("out of memory\n");
+ return FALSE;
+ }
+ td->type.additional_type = NEXT_TYPE(state);
+ td = &CURRENT(state)->additional_types[NEXT_TYPE(state)];
+ NEXT_TYPE(state)++ ;
+ }
+ }
+
+handle_typedef:
+ switch (IDL_NODE_TYPE(type)) {
+ case IDLN_TYPE_INTEGER: {
+ gboolean sign = IDL_TYPE_INTEGER(type).f_signed;
+ switch(IDL_TYPE_INTEGER(type).f_type) {
+ case IDL_INTEGER_TYPE_SHORT:
+ td->prefix.flags = sign ? TD_INT16 : TD_UINT16;
+ break;
+ case IDL_INTEGER_TYPE_LONG:
+ td->prefix.flags = sign ? TD_INT32 : TD_UINT32;
+ break;
+ case IDL_INTEGER_TYPE_LONGLONG:
+ td->prefix.flags = sign ? TD_INT64 : TD_UINT64;
+ break;
+ }
+ break;
+ }
+ case IDLN_TYPE_CHAR:
+ td->prefix.flags = TD_CHAR;
+ break;
+ case IDLN_TYPE_WIDE_CHAR:
+ td->prefix.flags = TD_WCHAR;
+ break;
+ case IDLN_TYPE_STRING:
+ if (is_array) {
+ td->prefix.flags = TD_PSTRING | XPT_TDP_POINTER;
+ } else {
+ if (!get_size_and_length(state, type,
+ &size_is_argnum, &length_is_argnum,
+ &has_size_is, &has_length_is)) {
+ /* error was reported by helper function */
+ return FALSE;
+ }
+ if (has_size_is) {
+ td->prefix.flags = TD_PSTRING_SIZE_IS | XPT_TDP_POINTER;
+ td->argnum = size_is_argnum;
+ if (has_length_is)
+ td->argnum2 = length_is_argnum;
+ else
+ td->argnum2 = size_is_argnum;
+ } else {
+ td->prefix.flags = TD_PSTRING | XPT_TDP_POINTER;
+ }
+ }
+ break;
+ case IDLN_TYPE_WIDE_STRING:
+ if (is_array) {
+ td->prefix.flags = TD_PWSTRING | XPT_TDP_POINTER;
+ } else {
+ if (!get_size_and_length(state, type,
+ &size_is_argnum, &length_is_argnum,
+ &has_size_is, &has_length_is)) {
+ /* error was reported by helper function */
+ return FALSE;
+ }
+ if (has_size_is) {
+ td->prefix.flags = TD_PWSTRING_SIZE_IS | XPT_TDP_POINTER;
+ td->argnum = size_is_argnum;
+ if (has_length_is)
+ td->argnum2 = length_is_argnum;
+ else
+ td->argnum2 = size_is_argnum;
+ } else {
+ td->prefix.flags = TD_PWSTRING | XPT_TDP_POINTER;
+ }
+ }
+ break;
+ case IDLN_TYPE_BOOLEAN:
+ td->prefix.flags = TD_BOOL;
+ break;
+ case IDLN_TYPE_OCTET:
+ td->prefix.flags = TD_UINT8;
+ break;
+ case IDLN_TYPE_FLOAT:
+ switch (IDL_TYPE_FLOAT (type).f_type) {
+ case IDL_FLOAT_TYPE_FLOAT:
+ td->prefix.flags = TD_FLOAT;
+ break;
+ case IDL_FLOAT_TYPE_DOUBLE:
+ td->prefix.flags = TD_DOUBLE;
+ break;
+ /* XXX 'long double' just ignored, or what? */
+ default: break;
+ }
+ break;
+ case IDLN_IDENT:
+ if (!(up = IDL_NODE_UP(type))) {
+ IDL_tree_error(state->tree,
+ "ERROR: orphan ident %s in param list\n",
+ IDL_IDENT(type).str);
+ return FALSE;
+ }
+ switch (IDL_NODE_TYPE(up)) {
+ /* This whole section is abominably ugly */
+ case IDLN_FORWARD_DCL:
+ case IDLN_INTERFACE: {
+ XPTInterfaceDirectoryEntry *ide, *ides;
+ uint16 num_ifaces;
+ char *className;
+ const char *iid_is;
+handle_iid_is:
+ ides = HEADER(state)->interface_directory;
+ num_ifaces = HEADER(state)->num_interfaces;
+ /* might get here via the goto, so re-check type */
+ if (IDL_NODE_TYPE(up) == IDLN_INTERFACE)
+ className = IDL_IDENT(IDL_INTERFACE(up).ident).str;
+ else if (IDL_NODE_TYPE(up) == IDLN_FORWARD_DCL)
+ className = IDL_IDENT(IDL_FORWARD_DCL(up).ident).str;
+ else
+ className = IDL_IDENT(IDL_NATIVE(up).ident).str;
+ iid_is = NULL;
+
+ if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL) {
+ iid_is =
+ IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator,
+ "iid_is");
+ }
+ if (iid_is) {
+ int16 argnum;
+ if (!find_arg_with_name(state, iid_is, &argnum)) {
+ IDL_tree_error(state->tree,
+ "can't find matching argument for "
+ "[iid_is(%s)]\n", iid_is);
+ return FALSE;
+ }
+ td->prefix.flags = TD_INTERFACE_IS_TYPE | XPT_TDP_POINTER;
+ td->argnum = argnum;
+ } else {
+ td->prefix.flags = TD_INTERFACE_TYPE | XPT_TDP_POINTER;
+ ide = FindInterfaceByName(ides, num_ifaces, className);
+ if (!ide || ide < ides || ide > ides + num_ifaces) {
+ IDL_tree_error(state->tree,
+ "unknown iface %s in param\n",
+ className);
+ return FALSE;
+ }
+ td->type.iface = ide - ides + 1;
+#ifdef DEBUG_shaver_index
+ fprintf(stderr, "DBG: index %d for %s\n",
+ td->type.iface, className);
+#endif
+ }
+ break;
+ }
+ case IDLN_NATIVE: {
+ char *ident;
+
+ /* jband - adding goto for iid_is when type is native */
+ if (IDL_NODE_TYPE(state->tree) == IDLN_PARAM_DCL &&
+ IDL_tree_property_get(IDL_PARAM_DCL(state->tree).simple_declarator,
+ "iid_is"))
+ goto handle_iid_is;
+
+ ident = IDL_IDENT(type).str;
+ if (IDL_tree_property_get(type, "nsid")) {
+ td->prefix.flags = TD_PNSIID;
+ if (IDL_tree_property_get(type, "ref"))
+ td->prefix.flags |= XPT_TDP_POINTER | XPT_TDP_REFERENCE;
+ else if (IDL_tree_property_get(type,"ptr"))
+ td->prefix.flags |= XPT_TDP_POINTER;
+ } else if (IDL_tree_property_get(type, "domstring")) {
+ td->prefix.flags = TD_DOMSTRING | XPT_TDP_POINTER;
+ if (IDL_tree_property_get(type, "ref"))
+ td->prefix.flags |= XPT_TDP_REFERENCE;
+ } else if (IDL_tree_property_get(type, "astring")) {
+ td->prefix.flags = TD_ASTRING | XPT_TDP_POINTER;
+ if (IDL_tree_property_get(type, "ref"))
+ td->prefix.flags |= XPT_TDP_REFERENCE;
+ } else if (IDL_tree_property_get(type, "utf8string")) {
+ td->prefix.flags = TD_UTF8STRING | XPT_TDP_POINTER;
+ if (IDL_tree_property_get(type, "ref"))
+ td->prefix.flags |= XPT_TDP_REFERENCE;
+ } else if (IDL_tree_property_get(type, "cstring")) {
+ td->prefix.flags = TD_CSTRING | XPT_TDP_POINTER;
+ if (IDL_tree_property_get(type, "ref"))
+ td->prefix.flags |= XPT_TDP_REFERENCE;
+ } else {
+ td->prefix.flags = TD_VOID | XPT_TDP_POINTER;
+ }
+ break;
+ }
+ default:
+ if (IDL_NODE_TYPE(IDL_NODE_UP(up)) == IDLN_TYPE_DCL) {
+ /* restart with the underlying type */
+ IDL_tree new_type;
+ new_type = IDL_TYPE_DCL(IDL_NODE_UP(up)).type_spec;
+#ifdef DEBUG_shaver_misc
+ fprintf(stderr, "following %s typedef to %s\n",
+ IDL_IDENT(type).str, IDL_NODE_TYPE_NAME(new_type));
+#endif
+ /*
+ * Do a nice messy goto rather than recursion so that
+ * we can avoid screwing up the *array* information.
+ */
+/* return fill_td_from_type(state, td, new_type); */
+ if (new_type) {
+ type = new_type;
+ goto handle_typedef;
+ } else {
+ /* do what we would do in recursion if !type */
+ td->prefix.flags = TD_VOID;
+ return TRUE;
+ }
+ }
+ IDL_tree_error(state->tree,
+ "can't handle %s ident in param list\n",
+#ifdef DEBUG_shaver
+ /* XXX is this safe to use on Win now? */
+ IDL_NODE_TYPE_NAME(IDL_NODE_UP(type))
+#else
+ "that type of"
+#endif
+ );
+#ifdef DEBUG_shaver
+ XPT_ASSERT(0);
+#endif
+ return FALSE;
+ }
+ break;
+ default:
+ IDL_tree_error(state->tree, "can't handle %s in param list\n",
+#ifdef DEBUG_shaver
+ /* XXX is this safe to use on Win now? */
+ IDL_NODE_TYPE_NAME(IDL_NODE_UP(type))
+#else
+ "that type"
+#endif
+ );
+ return FALSE;
+ }
+ } else {
+ td->prefix.flags = TD_VOID;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+fill_pd_from_type(TreeState *state, XPTParamDescriptor *pd, uint8 flags,
+ IDL_tree type)
+{
+ pd->flags = flags;
+ return fill_td_from_type(state, &pd->type, type);
+}
+
+static gboolean
+fill_pd_from_param(TreeState *state, XPTParamDescriptor *pd, IDL_tree tree)
+{
+ uint8 flags = 0;
+ gboolean is_dipper_type = DIPPER_TYPE(IDL_PARAM_DCL(tree).param_type_spec);
+
+ switch (IDL_PARAM_DCL(tree).attr) {
+ case IDL_PARAM_IN:
+ flags = XPT_PD_IN;
+ break;
+ case IDL_PARAM_OUT:
+ flags = XPT_PD_OUT;
+ break;
+ case IDL_PARAM_INOUT:
+ flags = XPT_PD_IN | XPT_PD_OUT;
+ break;
+ }
+
+ if (IDL_tree_property_get(IDL_PARAM_DCL(tree).simple_declarator,
+ "retval")) {
+ if (flags != XPT_PD_OUT) {
+ IDL_tree_error(tree, "can't have [retval] with in%s param "
+ "(only out)\n",
+ flags & XPT_PD_OUT ? "out" : "");
+ return FALSE;
+ }
+ flags |= XPT_PD_RETVAL;
+ }
+
+ if (is_dipper_type && (flags & XPT_PD_OUT)) {
+ flags &= ~XPT_PD_OUT;
+ flags |= XPT_PD_IN | XPT_PD_DIPPER;
+ }
+
+ if (IDL_tree_property_get(IDL_PARAM_DCL(tree).simple_declarator,
+ "shared")) {
+ if (flags & XPT_PD_IN) {
+ IDL_tree_error(tree, "can't have [shared] with in%s param "
+ "(only out)\n",
+ flags & XPT_PD_OUT ? "out" : "");
+ return FALSE;
+ }
+ flags |= XPT_PD_SHARED;
+ }
+
+ /* stick param where we can see it later */
+ state->tree = tree;
+ return fill_pd_from_type(state, pd, flags,
+ IDL_PARAM_DCL(tree).param_type_spec);
+}
+
+/* XXXshaver common with xpidl_header.c */
+#define ATTR_IDENT(tree) (IDL_IDENT(IDL_LIST(IDL_ATTR_DCL(tree).simple_declarations).data))
+#define ATTR_TYPE_DECL(tree) (IDL_ATTR_DCL(tree).param_type_spec)
+#define ATTR_TYPE(tree) (IDL_NODE_TYPE(ATTR_TYPE_DECL(tree)))
+
+static gboolean
+fill_pd_as_nsresult(XPTParamDescriptor *pd)
+{
+ pd->type.prefix.flags = TD_UINT32; /* TD_NSRESULT */
+ return TRUE;
+}
+
+static gboolean
+typelib_attr_accessor(TreeState *state, XPTMethodDescriptor *meth,
+ gboolean getter, gboolean hidden)
+{
+ uint8 methflags = 0;
+ uint8 pdflags = 0;
+
+ methflags |= getter ? XPT_MD_GETTER : XPT_MD_SETTER;
+ methflags |= hidden ? XPT_MD_HIDDEN : 0;
+ if (!XPT_FillMethodDescriptor(ARENA(state), meth, methflags,
+ ATTR_IDENT(state->tree).str, 1))
+ return FALSE;
+
+ if (getter) {
+ if (DIPPER_TYPE(ATTR_TYPE_DECL(state->tree))) {
+ pdflags |= (XPT_PD_RETVAL | XPT_PD_IN | XPT_PD_DIPPER);
+ } else {
+ pdflags |= (XPT_PD_RETVAL | XPT_PD_OUT);
+ }
+ } else {
+ pdflags |= XPT_PD_IN;
+ }
+
+ if (!fill_pd_from_type(state, meth->params, pdflags,
+ ATTR_TYPE_DECL(state->tree)))
+ return FALSE;
+
+ fill_pd_as_nsresult(meth->result);
+ NEXT_METH(state)++;
+ return TRUE;
+}
+
+static gboolean
+typelib_attr_dcl(TreeState *state)
+{
+ XPTInterfaceDescriptor *id = CURRENT(state);
+ XPTMethodDescriptor *meth;
+ gboolean read_only = IDL_ATTR_DCL(state->tree).f_readonly;
+
+ /* XXX this only handles the first ident; elsewhere too... */
+ IDL_tree ident =
+ IDL_LIST(IDL_ATTR_DCL(state->tree).simple_declarations).data;
+
+ /* If it's marked [noscript], mark it as hidden in the typelib. */
+ gboolean hidden = (IDL_tree_property_get(ident, "noscript") != NULL);
+
+ if (!verify_attribute_declaration(state->tree))
+ return FALSE;
+
+ if (!XPT_InterfaceDescriptorAddMethods(ARENA(state), id,
+ (PRUint16) (read_only ? 1 : 2)))
+ return FALSE;
+
+ meth = &id->method_descriptors[NEXT_METH(state)];
+
+ return typelib_attr_accessor(state, meth, TRUE, hidden) &&
+ (read_only || typelib_attr_accessor(state, meth + 1, FALSE, hidden));
+}
+
+static gboolean
+typelib_op_dcl(TreeState *state)
+{
+ XPTInterfaceDescriptor *id = CURRENT(state);
+ XPTMethodDescriptor *meth;
+ struct _IDL_OP_DCL *op = &IDL_OP_DCL(state->tree);
+ IDL_tree iter;
+ uint16 num_args = 0;
+ uint8 op_flags = 0;
+ gboolean op_notxpcom = (IDL_tree_property_get(op->ident, "notxpcom")
+ != NULL);
+ gboolean op_noscript = (IDL_tree_property_get(op->ident, "noscript")
+ != NULL);
+
+ if (!verify_method_declaration(state->tree))
+ return FALSE;
+
+ if (!XPT_InterfaceDescriptorAddMethods(ARENA(state), id, 1))
+ return FALSE;
+
+ meth = &id->method_descriptors[NEXT_METH(state)];
+
+ for (iter = op->parameter_dcls; iter; iter = IDL_LIST(iter).next)
+ num_args++; /* count params */
+ if (op->op_type_spec && !op_notxpcom)
+ num_args++; /* fake param for _retval */
+
+ if (op_noscript)
+ op_flags |= XPT_MD_HIDDEN;
+ if (op_notxpcom)
+ op_flags |= XPT_MD_NOTXPCOM;
+
+ /* XXXshaver constructor? */
+
+#ifdef DEBUG_shaver_method
+ fprintf(stdout, "DBG: adding method %s (nargs %d)\n",
+ IDL_IDENT(op->ident).str, num_args);
+#endif
+ if (!XPT_FillMethodDescriptor(ARENA(state), meth, op_flags,
+ IDL_IDENT(op->ident).str,
+ (uint8) num_args))
+ return FALSE;
+
+ for (num_args = 0, iter = op->parameter_dcls; iter;
+ iter = IDL_LIST(iter).next, num_args++) {
+ XPTParamDescriptor *pd = &meth->params[num_args];
+ if (!fill_pd_from_param(state, pd, IDL_LIST(iter).data))
+ return FALSE;
+ }
+
+ /* stick retval param where we can see it later */
+ state->tree = op->op_type_spec;
+
+ /* XXX unless [notxpcom] */
+ if (!op_notxpcom) {
+ if (op->op_type_spec) {
+ uint8 pdflags = DIPPER_TYPE(op->op_type_spec) ?
+ (XPT_PD_RETVAL | XPT_PD_IN | XPT_PD_DIPPER) :
+ (XPT_PD_RETVAL | XPT_PD_OUT);
+
+ if (!fill_pd_from_type(state, &meth->params[num_args],
+ pdflags, op->op_type_spec))
+ return FALSE;
+ }
+
+ if (!fill_pd_as_nsresult(meth->result))
+ return FALSE;
+ } else {
+#ifdef DEBUG_shaver_notxpcom
+ fprintf(stderr, "%s is notxpcom\n", IDL_IDENT(op->ident).str);
+#endif
+ if (!fill_pd_from_type(state, meth->result, XPT_PD_RETVAL,
+ op->op_type_spec))
+ return FALSE;
+ }
+ NEXT_METH(state)++;
+ return TRUE;
+}
+
+static gboolean
+typelib_const_dcl(TreeState *state)
+{
+ struct _IDL_CONST_DCL *dcl = &IDL_CONST_DCL(state->tree);
+ const char *name = IDL_IDENT(dcl->ident).str;
+ gboolean is_long;
+ gboolean sign;
+ IDL_tree real_type;
+ XPTInterfaceDescriptor *id;
+ XPTConstDescriptor *cd;
+ IDL_longlong_t value;
+
+ if (!verify_const_declaration(state->tree))
+ return FALSE;
+
+ /* Could be a typedef; try to map it to the real type. */
+ real_type = find_underlying_type(dcl->const_type);
+ real_type = real_type ? real_type : dcl->const_type;
+ is_long = (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG);
+
+ id = CURRENT(state);
+ if (!XPT_InterfaceDescriptorAddConsts(ARENA(state), id, 1))
+ return FALSE;
+ cd = &id->const_descriptors[NEXT_CONST(state)];
+
+ cd->name = IDL_IDENT(dcl->ident).str;
+#ifdef DEBUG_shaver_const
+ fprintf(stderr, "DBG: adding const %s\n", cd->name);
+#endif
+ if (!fill_td_from_type(state, &cd->type, dcl->const_type))
+ return FALSE;
+
+ value = IDL_INTEGER(dcl->const_exp).value;
+ sign = IDL_TYPE_INTEGER(dcl->const_type).f_signed;
+ if (is_long) {
+ if (sign)
+ cd->value.i32 = value;
+ else
+ cd->value.ui32 = value;
+ } else {
+ if (sign)
+ cd->value.i16 = value;
+ else
+ cd->value.ui16 = value;
+ }
+ NEXT_CONST(state)++;
+ return TRUE;
+}
+
+static gboolean
+typelib_enum(TreeState *state)
+{
+ XPIDL_WARNING((state->tree, IDL_WARNING1,
+ "enums not supported, enum \'%s\' ignored",
+ IDL_IDENT(IDL_TYPE_ENUM(state->tree).ident).str));
+ return TRUE;
+}
+
+backend *
+xpidl_typelib_dispatch(void)
+{
+ static backend result;
+ static nodeHandler table[IDLN_LAST];
+ static gboolean initialized = FALSE;
+
+ result.emit_prolog = typelib_prolog;
+ result.emit_epilog = typelib_epilog;
+
+ if (!initialized) {
+ /* Initialize non-NULL elements */
+ table[IDLN_LIST] = typelib_list;
+ table[IDLN_ATTR_DCL] = typelib_attr_dcl;
+ table[IDLN_OP_DCL] = typelib_op_dcl;
+ table[IDLN_INTERFACE] = typelib_interface;
+ table[IDLN_CONST_DCL] = typelib_const_dcl;
+ table[IDLN_TYPE_ENUM] = typelib_enum;
+ table[IDLN_NATIVE] = check_native;
+ initialized = TRUE;
+ }
+
+ result.dispatch_table = table;
+ return &result;
+}
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_util.c b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_util.c
new file mode 100644
index 00000000..25d04212
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpidl/xpidl_util.c
@@ -0,0 +1,851 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: NPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Netscape 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/NPL/
+ *
+ * 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 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 NPL, 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 NPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Utility functions called by various backends.
+ */
+
+#include "xpidl.h"
+
+/* XXXbe static */ char OOM[] = "ERROR: out of memory\n";
+
+void *
+xpidl_malloc(size_t nbytes)
+{
+ void *p = malloc(nbytes);
+ if (!p) {
+ fputs(OOM, stderr);
+ exit(1);
+ }
+ return p;
+}
+
+char *
+xpidl_strdup(const char *s)
+{
+#if defined(XP_MAC) || defined(XP_SOLARIS) /* bird: dunno why this is required, but whatever*/
+ size_t len = strlen(s);
+ char *ns = malloc(len + 1);
+ if (ns)
+ memcpy(ns, s, len + 1);
+#else
+ char *ns = strdup(s);
+#endif
+ if (!ns) {
+ fputs(OOM, stderr);
+ exit(1);
+ }
+ return ns;
+}
+
+void
+xpidl_write_comment(TreeState *state, int indent)
+{
+ fprintf(state->file, "%*s/* ", indent, "");
+ IDL_tree_to_IDL(state->tree, state->ns, state->file,
+ IDLF_OUTPUT_NO_NEWLINES |
+ IDLF_OUTPUT_NO_QUALIFY_IDENTS |
+ IDLF_OUTPUT_PROPERTIES);
+ fputs(" */\n", state->file);
+}
+
+/*
+ * Print an iid to into a supplied buffer; the buffer should be at least
+ * UUID_LENGTH bytes.
+ */
+gboolean
+xpidl_sprint_iid(nsID *id, char iidbuf[])
+{
+ int printed;
+
+ printed = sprintf(iidbuf,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ (PRUint32) id->m0, (PRUint32) id->m1,(PRUint32) id->m2,
+ (PRUint32) id->m3[0], (PRUint32) id->m3[1],
+ (PRUint32) id->m3[2], (PRUint32) id->m3[3],
+ (PRUint32) id->m3[4], (PRUint32) id->m3[5],
+ (PRUint32) id->m3[6], (PRUint32) id->m3[7]);
+
+#ifdef SPRINTF_RETURNS_STRING
+ return (printed && strlen((char *)printed) == 36);
+#else
+ return (printed == 36);
+#endif
+}
+
+/* We only parse the {}-less format. */
+static const char nsIDFmt2[] =
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
+
+/*
+ * Parse a uuid string into an nsID struct. We cannot link against libxpcom,
+ * so we re-implement nsID::Parse here.
+ */
+gboolean
+xpidl_parse_iid(nsID *id, const char *str)
+{
+ PRInt32 count = 0;
+ PRInt32 n1, n2, n3[8];
+ PRInt32 n0, i;
+
+ XPT_ASSERT(str != NULL);
+
+ if (strlen(str) != 36) {
+ return FALSE;
+ }
+
+#ifdef DEBUG_shaver_iid
+ fprintf(stderr, "parsing iid %s\n", str);
+#endif
+
+ count = sscanf(str, nsIDFmt2,
+ &n0, &n1, &n2,
+ &n3[0],&n3[1],&n3[2],&n3[3],
+ &n3[4],&n3[5],&n3[6],&n3[7]);
+
+ id->m0 = (PRInt32) n0;
+ id->m1 = (PRInt16) n1;
+ id->m2 = (PRInt16) n2;
+ for (i = 0; i < 8; i++) {
+ id->m3[i] = (PRInt8) n3[i];
+ }
+
+#ifdef DEBUG_shaver_iid
+ if (count == 11) {
+ fprintf(stderr, "IID parsed to ");
+ print_IID(id, stderr);
+ fputs("\n", stderr);
+ }
+#endif
+ return (gboolean)(count == 11);
+}
+
+gboolean
+verify_const_declaration(IDL_tree const_tree) {
+ struct _IDL_CONST_DCL *dcl = &IDL_CONST_DCL(const_tree);
+ const char *name = IDL_IDENT(dcl->ident).str;
+ IDL_tree real_type;
+
+ /* const -> list -> interface */
+ if (!IDL_NODE_UP(IDL_NODE_UP(const_tree)) ||
+ IDL_NODE_TYPE(IDL_NODE_UP(IDL_NODE_UP(const_tree)))
+ != IDLN_INTERFACE) {
+ IDL_tree_error(const_tree,
+ "const declaration \'%s\' outside interface",
+ name);
+ return FALSE;
+ }
+
+ /* Could be a typedef; try to map it to the real type. */
+ real_type = find_underlying_type(dcl->const_type);
+ real_type = real_type ? real_type : dcl->const_type;
+ if (IDL_NODE_TYPE(real_type) == IDLN_TYPE_INTEGER &&
+ (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_SHORT ||
+ IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG))
+ {
+ if (!IDL_TYPE_INTEGER(real_type).f_signed &&
+ IDL_INTEGER(dcl->const_exp).value < 0)
+ {
+#ifndef G_HAVE_GINT64
+ /*
+ * For platforms without longlong support turned on we can get
+ * confused by the high bit of the long value and think that it
+ * represents a negative value in an unsigned declaration.
+ * In that case we don't know if it is the programmer who is
+ * confused or the compiler. So we issue a warning instead of
+ * an error.
+ */
+ if (IDL_TYPE_INTEGER(real_type).f_type == IDL_INTEGER_TYPE_LONG)
+ {
+ XPIDL_WARNING((const_tree, IDL_WARNING1,
+ "unsigned const declaration \'%s\' "
+ "initialized with (possibly) negative constant",
+ name));
+ return TRUE;
+ }
+#endif
+ IDL_tree_error(const_tree,
+ "unsigned const declaration \'%s\' initialized with "
+ "negative constant",
+ name);
+ return FALSE;
+ }
+ } else {
+ IDL_tree_error(const_tree,
+ "const declaration \'%s\' must be of type short or long",
+ name);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+
+/*
+ * This method consolidates error checking needed when coercing the XPIDL compiler
+ * via the -t flag to generate output for a specific version of XPConnect.
+ */
+static gboolean
+verify_type_fits_version(IDL_tree in_tree, IDL_tree error_tree)
+{
+ if (major_version == 1 && minor_version == 1)
+ {
+ /* XPIDL Version 1.1 checks */
+
+ /* utf8string, cstring, and astring types are not supported */
+ if (IDL_tree_property_get(in_tree, "utf8string") != NULL ||
+ IDL_tree_property_get(in_tree, "cstring") != NULL ||
+ IDL_tree_property_get(in_tree, "astring") != NULL)
+ {
+ IDL_tree_error(error_tree,
+ "Cannot use [utf8string], [cstring] and [astring] "
+ "types when generating version 1.1 typelibs\n");
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+gboolean
+verify_attribute_declaration(IDL_tree attr_tree)
+{
+ IDL_tree iface;
+ IDL_tree ident;
+ IDL_tree attr_type;
+ gboolean scriptable_interface;
+
+ /* We don't support attributes named IID, conflicts with static GetIID
+ * member. The conflict is due to certain compilers (VC++) choosing a
+ * different vtable order, placing GetIID at the beginning regardless
+ * of it's placement
+ */
+ if (strcmp(
+ IDL_IDENT(
+ IDL_LIST(IDL_ATTR_DCL(attr_tree).simple_declarations).data).str,
+ "IID") == 0) {
+ IDL_tree_error(attr_tree,
+ "Attributes named IID not supported, causes vtable "
+ "ordering problems");
+ return FALSE;
+ }
+ /*
+ * Verify that we've been called on an interface, and decide if the
+ * interface was marked [scriptable].
+ */
+ if (IDL_NODE_UP(attr_tree) && IDL_NODE_UP(IDL_NODE_UP(attr_tree)) &&
+ IDL_NODE_TYPE(iface = IDL_NODE_UP(IDL_NODE_UP(attr_tree)))
+ == IDLN_INTERFACE)
+ {
+ scriptable_interface =
+ (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable")
+ != NULL);
+ } else {
+ IDL_tree_error(attr_tree,
+ "verify_attribute_declaration called on a non-interface?");
+ return FALSE;
+ }
+
+ /*
+ * Grab the first of the list of idents and hope that it'll
+ * say scriptable or no.
+ */
+ ident = IDL_LIST(IDL_ATTR_DCL(attr_tree).simple_declarations).data;
+
+ /*
+ * If the interface isn't scriptable, or the attribute is marked noscript,
+ * there's no need to check.
+ */
+ if (!scriptable_interface ||
+ IDL_tree_property_get(ident, "noscript") != NULL)
+ return TRUE;
+
+ /*
+ * If it should be scriptable, check that the type is non-native. nsid,
+ * domstring, utf8string, cstring, astring are exempted.
+ */
+ attr_type = IDL_ATTR_DCL(attr_tree).param_type_spec;
+
+ if (attr_type != NULL)
+ {
+ if (UP_IS_NATIVE(attr_type) &&
+ IDL_tree_property_get(attr_type, "nsid") == NULL &&
+ IDL_tree_property_get(attr_type, "domstring") == NULL &&
+ IDL_tree_property_get(attr_type, "utf8string") == NULL &&
+ IDL_tree_property_get(attr_type, "cstring") == NULL &&
+ IDL_tree_property_get(attr_type, "astring") == NULL)
+ {
+ IDL_tree_error(attr_tree,
+ "attributes in [scriptable] interfaces that are "
+ "non-scriptable because they refer to native "
+ "types must be marked [noscript]\n");
+ return FALSE;
+ }
+ /*
+ * We currently don't support properties of type nsid that aren't
+ * pointers or references, unless they are marked [notxpcom} and
+ * must be read-only
+ */
+
+ if ((IDL_tree_property_get(ident, "notxpcom") == NULL || !(IDL_ATTR_DCL(attr_tree).f_readonly)) &&
+ IDL_tree_property_get(attr_type,"nsid") != NULL &&
+ IDL_tree_property_get(attr_type,"ptr") == NULL &&
+ IDL_tree_property_get(attr_type,"ref") == NULL)
+ {
+ IDL_tree_error(attr_tree,
+ "Feature not currently supported: "
+ "attributes with a type of nsid must be marked "
+ "either [ptr] or [ref], or "
+ "else must be marked [notxpcom] "
+ "and must be read-only\n");
+ return FALSE;
+ }
+
+ /*
+ * Run additional error checks on the attribute type if targetting an
+ * older version of XPConnect.
+ */
+
+ if (!verify_type_fits_version(attr_type, attr_tree))
+ return FALSE;
+ }
+
+ if (IDL_LIST(IDL_ATTR_DCL(attr_tree).simple_declarations).next != NULL)
+ {
+ IDL_tree_error(attr_tree,
+ "multiple attributes in a single declaration is not supported\n");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ * Find the underlying type of an identifier typedef.
+ *
+ * All the needed tree-walking seems pretty shaky; isn't there something in
+ * libIDL to automate this?
+ */
+IDL_tree /* IDL_TYPE_DCL */
+find_underlying_type(IDL_tree typedef_ident)
+{
+ IDL_tree up;
+
+ if (typedef_ident == NULL || IDL_NODE_TYPE(typedef_ident) != IDLN_IDENT)
+ return NULL;
+
+ up = IDL_NODE_UP(typedef_ident);
+ if (up == NULL || IDL_NODE_TYPE(up) != IDLN_LIST)
+ return NULL;
+ up = IDL_NODE_UP(up);
+ if (up == NULL || IDL_NODE_TYPE(up) != IDLN_TYPE_DCL)
+ return NULL;
+
+ return IDL_TYPE_DCL(up).type_spec;
+}
+
+static IDL_tree /* IDL_PARAM_DCL */
+find_named_parameter(IDL_tree method_tree, const char *param_name)
+{
+ IDL_tree iter;
+ for (iter = IDL_OP_DCL(method_tree).parameter_dcls; iter;
+ iter = IDL_LIST(iter).next)
+ {
+ IDL_tree param = IDL_LIST(iter).data;
+ IDL_tree simple_decl = IDL_PARAM_DCL(param).simple_declarator;
+ const char *current_name = IDL_IDENT(simple_decl).str;
+ if (strcmp(current_name, param_name) == 0)
+ return param;
+ }
+ return NULL;
+}
+
+typedef enum ParamAttrType {
+ IID_IS,
+ LENGTH_IS,
+ SIZE_IS
+} ParamAttrType;
+
+/*
+ * Check that parameters referred to by attributes such as size_is exist and
+ * refer to parameters of the appropriate type.
+ */
+static gboolean
+check_param_attribute(IDL_tree method_tree, IDL_tree param,
+ ParamAttrType whattocheck)
+{
+ const char *method_name = IDL_IDENT(IDL_OP_DCL(method_tree).ident).str;
+ const char *referred_name = NULL;
+ IDL_tree param_type = IDL_PARAM_DCL(param).param_type_spec;
+ IDL_tree simple_decl = IDL_PARAM_DCL(param).simple_declarator;
+ const char *param_name = IDL_IDENT(simple_decl).str;
+ const char *attr_name;
+ const char *needed_type;
+
+ if (whattocheck == IID_IS) {
+ attr_name = "iid_is";
+ needed_type = "IID";
+ } else if (whattocheck == LENGTH_IS) {
+ attr_name = "length_is";
+ needed_type = "unsigned long (or PRUint32)";
+ } else if (whattocheck == SIZE_IS) {
+ attr_name = "size_is";
+ needed_type = "unsigned long (or PRUint32)";
+ } else {
+ XPT_ASSERT("asked to check an unknown attribute type!");
+ return TRUE;
+ }
+
+ referred_name = IDL_tree_property_get(simple_decl, attr_name);
+ if (referred_name != NULL) {
+ IDL_tree referred_param = find_named_parameter(method_tree,
+ referred_name);
+ IDL_tree referred_param_type;
+ if (referred_param == NULL) {
+ IDL_tree_error(method_tree,
+ "attribute [%s(%s)] refers to missing "
+ "parameter \"%s\"",
+ attr_name, referred_name, referred_name);
+ return FALSE;
+ }
+ if (referred_param == param) {
+ IDL_tree_error(method_tree,
+ "attribute [%s(%s)] refers to it's own parameter",
+ attr_name, referred_name);
+ return FALSE;
+ }
+
+ referred_param_type = IDL_PARAM_DCL(referred_param).param_type_spec;
+ if (whattocheck == IID_IS) {
+ /* require IID type */
+ if (IDL_tree_property_get(referred_param_type, "nsid") == NULL) {
+ IDL_tree_error(method_tree,
+ "target \"%s\" of [%s(%s)] attribute "
+ "must be of %s type",
+ referred_name, attr_name, referred_name,
+ needed_type);
+ return FALSE;
+ }
+ } else if (whattocheck == LENGTH_IS || whattocheck == SIZE_IS) {
+ /* require PRUint32 type */
+ IDL_tree real_type;
+
+ /* Could be a typedef; try to map it to the real type. */
+ real_type = find_underlying_type(referred_param_type);
+ real_type = real_type ? real_type : referred_param_type;
+
+ if (IDL_NODE_TYPE(real_type) != IDLN_TYPE_INTEGER ||
+ IDL_TYPE_INTEGER(real_type).f_signed != FALSE ||
+ IDL_TYPE_INTEGER(real_type).f_type != IDL_INTEGER_TYPE_LONG)
+ {
+ IDL_tree_error(method_tree,
+ "target \"%s\" of [%s(%s)] attribute "
+ "must be of %s type",
+ referred_name, attr_name, referred_name,
+ needed_type);
+
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Common method verification code, called by *op_dcl in the various backends.
+ */
+gboolean
+verify_method_declaration(IDL_tree method_tree)
+{
+ struct _IDL_OP_DCL *op = &IDL_OP_DCL(method_tree);
+ IDL_tree iface;
+ IDL_tree iter;
+ gboolean notxpcom;
+ gboolean scriptable_interface;
+ gboolean scriptable_method;
+ gboolean seen_retval = FALSE;
+ const char *method_name = IDL_IDENT(IDL_OP_DCL(method_tree).ident).str;
+
+ /* We don't support attributes named IID, conflicts with static GetIID
+ * member. The conflict is due to certain compilers (VC++) choosing a
+ * different vtable order, placing GetIID at the beginning regardless
+ * of it's placement
+ */
+ if (strcmp(method_name, "GetIID") == 0) {
+ IDL_tree_error(method_tree,
+ "Methods named GetIID not supported, causes vtable "
+ "ordering problems");
+ return FALSE;
+ }
+ if (op->f_varargs) {
+ /* We don't currently support varargs. */
+ IDL_tree_error(method_tree, "varargs are not currently supported");
+ return FALSE;
+ }
+
+ /*
+ * Verify that we've been called on an interface, and decide if the
+ * interface was marked [scriptable].
+ */
+ if (IDL_NODE_UP(method_tree) && IDL_NODE_UP(IDL_NODE_UP(method_tree)) &&
+ IDL_NODE_TYPE(iface = IDL_NODE_UP(IDL_NODE_UP(method_tree)))
+ == IDLN_INTERFACE)
+ {
+ scriptable_interface =
+ (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable")
+ != NULL);
+ } else {
+ IDL_tree_error(method_tree,
+ "verify_method_declaration called on a non-interface?");
+ return FALSE;
+ }
+
+ /*
+ * Require that any method in an interface marked as [scriptable], that
+ * *isn't* scriptable because it refers to some native type, be marked
+ * [noscript] or [notxpcom].
+ *
+ * Also check that iid_is points to nsid, and length_is, size_is points
+ * to unsigned long.
+ */
+ notxpcom = IDL_tree_property_get(op->ident, "notxpcom") != NULL;
+
+ scriptable_method = scriptable_interface &&
+ !notxpcom &&
+ IDL_tree_property_get(op->ident, "noscript") == NULL;
+
+ /* Loop through the parameters and check. */
+ for (iter = op->parameter_dcls; iter; iter = IDL_LIST(iter).next) {
+ IDL_tree param = IDL_LIST(iter).data;
+ IDL_tree param_type =
+ IDL_PARAM_DCL(param).param_type_spec;
+ IDL_tree simple_decl =
+ IDL_PARAM_DCL(param).simple_declarator;
+ const char *param_name = IDL_IDENT(simple_decl).str;
+
+ /*
+ * Reject this method if it should be scriptable and some parameter is
+ * native that isn't marked with either nsid, domstring, utf8string,
+ * cstring, astring or iid_is.
+ */
+ if (scriptable_method &&
+ UP_IS_NATIVE(param_type) &&
+ IDL_tree_property_get(param_type, "nsid") == NULL &&
+ IDL_tree_property_get(simple_decl, "iid_is") == NULL &&
+ IDL_tree_property_get(param_type, "domstring") == NULL &&
+ IDL_tree_property_get(param_type, "utf8string") == NULL &&
+ IDL_tree_property_get(param_type, "cstring") == NULL &&
+ IDL_tree_property_get(param_type, "astring") == NULL)
+ {
+ IDL_tree_error(method_tree,
+ "methods in [scriptable] interfaces that are "
+ "non-scriptable because they refer to native "
+ "types (parameter \"%s\") must be marked "
+ "[noscript]", param_name);
+ return FALSE;
+ }
+
+ /*
+ * nsid's parameters that aren't ptr's or ref's are not currently
+ * supported in xpcom or non-xpcom (marked with [notxpcom]) methods
+ * as input parameters
+ */
+ if (!(notxpcom && IDL_PARAM_DCL(param).attr != IDL_PARAM_IN) &&
+ IDL_tree_property_get(param_type, "nsid") != NULL &&
+ IDL_tree_property_get(param_type, "ptr") == NULL &&
+ IDL_tree_property_get(param_type, "ref") == NULL)
+ {
+ IDL_tree_error(method_tree,
+ "Feature currently not supported: "
+ "parameter \"%s\" is of type nsid and "
+ "must be marked either [ptr] or [ref] "
+ "or method \"%s\" must be marked [notxpcom] "
+ "and must not be an input parameter",
+ param_name,
+ method_name);
+ return FALSE;
+ }
+ /*
+ * Sanity checks on return values.
+ */
+ if (IDL_tree_property_get(simple_decl, "retval") != NULL) {
+ if (IDL_LIST(iter).next != NULL) {
+ IDL_tree_error(method_tree,
+ "only the last parameter can be marked [retval]");
+ return FALSE;
+ }
+ if (op->op_type_spec) {
+ IDL_tree_error(method_tree,
+ "can't have [retval] with non-void return type");
+ return FALSE;
+ }
+ /* In case XPConnect relaxes the retval-is-last restriction. */
+ if (seen_retval) {
+ IDL_tree_error(method_tree,
+ "can't have more than one [retval] parameter");
+ return FALSE;
+ }
+ seen_retval = TRUE;
+ }
+
+ /*
+ * Confirm that [shared] attributes are only used with string, wstring,
+ * or native (but not nsid, domstring, utf8string, cstring or astring)
+ * and can't be used with [array].
+ */
+ if (IDL_tree_property_get(simple_decl, "shared") != NULL) {
+ IDL_tree real_type;
+ real_type = find_underlying_type(param_type);
+ real_type = real_type ? real_type : param_type;
+
+ if (IDL_tree_property_get(simple_decl, "array") != NULL) {
+ IDL_tree_error(method_tree,
+ "[shared] parameter \"%s\" cannot "
+ "be of array type", param_name);
+ return FALSE;
+ }
+
+ if (!(IDL_NODE_TYPE(real_type) == IDLN_TYPE_STRING ||
+ IDL_NODE_TYPE(real_type) == IDLN_TYPE_WIDE_STRING ||
+ (UP_IS_NATIVE(real_type) &&
+ !IDL_tree_property_get(real_type, "nsid") &&
+ !IDL_tree_property_get(real_type, "domstring") &&
+ !IDL_tree_property_get(real_type, "utf8string") &&
+ !IDL_tree_property_get(real_type, "cstring") &&
+ !IDL_tree_property_get(real_type, "astring"))))
+ {
+ IDL_tree_error(method_tree,
+ "[shared] parameter \"%s\" must be of type "
+ "string, wstring or native", param_name);
+ return FALSE;
+ }
+ }
+
+ /*
+ * inout is not allowed with "domstring", "UTF8String", "CString"
+ * and "AString" types
+ */
+ if (IDL_PARAM_DCL(param).attr == IDL_PARAM_INOUT &&
+ UP_IS_NATIVE(param_type) &&
+ (IDL_tree_property_get(param_type, "domstring") != NULL ||
+ IDL_tree_property_get(param_type, "utf8string") != NULL ||
+ IDL_tree_property_get(param_type, "cstring") != NULL ||
+ IDL_tree_property_get(param_type, "astring") != NULL )) {
+ IDL_tree_error(method_tree,
+ "[domstring], [utf8string], [cstring], [astring] "
+ "types cannot be used as inout parameters");
+ return FALSE;
+ }
+
+
+ /*
+ * arrays of domstring, utf8string, cstring, astring types not allowed
+ */
+ if (IDL_tree_property_get(simple_decl, "array") != NULL &&
+ UP_IS_NATIVE(param_type) &&
+ (IDL_tree_property_get(param_type, "domstring") != NULL ||
+ IDL_tree_property_get(param_type, "utf8string") != NULL ||
+ IDL_tree_property_get(param_type, "cstring") != NULL ||
+ IDL_tree_property_get(param_type, "astring") != NULL)) {
+ IDL_tree_error(method_tree,
+ "[domstring], [utf8string], [cstring], [astring] "
+ "types cannot be used in array parameters");
+ return FALSE;
+ }
+
+ if (!check_param_attribute(method_tree, param, IID_IS) ||
+ !check_param_attribute(method_tree, param, LENGTH_IS) ||
+ !check_param_attribute(method_tree, param, SIZE_IS))
+ return FALSE;
+
+ /*
+ * Run additional error checks on the parameter type if targetting an
+ * older version of XPConnect.
+ */
+
+ if (!verify_type_fits_version(param_type, method_tree))
+ return FALSE;
+
+ }
+
+ /* XXX q: can return type be nsid? */
+ /* Native return type? */
+ if (scriptable_method &&
+ op->op_type_spec != NULL && UP_IS_NATIVE(op->op_type_spec) &&
+ IDL_tree_property_get(op->op_type_spec, "nsid") == NULL &&
+ IDL_tree_property_get(op->op_type_spec, "domstring") == NULL &&
+ IDL_tree_property_get(op->op_type_spec, "utf8string") == NULL &&
+ IDL_tree_property_get(op->op_type_spec, "cstring") == NULL &&
+ IDL_tree_property_get(op->op_type_spec, "astring") == NULL)
+ {
+ IDL_tree_error(method_tree,
+ "methods in [scriptable] interfaces that are "
+ "non-scriptable because they return native "
+ "types must be marked [noscript]");
+ return FALSE;
+ }
+
+
+ /*
+ * nsid's parameters that aren't ptr's or ref's are not currently
+ * supported in xpcom
+ */
+ if (!notxpcom &&
+ op->op_type_spec != NULL &&
+ IDL_tree_property_get(op->op_type_spec, "nsid") != NULL &&
+ IDL_tree_property_get(op->op_type_spec, "ptr") == NULL &&
+ IDL_tree_property_get(op->op_type_spec, "ref") == NULL)
+ {
+ IDL_tree_error(method_tree,
+ "Feature currently not supported: "
+ "return value is of type nsid and "
+ "must be marked either [ptr] or [ref], "
+ "or else method \"%s\" must be marked [notxpcom] ",
+ method_name);
+ return FALSE;
+ }
+
+ /*
+ * Run additional error checks on the return type if targetting an
+ * older version of XPConnect.
+ */
+
+ if (op->op_type_spec != NULL &&
+ !verify_type_fits_version(op->op_type_spec, method_tree))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*
+ * Verify that a native declaration has an associated C++ expression, i.e. that
+ * it's of the form native <idl-name>(<c++-name>)
+ */
+gboolean
+check_native(TreeState *state)
+{
+ char *native_name;
+ /* require that native declarations give a native type */
+ if (IDL_NATIVE(state->tree).user_type)
+ return TRUE;
+ native_name = IDL_IDENT(IDL_NATIVE(state->tree).ident).str;
+ IDL_tree_error(state->tree,
+ "``native %s;'' needs C++ type: ``native %s(<C++ type>);''",
+ native_name, native_name);
+ return FALSE;
+}
+
+/*
+ * Print a GSList as char strings to a file.
+ */
+void
+printlist(FILE *outfile, GSList *slist)
+{
+ guint i;
+ guint len = g_slist_length(slist);
+
+ for(i = 0; i < len; i++) {
+ fprintf(outfile,
+ "%s\n", (char *)g_slist_nth_data(slist, i));
+ }
+}
+
+void
+xpidl_list_foreach(IDL_tree p, IDL_tree_func foreach, gpointer user_data)
+{
+ IDL_tree_func_data tfd;
+
+ while (p) {
+ struct _IDL_LIST *list = &IDL_LIST(p);
+ tfd.tree = list->data;
+ if (!foreach(&tfd, user_data))
+ return;
+ p = list->next;
+ }
+}
+
+/*
+ * Verify that the interface declaration is correct
+ */
+gboolean
+verify_interface_declaration(IDL_tree interface_tree)
+{
+ IDL_tree iter;
+ /*
+ * If we have the scriptable attribute then make sure all of our direct
+ * parents have it as well.
+ * NOTE: We don't recurse since all interfaces will fall through here
+ */
+ if (IDL_tree_property_get(IDL_INTERFACE(interface_tree).ident,
+ "scriptable")) {
+ for (iter = IDL_INTERFACE(interface_tree).inheritance_spec; iter;
+ iter = IDL_LIST(iter).next) {
+ if (IDL_tree_property_get(
+ IDL_INTERFACE(iter).ident, "scriptable") == 0) {
+ XPIDL_WARNING((interface_tree,IDL_WARNING1,
+ "%s is scriptable but inherits from the non-scriptable interface %s\n",
+ IDL_IDENT(IDL_INTERFACE(interface_tree).ident).str,
+ IDL_IDENT(IDL_INTERFACE(iter).ident).str));
+ }
+ }
+ }
+ return TRUE;
+}
+
+/*
+ * Return a pointer to the start of the base filename of path
+ */
+char *
+xpidl_basename(const char * path)
+{
+ char * result = g_path_get_basename(path);
+ /*
+ *If this is windows then we'll handle either / or \ as a separator
+ * g_basename only handles \ for windows
+ */
+#if defined(XP_WIN32)
+# error adapt regarding g_basename() vs. g_path_get_basename()!
+ const char * slash = strrchr(path, '/');
+ /* If we found a slash and its after the current default OS separator */
+ if (slash != NULL && (slash > result))
+ result = slash + 1;
+#endif
+ return result;
+}
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/.cvsignore b/src/libs/xpcom18a4/xpcom/typelib/xpt/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/Makefile.in b/src/libs/xpcom18a4/xpcom/typelib/xpt/Makefile.in
new file mode 100644
index 00000000..1447128f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/Makefile.in
@@ -0,0 +1,50 @@
+#
+# ***** 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
+
+DIRS = public src tools
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/public/.cvsignore b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/public/Makefile.in b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/Makefile.in
new file mode 100644
index 00000000..3e452486
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/Makefile.in
@@ -0,0 +1,51 @@
+#
+# ***** 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
+
+EXPORTS = xpt_arena.h xpt_struct.h xpt_xdr.h
+EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_arena.h b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_arena.h
new file mode 100644
index 00000000..2b277467
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_arena.h
@@ -0,0 +1,145 @@
+/* -*- 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 ***** */
+
+/*
+ * Simple arena allocator for xpt (which avoids using NSPR).
+ */
+
+#ifndef __xpt_arena_h__
+#define __xpt_arena_h__
+
+#include "prtypes.h"
+#include <stdlib.h>
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define XPT_NewArena VBoxNsxpXPT_NewArena
+#define XPT_ArenaMalloc VBoxNsxpXPT_ArenaMalloc
+#define XPT_DestroyArena VBoxNsxpXPT_DestroyArena
+#define XPT_ArenaFree VBoxNsxpXPT_ArenaFree
+#define XPT_DestroyArena VBoxNsxpXPT_DestroyArena
+#define XPT_DumpStats VBoxNsxpXPT_DumpStats
+#define XPT_NotifyDoneLoading VBoxNsxpXPT_NotifyDoneLoading
+#define XPT_ArenaStrDup VBoxNsxpXPT_ArenaStrDup
+#define XPT_AssertFailed VBoxNsxpXPT_AssertFailed
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+/*
+ * The linkage of XPT API functions differs depending on whether the file is
+ * used within the XPT library or not. Any source file within the XPT
+ * library should define EXPORT_XPT_API whereas any client of the library
+ * should not.
+ */
+#ifdef EXPORT_XPT_API
+#define XPT_PUBLIC_API(t) PR_IMPLEMENT(t)
+#define XPT_PUBLIC_DATA(t) PR_IMPLEMENT_DATA(t)
+#else
+#ifdef _WIN32
+# define XPT_PUBLIC_API(t) __declspec(dllimport) t
+# define XPT_PUBLIC_DATA(t) __declspec(dllimport) t
+#else
+# define XPT_PUBLIC_API(t) PR_IMPLEMENT(t)
+# define XPT_PUBLIC_DATA(t) t
+#endif
+#endif
+#define XPT_FRIEND_API(t) XPT_PUBLIC_API(t)
+#define XPT_FRIEND_DATA(t) XPT_PUBLIC_DATA(t)
+
+PR_BEGIN_EXTERN_C
+
+/*
+ * Simple Arena support. Use with caution!
+ */
+
+typedef struct XPTArena XPTArena;
+
+XPT_PUBLIC_API(XPTArena *)
+XPT_NewArena(PRUint32 block_size, size_t alignment, const char* name);
+
+XPT_PUBLIC_API(void)
+XPT_DestroyArena(XPTArena *arena);
+
+XPT_PUBLIC_API(void)
+XPT_DumpStats(XPTArena *arena);
+
+XPT_PUBLIC_API(void *)
+XPT_ArenaMalloc(XPTArena *arena, size_t size);
+
+XPT_PUBLIC_API(char *)
+XPT_ArenaStrDup(XPTArena *arena, const char * s);
+
+XPT_PUBLIC_API(void)
+XPT_NotifyDoneLoading(XPTArena *arena);
+
+XPT_PUBLIC_API(void)
+XPT_ArenaFree(XPTArena *arena, void* block);
+
+/* --------------------------------------------------------- */
+
+#define XPT_MALLOC(_arena, _bytes) \
+ XPT_ArenaMalloc((_arena), (_bytes))
+
+#ifdef DEBUG
+#define XPT_FREE(_arena, _ptr) \
+ XPT_ArenaFree((_arena), (_ptr))
+#else
+#define XPT_FREE(_arena, _ptr) \
+ ((void)0)
+#endif
+
+#define XPT_STRDUP(_arena, _s) \
+ XPT_ArenaStrDup((_arena), (_s))
+
+#define XPT_CALLOC(_arena, _size) XPT_MALLOC((_arena), (_size))
+#define XPT_NEW(_arena, _struct) ((_struct *) XPT_MALLOC((_arena), sizeof(_struct)))
+#define XPT_NEWZAP(_arena, _struct) XPT_NEW((_arena), _struct)
+#define XPT_DELETE(_arena, _ptr) do{XPT_FREE((_arena), (_ptr)); ((_ptr)) = NULL;}while(0)
+#define XPT_FREEIF(_arena, _ptr) do{if ((_ptr)) XPT_FREE((_arena), (_ptr));}while(0)
+
+/* --------------------------------------------------------- */
+
+#ifdef DEBUG
+XPT_PUBLIC_API(void)
+XPT_AssertFailed(const char *s, const char *file, PRUint32 lineno);
+#define XPT_ASSERT(_expr) \
+ ((_expr)?((void)0):XPT_AssertFailed(# _expr, __FILE__, __LINE__))
+#else
+#define XPT_ASSERT(_expr) ((void)0)
+#endif
+
+PR_END_EXTERN_C
+
+#endif /* __xpt_arena_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_struct.h b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_struct.h
new file mode 100644
index 00000000..c7f36f2d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_struct.h
@@ -0,0 +1,562 @@
+/* -*- 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 ***** */
+
+/*
+ * Structures matching the in-memory representation of typelib structures.
+ * http://www.mozilla.org/scriptable/typelib_file.html
+ */
+
+#ifndef __xpt_struct_h__
+#define __xpt_struct_h__
+
+#include "xpt_arena.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define XPT_NewHeader VBoxNsxpXPT_NewHeader
+#define XPT_NewStringZ VBoxNsxpXPT_NewStringZ
+#define XPT_NewAnnotation VBoxNsxpXPT_NewAnnotation
+#define XPT_SizeOfHeaderBlock VBoxNsxpXPT_SizeOfHeaderBlock
+#define XPT_NewInterfaceDescriptor VBoxNsxpXPT_NewInterfaceDescriptor
+#define XPT_FillInterfaceDirectoryEntry VBoxNsxpXPT_FillInterfaceDirectoryEntry
+#define XPT_FillMethodDescriptor VBoxNsxpXPT_FillMethodDescriptor
+#define XPT_FreeHeader VBoxNsxpXPT_FreeHeader
+#define XPT_ParseVersionString VBoxNsxpXPT_ParseVersionString
+#define XPT_DestroyInterfaceDirectoryEntry VBoxNsxpXPT_DestroyInterfaceDirectoryEntry
+#define XPT_FillParamDescriptor VBoxNsxpXPT_FillParamDescriptor
+#define XPT_FreeInterfaceDescriptor VBoxNsxpXPT_FreeInterfaceDescriptor
+#define XPT_InterfaceDescriptorAddConsts VBoxNsxpXPT_InterfaceDescriptorAddConsts
+#define XPT_InterfaceDescriptorAddMethods VBoxNsxpXPT_InterfaceDescriptorAddMethods
+#define XPT_InterfaceDescriptorAddTypes VBoxNsxpXPT_InterfaceDescriptorAddTypes
+#define XPT_GetInterfaceIndexByName VBoxNsxpXPT_GetInterfaceIndexByName
+#define XPT_NewString VBoxNsxpXPT_NewString
+#define XPT_SizeOfHeader VBoxNsxpXPT_SizeOfHeader
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+/*
+ * Originally, I was going to have structures that exactly matched the on-disk
+ * representation, but that proved difficult: different compilers can pack
+ * their structs differently, and that makes overlaying them atop a
+ * read-from-disk byte buffer troublesome. So now I just have some structures
+ * that are used in memory, and we're going to write a nice XDR library to
+ * write them to disk and stuff. It is pure joy. -- shaver
+ */
+
+/* Structures for the typelib components */
+
+typedef struct XPTHeader XPTHeader;
+typedef struct XPTInterfaceDirectoryEntry XPTInterfaceDirectoryEntry;
+typedef struct XPTInterfaceDescriptor XPTInterfaceDescriptor;
+typedef struct XPTConstDescriptor XPTConstDescriptor;
+typedef struct XPTMethodDescriptor XPTMethodDescriptor;
+typedef struct XPTParamDescriptor XPTParamDescriptor;
+typedef struct XPTTypeDescriptor XPTTypeDescriptor;
+typedef struct XPTTypeDescriptorPrefix XPTTypeDescriptorPrefix;
+typedef struct XPTString XPTString;
+typedef struct XPTAnnotation XPTAnnotation;
+#ifndef nsID_h__
+/*
+ * We can't include nsID.h, because it's full of C++ goop and we're not doing
+ * C++ here, so we define our own minimal struct. We protect against multiple
+ * definitions of this struct, though, and use the same field naming.
+ */
+struct nsID {
+ PRUint32 m0;
+ PRUint16 m1;
+ PRUint16 m2;
+ PRUint8 m3[8];
+};
+
+typedef struct nsID nsID;
+#endif
+
+#define XPT_COPY_IID(to, from) \
+ (to).m0 = (from).m0; \
+ (to).m1 = (from).m1; \
+ (to).m2 = (from).m2; \
+ (to).m3[0] = (from).m3[0]; \
+ (to).m3[1] = (from).m3[1]; \
+ (to).m3[2] = (from).m3[2]; \
+ (to).m3[3] = (from).m3[3]; \
+ (to).m3[4] = (from).m3[4]; \
+ (to).m3[5] = (from).m3[5]; \
+ (to).m3[6] = (from).m3[6]; \
+ (to).m3[7] = (from).m3[7];
+
+
+/*
+ * Every XPCOM typelib file begins with a header.
+ */
+struct XPTHeader {
+ PRUint8 magic[16];
+ PRUint8 major_version;
+ PRUint8 minor_version;
+ PRUint16 num_interfaces;
+ PRUint32 file_length;
+ XPTInterfaceDirectoryEntry *interface_directory;
+ PRUint32 data_pool;
+ XPTAnnotation *annotations;
+};
+
+#define XPT_MAGIC "XPCOM\nTypeLib\r\n\032"
+/* For error messages. */
+#define XPT_MAGIC_STRING "XPCOM\\nTypeLib\\r\\n\\032"
+#define XPT_MAJOR_VERSION 0x01
+#define XPT_MINOR_VERSION 0x02
+
+/* Any file with a major version number of XPT_MAJOR_INCOMPATIBLE_VERSION
+ * or higher is to be considered incompatible by this version of xpt and
+ * we will refuse to read it. We will return a header with magic, major and
+ * minor versions set from the file. num_interfaces and file_length will be
+ * set to zero to confirm our inability to read the file; i.e. even if some
+ * client of this library gets out of sync with us regarding the agreed upon
+ * value for XPT_MAJOR_INCOMPATIBLE_VERSION, anytime num_interfaces and
+ * file_length are both zero we *know* that this library refused to read the
+ * file due to version imcompatibility.
+ */
+#define XPT_MAJOR_INCOMPATIBLE_VERSION 0x02
+
+/*
+ * The "[-t version number]" cmd line parameter to the XPIDL compiler and XPT
+ * linker specifies the major and minor version number of the output
+ * type library.
+ *
+ * The goal is for the compiler to check that the input IDL file only uses
+ * constructs that are supported in the version specified. The linker will
+ * check that all typelib files it reads are of the version specified or
+ * below.
+ *
+ * Both the compiler and the linker will report errors and abort if these
+ * checks fail.
+ *
+ * When you rev up major or minor versions of the type library in the future,
+ * think about the new stuff that you added to the type library and add checks
+ * to make sure that occurrences of that new "stuff" will get caught when [-t
+ * version number] is used with the compiler. Here's what you'll probably
+ * have to do each time you rev up major/minor versions:
+ *
+ * 1) Add the current version number string (before your change) to the
+ * XPT_TYPELIB_VERSIONS list.
+ *
+ * 2) Do your changes add new features to XPIDL? Ensure that those new
+ * features are rejected by the XPIDL compiler when any version number in
+ * the XPT_TYPELIB_VERSIONS list is specified on the command line. The
+ * one place that currently does this kind of error checking is the function
+ * verify_type_fits_version() in xpidl_util.c. It currently checks
+ * attribute types, parameter types, and return types. You'll probably have
+ * to add to it or generalize it further based on what kind of changes you
+ * are making.
+ *
+ * 3) You will probably NOT need to make any changes to the error checking
+ * in the linker.
+ */
+
+#define XPT_VERSION_UNKNOWN 0
+#define XPT_VERSION_UNSUPPORTED 1
+#define XPT_VERSION_OLD 2
+#define XPT_VERSION_CURRENT 3
+
+typedef struct {
+ const char* str;
+ PRUint8 major;
+ PRUint8 minor;
+ PRUint16 code;
+} XPT_TYPELIB_VERSIONS_STRUCT;
+
+/* Currently accepted list of versions for typelibs */
+#define XPT_TYPELIB_VERSIONS { \
+ {"1.0", 1, 0, XPT_VERSION_UNSUPPORTED}, \
+ {"1.1", 1, 1, XPT_VERSION_OLD}, \
+ {"1.2", 1, 2, XPT_VERSION_CURRENT} \
+}
+
+extern XPT_PUBLIC_API(PRUint16)
+XPT_ParseVersionString(const char* str, PRUint8* major, PRUint8* minor);
+
+extern XPT_PUBLIC_API(XPTHeader *)
+XPT_NewHeader(XPTArena *arena, PRUint16 num_interfaces,
+ PRUint8 major_version, PRUint8 minor_version);
+
+extern XPT_PUBLIC_API(void)
+XPT_FreeHeader(XPTArena *arena, XPTHeader* aHeader);
+
+/* size of header and annotations */
+extern XPT_PUBLIC_API(PRUint32)
+XPT_SizeOfHeader(XPTHeader *header);
+
+/* size of header and annotations and InterfaceDirectoryEntries */
+extern XPT_PUBLIC_API(PRUint32)
+XPT_SizeOfHeaderBlock(XPTHeader *header);
+
+/*
+ * A contiguous array of fixed-size InterfaceDirectoryEntry records begins at
+ * the byte offset identified by the interface_directory field in the file
+ * header. The array is used to quickly locate an interface description
+ * using its IID. No interface should appear more than once in the array.
+ */
+struct XPTInterfaceDirectoryEntry {
+ nsID iid;
+ char *name;
+ char *name_space;
+ XPTInterfaceDescriptor *interface_descriptor;
+
+#if 0 /* not yet */
+ /* not stored on disk */
+ PRUint32 offset; /* the offset for an ID still to be read */
+#endif
+};
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_FillInterfaceDirectoryEntry(XPTArena *arena,
+ XPTInterfaceDirectoryEntry *ide,
+ nsID *iid, char *name, char *name_space,
+ XPTInterfaceDescriptor *descriptor);
+
+extern XPT_PUBLIC_API(void)
+XPT_DestroyInterfaceDirectoryEntry(XPTArena *arena,
+ XPTInterfaceDirectoryEntry* ide);
+
+/*
+ * An InterfaceDescriptor is a variable-size record used to describe a
+ * single XPCOM interface, including all of its methods.
+ */
+struct XPTInterfaceDescriptor {
+ PRUint16 parent_interface;
+ PRUint16 num_methods;
+ XPTMethodDescriptor *method_descriptors;
+ PRUint16 num_constants;
+ XPTConstDescriptor *const_descriptors;
+ PRUint8 flags;
+
+ /* additional_types are used for arrays where we may need multiple
+ * XPTTypeDescriptors for a single XPTMethodDescriptor. Since we still
+ * want to have a simple array of XPTMethodDescriptor (each with a single
+ * embedded XPTTypeDescriptor), a XPTTypeDescriptor can have a reference
+ * to an 'additional_type'. That reference is an index in this
+ * "additional_types" array. So a given XPTMethodDescriptor might have
+ * a whole chain of these XPTTypeDescriptors to represent, say, a multi
+ * dimensional array.
+ *
+ * Note that in the typelib file these additional types are stored 'inline'
+ * in the MethodDescriptor. But, in the typelib MethodDescriptors can be
+ * of varying sizes, where in XPT's in memory mapping of the data we want
+ * them to be of fixed size. This additional_types scheme is here to allow
+ * for that.
+ */
+
+ XPTTypeDescriptor *additional_types;
+ PRUint16 num_additional_types;
+};
+
+#define XPT_ID_SCRIPTABLE 0x80
+#define XPT_ID_FUNCTION 0x40
+#define XPT_ID_FLAGMASK 0xc0
+#define XPT_ID_TAGMASK (~XPT_ID_FLAGMASK)
+#define XPT_ID_TAG(id) ((id).flags & XPT_ID_TAGMASK)
+
+#define XPT_ID_IS_SCRIPTABLE(flags) (flags & XPT_ID_SCRIPTABLE)
+#define XPT_ID_IS_FUNCTION(flags) (flags & XPT_ID_FUNCTION)
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_GetInterfaceIndexByName(XPTInterfaceDirectoryEntry *ide_block,
+ PRUint16 num_interfaces, char *name,
+ PRUint16 *indexp);
+
+extern XPT_PUBLIC_API(XPTInterfaceDescriptor *)
+XPT_NewInterfaceDescriptor(XPTArena *arena,
+ PRUint16 parent_interface, PRUint16 num_methods,
+ PRUint16 num_constants, PRUint8 flags);
+
+extern XPT_PUBLIC_API(void)
+XPT_FreeInterfaceDescriptor(XPTArena *arena, XPTInterfaceDescriptor* id);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_InterfaceDescriptorAddTypes(XPTArena *arena, XPTInterfaceDescriptor *id,
+ PRUint16 num);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_InterfaceDescriptorAddMethods(XPTArena *arena, XPTInterfaceDescriptor *id,
+ PRUint16 num);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_InterfaceDescriptorAddConsts(XPTArena *arena, XPTInterfaceDescriptor *id,
+ PRUint16 num);
+
+/*
+ * This is our special string struct with a length value associated with it,
+ * which means that it can contains embedded NULs.
+ */
+struct XPTString {
+ PRUint16 length;
+ char *bytes;
+};
+
+extern XPT_PUBLIC_API(XPTString *)
+XPT_NewString(XPTArena *arena, PRUint16 length, char *bytes);
+
+extern XPT_PUBLIC_API(XPTString *)
+XPT_NewStringZ(XPTArena *arena, char *bytes);
+
+/*
+ * A TypeDescriptor is a variable-size record used to identify the type of a
+ * method argument or return value.
+ *
+ * There are three types of TypeDescriptors:
+ *
+ * SimpleTypeDescriptor
+ * InterfaceTypeDescriptor
+ * InterfaceIsTypeDescriptor
+ *
+ * The tag field in the prefix indicates which of the variant TypeDescriptor
+ * records is being used, and hence the way any remaining fields should be
+ * parsed. Values from 0 to 17 refer to SimpleTypeDescriptors. The value 18
+ * designates an InterfaceTypeDescriptor, while 19 represents an
+ * InterfaceIsTypeDescriptor.
+ */
+
+/* why bother with a struct? - other code relies on this being a struct */
+struct XPTTypeDescriptorPrefix {
+ PRUint8 flags;
+};
+
+/* flag bits -- fur and jband were right, I was miserably wrong */
+#define XPT_TDP_POINTER 0x80
+#define XPT_TDP_UNIQUE_POINTER 0x40
+#define XPT_TDP_REFERENCE 0x20
+#define XPT_TDP_FLAGMASK 0xe0
+#define XPT_TDP_TAGMASK (~XPT_TDP_FLAGMASK)
+#define XPT_TDP_TAG(tdp) ((tdp).flags & XPT_TDP_TAGMASK)
+
+#define XPT_TDP_IS_POINTER(flags) (flags & XPT_TDP_POINTER)
+#define XPT_TDP_IS_UNIQUE_POINTER(flags) (flags & XPT_TDP_UNIQUE_POINTER)
+#define XPT_TDP_IS_REFERENCE(flags) (flags & XPT_TDP_REFERENCE)
+
+/*
+ * The following enum maps mnemonic names to the different numeric values
+ * of XPTTypeDescriptor->tag.
+ */
+enum XPTTypeDescriptorTags {
+ TD_INT8 = 0,
+ TD_INT16 = 1,
+ TD_INT32 = 2,
+ TD_INT64 = 3,
+ TD_UINT8 = 4,
+ TD_UINT16 = 5,
+ TD_UINT32 = 6,
+ TD_UINT64 = 7,
+ TD_FLOAT = 8,
+ TD_DOUBLE = 9,
+ TD_BOOL = 10,
+ TD_CHAR = 11,
+ TD_WCHAR = 12,
+ TD_VOID = 13,
+ TD_PNSIID = 14,
+ TD_DOMSTRING = 15,
+ TD_PSTRING = 16,
+ TD_PWSTRING = 17,
+ TD_INTERFACE_TYPE = 18,
+ TD_INTERFACE_IS_TYPE = 19,
+ TD_ARRAY = 20,
+ TD_PSTRING_SIZE_IS = 21,
+ TD_PWSTRING_SIZE_IS = 22,
+ TD_UTF8STRING = 23,
+ TD_CSTRING = 24,
+ TD_ASTRING = 25
+};
+
+struct XPTTypeDescriptor {
+ XPTTypeDescriptorPrefix prefix;
+ PRUint8 argnum; /* used for iid_is and size_is */
+ PRUint8 argnum2; /* used for length_is */
+ union {
+ PRUint16 iface; /* used for TD_INTERFACE_TYPE */
+ PRUint16 additional_type; /* used for TD_ARRAY */
+ } type;
+};
+
+#define XPT_COPY_TYPE(to, from) \
+ (to).prefix.flags = (from).prefix.flags; \
+ (to).argnum = (from).argnum; \
+ (to).argnum2 = (from).argnum2; \
+ (to).type.additional_type = (from).type.additional_type;
+
+/*
+ * A ConstDescriptor is a variable-size record that records the name and
+ * value of a scoped interface constant.
+ *
+ * The types of the method parameter are restricted to the following subset
+ * of TypeDescriptors:
+ *
+ * int8, uint8, int16, uint16, int32, uint32,
+ * int64, uint64, wchar_t, char, string
+ *
+ * The type (and thus the size) of the value record is determined by the
+ * contents of the associated TypeDescriptor record. For instance, if type
+ * corresponds to int16, then value is a two-byte record consisting of a
+ * 16-bit signed integer. For a ConstDescriptor type of string, the value
+ * record is of type String*, i.e. an offset within the data pool to a
+ * String record containing the constant string.
+ */
+union XPTConstValue {
+ PRInt8 i8;
+ PRUint8 ui8;
+ PRInt16 i16;
+ PRUint16 ui16;
+ PRInt32 i32;
+ PRUint32 ui32;
+ PRInt64 i64;
+ PRUint64 ui64;
+ float flt;
+ double dbl;
+ PRBool bul;
+ char ch;
+ PRUint16 wch;
+ nsID *iid;
+ XPTString *string;
+ char *str;
+ PRUint16 *wstr;
+}; /* varies according to type */
+
+struct XPTConstDescriptor {
+ char *name;
+ XPTTypeDescriptor type;
+ union XPTConstValue value;
+};
+
+/*
+ * A ParamDescriptor is a variable-size record used to describe either a
+ * single argument to a method or a method's result.
+ */
+struct XPTParamDescriptor {
+ PRUint8 flags;
+ XPTTypeDescriptor type;
+};
+
+/* flag bits -- jband and fur were right, and I was miserably wrong */
+#define XPT_PD_IN 0x80
+#define XPT_PD_OUT 0x40
+#define XPT_PD_RETVAL 0x20
+#define XPT_PD_SHARED 0x10
+#define XPT_PD_DIPPER 0x08
+#define XPT_PD_FLAGMASK 0xf8
+
+#define XPT_PD_IS_IN(flags) (flags & XPT_PD_IN)
+#define XPT_PD_IS_OUT(flags) (flags & XPT_PD_OUT)
+#define XPT_PD_IS_RETVAL(flags) (flags & XPT_PD_RETVAL)
+#define XPT_PD_IS_SHARED(flags) (flags & XPT_PD_SHARED)
+#define XPT_PD_IS_DIPPER(flags) (flags & XPT_PD_DIPPER)
+
+/* this is bogus
+#define XPT_PARAMDESCRIPTOR_SIZE (XPT_TYPEDESCRIPTOR_SIZE + 1)
+*/
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_FillParamDescriptor(XPTArena *arena,
+ XPTParamDescriptor *pd, PRUint8 flags,
+ XPTTypeDescriptor *type);
+
+/*
+ * A MethodDescriptor is a variable-size record used to describe a single
+ * interface method.
+ */
+struct XPTMethodDescriptor {
+ char *name;
+ XPTParamDescriptor *params;
+ XPTParamDescriptor *result;
+ PRUint8 flags;
+ PRUint8 num_args;
+};
+
+/* flag bits -- jband and fur were right, and I was miserably wrong */
+#define XPT_MD_GETTER 0x80
+#define XPT_MD_SETTER 0x40
+#define XPT_MD_NOTXPCOM 0x20
+#define XPT_MD_CTOR 0x10
+#define XPT_MD_HIDDEN 0x08
+#define XPT_MD_FLAGMASK 0xf8
+
+#define XPT_MD_IS_GETTER(flags) (flags & XPT_MD_GETTER)
+#define XPT_MD_IS_SETTER(flags) (flags & XPT_MD_SETTER)
+#define XPT_MD_IS_NOTXPCOM(flags) (flags & XPT_MD_NOTXPCOM)
+#define XPT_MD_IS_CTOR(flags) (flags & XPT_MD_CTOR)
+#define XPT_MD_IS_HIDDEN(flags) (flags & XPT_MD_HIDDEN)
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_FillMethodDescriptor(XPTArena *arena,
+ XPTMethodDescriptor *meth, PRUint8 flags, char *name,
+ PRUint8 num_args);
+
+/*
+ * Annotation records are variable-size records used to store secondary
+ * information about the typelib, e.g. such as the name of the tool that
+ * generated the typelib file, the date it was generated, etc. The
+ * information is stored with very loose format requirements so as to
+ * allow virtually any private data to be stored in the typelib.
+ *
+ * There are two types of Annotations:
+ *
+ * EmptyAnnotation
+ * PrivateAnnotation
+ *
+ * The tag field of the prefix discriminates among the variant record
+ * types for Annotation's. If the tag is 0, this record is an
+ * EmptyAnnotation. EmptyAnnotation's are ignored - they're only used to
+ * indicate an array of Annotation's that's completely empty. If the tag
+ * is 1, the record is a PrivateAnnotation.
+ */
+
+struct XPTAnnotation {
+ XPTAnnotation *next;
+ PRUint8 flags;
+ /* remaining fields are present in typelib iff XPT_ANN_IS_PRIVATE */
+ XPTString *creator;
+ XPTString *private_data;
+};
+
+#define XPT_ANN_LAST 0x80
+#define XPT_ANN_IS_LAST(flags) (flags & XPT_ANN_LAST)
+#define XPT_ANN_PRIVATE 0x40
+#define XPT_ANN_IS_PRIVATE(flags) (flags & XPT_ANN_PRIVATE)
+
+extern XPT_PUBLIC_API(XPTAnnotation *)
+XPT_NewAnnotation(XPTArena *arena, PRUint8 flags, XPTString *creator,
+ XPTString *private_data);
+
+PR_END_EXTERN_C
+
+#endif /* __xpt_struct_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_xdr.h b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_xdr.h
new file mode 100644
index 00000000..89d1c3f6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/public/xpt_xdr.h
@@ -0,0 +1,240 @@
+/* -*- 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 ***** */
+
+/*
+ * Basic APIs for streaming typelib structures to/from disk.
+ */
+
+#ifndef __xpt_xdr_h__
+#define __xpt_xdr_h__
+
+#include "xpt_struct.h"
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+#define XPT_Do8 VBoxNsxpXPT_Do8
+#define XPT_Do16 VBoxNsxpXPT_Do16
+#define XPT_Do32 VBoxNsxpXPT_Do32
+#define XPT_Do64 VBoxNsxpXPT_Do64
+#define XPT_DoIID VBoxNsxpXPT_DoIID
+#define XPT_DoCString VBoxNsxpXPT_DoCString
+#define XPT_DoString VBoxNsxpXPT_DoString
+#define XPT_DoStringInline VBoxNsxpXPT_DoStringInline
+#define XPT_NewXDRState VBoxNsxpXPT_NewXDRState
+#define XPT_SetDataOffset VBoxNsxpXPT_SetDataOffset
+#define XPT_SeekTo VBoxNsxpXPT_SeekTo
+#define XPT_MakeCursor VBoxNsxpXPT_MakeCursor
+#define XPT_DestroyXDRState VBoxNsxpXPT_DestroyXDRState
+#define XPT_GetXDRData VBoxNsxpXPT_GetXDRData
+#define XPT_GetXDRDataLength VBoxNsxpXPT_GetXDRDataLength
+#define XPT_DoHeader VBoxNsxpXPT_DoHeader
+#define XPT_DoHeaderPrologue VBoxNsxpXPT_DoHeaderPrologue
+#define XPT_UpdateFileLength VBoxNsxpXPT_UpdateFileLength
+#define XPT_DataOffset VBoxNsxpXPT_DataOffset
+#define XPT_GetOffsetForAddr VBoxNsxpXPT_GetOffsetForAddr
+#define XPT_SetOffsetForAddr VBoxNsxpXPT_SetOffsetForAddr
+#define XPT_SetAddrForOffset VBoxNsxpXPT_SetAddrForOffset
+#define XPT_GetAddrForOffset VBoxNsxpXPT_GetAddrForOffset
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+PR_BEGIN_EXTERN_C
+
+typedef struct XPTState XPTState;
+typedef struct XPTDatapool XPTDatapool;
+typedef struct XPTCursor XPTCursor;
+
+/* Opaque type, for internal use */
+typedef struct XPTHashTable XPTHashTable;
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_DoString(XPTArena *arena, XPTCursor *cursor, XPTString **strp);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_DoStringInline(XPTArena *arena, XPTCursor *cursor, XPTString **strp);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_DoCString(XPTArena *arena, XPTCursor *cursor, char **strp);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_DoIID(XPTCursor *cursor, nsID *iidp);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_Do64(XPTCursor *cursor, PRInt64 *u64p);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_Do32(XPTCursor *cursor, PRUint32 *u32p);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_Do16(XPTCursor *cursor, PRUint16 *u16p);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_Do8(XPTCursor *cursor, PRUint8 *u8p);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_DoHeaderPrologue(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp, PRUint32 * ide_offset);
+extern XPT_PUBLIC_API(PRBool)
+XPT_DoHeader(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp);
+
+typedef enum {
+ XPT_ENCODE,
+ XPT_DECODE
+} XPTMode;
+
+typedef enum {
+ XPT_HEADER = 0,
+ XPT_DATA = 1
+} XPTPool;
+
+struct XPTState {
+ XPTMode mode;
+ PRUint32 data_offset;
+ PRUint32 next_cursor[2];
+ XPTDatapool *pool;
+ XPTArena *arena;
+};
+
+struct XPTDatapool {
+ XPTHashTable *offset_map;
+ char *data;
+ PRUint32 count;
+ PRUint32 allocated;
+};
+
+struct XPTCursor {
+ XPTState *state;
+ XPTPool pool;
+ PRUint32 offset;
+ PRUint8 bits;
+};
+
+extern XPT_PUBLIC_API(XPTState *)
+XPT_NewXDRState(XPTMode mode, char *data, PRUint32 len);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_MakeCursor(XPTState *state, XPTPool pool, PRUint32 len, XPTCursor *cursor);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_SeekTo(XPTCursor *cursor, PRUint32 offset);
+
+extern XPT_PUBLIC_API(void)
+XPT_DestroyXDRState(XPTState *state);
+
+/* Set file_length based on the data used in the state. (Only ENCODE.) */
+extern XPT_PUBLIC_API(PRBool)
+XPT_UpdateFileLength(XPTState *state);
+
+/* returns the length of the specified data block */
+extern XPT_PUBLIC_API(void)
+XPT_GetXDRDataLength(XPTState *state, XPTPool pool, PRUint32 *len);
+
+extern XPT_PUBLIC_API(void)
+XPT_GetXDRData(XPTState *state, XPTPool pool, char **data, PRUint32 *len);
+
+/* set or get the data offset for the state, depending on mode */
+extern XPT_PUBLIC_API(void)
+XPT_DataOffset(XPTState *state, PRUint32 *data_offsetp);
+
+extern XPT_PUBLIC_API(void)
+XPT_SetDataOffset(XPTState *state, PRUint32 data_offset);
+
+extern XPT_PUBLIC_API(PRUint32)
+XPT_GetOffsetForAddr(XPTCursor *cursor, void *addr);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_SetOffsetForAddr(XPTCursor *cursor, void *addr, PRUint32 offset);
+
+extern XPT_PUBLIC_API(PRBool)
+XPT_SetAddrForOffset(XPTCursor *cursor, PRUint32 offset, void *addr);
+
+extern XPT_PUBLIC_API(void *)
+XPT_GetAddrForOffset(XPTCursor *cursor, PRUint32 offset);
+
+/* all data structures are big-endian */
+
+#if defined IS_BIG_ENDIAN
+# ifdef VBOX
+# error "Misconfigured endian!"
+# endif
+# define XPT_SWAB32(x) x
+# define XPT_SWAB16(x) x
+#elif defined IS_LITTLE_ENDIAN
+# define XPT_SWAB32(x) (((x) >> 24) | \
+ (((x) >> 8) & 0xff00) | \
+ (((x) << 8) & 0xff0000) | \
+ ((x) << 24))
+# define XPT_SWAB16(x) (((x) >> 8) | ((x) << 8))
+#else
+# error "unknown byte order"
+#endif
+
+/*
+ * If we're decoding, we want to read the offset before we check
+ * for already-decoded values.
+ *
+ * Then we check for repetition: CheckForRepeat will see if we've already
+ * encoded/decoded this value, and if so will set offset/addr correctly
+ * and make already be true. If not, it will set up the cursor for
+ * encoding (reserve space) or decoding (seek to correct location) as
+ * appropriate. In the encode case, it will also set the addr->offset
+ * mapping.
+ */
+
+#define XPT_PREAMBLE_(cursor, addrp, pool, size, new_curs, already) \
+ XPTMode mode = cursor->state->mode; \
+ if (!(mode == XPT_ENCODE || XPT_Do32(cursor, &new_curs.offset)) || \
+ !CheckForRepeat(cursor, (void **)addrp, pool, \
+ mode == XPT_ENCODE ? size : 0u, &new_curs, \
+ &already) || \
+ !(mode == XPT_DECODE || XPT_Do32(cursor, &new_curs.offset))) \
+ return PR_FALSE; \
+ if (already) \
+ return PR_TRUE; \
+
+#define XPT_PREAMBLE_NO_ALLOC(cursor, addrp, pool, size, new_curs, already) \
+ { \
+ XPT_PREAMBLE_(cursor, addrp, pool, size, new_curs, already) \
+ }
+
+#define XPT_ERROR_HANDLE(arena, free_it) \
+ error: \
+ if (cursor->state->mode == XPT_DECODE) \
+ XPT_FREEIF(arena, free_it); \
+ return PR_FALSE;
+
+
+PR_END_EXTERN_C
+
+#endif /* __xpt_xdr_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/src/.cvsignore b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/src/Makefile.in b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/Makefile.in
new file mode 100644
index 00000000..e0578556
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/Makefile.in
@@ -0,0 +1,76 @@
+#
+# ***** 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
+LIBRARY_NAME = xpt
+LIB_IS_C_ONLY = 1
+ifdef CROSS_COMPILE
+HOST_LIBRARY_NAME = hostxpt
+endif
+
+CSRCS = xpt_arena.c xpt_struct.c xpt_xdr.c
+HOST_CSRCS = $(CSRCS)
+
+# 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 += -DEXPORT_XPT_API
+HOST_CFLAGS += -DEXPORT_XPT_API
+
+# Build libxpt early so that it'll be available to xpidl, which also
+# must be built early.
+export::
+ @$(MAKE) libs
+
+ifdef CROSS_COMPILE
+ifdef HOST_NSPR_MDCPUCFG
+HOST_CFLAGS += -DMDCPUCFG=$(HOST_NSPR_MDCPUCFG)
+endif
+endif
+
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_arena.c b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_arena.c
new file mode 100644
index 00000000..a0813b8f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_arena.c
@@ -0,0 +1,358 @@
+/* -*- 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 ***** */
+
+/* Quick arena hack for xpt. */
+
+/* XXX This exists because we don't want to drag in NSPR. It *seemed*
+* to make more sense to write a quick and dirty arena than to clone
+* plarena (like js/src did). This is not optimal, but it works.
+* Half of the code here is instrumentation.
+*/
+
+#include "xpt_arena.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+# include <iprt/mem.h>
+#endif
+
+
+/*************************/
+/* logging stats support */
+
+#if 0 && defined(DEBUG_jband)
+#define XPT_ARENA_LOGGING 1
+#endif
+
+#ifdef XPT_ARENA_LOGGING
+
+#define LOG_MALLOC(_a, _req, _used) \
+ do{ \
+ XPT_ASSERT((_a)); \
+ ++(_a)->LOG_MallocCallCount; \
+ (_a)->LOG_MallocTotalBytesRequested += (_req); \
+ (_a)->LOG_MallocTotalBytesUsed += (_used); \
+ } while(0)
+
+#define LOG_REAL_MALLOC(_a, _size) \
+ do{ \
+ XPT_ASSERT((_a)); \
+ ++(_a)->LOG_RealMallocCallCount; \
+ (_a)->LOG_RealMallocTotalBytesRequested += (_size); \
+ } while(0)
+
+#define LOG_FREE(_a) \
+ do{ \
+ XPT_ASSERT((_a)); \
+ ++(_a)->LOG_FreeCallCount; \
+ } while(0)
+
+#define LOG_DONE_LOADING(_a) \
+ do{ \
+ XPT_ASSERT((_a)); \
+ (_a)->LOG_LoadingFreeCallCount = (_a)->LOG_FreeCallCount; \
+ } while(0)
+
+#define PRINT_STATS(_a) xpt_DebugPrintArenaStats((_a))
+static void xpt_DebugPrintArenaStats(XPTArena *arena);
+
+#else /* !XPT_ARENA_LOGGING */
+
+#define LOG_MALLOC(_a, _req, _used) ((void)0)
+#define LOG_REAL_MALLOC(_a, _size) ((void)0)
+#define LOG_FREE(_a) ((void)0)
+
+#define LOG_DONE_LOADING(_a) ((void)0)
+#define PRINT_STATS(_a) ((void)0)
+
+#endif /* XPT_ARENA_LOGGING */
+
+/****************************************************/
+
+/* Block header for each block in the arena */
+typedef struct BLK_HDR BLK_HDR;
+struct BLK_HDR
+{
+ BLK_HDR *next;
+ size_t size;
+};
+
+#define XPT_MIN_BLOCK_SIZE 32
+
+/* XXX this is lame. Should clone the code to do this bitwise */
+#define ALIGN_RND(s,a) ((a)==1?(s):((((s)+(a)-1)/(a))*(a)))
+
+struct XPTArena
+{
+ BLK_HDR *first;
+ PRUint8 *next;
+ size_t space;
+ size_t alignment;
+ size_t block_size;
+ char *name;
+
+#ifdef XPT_ARENA_LOGGING
+ PRUint32 LOG_MallocCallCount;
+ PRUint32 LOG_MallocTotalBytesRequested;
+ PRUint32 LOG_MallocTotalBytesUsed;
+ PRUint32 LOG_FreeCallCount;
+ PRUint32 LOG_LoadingFreeCallCount;
+ PRUint32 LOG_RealMallocCallCount;
+ PRUint32 LOG_RealMallocTotalBytesRequested;
+#endif /* XPT_ARENA_LOGGING */
+};
+
+XPT_PUBLIC_API(XPTArena *)
+XPT_NewArena(PRUint32 block_size, size_t alignment, const char* name)
+{
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ XPTArena *arena = RTMemAllocZ(sizeof(XPTArena));
+#else
+ XPTArena *arena = calloc(1, sizeof(XPTArena));
+#endif
+ if (arena) {
+ XPT_ASSERT(alignment);
+ if (alignment > sizeof(double))
+ alignment = sizeof(double);
+ arena->alignment = alignment;
+
+ if (block_size < XPT_MIN_BLOCK_SIZE)
+ block_size = XPT_MIN_BLOCK_SIZE;
+ arena->block_size = ALIGN_RND(block_size, alignment);
+
+ /* must have room for at least one item! */
+ XPT_ASSERT(arena->block_size >=
+ ALIGN_RND(sizeof(BLK_HDR), alignment) +
+ ALIGN_RND(1, alignment));
+
+ if (name) {
+ arena->name = XPT_STRDUP(arena, name);
+#ifdef XPT_ARENA_LOGGING
+ /* fudge the stats since we are using space in the arena */
+ arena->LOG_MallocCallCount = 0;
+ arena->LOG_MallocTotalBytesRequested = 0;
+ arena->LOG_MallocTotalBytesUsed = 0;
+#endif /* XPT_ARENA_LOGGING */
+ }
+ }
+ return arena;
+}
+
+XPT_PUBLIC_API(void)
+XPT_DestroyArena(XPTArena *arena)
+{
+ BLK_HDR* cur;
+ BLK_HDR* next;
+
+ cur = arena->first;
+ while (cur) {
+ next = cur->next;
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(cur);
+#else
+ free(cur);
+#endif
+ cur = next;
+ }
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ RTMemFree(arena);
+#else
+ free(arena);
+#endif
+}
+
+XPT_PUBLIC_API(void)
+XPT_DumpStats(XPTArena *arena)
+{
+ PRINT_STATS(arena);
+}
+
+
+/*
+* Our alignment rule is that we always round up the size of each allocation
+* so that the 'arena->next' pointer one will point to properly aligned space.
+*/
+
+XPT_PUBLIC_API(void *)
+XPT_ArenaMalloc(XPTArena *arena, size_t size)
+{
+ PRUint8 *cur;
+ size_t bytes;
+
+ if (!size)
+ return NULL;
+
+ if (!arena) {
+ XPT_ASSERT(0);
+ return NULL;
+ }
+
+ bytes = ALIGN_RND(size, arena->alignment);
+
+ LOG_MALLOC(arena, size, bytes);
+
+ if (bytes > arena->space) {
+ BLK_HDR* new_block;
+ size_t block_header_size = ALIGN_RND(sizeof(BLK_HDR), arena->alignment);
+ size_t new_space = arena->block_size;
+
+ if (bytes > new_space - block_header_size)
+ new_space += bytes;
+
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ new_block = (BLK_HDR*) RTMemAllocZ(new_space/arena->alignment * (size_t)arena->alignment);
+#else
+ new_block = (BLK_HDR*) calloc(new_space/arena->alignment,
+ arena->alignment);
+#endif
+ if (!new_block) {
+ arena->next = NULL;
+ arena->space = 0;
+ return NULL;
+ }
+
+ LOG_REAL_MALLOC(arena, new_space);
+
+ /* link block into the list of blocks for use when we destroy */
+ new_block->next = arena->first;
+ arena->first = new_block;
+
+ /* save other block header info */
+ new_block->size = new_space;
+
+ /* set info for current block */
+ arena->next = ((PRUint8*)new_block) + block_header_size;
+ arena->space = new_space - block_header_size;
+
+#ifdef DEBUG
+ /* mark block for corruption check */
+ memset(arena->next, 0xcd, arena->space);
+#endif
+ }
+
+#ifdef DEBUG
+ {
+ /* do corruption check */
+ size_t i;
+ for (i = 0; i < bytes; ++i) {
+ XPT_ASSERT(arena->next[i] == 0xcd);
+ }
+ /* we guarantee that the block will be filled with zeros */
+ memset(arena->next, 0, bytes);
+ }
+#endif
+
+ cur = arena->next;
+ arena->next += bytes;
+ arena->space -= bytes;
+
+ return cur;
+}
+
+
+XPT_PUBLIC_API(char *)
+XPT_ArenaStrDup(XPTArena *arena, const char * s)
+{
+ size_t len;
+ char* cur;
+
+ if (!s)
+ return NULL;
+
+ len = strlen(s)+1;
+ cur = XPT_ArenaMalloc(arena, len);
+ memcpy(cur, s, len);
+ return cur;
+}
+
+XPT_PUBLIC_API(void)
+XPT_NotifyDoneLoading(XPTArena *arena)
+{
+#ifdef XPT_ARENA_LOGGING
+ if (arena) {
+ LOG_DONE_LOADING(arena);
+ }
+#endif
+}
+
+XPT_PUBLIC_API(void)
+XPT_ArenaFree(XPTArena *arena, void *block)
+{
+ LOG_FREE(arena);
+}
+
+#ifdef XPT_ARENA_LOGGING
+static void xpt_DebugPrintArenaStats(XPTArena *arena)
+{
+ printf("()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()\n");
+ printf("Start xpt arena stats for \"%s\"\n",
+ arena->name ? arena->name : "unnamed arena");
+ printf("\n");
+ printf("%d times arena malloc called\n", (int) arena->LOG_MallocCallCount);
+ printf("%d total bytes requested from arena malloc\n", (int) arena->LOG_MallocTotalBytesRequested);
+ printf("%d average bytes requested per call to arena malloc\n", (int)arena->LOG_MallocCallCount ? (arena->LOG_MallocTotalBytesRequested/arena->LOG_MallocCallCount) : 0);
+ printf("%d average bytes used per call (accounts for alignment overhead)\n", (int)arena->LOG_MallocCallCount ? (arena->LOG_MallocTotalBytesUsed/arena->LOG_MallocCallCount) : 0);
+ printf("%d average bytes used per call (accounts for all overhead and waste)\n", (int)arena->LOG_MallocCallCount ? (arena->LOG_RealMallocTotalBytesRequested/arena->LOG_MallocCallCount) : 0);
+ printf("\n");
+ printf("%d during loading times arena free called\n", (int) arena->LOG_LoadingFreeCallCount);
+ printf("%d during loading approx total bytes not freed\n", (int) arena->LOG_LoadingFreeCallCount * (int) (arena->LOG_MallocCallCount ? (arena->LOG_MallocTotalBytesUsed/arena->LOG_MallocCallCount) : 0));
+ printf("\n");
+ printf("%d total times arena free called\n", (int) arena->LOG_FreeCallCount);
+ printf("%d approx total bytes not freed until arena destruction\n", (int) arena->LOG_FreeCallCount * (int) (arena->LOG_MallocCallCount ? (arena->LOG_MallocTotalBytesUsed/arena->LOG_MallocCallCount) : 0 ));
+ printf("\n");
+ printf("%d times arena called system malloc\n", (int) arena->LOG_RealMallocCallCount);
+ printf("%d total bytes arena requested from system\n", (int) arena->LOG_RealMallocTotalBytesRequested);
+ printf("%d byte block size specified at arena creation time\n", (int) arena->block_size);
+ printf("%d byte block alignment specified at arena creation time\n", (int) arena->alignment);
+ printf("\n");
+ printf("End xpt arena stats\n");
+ printf("()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()\n");
+}
+#endif
+
+/***************************************************************************/
+
+#ifdef DEBUG
+XPT_PUBLIC_API(void)
+XPT_AssertFailed(const char *s, const char *file, PRUint32 lineno)
+{
+ fprintf(stderr, "Assertion failed: %s, file %s, line %d\n",
+ s, file, lineno);
+ abort();
+}
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_struct.c b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_struct.c
new file mode 100644
index 00000000..93435910
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_struct.c
@@ -0,0 +1,956 @@
+/* -*- 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 ***** */
+
+/* Implementation of XDR routines for typelib structures. */
+
+#include "xpt_xdr.h"
+#include "xpt_struct.h"
+#include <string.h>
+#include <stdio.h>
+
+/***************************************************************************/
+/* Forward declarations. */
+
+static PRUint32
+SizeOfTypeDescriptor(XPTTypeDescriptor *td, XPTInterfaceDescriptor *id);
+
+static PRUint32
+SizeOfMethodDescriptor(XPTMethodDescriptor *md, XPTInterfaceDescriptor *id);
+
+static PRUint32
+SizeOfConstDescriptor(XPTConstDescriptor *cd, XPTInterfaceDescriptor *id);
+
+static PRUint32
+SizeOfInterfaceDescriptor(XPTInterfaceDescriptor *id);
+
+static PRBool
+DoInterfaceDirectoryEntry(XPTArena *arena, XPTCursor *cursor,
+ XPTInterfaceDirectoryEntry *ide, PRUint16 entry_index);
+
+static PRBool
+DoConstDescriptor(XPTArena *arena, XPTCursor *cursor, XPTConstDescriptor *cd,
+ XPTInterfaceDescriptor *id);
+
+static PRBool
+DoMethodDescriptor(XPTArena *arena, XPTCursor *cursor, XPTMethodDescriptor *md,
+ XPTInterfaceDescriptor *id);
+
+static PRBool
+DoAnnotation(XPTArena *arena, XPTCursor *cursor, XPTAnnotation **annp);
+
+static PRBool
+DoInterfaceDescriptor(XPTArena *arena, XPTCursor *outer, XPTInterfaceDescriptor **idp);
+
+static PRBool
+DoTypeDescriptorPrefix(XPTArena *arena, XPTCursor *cursor, XPTTypeDescriptorPrefix *tdp);
+
+static PRBool
+DoTypeDescriptor(XPTArena *arena, XPTCursor *cursor, XPTTypeDescriptor *td,
+ XPTInterfaceDescriptor *id);
+
+static PRBool
+DoParamDescriptor(XPTArena *arena, XPTCursor *cursor, XPTParamDescriptor *pd,
+ XPTInterfaceDescriptor *id);
+
+/***************************************************************************/
+
+XPT_PUBLIC_API(PRUint32)
+XPT_SizeOfHeader(XPTHeader *header)
+{
+ XPTAnnotation *ann, *last;
+ PRUint32 size = 16 /* magic */ +
+ 1 /* major */ + 1 /* minor */ +
+ 2 /* num_interfaces */ + 4 /* file_length */ +
+ 4 /* interface_directory */ + 4 /* data_pool */;
+
+ ann = header->annotations;
+ do {
+ size += 1; /* Annotation prefix */
+ if (XPT_ANN_IS_PRIVATE(ann->flags))
+ size += 2 + ann->creator->length + 2 + ann->private_data->length;
+ last = ann;
+ ann = ann->next;
+ } while (!XPT_ANN_IS_LAST(last->flags));
+
+ return size;
+}
+
+XPT_PUBLIC_API(PRUint32)
+XPT_SizeOfHeaderBlock(XPTHeader *header)
+{
+ PRUint32 size = XPT_SizeOfHeader(header);
+
+ size += header->num_interfaces * sizeof (XPTInterfaceDirectoryEntry);
+
+ return size;
+}
+
+XPT_PUBLIC_API(XPTHeader *)
+XPT_NewHeader(XPTArena *arena, PRUint16 num_interfaces, PRUint8 major_version, PRUint8 minor_version)
+{
+ XPTHeader *header = XPT_NEWZAP(arena, XPTHeader);
+ if (!header)
+ return NULL;
+ memcpy(header->magic, XPT_MAGIC, 16);
+ header->major_version = major_version;
+ header->minor_version = minor_version;
+ header->num_interfaces = num_interfaces;
+ if (num_interfaces) {
+ header->interface_directory =
+ XPT_CALLOC(arena,
+ num_interfaces * sizeof(XPTInterfaceDirectoryEntry));
+ if (!header->interface_directory) {
+ XPT_DELETE(arena, header);
+ return NULL;
+ }
+ }
+ header->data_pool = 0; /* XXX do we even need this struct any more? */
+
+ return header;
+}
+
+XPT_PUBLIC_API(void)
+XPT_FreeHeader(XPTArena *arena, XPTHeader* aHeader)
+{
+ if (aHeader) {
+ XPTAnnotation* ann;
+ XPTInterfaceDirectoryEntry* entry = aHeader->interface_directory;
+ XPTInterfaceDirectoryEntry* end = entry + aHeader->num_interfaces;
+ for (; entry < end; entry++) {
+ XPT_DestroyInterfaceDirectoryEntry(arena, entry);
+ }
+
+ ann = aHeader->annotations;
+ while (ann) {
+ XPTAnnotation* next = ann->next;
+ if (XPT_ANN_IS_PRIVATE(ann->flags)) {
+ XPT_FREEIF(arena, ann->creator);
+ XPT_FREEIF(arena, ann->private_data);
+ }
+ XPT_DELETE(arena, ann);
+ ann = next;
+ }
+
+ XPT_FREEIF(arena, aHeader->interface_directory);
+ XPT_DELETE(arena, aHeader);
+ }
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_DoHeaderPrologue(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp, PRUint32 * ide_offset)
+{
+ XPTMode mode = cursor->state->mode;
+ unsigned int i;
+ XPTHeader * header;
+
+ if (mode == XPT_DECODE) {
+ header = XPT_NEWZAP(arena, XPTHeader);
+ if (!header)
+ return PR_FALSE;
+ *headerp = header;
+ } else {
+ header = *headerp;
+ }
+
+ if (mode == XPT_ENCODE) {
+ /* IDEs appear after header, including annotations */
+ if (ide_offset != NULL)
+ {
+ *ide_offset = XPT_SizeOfHeader(*headerp) + 1; /* one-based offset */
+ }
+ header->data_pool = XPT_SizeOfHeaderBlock(*headerp);
+ XPT_SetDataOffset(cursor->state, header->data_pool);
+ }
+
+ for (i = 0; i < sizeof(header->magic); i++) {
+ if (!XPT_Do8(cursor, &header->magic[i]))
+ goto error;
+ }
+
+ if (mode == XPT_DECODE &&
+ strncmp((const char*)header->magic, XPT_MAGIC, 16) != 0)
+ {
+ /* Require that the header contain the proper magic */
+ fprintf(stderr,
+ "libxpt: bad magic header in input file; "
+ "found '%s', expected '%s'\n",
+ header->magic, XPT_MAGIC_STRING);
+ goto error;
+ }
+
+ if (!XPT_Do8(cursor, &header->major_version) ||
+ !XPT_Do8(cursor, &header->minor_version)) {
+ goto error;
+ }
+
+ if (mode == XPT_DECODE &&
+ header->major_version >= XPT_MAJOR_INCOMPATIBLE_VERSION) {
+ /* This file is newer than we are and set to an incompatible version
+ * number. We must set the header state thusly and return.
+ */
+ header->num_interfaces = 0;
+ header->file_length = 0;
+ return PR_TRUE;
+ }
+
+ if (!XPT_Do16(cursor, &header->num_interfaces) ||
+ !XPT_Do32(cursor, &header->file_length) ||
+ (ide_offset != NULL && !XPT_Do32(cursor, ide_offset))) {
+ goto error;
+ }
+ return PR_TRUE;
+ /* XXX need to free child data sometimes! */
+ XPT_ERROR_HANDLE(arena, header);
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_DoHeader(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp)
+{
+ const int HEADER_SIZE = 24;
+ XPTMode mode = cursor->state->mode;
+ XPTHeader * header;
+ PRUint32 ide_offset;
+ int i;
+ XPTAnnotation *ann, *next, **annp;
+
+ if (!XPT_DoHeaderPrologue(arena, cursor, headerp, &ide_offset))
+ return PR_FALSE;
+ header = *headerp;
+ /*
+ * Make sure the file length reported in the header is the same size as
+ * as our buffer unless it is zero (not set)
+ */
+ if (mode == XPT_DECODE && (header->file_length != 0 &&
+ cursor->state->pool->allocated < header->file_length)) {
+ fputs("libxpt: File length in header does not match actual length. File may be corrupt\n",
+ stderr);
+ goto error;
+ }
+
+ if (mode == XPT_ENCODE)
+ XPT_DataOffset(cursor->state, &header->data_pool);
+ if (!XPT_Do32(cursor, &header->data_pool))
+ goto error;
+ if (mode == XPT_DECODE)
+ XPT_DataOffset(cursor->state, &header->data_pool);
+
+ if (mode == XPT_DECODE && header->num_interfaces) {
+ header->interface_directory =
+ XPT_CALLOC(arena, header->num_interfaces *
+ sizeof(XPTInterfaceDirectoryEntry));
+ if (!header->interface_directory)
+ goto error;
+ }
+
+ /*
+ * Iterate through the annotations rather than recurring, to avoid blowing
+ * the stack on large xpt files.
+ */
+ ann = next = header->annotations;
+ annp = &header->annotations;
+ do {
+ ann = next;
+ if (!DoAnnotation(arena, cursor, &ann))
+ goto error;
+ if (mode == XPT_DECODE) {
+ /*
+ * Make sure that we store the address of the newly allocated
+ * annotation in the previous annotation's ``next'' slot, or
+ * header->annotations for the first one.
+ */
+ *annp = ann;
+ annp = &ann->next;
+ }
+ next = ann->next;
+ } while (!XPT_ANN_IS_LAST(ann->flags));
+
+ /* shouldn't be necessary now, but maybe later */
+ XPT_SeekTo(cursor, ide_offset);
+
+ for (i = 0; i < header->num_interfaces; i++) {
+ if (!DoInterfaceDirectoryEntry(arena, cursor,
+ &header->interface_directory[i],
+ (PRUint16)(i + 1)))
+ goto error;
+ }
+
+ return PR_TRUE;
+
+ /* XXX need to free child data sometimes! */
+ XPT_ERROR_HANDLE(arena, header);
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_FillInterfaceDirectoryEntry(XPTArena *arena,
+ XPTInterfaceDirectoryEntry *ide,
+ nsID *iid, char *name, char *name_space,
+ XPTInterfaceDescriptor *descriptor)
+{
+ XPT_COPY_IID(ide->iid, *iid);
+ ide->name = name ? XPT_STRDUP(arena, name) : NULL; /* what good is it w/o a name? */
+ ide->name_space = name_space ? XPT_STRDUP(arena, name_space) : NULL;
+ ide->interface_descriptor = descriptor;
+ return PR_TRUE;
+}
+
+XPT_PUBLIC_API(void)
+XPT_DestroyInterfaceDirectoryEntry(XPTArena *arena,
+ XPTInterfaceDirectoryEntry* ide)
+{
+ if (ide) {
+ if (ide->name) XPT_FREE(arena, ide->name);
+ if (ide->name_space) XPT_FREE(arena, ide->name_space);
+ XPT_FreeInterfaceDescriptor(arena, ide->interface_descriptor);
+ }
+}
+
+/* InterfaceDirectoryEntry records go in the header */
+PRBool
+DoInterfaceDirectoryEntry(XPTArena *arena, XPTCursor *cursor,
+ XPTInterfaceDirectoryEntry *ide, PRUint16 entry_index)
+{
+ XPTMode mode = cursor->state->mode;
+
+ /* write the IID in our cursor space */
+ if (!XPT_DoIID(cursor, &(ide->iid)) ||
+
+ /* write the name string in the data pool, and the offset in our
+ cursor space */
+ !XPT_DoCString(arena, cursor, &(ide->name)) ||
+
+ /* write the name_space string in the data pool, and the offset in our
+ cursor space */
+ !XPT_DoCString(arena, cursor, &(ide->name_space)) ||
+
+ /* do InterfaceDescriptors -- later, only on encode (see below) */
+ !DoInterfaceDescriptor(arena, cursor, &ide->interface_descriptor)) {
+ goto error;
+ }
+
+ if (mode == XPT_DECODE)
+ XPT_SetOffsetForAddr(cursor, ide, entry_index);
+
+ return PR_TRUE;
+
+ XPT_ERROR_HANDLE(arena, ide);
+}
+
+XPT_PUBLIC_API(XPTInterfaceDescriptor *)
+XPT_NewInterfaceDescriptor(XPTArena *arena,
+ PRUint16 parent_interface, PRUint16 num_methods,
+ PRUint16 num_constants, PRUint8 flags)
+{
+
+ XPTInterfaceDescriptor *id = XPT_NEWZAP(arena, XPTInterfaceDescriptor);
+ if (!id)
+ return NULL;
+
+ if (num_methods) {
+ id->method_descriptors = XPT_CALLOC(arena, num_methods *
+ sizeof(XPTMethodDescriptor));
+ if (!id->method_descriptors)
+ goto free_id;
+ id->num_methods = num_methods;
+ }
+
+ if (num_constants) {
+ id->const_descriptors = XPT_CALLOC(arena, num_constants *
+ sizeof(XPTConstDescriptor));
+ if (!id->const_descriptors)
+ goto free_meth;
+ id->num_constants = num_constants;
+ }
+
+ if (parent_interface) {
+ id->parent_interface = parent_interface;
+ } else {
+ id->parent_interface = 0;
+ }
+
+ id->flags = flags;
+
+ return id;
+
+ free_meth:
+ XPT_FREEIF(arena, id->method_descriptors);
+ free_id:
+ XPT_DELETE(arena, id);
+ return NULL;
+}
+
+XPT_PUBLIC_API(void)
+XPT_FreeInterfaceDescriptor(XPTArena *arena, XPTInterfaceDescriptor* id)
+{
+ if (id) {
+ XPTMethodDescriptor *md, *mdend;
+ XPTConstDescriptor *cd, *cdend;
+
+ /* Free up method descriptors */
+ md = id->method_descriptors;
+ mdend = md + id->num_methods;
+ for (; md < mdend; md++) {
+ XPT_FREEIF(arena, md->name);
+ XPT_FREEIF(arena, md->params);
+ XPT_FREEIF(arena, md->result);
+ }
+ XPT_FREEIF(arena, id->method_descriptors);
+
+ /* Free up const descriptors */
+ cd = id->const_descriptors;
+ cdend = cd + id->num_constants;
+ for (; cd < cdend; cd++) {
+ XPT_FREEIF(arena, cd->name);
+ }
+ XPT_FREEIF(arena, id->const_descriptors);
+
+ /* Free up type descriptors */
+ XPT_FREEIF(arena, id->additional_types);
+
+ XPT_DELETE(arena, id);
+ }
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_InterfaceDescriptorAddTypes(XPTArena *arena, XPTInterfaceDescriptor *id,
+ PRUint16 num)
+{
+ XPTTypeDescriptor *old = id->additional_types;
+ XPTTypeDescriptor *new;
+ size_t old_size = id->num_additional_types * sizeof(XPTTypeDescriptor);
+ size_t new_size = (num * sizeof(XPTTypeDescriptor)) + old_size;
+
+ /* XXX should grow in chunks to minimize alloc overhead */
+ new = XPT_CALLOC(arena, new_size);
+ if (!new)
+ return PR_FALSE;
+ if (old) {
+ if (old_size)
+ memcpy(new, old, old_size);
+ XPT_FREE(arena, old);
+ }
+ id->additional_types = new;
+ id->num_additional_types += num;
+ return PR_TRUE;
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_InterfaceDescriptorAddMethods(XPTArena *arena, XPTInterfaceDescriptor *id,
+ PRUint16 num)
+{
+ XPTMethodDescriptor *old = id->method_descriptors;
+ XPTMethodDescriptor *new;
+ size_t old_size = id->num_methods * sizeof(XPTMethodDescriptor);
+ size_t new_size = (num * sizeof(XPTMethodDescriptor)) + old_size;
+
+ /* XXX should grow in chunks to minimize alloc overhead */
+ new = XPT_CALLOC(arena, new_size);
+ if (!new)
+ return PR_FALSE;
+ if (old) {
+ if (old_size)
+ memcpy(new, old, old_size);
+ XPT_FREE(arena, old);
+ }
+ id->method_descriptors = new;
+ id->num_methods += num;
+ return PR_TRUE;
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_InterfaceDescriptorAddConsts(XPTArena *arena, XPTInterfaceDescriptor *id,
+ PRUint16 num)
+{
+ XPTConstDescriptor *old = id->const_descriptors;
+ XPTConstDescriptor *new;
+ size_t old_size = id->num_constants * sizeof(XPTConstDescriptor);
+ size_t new_size = (num * sizeof(XPTConstDescriptor)) + old_size;
+
+ /* XXX should grow in chunks to minimize alloc overhead */
+ new = XPT_CALLOC(arena, new_size);
+ if (!new)
+ return PR_FALSE;
+ if (old) {
+ if (old_size)
+ memcpy(new, old, old_size);
+ XPT_FREE(arena, old);
+ }
+ id->const_descriptors = new;
+ id->num_constants += num;
+ return PR_TRUE;
+}
+
+PRUint32
+SizeOfTypeDescriptor(XPTTypeDescriptor *td, XPTInterfaceDescriptor *id)
+{
+ PRUint32 size = 1; /* prefix */
+
+ switch (XPT_TDP_TAG(td->prefix)) {
+ case TD_INTERFACE_TYPE:
+ size += 2; /* interface_index */
+ break;
+ case TD_INTERFACE_IS_TYPE:
+ size += 1; /* argnum */
+ break;
+ case TD_ARRAY:
+ size += 2 + SizeOfTypeDescriptor(
+ &id->additional_types[td->type.additional_type], id);
+ break;
+ case TD_PSTRING_SIZE_IS:
+ size += 2; /* argnum + argnum2 */
+ break;
+ case TD_PWSTRING_SIZE_IS:
+ size += 2; /* argnum + argnum2 */
+ break;
+ default:
+ /* nothing special */
+ break;
+ }
+ return size;
+}
+
+PRUint32
+SizeOfMethodDescriptor(XPTMethodDescriptor *md, XPTInterfaceDescriptor *id)
+{
+ PRUint32 i, size = 1 /* flags */ + 4 /* name */ + 1 /* num_args */;
+
+ for (i = 0; i < md->num_args; i++)
+ size += 1 + SizeOfTypeDescriptor(&md->params[i].type, id);
+
+ size += 1 + SizeOfTypeDescriptor(&md->result->type, id);
+ return size;
+}
+
+PRUint32
+SizeOfConstDescriptor(XPTConstDescriptor *cd, XPTInterfaceDescriptor *id)
+{
+ PRUint32 size = 4 /* name */ + SizeOfTypeDescriptor(&cd->type, id);
+
+ switch (XPT_TDP_TAG(cd->type.prefix)) {
+ case TD_INT8:
+ case TD_UINT8:
+ case TD_CHAR:
+ size ++;
+ break;
+ case TD_INT16:
+ case TD_UINT16:
+ case TD_WCHAR:
+ size += 2;
+ break;
+ case TD_INT32:
+ case TD_UINT32:
+ case TD_PSTRING:
+ size += 4;
+ break;
+ case TD_INT64:
+ case TD_UINT64:
+ size += 8;
+ break;
+ default:
+ fprintf(stderr, "libxpt: illegal type in ConstDescriptor: 0x%02x\n",
+ XPT_TDP_TAG(cd->type.prefix));
+ return 0;
+ }
+
+ return size;
+}
+
+PRUint32
+SizeOfInterfaceDescriptor(XPTInterfaceDescriptor *id)
+{
+ PRUint32 size = 2 /* parent interface */ + 2 /* num_methods */
+ + 2 /* num_constants */ + 1 /* flags */, i;
+ for (i = 0; i < id->num_methods; i++)
+ size += SizeOfMethodDescriptor(&id->method_descriptors[i], id);
+ for (i = 0; i < id->num_constants; i++)
+ size += SizeOfConstDescriptor(&id->const_descriptors[i], id);
+ return size;
+}
+
+PRBool
+DoInterfaceDescriptor(XPTArena *arena, XPTCursor *outer,
+ XPTInterfaceDescriptor **idp)
+{
+ XPTMode mode = outer->state->mode;
+ XPTInterfaceDescriptor *id;
+ XPTCursor curs, *cursor = &curs;
+ PRUint32 i, id_sz = 0;
+
+ if (mode == XPT_DECODE) {
+ id = XPT_NEWZAP(arena, XPTInterfaceDescriptor);
+ if (!id)
+ return PR_FALSE;
+ *idp = id;
+ } else {
+ id = *idp;
+ if (!id) {
+ id_sz = 0;
+ return XPT_Do32(outer, &id_sz);
+ }
+ id_sz = SizeOfInterfaceDescriptor(id);
+ }
+
+ if (!XPT_MakeCursor(outer->state, XPT_DATA, id_sz, cursor))
+ goto error;
+
+ if (!XPT_Do32(outer, &cursor->offset))
+ goto error;
+ if (mode == XPT_DECODE && !cursor->offset) {
+ XPT_DELETE(arena, *idp);
+ return PR_TRUE;
+ }
+ if(!XPT_Do16(cursor, &id->parent_interface) ||
+ !XPT_Do16(cursor, &id->num_methods)) {
+ goto error;
+ }
+
+ if (mode == XPT_DECODE && id->num_methods) {
+ id->method_descriptors = XPT_CALLOC(arena, id->num_methods *
+ sizeof(XPTMethodDescriptor));
+ if (!id->method_descriptors)
+ goto error;
+ }
+
+ for (i = 0; i < id->num_methods; i++) {
+ if (!DoMethodDescriptor(arena, cursor, &id->method_descriptors[i], id))
+ goto error;
+ }
+
+ if (!XPT_Do16(cursor, &id->num_constants)) {
+ goto error;
+ }
+
+ if (mode == XPT_DECODE && id->num_constants) {
+ id->const_descriptors = XPT_CALLOC(arena, id->num_constants *
+ sizeof(XPTConstDescriptor));
+ if (!id->const_descriptors)
+ goto error;
+ }
+
+ for (i = 0; i < id->num_constants; i++) {
+ if (!DoConstDescriptor(arena, cursor, &id->const_descriptors[i], id)) {
+ goto error;
+ }
+ }
+
+ if (!XPT_Do8(cursor, &id->flags)) {
+ goto error;
+ }
+
+ return PR_TRUE;
+
+ XPT_ERROR_HANDLE(arena, id);
+}
+
+PRBool
+DoConstDescriptor(XPTArena *arena, XPTCursor *cursor, XPTConstDescriptor *cd,
+ XPTInterfaceDescriptor *id)
+{
+ PRBool ok = PR_FALSE;
+
+ if (!XPT_DoCString(arena, cursor, &cd->name) ||
+ !DoTypeDescriptor(arena, cursor, &cd->type, id)) {
+
+ return PR_FALSE;
+ }
+
+ switch(XPT_TDP_TAG(cd->type.prefix)) {
+ case TD_INT8:
+ ok = XPT_Do8(cursor, (PRUint8*) &cd->value.i8);
+ break;
+ case TD_INT16:
+ ok = XPT_Do16(cursor, (PRUint16*) &cd->value.i16);
+ break;
+ case TD_INT32:
+ ok = XPT_Do32(cursor, (PRUint32*) &cd->value.i32);
+ break;
+ case TD_INT64:
+ ok = XPT_Do64(cursor, &cd->value.i64);
+ break;
+ case TD_UINT8:
+ ok = XPT_Do8(cursor, &cd->value.ui8);
+ break;
+ case TD_UINT16:
+ ok = XPT_Do16(cursor, &cd->value.ui16);
+ break;
+ case TD_UINT32:
+ ok = XPT_Do32(cursor, &cd->value.ui32);
+ break;
+ case TD_UINT64:
+ ok = XPT_Do64(cursor, (PRInt64 *)&cd->value.ui64);
+ break;
+ case TD_CHAR:
+ ok = XPT_Do8(cursor, (PRUint8*) &cd->value.ch);
+ break;
+ case TD_WCHAR:
+ ok = XPT_Do16(cursor, &cd->value.wch);
+ break;
+ /* fall-through */
+ default:
+ fprintf(stderr, "illegal type!\n");
+ break;
+ }
+
+ return ok;
+
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_FillMethodDescriptor(XPTArena *arena, XPTMethodDescriptor *meth,
+ PRUint8 flags, char *name, PRUint8 num_args)
+{
+ meth->flags = flags & XPT_MD_FLAGMASK;
+ meth->name = XPT_STRDUP(arena, name);
+ if (!meth->name)
+ return PR_FALSE;
+ meth->num_args = num_args;
+ if (num_args) {
+ meth->params = XPT_CALLOC(arena, num_args * sizeof(XPTParamDescriptor));
+ if (!meth->params)
+ goto free_name;
+ } else {
+ meth->params = NULL;
+ }
+ meth->result = XPT_NEWZAP(arena, XPTParamDescriptor);
+ if (!meth->result)
+ goto free_params;
+ return PR_TRUE;
+
+ free_params:
+ XPT_DELETE(arena, meth->params);
+ free_name:
+ XPT_DELETE(arena, meth->name);
+ return PR_FALSE;
+}
+
+PRBool
+DoMethodDescriptor(XPTArena *arena, XPTCursor *cursor, XPTMethodDescriptor *md,
+ XPTInterfaceDescriptor *id)
+{
+ XPTMode mode = cursor->state->mode;
+ int i;
+
+ if (!XPT_Do8(cursor, &md->flags) ||
+ !XPT_DoCString(arena, cursor, &md->name) ||
+ !XPT_Do8(cursor, &md->num_args))
+ return PR_FALSE;
+
+ if (mode == XPT_DECODE && md->num_args) {
+ md->params = XPT_CALLOC(arena, md->num_args * sizeof(XPTParamDescriptor));
+ if (!md->params)
+ return PR_FALSE;
+ }
+
+ for(i = 0; i < md->num_args; i++) {
+ if (!DoParamDescriptor(arena, cursor, &md->params[i], id))
+ goto error;
+ }
+
+ if (mode == XPT_DECODE) {
+ md->result = XPT_NEWZAP(arena, XPTParamDescriptor);
+ if (!md->result)
+ return PR_FALSE;
+ }
+
+ if (!md->result ||
+ !DoParamDescriptor(arena, cursor, md->result, id))
+ goto error;
+
+ return PR_TRUE;
+
+ XPT_ERROR_HANDLE(arena, md->params);
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_FillParamDescriptor(XPTArena *arena, XPTParamDescriptor *pd, PRUint8 flags,
+ XPTTypeDescriptor *type)
+{
+ pd->flags = flags & XPT_PD_FLAGMASK;
+ XPT_COPY_TYPE(pd->type, *type);
+ return PR_TRUE;
+}
+
+PRBool
+DoParamDescriptor(XPTArena *arena, XPTCursor *cursor, XPTParamDescriptor *pd,
+ XPTInterfaceDescriptor *id)
+{
+ if (!XPT_Do8(cursor, &pd->flags) ||
+ !DoTypeDescriptor(arena, cursor, &pd->type, id))
+ return PR_FALSE;
+
+ return PR_TRUE;
+}
+
+PRBool
+DoTypeDescriptorPrefix(XPTArena *arena, XPTCursor *cursor, XPTTypeDescriptorPrefix *tdp)
+{
+ return XPT_Do8(cursor, &tdp->flags);
+}
+
+PRBool
+DoTypeDescriptor(XPTArena *arena, XPTCursor *cursor, XPTTypeDescriptor *td,
+ XPTInterfaceDescriptor *id)
+{
+ if (!DoTypeDescriptorPrefix(arena, cursor, &td->prefix)) {
+ goto error;
+ }
+
+ switch (XPT_TDP_TAG(td->prefix)) {
+ case TD_INTERFACE_TYPE:
+ if (!XPT_Do16(cursor, &td->type.iface))
+ goto error;
+ break;
+ case TD_INTERFACE_IS_TYPE:
+ if (!XPT_Do8(cursor, &td->argnum))
+ goto error;
+ break;
+ case TD_ARRAY:
+ if (!XPT_Do8(cursor, &td->argnum) ||
+ !XPT_Do8(cursor, &td->argnum2))
+ goto error;
+
+ if (cursor->state->mode == XPT_DECODE) {
+ if(!XPT_InterfaceDescriptorAddTypes(arena, id, 1))
+ goto error;
+ td->type.additional_type = id->num_additional_types - 1;
+ }
+
+ if (!DoTypeDescriptor(arena, cursor,
+ &id->additional_types[td->type.additional_type],
+ id))
+ goto error;
+ break;
+ case TD_PSTRING_SIZE_IS:
+ case TD_PWSTRING_SIZE_IS:
+ if (!XPT_Do8(cursor, &td->argnum) ||
+ !XPT_Do8(cursor, &td->argnum2))
+ goto error;
+ break;
+
+ default:
+ /* nothing special */
+ break;
+ }
+ return PR_TRUE;
+
+ XPT_ERROR_HANDLE(arena, td);
+}
+
+XPT_PUBLIC_API(XPTAnnotation *)
+XPT_NewAnnotation(XPTArena *arena, PRUint8 flags, XPTString *creator,
+ XPTString *private_data)
+{
+ XPTAnnotation *ann = XPT_NEWZAP(arena, XPTAnnotation);
+ if (!ann)
+ return NULL;
+ ann->flags = flags;
+ if (XPT_ANN_IS_PRIVATE(flags)) {
+ ann->creator = creator;
+ ann->private_data = private_data;
+ }
+ return ann;
+}
+
+PRBool
+DoAnnotation(XPTArena *arena, XPTCursor *cursor, XPTAnnotation **annp)
+{
+ XPTMode mode = cursor->state->mode;
+ XPTAnnotation *ann;
+
+ if (mode == XPT_DECODE) {
+ ann = XPT_NEWZAP(arena, XPTAnnotation);
+ if (!ann)
+ return PR_FALSE;
+ *annp = ann;
+ } else {
+ ann = *annp;
+ }
+
+ if (!XPT_Do8(cursor, &ann->flags))
+ goto error;
+
+ if (XPT_ANN_IS_PRIVATE(ann->flags)) {
+ if (!XPT_DoStringInline(arena, cursor, &ann->creator) ||
+ !XPT_DoStringInline(arena, cursor, &ann->private_data))
+ goto error_2;
+ }
+
+ return PR_TRUE;
+
+ error_2:
+ if (ann && XPT_ANN_IS_PRIVATE(ann->flags)) {
+ XPT_FREEIF(arena, ann->creator);
+ XPT_FREEIF(arena, ann->private_data);
+ }
+ XPT_ERROR_HANDLE(arena, ann);
+}
+
+PRBool
+XPT_GetInterfaceIndexByName(XPTInterfaceDirectoryEntry *ide_block,
+ PRUint16 num_interfaces, char *name,
+ PRUint16 *indexp)
+{
+ int i;
+
+ for (i=1; i<=num_interfaces; i++) {
+ fprintf(stderr, "%s == %s ?\n", ide_block[i].name, name);
+ if (strcmp(ide_block[i].name, name) == 0) {
+ *indexp = i;
+ return PR_TRUE;
+ }
+ }
+ *indexp = 0;
+ return PR_FALSE;
+}
+
+static XPT_TYPELIB_VERSIONS_STRUCT versions[] = XPT_TYPELIB_VERSIONS;
+#define XPT_TYPELIB_VERSIONS_COUNT (sizeof(versions) / sizeof(versions[0]))
+
+XPT_PUBLIC_API(PRUint16)
+XPT_ParseVersionString(const char* str, PRUint8* major, PRUint8* minor)
+{
+ int i;
+ for (i = 0; i < XPT_TYPELIB_VERSIONS_COUNT; i++) {
+ if (!strcmp(versions[i].str, str)) {
+ *major = versions[i].major;
+ *minor = versions[i].minor;
+ return versions[i].code;
+ }
+ }
+ return XPT_VERSION_UNKNOWN;
+}
+
+
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_xdr.c b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_xdr.c
new file mode 100644
index 00000000..cd9261d0
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/src/xpt_xdr.c
@@ -0,0 +1,665 @@
+/* -*- 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 ***** */
+
+/* Implementation of XDR primitives. */
+
+#include "xpt_xdr.h"
+#include "nspr.h"
+#include <string.h> /* strchr */
+
+static PRBool
+CheckForRepeat(XPTCursor *cursor, void **addrp, XPTPool pool, PRUint32 len,
+ XPTCursor *new_cursor, PRBool *already);
+
+#define ENCODING(cursor) \
+ ((cursor)->state->mode == XPT_ENCODE)
+
+#define CURS_POOL_OFFSET_RAW(cursor) \
+ ((cursor)->pool == XPT_HEADER \
+ ? (cursor)->offset \
+ : (XPT_ASSERT((cursor)->state->data_offset), \
+ (cursor)->offset + (cursor)->state->data_offset))
+
+#define CURS_POOL_OFFSET(cursor) \
+ (CURS_POOL_OFFSET_RAW(cursor) - 1)
+
+/* can be used as lvalue */
+#define CURS_POINT(cursor) \
+ ((cursor)->state->pool->data[CURS_POOL_OFFSET(cursor)])
+
+#if defined(DEBUG_shaver) || defined(DEBUG_jband) || defined(DEBUG_mccabe)
+#define DBG(x) printf##x
+#else
+#define DBG(x) (0)
+#endif
+
+/* XXX fail if XPT_DATA and !state->data_offset */
+#define CHECK_COUNT_(cursor, space) \
+ /* if we're in the header, then exceeding the data_offset is illegal */ \
+((cursor)->pool == XPT_HEADER ? \
+ (ENCODING(cursor) && \
+ ((cursor)->state->data_offset && \
+ ((cursor)->offset - 1 + (space) > (cursor)->state->data_offset)) \
+ ? (DBG(("no space left in HEADER %d + %d > %d\n", (cursor)->offset, \
+ (space), (cursor)->state->data_offset)) && PR_FALSE) \
+ : PR_TRUE) : \
+ /* if we're in the data area and we're about to exceed the allocation */ \
+ (CURS_POOL_OFFSET(cursor) + (space) > (cursor)->state->pool->allocated ? \
+ /* then grow if we're in ENCODE mode */ \
+ (ENCODING(cursor) ? GrowPool((cursor)->state->arena, \
+ (cursor)->state->pool, \
+ (cursor)->state->pool->allocated, \
+ 0, CURS_POOL_OFFSET(cursor) + (space)) \
+ /* and fail if we're in DECODE mode */ \
+ : (DBG(("can't extend in DECODE")) && PR_FALSE)) \
+ /* otherwise we're OK */ \
+ : PR_TRUE))
+
+#define CHECK_COUNT(cursor, space) \
+ (CHECK_COUNT_(cursor, space) \
+ ? PR_TRUE \
+ : (XPT_ASSERT(0), \
+ fprintf(stderr, "FATAL: can't no room for %d in cursor\n", space), \
+ PR_FALSE))
+
+/* increase the data allocation for the pool by XPT_GROW_CHUNK */
+#define XPT_GROW_CHUNK 8192
+
+/*
+ * quick and dirty hardcoded hashtable, to avoid dependence on nspr or glib.
+ * XXXmccabe it might turn out that we could use a simpler data structure here.
+ */
+typedef struct XPTHashRecord {
+ void *key;
+ void *value;
+ struct XPTHashRecord *next;
+} XPTHashRecord;
+
+#define XPT_HASHSIZE 512
+
+struct XPTHashTable { /* it's already typedef'ed from before. */
+ XPTHashRecord *buckets[XPT_HASHSIZE];
+ XPTArena *arena;
+};
+
+static XPTHashTable *
+XPT_NewHashTable(XPTArena *arena) {
+ XPTHashTable *table;
+ table = XPT_NEWZAP(arena, XPTHashTable);
+ if (table)
+ table->arena = arena;
+ return table;
+}
+
+static void trimrecord(XPTArena* arena, XPTHashRecord *record) {
+ if (record == NULL)
+ return;
+ trimrecord(arena, record->next);
+ XPT_DELETE(arena, record);
+}
+
+static void
+XPT_HashTableDestroy(XPTHashTable *table) {
+ int i;
+ for (i = 0; i < XPT_HASHSIZE; i++)
+ trimrecord(table->arena, table->buckets[i]);
+ XPT_FREE(table->arena, table);
+}
+
+static void *
+XPT_HashTableAdd(XPTHashTable *table, void *key, void *value) {
+ XPTHashRecord **bucketloc = table->buckets +
+ (((PRUint32)(uintptr_t)key) % XPT_HASHSIZE);
+ XPTHashRecord *bucket;
+
+ while (*bucketloc != NULL)
+ bucketloc = &((*bucketloc)->next);
+
+ bucket = XPT_NEW(table->arena, XPTHashRecord);
+ bucket->key = key;
+ bucket->value = value;
+ bucket->next = NULL;
+ *bucketloc = bucket;
+ return value;
+}
+
+static void *
+XPT_HashTableLookup(XPTHashTable *table, void *key) {
+ XPTHashRecord *bucket = table->buckets[(PRUint32)(uintptr_t)key % XPT_HASHSIZE];
+ while (bucket != NULL) {
+ if (bucket->key == key)
+ return bucket->value;
+ bucket = bucket->next;
+ }
+ return NULL;
+}
+
+XPT_PUBLIC_API(XPTState *)
+XPT_NewXDRState(XPTMode mode, char *data, PRUint32 len)
+{
+ XPTState *state;
+ XPTArena *arena;
+
+ arena = XPT_NewArena(512, sizeof(double), "an XDRState");
+ if (!arena)
+ return NULL;
+
+ state = XPT_NEWZAP(arena, XPTState);
+ if (!state)
+ goto err_free_arena;
+
+ state->arena = arena;
+ state->mode = mode;
+ state->pool = XPT_NEW(arena, XPTDatapool);
+ state->next_cursor[0] = state->next_cursor[1] = 1;
+ if (!state->pool)
+ goto err_free_state;
+
+ state->pool->count = 0;
+ state->pool->offset_map = XPT_NewHashTable(arena);
+
+ if (!state->pool->offset_map)
+ goto err_free_pool;
+ if (mode == XPT_DECODE) {
+ state->pool->data = data;
+ state->pool->allocated = len;
+ } else {
+ state->pool->data = XPT_MALLOC(arena, XPT_GROW_CHUNK);
+ if (!state->pool->data)
+ goto err_free_hash;
+ state->pool->allocated = XPT_GROW_CHUNK;
+ }
+
+ return state;
+
+ err_free_hash:
+ XPT_HashTableDestroy(state->pool->offset_map);
+ err_free_pool:
+ XPT_DELETE(arena, state->pool);
+ err_free_state:
+ XPT_DELETE(arena, state);
+ err_free_arena:
+ if (arena)
+ XPT_DestroyArena(arena);
+ return NULL;
+}
+
+XPT_PUBLIC_API(void)
+XPT_DestroyXDRState(XPTState *state)
+{
+ XPTArena *arena = state->arena;
+
+ if (state->pool->offset_map)
+ XPT_HashTableDestroy(state->pool->offset_map);
+ if (state->mode == XPT_ENCODE)
+ XPT_DELETE(arena, state->pool->data);
+ XPT_DELETE(arena, state->pool);
+ XPT_DELETE(arena, state);
+ if (arena)
+ XPT_DestroyArena(arena);
+}
+
+XPT_PUBLIC_API(void)
+XPT_GetXDRDataLength(XPTState *state, XPTPool pool, PRUint32 *len)
+{
+ *len = state->next_cursor[pool] - 1;
+}
+
+XPT_PUBLIC_API(void)
+XPT_GetXDRData(XPTState *state, XPTPool pool, char **data, PRUint32 *len)
+{
+ if (pool == XPT_HEADER) {
+ *data = state->pool->data;
+ } else {
+ *data = state->pool->data + state->data_offset;
+ }
+ *len = state->next_cursor[pool] - 1;
+}
+
+/* All offsets are 1-based */
+XPT_PUBLIC_API(void)
+XPT_DataOffset(XPTState *state, PRUint32 *data_offsetp)
+{
+ if (state->mode == XPT_DECODE)
+ XPT_SetDataOffset(state, *data_offsetp);
+ else
+ *data_offsetp = state->data_offset;
+}
+
+/* if 'exact' is set use that, else grow by the next chunk but
+ * be sure to grow no less that 'at_least' so that we can't get
+ * behind on required space.
+ */
+static PRBool
+GrowPool(XPTArena *arena, XPTDatapool *pool, PRUint32 old_size,
+ PRUint32 exact, PRUint32 at_least)
+{
+ PRUint32 total_size;
+ char *newdata;
+
+ if (exact) {
+ XPT_ASSERT(exact > pool->allocated);
+ total_size = exact;
+ } else {
+ total_size = pool->allocated + XPT_GROW_CHUNK;
+ if (at_least > total_size)
+ total_size = at_least;
+ }
+
+ newdata = XPT_MALLOC(arena, total_size);
+ if (!newdata)
+ return PR_FALSE;
+ if (pool->data) {
+ if (old_size)
+ memcpy(newdata, pool->data, old_size);
+ XPT_FREE(arena, pool->data);
+ }
+ pool->data = newdata;
+ pool->allocated = total_size;
+ return PR_TRUE;
+}
+
+XPT_PUBLIC_API(void)
+XPT_SetDataOffset(XPTState *state, PRUint32 data_offset)
+{
+ state->data_offset = data_offset;
+ /* make sure we've allocated enough space for the header */
+ if (state->mode == XPT_ENCODE &&
+ data_offset > state->pool->allocated) {
+ (void)GrowPool(state->arena, state->pool, state->pool->allocated,
+ data_offset, 0);
+ }
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_MakeCursor(XPTState *state, XPTPool pool, PRUint32 len, XPTCursor *cursor)
+{
+ cursor->state = state;
+ cursor->pool = pool;
+ cursor->bits = 0;
+ cursor->offset = state->next_cursor[pool];
+
+ if (!(CHECK_COUNT(cursor, len)))
+ return PR_FALSE;
+
+ /* this check should be in CHECK_CURSOR */
+ if (pool == XPT_DATA && !state->data_offset) {
+ fprintf(stderr, "no data offset for XPT_DATA cursor!\n");
+ return PR_FALSE;
+ }
+
+ state->next_cursor[pool] += len;
+
+ return PR_TRUE;
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_SeekTo(XPTCursor *cursor, PRUint32 offset)
+{
+ /* XXX do some real checking and update len and stuff */
+ cursor->offset = offset;
+ return PR_TRUE;
+}
+
+XPT_PUBLIC_API(XPTString *)
+XPT_NewString(XPTArena *arena, PRUint16 length, char *bytes)
+{
+ XPTString *str = XPT_NEW(arena, XPTString);
+ if (!str)
+ return NULL;
+ str->length = length;
+ /* Alloc one extra to store the trailing nul. */
+ str->bytes = XPT_MALLOC(arena, length + 1u);
+ if (!str->bytes) {
+ XPT_DELETE(arena, str);
+ return NULL;
+ }
+ memcpy(str->bytes, bytes, length);
+ /* nul-terminate it. */
+ str->bytes[length] = '\0';
+ return str;
+}
+
+XPT_PUBLIC_API(XPTString *)
+XPT_NewStringZ(XPTArena *arena, char *bytes)
+{
+ PRUint32 length = strlen(bytes);
+ if (length > 0xffff)
+ return NULL; /* too long */
+ return XPT_NewString(arena, (PRUint16)length, bytes);
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_DoStringInline(XPTArena *arena, XPTCursor *cursor, XPTString **strp)
+{
+ XPTString *str = *strp;
+ XPTMode mode = cursor->state->mode;
+ int i;
+
+ if (mode == XPT_DECODE) {
+ str = XPT_NEWZAP(arena, XPTString);
+ if (!str)
+ return PR_FALSE;
+ *strp = str;
+ }
+
+ if (!XPT_Do16(cursor, &str->length))
+ goto error;
+
+ if (mode == XPT_DECODE)
+ if (!(str->bytes = XPT_MALLOC(arena, str->length + 1u)))
+ goto error;
+
+ for (i = 0; i < str->length; i++)
+ if (!XPT_Do8(cursor, (PRUint8 *)&str->bytes[i]))
+ goto error_2;
+
+ if (mode == XPT_DECODE)
+ str->bytes[str->length] = 0;
+
+ return PR_TRUE;
+ error_2:
+ XPT_DELETE(arena, str->bytes);
+ error:
+ XPT_DELETE(arena, str);
+ return PR_FALSE;
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_DoString(XPTArena *arena, XPTCursor *cursor, XPTString **strp)
+{
+ XPTCursor my_cursor;
+ XPTString *str = *strp;
+ PRBool already;
+
+ XPT_PREAMBLE_NO_ALLOC(cursor, strp, XPT_DATA, str->length + 2, my_cursor,
+ already)
+
+ return XPT_DoStringInline(arena, &my_cursor, strp);
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_DoCString(XPTArena *arena, XPTCursor *cursor, char **identp)
+{
+ XPTCursor my_cursor;
+ char *ident = *identp;
+ PRUint32 offset = 0;
+
+ XPTMode mode = cursor->state->mode;
+
+ if (mode == XPT_DECODE) {
+ char *start, *end;
+ int len;
+
+ if (!XPT_Do32(cursor, &offset))
+ return PR_FALSE;
+
+ if (!offset) {
+ *identp = NULL;
+ return PR_TRUE;
+ }
+
+ my_cursor.pool = XPT_DATA;
+ my_cursor.offset = offset;
+ my_cursor.state = cursor->state;
+ start = &CURS_POINT(&my_cursor);
+
+ end = strchr(start, 0); /* find the end of the string */
+ if (!end) {
+ fprintf(stderr, "didn't find end of string on decode!\n");
+ return PR_FALSE;
+ }
+ len = end - start;
+ XPT_ASSERT(len > 0);
+
+ ident = XPT_MALLOC(arena, len + 1u);
+ if (!ident)
+ return PR_FALSE;
+
+ memcpy(ident, start, (size_t)len);
+ ident[len] = 0;
+ *identp = ident;
+
+ } else {
+
+ if (!ident) {
+ offset = 0;
+ if (!XPT_Do32(cursor, &offset))
+ return PR_FALSE;
+ return PR_TRUE;
+ }
+
+ if (!XPT_MakeCursor(cursor->state, XPT_DATA, strlen(ident) + 1,
+ &my_cursor) ||
+ !XPT_Do32(cursor, &my_cursor.offset))
+ return PR_FALSE;
+
+ while(*ident)
+ if (!XPT_Do8(&my_cursor, (PRUint8 *)ident++))
+ return PR_FALSE;
+ if (!XPT_Do8(&my_cursor, (PRUint8 *)ident)) /* write trailing zero */
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+}
+
+/* XXXjband it bothers me that this is one hashtable instead of two.
+ */
+XPT_PUBLIC_API(PRUint32)
+XPT_GetOffsetForAddr(XPTCursor *cursor, void *addr)
+{
+ return (PRUint32)(uintptr_t)XPT_HashTableLookup(cursor->state->pool->offset_map, addr);
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_SetOffsetForAddr(XPTCursor *cursor, void *addr, PRUint32 offset)
+{
+ return XPT_HashTableAdd(cursor->state->pool->offset_map,
+ addr, (void *)(uintptr_t)offset) != NULL;
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_SetAddrForOffset(XPTCursor *cursor, PRUint32 offset, void *addr)
+{
+ return XPT_HashTableAdd(cursor->state->pool->offset_map,
+ (void *)(uintptr_t)offset, addr) != NULL;
+}
+
+XPT_PUBLIC_API(void *)
+XPT_GetAddrForOffset(XPTCursor *cursor, PRUint32 offset)
+{
+ return XPT_HashTableLookup(cursor->state->pool->offset_map, (void *)(uintptr_t)offset);
+}
+
+/* Used by XPT_PREAMBLE_NO_ALLOC. */
+static PRBool
+CheckForRepeat(XPTCursor *cursor, void **addrp, XPTPool pool, PRUint32 len,
+ XPTCursor *new_cursor, PRBool *already)
+{
+ void *last = *addrp;
+
+ *already = PR_FALSE;
+ new_cursor->state = cursor->state;
+ new_cursor->pool = pool;
+ new_cursor->bits = 0;
+
+ if (cursor->state->mode == XPT_DECODE) {
+
+ last = XPT_GetAddrForOffset(new_cursor, new_cursor->offset);
+
+ if (last) {
+ *already = PR_TRUE;
+ *addrp = last;
+ }
+
+ } else {
+
+ new_cursor->offset = XPT_GetOffsetForAddr(new_cursor, last);
+ if (new_cursor->offset) {
+ *already = PR_TRUE;
+ return PR_TRUE;
+ }
+
+ /* haven't already found it, so allocate room for it. */
+ if (!XPT_MakeCursor(cursor->state, pool, len, new_cursor) ||
+ !XPT_SetOffsetForAddr(new_cursor, *addrp, new_cursor->offset))
+ return PR_FALSE;
+ }
+ return PR_TRUE;
+}
+
+/*
+ * IIDs are written in struct order, in the usual big-endian way. From the
+ * typelib file spec:
+ *
+ * "For example, this IID:
+ * {00112233-4455-6677-8899-aabbccddeeff}
+ * is converted to the 128-bit value
+ * 0x00112233445566778899aabbccddeeff
+ * Note that the byte storage order corresponds to the layout of the nsIID
+ * C-struct on a big-endian architecture."
+ *
+ * (http://www.mozilla.org/scriptable/typelib_file.html#iid)
+ */
+XPT_PUBLIC_API(PRBool)
+XPT_DoIID(XPTCursor *cursor, nsID *iidp)
+{
+ int i;
+
+ if (!XPT_Do32(cursor, &iidp->m0) ||
+ !XPT_Do16(cursor, &iidp->m1) ||
+ !XPT_Do16(cursor, &iidp->m2))
+ return PR_FALSE;
+
+ for (i = 0; i < 8; i++)
+ if (!XPT_Do8(cursor, (PRUint8 *)&iidp->m3[i]))
+ return PR_FALSE;
+
+ return PR_TRUE;
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_Do64(XPTCursor *cursor, PRInt64 *u64p)
+{
+ return XPT_Do32(cursor, (PRUint32 *)u64p) &&
+ XPT_Do32(cursor, ((PRUint32 *)u64p) + 1);
+}
+
+/*
+ * When we're writing 32- or 16-bit quantities, we write a byte at a time to
+ * avoid alignment issues. Someone could come and optimize this to detect
+ * well-aligned cases and do a single store, if they cared. I might care
+ * later.
+ */
+XPT_PUBLIC_API(PRBool)
+XPT_Do32(XPTCursor *cursor, PRUint32 *u32p)
+{
+ union {
+ PRUint8 b8[4];
+ PRUint32 b32;
+ } u;
+
+ if (!CHECK_COUNT(cursor, 4))
+ return PR_FALSE;
+
+ if (ENCODING(cursor)) {
+ u.b32 = XPT_SWAB32(*u32p);
+ CURS_POINT(cursor) = u.b8[0];
+ cursor->offset++;
+ CURS_POINT(cursor) = u.b8[1];
+ cursor->offset++;
+ CURS_POINT(cursor) = u.b8[2];
+ cursor->offset++;
+ CURS_POINT(cursor) = u.b8[3];
+ } else {
+ u.b8[0] = CURS_POINT(cursor);
+ cursor->offset++;
+ u.b8[1] = CURS_POINT(cursor);
+ cursor->offset++;
+ u.b8[2] = CURS_POINT(cursor);
+ cursor->offset++;
+ u.b8[3] = CURS_POINT(cursor);
+ *u32p = XPT_SWAB32(u.b32);
+ }
+ cursor->offset++;
+ return PR_TRUE;
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_Do16(XPTCursor *cursor, PRUint16 *u16p)
+{
+ union {
+ PRUint8 b8[2];
+ PRUint16 b16;
+ } u;
+
+ if (!CHECK_COUNT(cursor, 2))
+ return PR_FALSE;
+
+ if (ENCODING(cursor)) {
+ u.b16 = XPT_SWAB16(*u16p);
+ CURS_POINT(cursor) = u.b8[0];
+ cursor->offset++;
+ CURS_POINT(cursor) = u.b8[1];
+ } else {
+ u.b8[0] = CURS_POINT(cursor);
+ cursor->offset++;
+ u.b8[1] = CURS_POINT(cursor);
+ *u16p = XPT_SWAB16(u.b16);
+ }
+ cursor->offset++;
+
+ return PR_TRUE;
+}
+
+XPT_PUBLIC_API(PRBool)
+XPT_Do8(XPTCursor *cursor, PRUint8 *u8p)
+{
+ if (!CHECK_COUNT(cursor, 1))
+ return PR_FALSE;
+ if (cursor->state->mode == XPT_ENCODE)
+ CURS_POINT(cursor) = *u8p;
+ else
+ *u8p = CURS_POINT(cursor);
+
+ cursor->offset++;
+
+ return PR_TRUE;
+}
+
+
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/.cvsignore b/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/.cvsignore
new file mode 100644
index 00000000..ebc62d94
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/.cvsignore
@@ -0,0 +1,3 @@
+Makefile
+PrimitiveTest
+SimpleTypeLib
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/Makefile.in b/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/Makefile.in
new file mode 100644
index 00000000..afdc31b3
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/Makefile.in
@@ -0,0 +1,59 @@
+#
+# ***** 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
+CPP_PROG_LINK = 1
+
+SIMPLE_PROGRAMS = PrimitiveTest$(BIN_SUFFIX) SimpleTypeLib$(BIN_SUFFIX)
+
+CSRCS = PrimitiveTest.c SimpleTypeLib.c
+
+LIBS = \
+ $(XPCOM_LIBS) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -DEXPORT_XPT_API
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/PrimitiveTest.c b/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/PrimitiveTest.c
new file mode 100644
index 00000000..aad33ccc
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/PrimitiveTest.c
@@ -0,0 +1,157 @@
+/* -*- 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 ***** */
+
+/* Test the xdr primitives from xpt_xdr.c */
+
+#include "xpt_xdr.h"
+#include <stdio.h>
+#include <string.h> /* for memcpy */
+
+#define PASS(msg) \
+ fprintf(stderr, "PASSED : %s\n", msg);
+
+#define FAIL(msg) \
+ fprintf(stderr, "FAILURE: %s\n", msg);
+
+#define TRY_(msg, cond, silent) \
+ if ((cond) && !silent) { \
+ PASS(msg); \
+ } else { \
+ FAIL(msg); \
+ return 1; \
+ }
+
+#define TRY(msg, cond) TRY_(msg, cond, 0)
+#define TRY_Q(msg, cond) TRY_(msg, cond, 1);
+
+XPTString in_str = { 4, "bazz" };
+
+struct TestData {
+ PRUint32 bit32;
+ PRUint16 bit16;
+ PRUint8 bit8[2];
+ char *cstr;
+ XPTString *str;
+} input = { 0xdeadbeef, 0xcafe, {0xba, 0xbe}, "foobar", &in_str},
+ output = {0, 0, {0, 0}, NULL, NULL };
+
+void
+dump_struct(char *label, struct TestData *str)
+{
+ fprintf(stderr, "%s: {%#08x, %#04x, {%#02x, %#02x}, %s, %d/%s}\n",
+ label, str->bit32, str->bit16, str->bit8[0], str->bit8[1],
+ str->cstr, str->str->length, str->str->bytes);
+}
+
+PRBool
+XDR(XPTArena *arena, XPTCursor *cursor, struct TestData *str)
+{
+ TRY("Do32", XPT_Do32(cursor, &str->bit32));
+ TRY("Do16", XPT_Do16(cursor, &str->bit16));
+ TRY("Do8", XPT_Do8 (cursor, &str->bit8[0]));
+ TRY("Do8", XPT_Do8 (cursor, &str->bit8[1]));
+ TRY("DoCString", XPT_DoCString(arena, cursor, &str->cstr));
+ TRY("DoString", XPT_DoString(arena, cursor, &str->str));
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ XPTArena *arena;
+ XPTState *state;
+ XPTCursor curs, *cursor = &curs;
+ char *header, *data, *whole;
+ PRUint32 hlen, dlen, i;
+
+ TRY("XPT_NewArena", (arena = XPT_NewArena(1024, sizeof(double), "main")));
+
+ TRY("NewState (ENCODE)", (state = XPT_NewXDRState(XPT_ENCODE, NULL, 0)));
+
+ XPT_SetDataOffset(state, sizeof input);
+
+ TRY("MakeCursor", XPT_MakeCursor(state, XPT_HEADER, sizeof input, cursor));
+
+ dump_struct("before", &input);
+
+ if (XDR(arena, cursor, &input))
+ return 1;
+
+ fprintf(stderr, "ENCODE successful\n");
+ XPT_GetXDRData(state, XPT_HEADER, &header, &hlen);
+ fprintf(stderr, "XDR header %d bytes at %p:",
+ hlen, header);
+ for (i = 0; i < hlen; i++)
+ fprintf(stderr, "%c%02x", i ? ',' : ' ', (uint8)header[i]);
+ fprintf(stderr, "\n");
+
+ XPT_GetXDRData(state, XPT_DATA, &data, &dlen);
+
+ fprintf(stderr, "XDR data %d bytes at %p:",
+ dlen, data);
+ for (i = 0; i < dlen; i++)
+ fprintf(stderr, "%c%02x/%c", i ? ',' : ' ', (uint8)data[i],
+ (uint8)data[i]);
+ fprintf(stderr, "\n");
+
+ whole = malloc(dlen + hlen);
+ if (!whole) {
+ fprintf(stderr, "malloc %d failed!\n", dlen + hlen);
+ return 1;
+ }
+
+ /* TRY_Q("malloc", (data2 = malloc(len))); */
+ memcpy(whole, header, hlen);
+ memcpy(whole + hlen, data, dlen);
+ XPT_DestroyXDRState(state);
+
+ TRY("NewState (DECODE)", (state = XPT_NewXDRState(XPT_DECODE, whole,
+ hlen + dlen)));
+
+ TRY("MakeCursor", XPT_MakeCursor(state, XPT_HEADER, sizeof input, cursor));
+ XPT_SetDataOffset(state, sizeof input);
+
+ if (XDR(arena, cursor, &output))
+ return 1;
+
+ dump_struct("after", &output);
+ XPT_DestroyXDRState(state);
+ XPT_DestroyArena(arena);
+ free(whole);
+
+ return 0;
+}
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/SimpleTypeLib.c b/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/SimpleTypeLib.c
new file mode 100644
index 00000000..305b8520
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/tests/SimpleTypeLib.c
@@ -0,0 +1,192 @@
+/* -*- 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 ***** */
+
+/* Test the structure creation and serialization APIs from xpt_struct.c */
+#include <stdio.h>
+
+#include "xpt_xdr.h"
+#include "xpt_struct.h"
+
+#define PASS(msg) \
+ fprintf(stderr, "PASSED : %s\n", msg);
+
+#define FAIL(msg) \
+ fprintf(stderr, "FAILURE: %s\n", msg);
+
+#define TRY_(msg, cond, silent) \
+ if ((cond) && !silent) { \
+ PASS(msg); \
+ } else { \
+ FAIL(msg); \
+ return 1; \
+ }
+
+#define TRY(msg, cond) TRY_(msg, cond, 0)
+#define TRY_Q(msg, cond) TRY_(msg, cond, 1);
+
+struct nsID iid = {
+ 0x00112233,
+ 0x4455,
+ 0x6677,
+ {0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}
+};
+
+XPTTypeDescriptor td_void;
+
+int
+main(int argc, char **argv)
+{
+ XPTArena *arena;
+ XPTHeader *header;
+ XPTAnnotation *ann;
+ XPTInterfaceDescriptor *id;
+ XPTMethodDescriptor *meth;
+
+ XPTState *state;
+ XPTCursor curs, *cursor = &curs;
+ char *data, *head;
+ FILE *out;
+ PRUint32 len, header_sz;
+
+ PRBool ok;
+
+ td_void.prefix.flags = TD_VOID;
+
+#ifdef XP_MAC
+ if (argc == 0) {
+ static char* args[] = { "SimpleTypeLib", "simple.xpt", NULL };
+ argc = 2;
+ argv = args;
+ }
+#endif
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <filename.xpt>\n"
+ " Creates a simple typelib file.\n", argv[0]);
+
+ return 1;
+ }
+
+ arena = XPT_NewArena(1024, sizeof(double), "main");
+ TRY("XPT_NewArena", arena);
+
+ /* construct a header */
+ header = XPT_NewHeader(arena, 1, XPT_MAJOR_VERSION, XPT_MINOR_VERSION);
+ TRY("NewHeader", header);
+
+
+ ann = XPT_NewAnnotation(arena, XPT_ANN_LAST | XPT_ANN_PRIVATE,
+ XPT_NewStringZ(arena, "SimpleTypeLib 1.0"),
+ XPT_NewStringZ(arena, "See You In Rome"));
+ TRY("NewAnnotation", ann);
+ header->annotations = ann;
+
+ header_sz = XPT_SizeOfHeaderBlock(header);
+
+ id = XPT_NewInterfaceDescriptor(arena, 0, 2, 2, 0);
+ TRY("NewInterfaceDescriptor", id);
+
+ ok = XPT_FillInterfaceDirectoryEntry(arena, header->interface_directory, &iid,
+ "Interface", "NS", id);
+ TRY("FillInterfaceDirectoryEntry", ok);
+
+ /* void method1(void) */
+ meth = &id->method_descriptors[0];
+ ok = XPT_FillMethodDescriptor(arena, meth, 0, "method1", 0);
+ TRY("FillMethodDescriptor", ok);
+ meth->result->flags = 0;
+ meth->result->type.prefix.flags = TD_VOID;
+
+ /* wstring method2(in uint32, in bool) */
+ meth = &id->method_descriptors[1];
+ ok = XPT_FillMethodDescriptor(arena, meth, 0, "method2", 2);
+ TRY("FillMethodDescriptor", ok);
+
+ meth->result->flags = 0;
+ meth->result->type.prefix.flags = TD_PSTRING | XPT_TDP_POINTER;
+ meth->params[0].type.prefix.flags = TD_UINT32;
+ meth->params[0].flags = XPT_PD_IN;
+ meth->params[1].type.prefix.flags = TD_BOOL;
+ meth->params[1].flags = XPT_PD_IN;
+
+#if 0
+ /* const one = 1; */
+ id->const_descriptors[0].name = "one";
+ id->const_descriptors[0].type.prefix.flags = TD_UINT16;
+ id->const_descriptors[0].value.ui16 = 1;
+
+ /* const squeamish = "ossifrage"; */
+ id->const_descriptors[1].name = "squeamish";
+ id->const_descriptors[1].type.prefix.flags = TD_PBSTR | XPT_TDP_POINTER;
+ id->const_descriptors[1].value.string = XPT_NewStringZ(arena, "ossifrage");
+#endif
+
+ /* serialize it */
+ state = XPT_NewXDRState(XPT_ENCODE, NULL, 0);
+ TRY("NewState (ENCODE)", state);
+
+ ok = XPT_MakeCursor(state, XPT_HEADER, header_sz, cursor);
+ TRY("MakeCursor", ok);
+
+ ok = XPT_DoHeader(arena, cursor, &header);
+ TRY("DoHeader", ok);
+
+ out = fopen(argv[1], "wb");
+ if (!out) {
+ perror("FAILED: fopen");
+ return 1;
+ }
+
+ XPT_GetXDRData(state, XPT_HEADER, &head, &len);
+ fwrite(head, len, 1, out);
+
+ XPT_GetXDRData(state, XPT_DATA, &data, &len);
+ fwrite(data, len, 1, out);
+
+ if (ferror(out) != 0 || fclose(out) != 0) {
+ fprintf(stderr, "\nError writing file: %s\n\n", argv[1]);
+ } else {
+ fprintf(stderr, "\nFile written: %s\n\n", argv[1]);
+ }
+ XPT_DestroyXDRState(state);
+
+ XPT_FreeHeader(arena, header);
+ XPT_DestroyArena(arena);
+
+ return 0;
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/.cvsignore b/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/.cvsignore
new file mode 100644
index 00000000..985cc7a7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/.cvsignore
@@ -0,0 +1,3 @@
+Makefile
+xpt_dump
+xpt_link
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/Makefile.in b/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/Makefile.in
new file mode 100644
index 00000000..bedece8e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/Makefile.in
@@ -0,0 +1,90 @@
+#
+# ***** 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
+INTERNAL_TOOLS = 1
+
+SIMPLE_PROGRAMS = xpt_dump$(BIN_SUFFIX) xpt_link$(BIN_SUFFIX)
+
+CSRCS = xpt_dump.c xpt_link.c
+
+SDK_BINARY = \
+ $(SIMPLE_PROGRAMS) \
+ $(NULL)
+
+ifdef CROSS_COMPILE
+HOST_SIMPLE_PROGRAMS = $(addprefix host_, $(SIMPLE_PROGRAMS:$(BIN_SUFFIX)=$(HOST_BIN_SUFFIX)))
+HOST_CSRCS = $(CSRCS)
+endif
+
+include $(topsrcdir)/config/rules.mk
+
+# Compile directly against the static lib, so we can use the tools
+# during the build without the shared library path being set.
+ifeq ($(OS_ARCH),WINNT)
+DEFINES += -DEXPORT_XPT_API
+endif
+
+LIBS = $(DIST)/lib/$(LIB_PREFIX)xpt.$(LIB_SUFFIX)
+
+# Tell the $(SIMPLE_PROGRAMS) target that we need to be recompiled
+# when libxpt changes.
+EXTRA_DEPS = $(wildcard $(DIST)/lib/$(LIB_PREFIX)xpt.*)
+
+ifdef CROSS_COMPILE
+HOST_LIBS = $(DIST)/host/lib/libhostxpt.$(LIB_SUFFIX)
+HOST_EXTRA_DEPS = $(wildcard $(DIST)/host/lib/libhostxpt.*)
+
+ifdef HOST_NSPR_MDCPUCFG
+HOST_CFLAGS += -DMDCPUCFG=$(HOST_NSPR_MDCPUCFG)
+endif
+endif
+
+
+# Build xpt_link and xpt_dump early. (libs creates .deps used by libs.)
+export::
+ @$(MAKE) libs
+
+
+
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/xpt_dump.c b/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/xpt_dump.c
new file mode 100644
index 00000000..8926b9c9
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/xpt_dump.c
@@ -0,0 +1,941 @@
+/* -*- 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 ***** */
+
+/*
+ * A utility for dumping the contents of a typelib file (.xpt) to screen
+ */
+
+#include "xpt_xdr.h"
+#include <stdio.h>
+#ifdef XP_MAC
+#include <stat.h>
+#include <StandardFile.h>
+#include "FullPath.h"
+#else
+#ifdef XP_OS2_EMX
+#include <sys/types.h>
+#endif
+#include <sys/stat.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include "prprf.h"
+
+#define BASE_INDENT 3
+
+static char *type_array[32] =
+ {"int8", "int16", "int32", "int64",
+ "uint8", "uint16", "uint32", "uint64",
+ "float", "double", "boolean", "char",
+ "wchar_t", "void", "reserved", "reserved",
+ "reserved", "reserved", "reserved", "reserved",
+ "reserved", "reserved", "reserved", "reserved",
+ "reserved", "reserved", "reserved", "reserved",
+ "reserved", "reserved", "reserved", "reserved"};
+
+static char *ptype_array[32] =
+ {"int8 *", "int16 *", "int32 *", "int64 *",
+ "uint8 *", "uint16 *", "uint32 *", "uint64 *",
+ "float *", "double *", "boolean *", "char *",
+ "wchar_t *", "void *", "nsIID *", "DOMString *",
+ "string", "wstring", "Interface *", "InterfaceIs *",
+ "array", "string_s", "wstring_s", "UTF8String *",
+ "CString *", "AString *", "reserved", "reserved",
+ "reserved", "reserved", "reserved", "reserved"};
+
+static char *rtype_array[32] =
+ {"int8 &", "int16 &", "int32 &", "int64 &",
+ "uint8 &", "uint16 &", "uint32 &", "uint64 &",
+ "float &", "double &", "boolean &", "char &",
+ "wchar_t &", "void &", "nsIID &", "DOMString &",
+ "string &", "wstring &", "Interface &", "InterfaceIs &",
+ "array &", "string_s &", "wstring_s &", "UTF8String &",
+ "CString &", "AString &", "reserved", "reserved",
+ "reserved", "reserved", "reserved", "reserved"};
+
+PRBool param_problems = PR_FALSE;
+
+PRBool
+XPT_DumpHeader(XPTCursor *cursor, XPTHeader *header,
+ const int indent, PRBool verbose_mode);
+
+PRBool
+XPT_DumpAnnotations(XPTAnnotation *ann, const int indent, PRBool verbose_mode);
+
+PRBool
+XPT_DumpInterfaceDirectoryEntry(XPTCursor *cursor,
+ XPTInterfaceDirectoryEntry *ide,
+ XPTHeader *header, const int indent,
+ PRBool verbose_mode);
+
+PRBool
+XPT_DumpInterfaceDescriptor(XPTCursor *cursor, XPTInterfaceDescriptor *id,
+ XPTHeader *header, const int indent,
+ PRBool verbose_mode);
+
+PRBool
+XPT_DumpMethodDescriptor(XPTHeader *header, XPTMethodDescriptor *md,
+ XPTInterfaceDescriptor *id,
+ const int indent, PRBool verbose_mode);
+PRBool
+XPT_GetStringForType(XPTHeader *header, XPTTypeDescriptor *td,
+ XPTInterfaceDescriptor *id,
+ char **type_string);
+
+PRBool
+XPT_DumpXPTString(XPTString *str);
+
+PRBool
+XPT_DumpParamDescriptor(XPTHeader *header, XPTParamDescriptor *pd,
+ XPTInterfaceDescriptor *id,
+ const int indent, PRBool verbose_mode,
+ PRBool is_result);
+
+PRBool
+XPT_DumpTypeDescriptor(XPTTypeDescriptor *td,
+ XPTInterfaceDescriptor *id,
+ int indent, PRBool verbose_mode);
+
+PRBool
+XPT_DumpConstDescriptor(XPTHeader *header, XPTConstDescriptor *cd,
+ XPTInterfaceDescriptor *id,
+ const int indent, PRBool verbose_mode);
+
+static void
+xpt_dump_usage(char *argv[]) {
+ fprintf(stdout, "Usage: %s [-v] <filename.xpt>\n"
+ " -v verbose mode\n", argv[0]);
+}
+
+#if defined(XP_MAC) && defined(XPIDL_PLUGIN)
+
+#define main xptdump_main
+int xptdump_main(int argc, char *argv[]);
+
+#define get_file_length mac_get_file_length
+extern size_t mac_get_file_length(const char* filename);
+
+#else /* !(XP_MAC && XPIDL_PLUGIN) */
+
+static size_t get_file_length(const char* filename)
+{
+ struct stat file_stat;
+ if (stat(filename, &file_stat) != 0) {
+ perror("FAILED: get_file_length");
+ exit(1);
+ }
+ return file_stat.st_size;
+}
+
+#endif /* !(XP_MAC && XPIDL_PLUGIN) */
+
+int
+main(int argc, char **argv)
+{
+ PRBool verbose_mode = PR_FALSE;
+ XPTArena *arena;
+ XPTState *state;
+ XPTCursor curs, *cursor = &curs;
+ XPTHeader *header;
+ size_t flen;
+ char *name;
+ char *whole;
+ FILE *in;
+ int result = 1;
+
+ switch (argc) {
+ case 2:
+ if (argv[1][0] == '-') {
+ xpt_dump_usage(argv);
+ return 1;
+ }
+ name = argv[1];
+ flen = get_file_length(name);
+ in = fopen(name, "rb");
+ break;
+ case 3:
+ verbose_mode = PR_TRUE;
+ if (argv[1][0] != '-' || argv[1][1] != 'v') {
+ xpt_dump_usage(argv);
+ return 1;
+ }
+ name = argv[2];
+ flen = get_file_length(name);
+ in = fopen(name, "rb");
+ break;
+ default:
+ xpt_dump_usage(argv);
+ return 1;
+ }
+
+ if (!in) {
+ perror("FAILED: fopen");
+ return 1;
+ }
+
+ arena = XPT_NewArena(1024, sizeof(double), "main xpt_dump arena");
+ if (!arena) {
+ perror("XPT_NewArena failed");
+ return 1;
+ }
+
+ /* after arena creation all exits via 'goto out' */
+
+ whole = XPT_MALLOC(arena, flen);
+ if (!whole) {
+ perror("FAILED: XPT_MALLOC for whole");
+ goto out;
+ }
+
+ if (flen > 0) {
+ size_t rv = fread(whole, 1, flen, in);
+ if (rv < flen) {
+ fprintf(stderr, "short read (%zd vs %zd)! ouch!\n", rv, flen);
+ goto out;
+ }
+ if (ferror(in) != 0 || fclose(in) != 0)
+ perror("FAILED: Unable to read typelib file.\n");
+
+ state = XPT_NewXDRState(XPT_DECODE, whole, flen);
+ if (!XPT_MakeCursor(state, XPT_HEADER, 0, cursor)) {
+ fprintf(stdout, "XPT_MakeCursor failed for %s\n", name);
+ goto out;
+ }
+ if (!XPT_DoHeader(arena, cursor, &header)) {
+ fprintf(stdout,
+ "DoHeader failed for %s. Is %s a valid .xpt file?\n",
+ name, name);
+ goto out;
+ }
+
+ if (!XPT_DumpHeader(cursor, header, BASE_INDENT, verbose_mode)) {
+ perror("FAILED: XPT_DumpHeader");
+ goto out;
+ }
+
+ if (param_problems) {
+ fprintf(stdout, "\nWARNING: ParamDescriptors are present with "
+ "bad in/out/retval flag information.\n"
+ "These have been marked with 'XXX'.\n"
+ "Remember, retval params should always be marked as out!\n");
+ }
+
+ XPT_DestroyXDRState(state);
+ XPT_FREE(arena, whole);
+
+ } else {
+ fclose(in);
+ perror("FAILED: file length <= 0");
+ goto out;
+ }
+
+ result = 0;
+
+out:
+ XPT_DestroyArena(arena);
+ return result;
+}
+
+PRBool
+XPT_DumpHeader(XPTCursor *cursor, XPTHeader *header,
+ const int indent, PRBool verbose_mode)
+{
+ int i;
+
+ fprintf(stdout, "Header:\n");
+
+ if (verbose_mode) {
+ fprintf(stdout, "%*sMagic beans: ", indent, " ");
+ for (i=0; i<16; i++) {
+ fprintf(stdout, "%02x", header->magic[i]);
+ }
+ fprintf(stdout, "\n");
+ if (strncmp((const char*)header->magic, XPT_MAGIC, 16) == 0)
+ fprintf(stdout, "%*s PASSED\n", indent, " ");
+ else
+ fprintf(stdout, "%*s FAILED\n", indent, " ");
+ }
+ fprintf(stdout, "%*sMajor version: %d\n", indent, " ",
+ header->major_version);
+ fprintf(stdout, "%*sMinor version: %d\n", indent, " ",
+ header->minor_version);
+ fprintf(stdout, "%*sNumber of interfaces: %d\n", indent, " ",
+ header->num_interfaces);
+
+ if (verbose_mode) {
+ fprintf(stdout, "%*sFile length: %d\n", indent, " ",
+ header->file_length);
+ fprintf(stdout, "%*sData pool offset: %d\n\n", indent, " ",
+ header->data_pool);
+ }
+
+ fprintf(stdout, "%*sAnnotations:\n", indent, " ");
+ if (!XPT_DumpAnnotations(header->annotations, indent*2, verbose_mode))
+ return PR_FALSE;
+
+ fprintf(stdout, "\nInterface Directory:\n");
+ for (i=0; i<header->num_interfaces; i++) {
+ if (verbose_mode) {
+ fprintf(stdout, "%*sInterface #%d:\n", indent, " ", i);
+ if (!XPT_DumpInterfaceDirectoryEntry(cursor,
+ &header->interface_directory[i],
+ header, indent*2,
+ verbose_mode)) {
+ return PR_FALSE;
+ }
+ } else {
+ if (!XPT_DumpInterfaceDirectoryEntry(cursor,
+ &header->interface_directory[i],
+ header, indent,
+ verbose_mode)) {
+ return PR_FALSE;
+ }
+ }
+ }
+
+ return PR_TRUE;
+}
+
+PRBool
+XPT_DumpAnnotations(XPTAnnotation *ann, const int indent, PRBool verbose_mode)
+{
+ int i = -1;
+ XPTAnnotation *last;
+ int new_indent = indent + BASE_INDENT;
+
+ do {
+ i++;
+ if (XPT_ANN_IS_PRIVATE(ann->flags)) {
+ if (verbose_mode) {
+ fprintf(stdout, "%*sAnnotation #%d is private.\n",
+ indent, " ", i);
+ } else {
+ fprintf(stdout, "%*sAnnotation #%d:\n",
+ indent, " ", i);
+ }
+ fprintf(stdout, "%*sCreator: ", new_indent, " ");
+ if (!XPT_DumpXPTString(ann->creator))
+ return PR_FALSE;
+ fprintf(stdout, "\n");
+ fprintf(stdout, "%*sPrivate Data: ", new_indent, " ");
+ if (!XPT_DumpXPTString(ann->private_data))
+ return PR_FALSE;
+ fprintf(stdout, "\n");
+ } else {
+ fprintf(stdout, "%*sAnnotation #%d is empty.\n",
+ indent, " ", i);
+ }
+ last = ann;
+ ann = ann->next;
+ } while (!XPT_ANN_IS_LAST(last->flags));
+
+ if (verbose_mode) {
+ fprintf(stdout, "%*sAnnotation #%d is the last annotation.\n",
+ indent, " ", i);
+ }
+
+ return PR_TRUE;
+}
+
+static void
+print_IID(struct nsID *iid, FILE *file)
+{
+ fprintf(file, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ (PRUint32) iid->m0, (PRUint32) iid->m1,(PRUint32) iid->m2,
+ (PRUint32) iid->m3[0], (PRUint32) iid->m3[1],
+ (PRUint32) iid->m3[2], (PRUint32) iid->m3[3],
+ (PRUint32) iid->m3[4], (PRUint32) iid->m3[5],
+ (PRUint32) iid->m3[6], (PRUint32) iid->m3[7]);
+
+}
+
+PRBool
+XPT_DumpInterfaceDirectoryEntry(XPTCursor *cursor,
+ XPTInterfaceDirectoryEntry *ide,
+ XPTHeader *header, const int indent,
+ PRBool verbose_mode)
+{
+ int new_indent = indent + BASE_INDENT;
+
+ if (verbose_mode) {
+ fprintf(stdout, "%*sIID: ", indent, " ");
+ print_IID(&ide->iid, stdout);
+ fprintf(stdout, "\n");
+
+ fprintf(stdout, "%*sName: %s\n",
+ indent, " ", ide->name);
+ fprintf(stdout, "%*sNamespace: %s\n",
+ indent, " ", ide->name_space ? ide->name_space : "none");
+ fprintf(stdout, "%*sAddress of interface descriptor: %p\n",
+ indent, " ", ide->interface_descriptor);
+
+ fprintf(stdout, "%*sDescriptor:\n", indent, " ");
+
+ if (!XPT_DumpInterfaceDescriptor(cursor, ide->interface_descriptor,
+ header, new_indent, verbose_mode)) {
+ return PR_FALSE;
+ }
+ } else {
+ fprintf(stdout, "%*s- %s::%s (", indent, " ",
+ ide->name_space ? ide->name_space : "", ide->name);
+ print_IID(&ide->iid, stdout);
+ fprintf(stdout, "):\n");
+ if (!XPT_DumpInterfaceDescriptor(cursor, ide->interface_descriptor,
+ header, new_indent, verbose_mode)) {
+ return PR_FALSE;
+ }
+ }
+
+ return PR_TRUE;
+}
+
+PRBool
+XPT_DumpInterfaceDescriptor(XPTCursor *cursor, XPTInterfaceDescriptor *id,
+ XPTHeader *header, const int indent,
+ PRBool verbose_mode)
+{
+ XPTInterfaceDirectoryEntry *parent_ide;
+ int i;
+ int new_indent = indent + BASE_INDENT;
+ int more_indent = new_indent + BASE_INDENT;
+
+ if (!id) {
+ fprintf(stdout, "%*s[Unresolved]\n", indent, " ");
+ return PR_TRUE;
+ }
+
+ if (id->parent_interface) {
+
+ parent_ide = &header->interface_directory[id->parent_interface - 1];
+
+ fprintf(stdout, "%*sParent: %s::%s\n", indent, " ",
+ parent_ide->name_space ?
+ parent_ide->name_space : "",
+ parent_ide->name);
+ }
+
+ fprintf(stdout, "%*sFlags:\n", indent, " ");
+
+ fprintf(stdout, "%*sScriptable: %s\n", new_indent, " ",
+ XPT_ID_IS_SCRIPTABLE(id->flags) ? "TRUE" : "FALSE");
+
+ fprintf(stdout, "%*sFunction: %s\n", new_indent, " ",
+ XPT_ID_IS_FUNCTION(id->flags) ? "TRUE" : "FALSE");
+
+ if (verbose_mode) {
+ if (id->parent_interface) {
+ fprintf(stdout,
+ "%*sIndex of parent interface (in data pool): %d\n",
+ indent, " ", id->parent_interface);
+
+ }
+ } else {
+ }
+
+ if (id->num_methods > 0) {
+ if (verbose_mode) {
+ fprintf(stdout,
+ "%*s# of Method Descriptors: %d\n",
+ indent, " ", id->num_methods);
+ } else {
+ fprintf(stdout, "%*sMethods:\n", indent, " ");
+ }
+
+ for (i=0; i<id->num_methods; i++) {
+ if (verbose_mode) {
+ fprintf(stdout, "%*sMethod #%d:\n", new_indent, " ", i);
+ if (!XPT_DumpMethodDescriptor(header,
+ &id->method_descriptors[i], id,
+ more_indent, verbose_mode)) {
+ return PR_FALSE;
+ }
+ } else {
+ if (!XPT_DumpMethodDescriptor(header,
+ &id->method_descriptors[i], id,
+ new_indent, verbose_mode)) {
+ return PR_FALSE;
+ }
+ }
+ }
+ } else {
+ fprintf(stdout, "%*sMethods:\n", indent, " ");
+ fprintf(stdout, "%*sNo Methods\n", new_indent, " ");
+ }
+
+ if (id->num_constants > 0) {
+ if (verbose_mode) {
+ fprintf(stdout,
+ "%*s# of Constant Descriptors: %d\n",
+ indent, " ", id->num_constants);
+ } else {
+ fprintf(stdout, "%*sConstants:\n", indent, " ");
+ }
+
+ for (i=0; i<id->num_constants; i++) {
+ if (verbose_mode) {
+ fprintf(stdout, "%*sConstant #%d:\n", new_indent, " ", i);
+ if (!XPT_DumpConstDescriptor(header,
+ &id->const_descriptors[i], id,
+ more_indent, verbose_mode))
+ return PR_FALSE;
+ } else {
+ if (!XPT_DumpConstDescriptor(header,
+ &id->const_descriptors[i], id,
+ new_indent, verbose_mode)) {
+ return PR_FALSE;
+ }
+ }
+ }
+ } else {
+ fprintf(stdout, "%*sConstants:\n", indent, " ");
+ fprintf(stdout, "%*sNo Constants\n", new_indent, " ");
+ }
+
+ return PR_TRUE;
+}
+
+PRBool
+XPT_DumpMethodDescriptor(XPTHeader *header, XPTMethodDescriptor *md,
+ XPTInterfaceDescriptor *id,
+ const int indent, PRBool verbose_mode)
+{
+ int i;
+ int new_indent = indent + BASE_INDENT;
+ int more_indent = new_indent + BASE_INDENT;
+
+ if (verbose_mode) {
+ fprintf(stdout, "%*sName: %s\n", indent, " ", md->name);
+ fprintf(stdout, "%*sIs Getter? ", indent, " ");
+ if (XPT_MD_IS_GETTER(md->flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+ fprintf(stdout, "%*sIs Setter? ", indent, " ");
+ if (XPT_MD_IS_SETTER(md->flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+ fprintf(stdout, "%*sIs NotXPCOM? ", indent, " ");
+ if (XPT_MD_IS_NOTXPCOM(md->flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+ fprintf(stdout, "%*sIs Constructor? ", indent, " ");
+ if (XPT_MD_IS_CTOR(md->flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+ fprintf(stdout, "%*sIs Hidden? ", indent, " ");
+ if (XPT_MD_IS_HIDDEN(md->flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+ fprintf(stdout, "%*s# of arguments: %d\n", indent, " ", md->num_args);
+ fprintf(stdout, "%*sParameter Descriptors:\n", indent, " ");
+
+ for (i=0; i<md->num_args; i++) {
+ fprintf(stdout, "%*sParameter #%d:\n", new_indent, " ", i);
+
+ if (!XPT_DumpParamDescriptor(header, &md->params[i], id,
+ more_indent, verbose_mode, PR_FALSE))
+ return PR_FALSE;
+ }
+
+ fprintf(stdout, "%*sResult:\n", indent, " ");
+ if (!XPT_DumpParamDescriptor(header, md->result, id, new_indent,
+ verbose_mode, PR_TRUE)) {
+ return PR_FALSE;
+ }
+ } else {
+ char *param_type;
+ XPTParamDescriptor *pd;
+
+ if (!XPT_GetStringForType(header, &md->result->type, id, &param_type)) {
+ return PR_FALSE;
+ }
+ fprintf(stdout, "%*s%c%c%c%c%c %s %s(", indent - 6, " ",
+ XPT_MD_IS_GETTER(md->flags) ? 'G' : ' ',
+ XPT_MD_IS_SETTER(md->flags) ? 'S' : ' ',
+ XPT_MD_IS_HIDDEN(md->flags) ? 'H' : ' ',
+ XPT_MD_IS_NOTXPCOM(md->flags) ? 'N' : ' ',
+ XPT_MD_IS_CTOR(md->flags) ? 'C' : ' ',
+ param_type, md->name);
+ for (i=0; i<md->num_args; i++) {
+ if (i!=0) {
+ fprintf(stdout, ", ");
+ }
+ pd = &md->params[i];
+ if (XPT_PD_IS_IN(pd->flags)) {
+ fprintf(stdout, "in");
+ if (XPT_PD_IS_OUT(pd->flags)) {
+ fprintf(stdout, "out ");
+ if (XPT_PD_IS_RETVAL(pd->flags)) {
+ fprintf(stdout, "retval ");
+ }
+ if (XPT_PD_IS_SHARED(pd->flags)) {
+ fprintf(stdout, "shared ");
+ }
+ } else {
+ fprintf(stdout, " ");
+ if (XPT_PD_IS_DIPPER(pd->flags)) {
+ fprintf(stdout, "dipper ");
+ }
+ if (XPT_PD_IS_RETVAL(pd->flags)) {
+ fprintf(stdout, "retval ");
+ }
+ }
+ } else {
+ if (XPT_PD_IS_OUT(pd->flags)) {
+ fprintf(stdout, "out ");
+ if (XPT_PD_IS_RETVAL(pd->flags)) {
+ fprintf(stdout, "retval ");
+ }
+ if (XPT_PD_IS_SHARED(pd->flags)) {
+ fprintf(stdout, "shared ");
+ }
+ } else {
+ param_problems = PR_TRUE;
+ fprintf(stdout, "XXX ");
+ }
+ }
+ if (!XPT_GetStringForType(header, &pd->type, id, &param_type)) {
+ return PR_FALSE;
+ }
+ fprintf(stdout, "%s", param_type);
+ }
+ fprintf(stdout, ");\n");
+ }
+ return PR_TRUE;
+}
+
+PRBool
+XPT_GetStringForType(XPTHeader *header, XPTTypeDescriptor *td,
+ XPTInterfaceDescriptor *id,
+ char **type_string)
+{
+ static char buf[128]; /* ugly non-reentrant use of static buffer! */
+ PRBool isArray = PR_FALSE;
+
+ int tag = XPT_TDP_TAG(td->prefix);
+
+ if (tag == TD_ARRAY) {
+ isArray = PR_TRUE;
+ td = &id->additional_types[td->type.additional_type];
+ tag = XPT_TDP_TAG(td->prefix);
+ }
+
+ if (tag == TD_INTERFACE_TYPE) {
+ int idx = td->type.iface;
+ if (!idx || idx > header->num_interfaces)
+ *type_string = "UNKNOWN_INTERFACE";
+ else
+ *type_string = header->interface_directory[idx-1].name;
+ } else if (XPT_TDP_IS_POINTER(td->prefix.flags)) {
+ if (XPT_TDP_IS_REFERENCE(td->prefix.flags))
+ *type_string = rtype_array[tag];
+ else
+ *type_string = ptype_array[tag];
+ } else {
+ *type_string = type_array[tag];
+ }
+
+ if(isArray) {
+ sprintf(buf, "%s []", *type_string);
+ *type_string = buf;
+ }
+
+ return PR_TRUE;
+}
+
+PRBool
+XPT_DumpXPTString(XPTString *str)
+{
+ int i;
+ for (i=0; i<str->length; i++) {
+ fprintf(stdout, "%c", str->bytes[i]);
+ }
+ return PR_TRUE;
+}
+
+PRBool
+XPT_DumpParamDescriptor(XPTHeader *header, XPTParamDescriptor *pd,
+ XPTInterfaceDescriptor *id,
+ const int indent, PRBool verbose_mode,
+ PRBool is_result)
+{
+ int new_indent = indent + BASE_INDENT;
+
+ if (!XPT_PD_IS_IN(pd->flags) &&
+ !XPT_PD_IS_OUT(pd->flags) &&
+ (XPT_PD_IS_RETVAL(pd->flags) ||
+ XPT_PD_IS_SHARED(pd->flags))) {
+ param_problems = PR_TRUE;
+ fprintf(stdout, "XXX\n");
+ } else {
+ if (!XPT_PD_IS_IN(pd->flags) && !XPT_PD_IS_OUT(pd->flags)) {
+ if (is_result) {
+ if (XPT_TDP_TAG(pd->type.prefix) != TD_UINT32 &&
+ XPT_TDP_TAG(pd->type.prefix) != TD_VOID) {
+ param_problems = PR_TRUE;
+ fprintf(stdout, "XXX\n");
+ }
+ } else {
+ param_problems = PR_TRUE;
+ fprintf(stdout, "XXX\n");
+ }
+ }
+ }
+
+ fprintf(stdout, "%*sIn Param? ", indent, " ");
+ if (XPT_PD_IS_IN(pd->flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+ fprintf(stdout, "%*sOut Param? ", indent, " ");
+ if (XPT_PD_IS_OUT(pd->flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+ fprintf(stdout, "%*sRetval? ", indent, " ");
+ if (XPT_PD_IS_RETVAL(pd->flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+ fprintf(stdout, "%*sShared? ", indent, " ");
+ if (XPT_PD_IS_SHARED(pd->flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+ fprintf(stdout, "%*sDipper? ", indent, " ");
+ if (XPT_PD_IS_DIPPER(pd->flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+
+ fprintf(stdout, "%*sType Descriptor:\n", indent, " ");
+ if (!XPT_DumpTypeDescriptor(&pd->type, id, new_indent, verbose_mode))
+ return PR_FALSE;
+
+ return PR_TRUE;
+}
+
+PRBool
+XPT_DumpTypeDescriptor(XPTTypeDescriptor *td,
+ XPTInterfaceDescriptor *id,
+ int indent, PRBool verbose_mode)
+{
+ int new_indent;
+
+ if (XPT_TDP_TAG(td->prefix) == TD_ARRAY) {
+ fprintf(stdout, "%*sArray (size in arg %d and length in arg %d) of...\n",
+ indent, " ", td->argnum, td->argnum2);
+ td = &id->additional_types[td->type.additional_type];
+ indent += BASE_INDENT;
+ }
+
+ new_indent = indent + BASE_INDENT;
+
+ fprintf(stdout, "%*sIs Pointer? ", indent, " ");
+ if (XPT_TDP_IS_POINTER(td->prefix.flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+ fprintf(stdout, "%*sIs Unique Pointer? ", indent, " ");
+ if (XPT_TDP_IS_UNIQUE_POINTER(td->prefix.flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+ fprintf(stdout, "%*sIs Reference? ", indent, " ");
+ if (XPT_TDP_IS_REFERENCE(td->prefix.flags))
+ fprintf(stdout, "TRUE\n");
+ else
+ fprintf(stdout, "FALSE\n");
+
+ fprintf(stdout, "%*sTag: %d\n", indent, " ",
+ XPT_TDP_TAG(td->prefix));
+
+ if (XPT_TDP_TAG(td->prefix) == TD_PSTRING_SIZE_IS ||
+ XPT_TDP_TAG(td->prefix) == TD_PWSTRING_SIZE_IS) {
+ fprintf(stdout, "%*s - size in arg %d and length in arg %d\n",
+ indent, " ", td->argnum, td->argnum2);
+ }
+
+ if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_TYPE) {
+ fprintf(stdout, "%*sInterfaceTypeDescriptor:\n", indent, " ");
+ fprintf(stdout, "%*sIndex of IDE: %d\n", new_indent, " ",
+ td->type.iface);
+ }
+
+ if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_IS_TYPE) {
+ fprintf(stdout, "%*sInterfaceTypeDescriptor:\n", indent, " ");
+ fprintf(stdout, "%*sIndex of Method Argument: %d\n", new_indent, " ",
+ td->argnum);
+ }
+
+ return PR_TRUE;
+}
+
+PRBool
+XPT_DumpConstDescriptor(XPTHeader *header, XPTConstDescriptor *cd,
+ XPTInterfaceDescriptor *id,
+ const int indent, PRBool verbose_mode)
+{
+ int new_indent = indent + BASE_INDENT;
+ char *const_type;
+/* char *out; */
+ PRUint32 uintout;
+ PRInt32 intout;
+
+ if (verbose_mode) {
+ fprintf(stdout, "%*sName: %s\n", indent, " ", cd->name);
+ fprintf(stdout, "%*sType Descriptor: \n", indent, " ");
+ if (!XPT_DumpTypeDescriptor(&cd->type, id, new_indent, verbose_mode))
+ return PR_FALSE;
+ fprintf(stdout, "%*sValue: ", indent, " ");
+ } else {
+ if (!XPT_GetStringForType(header, &cd->type, id, &const_type)) {
+ return PR_FALSE;
+ }
+ fprintf(stdout, "%*s%s %s = ", indent, " ", const_type, cd->name);
+ }
+
+ switch(XPT_TDP_TAG(cd->type.prefix)) {
+ case TD_INT8:
+ fprintf(stdout, "%d", cd->value.i8);
+ break;
+ case TD_INT16:
+ fprintf(stdout, "%d", cd->value.i16);
+ break;
+ case TD_INT64:
+ /* XXX punt for now to remove NSPR linkage...
+ * borrow from mozilla/nsprpub/pr/src/io/prprf.c::cvt_ll? */
+
+/* out = PR_smprintf("%lld", cd->value.i64); */
+/* fputs(out, stdout); */
+/* PR_smprintf_free(out); */
+ LL_L2I(intout, cd->value.i64);
+ fprintf(stdout, "%d", intout);
+ break;
+ case TD_INT32:
+ fprintf(stdout, "%d", cd->value.i32);
+ break;
+ case TD_UINT8:
+ fprintf(stdout, "%u", cd->value.ui8);
+ break;
+ case TD_UINT16:
+ fprintf(stdout, "%u", cd->value.ui16);
+ break;
+ case TD_UINT64:
+/* out = PR_smprintf("%lld", cd->value.ui64); */
+/* fputs(out, stdout); */
+/* PR_smprintf_free(out); */
+ /* XXX punt for now to remove NSPR linkage. */
+ LL_L2UI(uintout, cd->value.ui64);
+ fprintf(stdout, "%u", uintout);
+ break;
+ case TD_UINT32:
+ fprintf(stdout, "%u", cd->value.ui32);
+ break;
+ case TD_FLOAT:
+ fprintf(stdout, "%f", cd->value.flt);
+ break;
+ case TD_DOUBLE:
+ fprintf(stdout, "%g", cd->value.dbl);
+ break;
+ case TD_BOOL:
+ if (cd->value.bul)
+ fprintf(stdout, "TRUE");
+ else
+ fprintf(stdout, "FALSE");
+ break;
+ case TD_CHAR:
+ fprintf(stdout, "%c", cd->value.ch);
+ break;
+ case TD_WCHAR:
+ fprintf(stdout, "%c", cd->value.wch & 0xff);
+ break;
+ case TD_VOID:
+ fprintf(stdout, "VOID");
+ break;
+ case TD_PNSIID:
+ if (XPT_TDP_IS_POINTER(cd->type.prefix.flags)) {
+ print_IID(cd->value.iid, stdout);
+ } else
+ return PR_FALSE;
+ break;
+ case TD_PSTRING:
+ if (XPT_TDP_IS_POINTER(cd->type.prefix.flags)) {
+ fprintf(stdout, "%s", cd->value.str);
+ } else
+ return PR_FALSE;
+ break;
+ case TD_PWSTRING:
+ if (XPT_TDP_IS_POINTER(cd->type.prefix.flags)) {
+ PRUint16 *ch = cd->value.wstr;
+ while (*ch) {
+ fprintf(stdout, "%c", *ch & 0xff);
+ ch++;
+ }
+ } else
+ return PR_FALSE;
+ break;
+ default:
+ perror("Unrecognized type");
+ return PR_FALSE;
+ break;
+ }
+
+ if (verbose_mode) {
+ fprintf(stdout, "\n");
+ } else {
+ fprintf(stdout, ";\n");
+ }
+
+ return PR_TRUE;
+}
diff --git a/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/xpt_link.c b/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/xpt_link.c
new file mode 100644
index 00000000..872b96fd
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/typelib/xpt/tools/xpt_link.c
@@ -0,0 +1,883 @@
+/* -*- 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 ***** */
+
+/*
+ * A utility for linking multiple typelib files.
+ */
+
+#include "xpt_xdr.h"
+#include <stdio.h>
+#ifdef XP_MAC
+#include <stat.h>
+#else
+#include <sys/stat.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include "prlong.h"
+
+#ifndef NULL
+#define NULL (void *) 0
+#endif
+
+/* Forward declarations. */
+typedef struct fixElement fixElement;
+static int compare_IDEs_by_IID(const void *ap, const void *bp);
+static int compare_IDE_with_zero(const void *ap);
+static int compare_IDEs_by_name(const void *ap, const void *bp);
+static int compare_IDEs_by_name_space(const void *ap, const void *bp);
+static int compare_strings(const void *ap, const void *bp);
+static int compare_pointers(const void *ap, const void *bp);
+static int compare_fixElements_by_IID(const void *ap, const void *bp);
+static int compare_fixElements_by_name(const void *ap, const void *bp);
+static int compare_IIDs(const void *ap, const void *bp);
+PRBool shrink_IDE_array(XPTInterfaceDirectoryEntry *ide,
+ int element_to_delete, int num_interfaces);
+PRBool update_fix_array(XPTArena *arena, fixElement *fix, int element_to_delete,
+ int num_interfaces, int replacement);
+static int get_new_index(const fixElement *fix, int num_elements,
+ int target_file, int target_interface);
+PRBool copy_IDE(XPTInterfaceDirectoryEntry *from,
+ XPTInterfaceDirectoryEntry *to);
+PRBool copy_fixElement(fixElement *from, fixElement *to);
+static void print_IID(struct nsID *iid, FILE *file);
+static void xpt_link_usage(char *argv[]);
+
+struct fixElement {
+ nsID iid;
+ char* name;
+ int file_num;
+ int interface_num;
+ PRBool is_deleted;
+ /* These next two variables will point you to the substitute interface
+ * if this one has been deleted.
+ */
+ int maps_to_file_num;
+ int maps_to_interface_num;
+};
+
+/* Global variables. */
+PRUint16 trueNumberOfInterfaces = 0;
+PRUint16 totalNumberOfInterfaces = 0;
+PRUint16 oldTotalNumberOfInterfaces = 0;
+
+/* The following globals are explained in xpt_struct.h */
+PRUint8 major_version = XPT_MAJOR_VERSION;
+PRUint8 minor_version = XPT_MINOR_VERSION;
+
+#if defined(XP_MAC) && defined(XPIDL_PLUGIN)
+
+#define main xptlink_main
+int xptlink_main(int argc, char *argv[]);
+extern size_t mac_get_file_length(const char* filename);
+#define get_file_length mac_get_file_length
+
+#else
+
+static size_t get_file_length(const char* filename)
+{
+ struct stat file_stat;
+ if (stat(filename, &file_stat) != 0) {
+ perror("FAILED: get_file_length");
+ exit(1);
+ }
+ return file_stat.st_size;
+}
+
+#endif /* XP_MAC && XPIDL_PLUGIN */
+
+int
+main(int argc, char **argv)
+{
+ XPTArena *arena;
+ XPTState *state;
+ XPTCursor curs, *cursor = &curs;
+ XPTHeader *header;
+ XPTInterfaceDirectoryEntry *IDE_array = NULL;
+ XPTInterfaceDescriptor *id;
+ XPTTypeDescriptor *td;
+ XPTAnnotation *ann, *first_ann;
+ PRUint32 header_sz, len;
+ PRUint32 oldOffset;
+ PRUint32 newOffset;
+ size_t flen = 0;
+ char *head, *data, *whole;
+ const char *outFileName;
+ FILE *in, *out;
+ fixElement *fix_array = NULL;
+ int i,j;
+ int k = 0;
+
+ if (argc < 3) {
+ xpt_link_usage(argv);
+ return 1;
+ }
+
+ arena = XPT_NewArena(1024 * 10, sizeof(double), "main xpt_link arena");
+ if (!arena) {
+ perror("FAILED: XPT_NewArena");
+ return 1;
+ }
+
+ first_ann = XPT_NewAnnotation(arena, XPT_ANN_LAST, NULL, NULL);
+
+ /* Check if the "-t version numnber" cmd line arg is present */
+ i = 1;
+ if (argv[i][0] == '-' && argv[i][1] == 't') {
+ /* Parse for "-t version number" */
+
+ /* If -t is the last argument on the command line, we have a problem */
+ if (i + 1 == argc) {
+ fprintf(stderr, "ERROR: missing version number after -t\n");
+ xpt_link_usage(argv);
+ return 1;
+ }
+
+ /*
+ * Assume that the argument after "-t" is the version number string
+ * and search for it in our internal list of acceptable version
+ * numbers.
+ */
+
+ switch (XPT_ParseVersionString(argv[++i], &major_version,
+ &minor_version)) {
+ case XPT_VERSION_CURRENT:
+ case XPT_VERSION_OLD:
+ break;
+ case XPT_VERSION_UNSUPPORTED:
+ fprintf(stderr, "ERROR: version \"%s\" not supported.\n",
+ argv[i]);
+ xpt_link_usage(argv);
+ return 1;
+ case XPT_VERSION_UNKNOWN:
+ default:
+ fprintf(stderr, "ERROR: version \"%s\" not recognised.\n",
+ argv[i]);
+ xpt_link_usage(argv);
+ return 1;
+ }
+
+ /* Hang onto the output file name. It's needed later. */
+ outFileName = argv[++i];
+
+ /* Increment i to the cmd line arg after outFileName */
+ i++;
+ }
+ else {
+ outFileName = argv[1];
+ i = 2;
+ }
+
+ for ( /* use i from earlier */ ; i < argc; i++) {
+ char *name = argv[i];
+
+ flen = get_file_length(name);
+ if (!flen) {
+ fprintf(stderr, "ERROR: file %s is zero length\n", name);
+ return 1;
+ }
+
+ in = fopen(name, "rb");
+ if (!in) {
+ perror("FAILED: fopen");
+ return 1;
+ }
+
+ whole = XPT_MALLOC(arena, flen);
+ if (!whole) {
+ perror("FAILED: XPT_MALLOC for whole");
+ return 1;
+ }
+
+ if (flen > 0) {
+ size_t rv = fread(whole, 1, flen, in);
+ if (rv < flen) {
+ fprintf(stderr, "short read (%zd vs %zd)! ouch!\n", rv, flen);
+ return 1;
+ }
+ if (ferror(in) != 0 || fclose(in) != 0) {
+ perror("FAILED: Unable to read typelib file.\n");
+ return 1;
+ }
+
+ state = XPT_NewXDRState(XPT_DECODE, whole, flen);
+ if (!XPT_MakeCursor(state, XPT_HEADER, 0, cursor)) {
+ fprintf(stdout, "XPT_MakeCursor failed for %s\n", name);
+ return 1;
+ }
+ if (!XPT_DoHeader(arena, cursor, &header)) {
+ fprintf(stdout,
+ "DoHeader failed for %s. Is %s a valid .xpt file?\n",
+ name, name);
+ return 1;
+ }
+
+ /*
+ * Make sure that the version of the typelib file is less than or
+ * equal to the version specified in the -t cmd line arg.
+ */
+
+ if (header &&
+ (header->major_version > major_version ||
+ (header->major_version == major_version &&
+ header->minor_version > minor_version))) {
+ fprintf(stderr, "FAILED: %s's version, %d.%d, is newer than "
+ "the version (%d.%d) specified in the -t "
+ "command line argument.\n",
+ name, header->major_version, header->minor_version,
+ major_version, minor_version);
+ return 1;
+ }
+
+ oldTotalNumberOfInterfaces = totalNumberOfInterfaces;
+ totalNumberOfInterfaces += header->num_interfaces;
+ if (header->num_interfaces > 0) {
+ XPTInterfaceDirectoryEntry *newIDE;
+ fixElement *newFix;
+
+ newIDE = (XPTInterfaceDirectoryEntry *)
+ XPT_MALLOC(arena, totalNumberOfInterfaces *
+ sizeof(XPTInterfaceDirectoryEntry));
+ if (!newIDE) {
+ perror("FAILED: XPT_MALLOC of IDE_array");
+ return 1;
+ }
+
+ if (IDE_array) {
+ if (oldTotalNumberOfInterfaces)
+ memcpy(newIDE, IDE_array,
+ oldTotalNumberOfInterfaces *
+ sizeof(XPTInterfaceDirectoryEntry));
+ XPT_FREE(arena, IDE_array);
+ }
+ IDE_array = newIDE;
+
+
+ newFix = (fixElement *)
+ XPT_MALLOC(arena,
+ totalNumberOfInterfaces * sizeof(fixElement));
+ if (!newFix) {
+ perror("FAILED: XPT_MALLOC of fix_array");
+ return 1;
+ }
+
+ if (fix_array) {
+ if (oldTotalNumberOfInterfaces)
+ memcpy(newFix, fix_array,
+ oldTotalNumberOfInterfaces *
+ sizeof(fixElement));
+ XPT_FREE(arena, fix_array);
+ }
+ fix_array = newFix;
+
+ for (j=0; j<header->num_interfaces; j++) {
+ if (!copy_IDE(&header->interface_directory[j],
+ &IDE_array[k])) {
+ perror("FAILED: 1st copying of IDE");
+ return 1;
+ }
+ fix_array[k].iid = IDE_array[k].iid;
+ fix_array[k].name = IDE_array[k].name;
+ fix_array[k].file_num = i-2;
+ fix_array[k].interface_num = j+1;
+ fix_array[k].is_deleted = PR_FALSE;
+ fix_array[k].maps_to_file_num = i-2;
+ fix_array[k].maps_to_interface_num = j+1;
+
+ k++;
+ }
+ }
+
+ /* Copy the annotations if they are not 'empty'
+ */
+ if (header->annotations != NULL &&
+ header->annotations->flags != XPT_ANN_LAST) {
+ ann = first_ann;
+ while (ann->next != NULL) {
+ ann = ann->next;
+ }
+ ann->next = header->annotations;
+ }
+
+ XPT_FREEIF(arena, header);
+ if (state)
+ XPT_DestroyXDRState(state);
+ XPT_FREE(arena, whole);
+ flen = 0;
+
+ } else {
+ fclose(in);
+ perror("FAILED: file length <= 0");
+ return 1;
+ }
+ }
+
+ /* Make sure the last annotation is the only one marked as XP_ANN_LAST.
+ */
+ ann = first_ann;
+ while (ann->next != NULL) {
+ ann->flags &= ~XPT_ANN_LAST;
+ ann = ann->next;
+ }
+ ann->flags |= XPT_ANN_LAST;
+
+ /* Sort both IDE_array and fix_array by name so we can check for
+ * name_space::name collisions.
+ */
+ qsort(IDE_array,
+ totalNumberOfInterfaces,
+ sizeof(XPTInterfaceDirectoryEntry),
+ compare_IDEs_by_name);
+
+ qsort(fix_array,
+ totalNumberOfInterfaces,
+ sizeof(fixElement),
+ compare_fixElements_by_name);
+
+ /* trueNumberOfInterfaces == number of interfaces left after deletions
+ * are made. Initialize it here to be the same as the total number of
+ * interfaces we'ce encountered thus far.
+ */
+ trueNumberOfInterfaces = totalNumberOfInterfaces;
+
+ /* Iterate through the sorted interfaces. Start at one so we don't
+ * accidentally walk off the end of the array.
+ */
+ i = 1;
+ while (i != trueNumberOfInterfaces) {
+
+ /* Check for name_space::name collision.
+ */
+ if (compare_strings(IDE_array[i-1].name,
+ IDE_array[i].name) == 0 &&
+ compare_strings(IDE_array[i-1].name_space,
+ IDE_array[i].name_space) == 0) {
+
+ /* If one of the interfaces is unresolved, delete that one
+ * preferentailly.
+ */
+ if (!IDE_array[i-1].interface_descriptor) {
+ /* Shrink the IDE_array to delete the duplicate interface.
+ */
+ if (!shrink_IDE_array(IDE_array,
+ i-1,
+ trueNumberOfInterfaces)) {
+ perror("FAILED: shrink_IDE_array");
+ return 1;
+ }
+ /* Update the fix array. This involves moving the deleted
+ * entry to the end of the array (rather than deleting it)
+ * and mapping it to the "replacement" element so we can
+ * update interface indices appropriately later.
+ */
+ update_fix_array(arena, fix_array, i-1,
+ totalNumberOfInterfaces, i);
+ /* Decrement the true number of interfaces since we just
+ * deleted one. There's more than one way to get out of
+ * this loop.
+ */
+ trueNumberOfInterfaces--;
+ } else {
+ if (!IDE_array[i].interface_descriptor ||
+ (compare_IIDs(&IDE_array[i-1].iid, &IDE_array[i].iid) == 0))
+ {
+ /* Shrink the IDE_array to delete the duplicate interface.
+ */
+ if (!shrink_IDE_array(IDE_array,
+ i,
+ trueNumberOfInterfaces)) {
+ perror("FAILED: shrink_IDE_array");
+ return 1;
+ }
+ /* Update the fix array. This involves moving the deleted
+ * entry to the end of the array (rather than deleting it)
+ * and mapping it to the "replacement" element so we can
+ * update interface indices appropriately later.
+ */
+ update_fix_array(arena, fix_array, i,
+ totalNumberOfInterfaces, i-1);
+ /* Decrement the true number of interfaces since we just
+ * deleted one. There's more than one way to get out of
+ * this loop.
+ */
+ trueNumberOfInterfaces--;
+ } else {
+ /* Found interfaces with duplicate names but different
+ * iids! */
+ char *ns = IDE_array[i].name_space;
+ fprintf(stderr,
+ "ERROR: found duplicate definitions of interface "
+ "%s%s%s with iids \n",
+ ns ? ns : "", ns ? "::" : "", IDE_array[i].name);
+ print_IID(&IDE_array[i].iid, stderr);
+ fprintf(stderr, " and ");
+ print_IID(&IDE_array[i-1].iid, stderr);
+ fprintf(stderr, "\n");
+ return 1;
+ }
+ }
+ } else {
+ /* Only increment if there was no name_space::name collision.
+ */
+ i++;
+ }
+ }
+
+ /* Sort the IDE_array (put them in their final order) so that updating
+ * of indices will be meaningful.
+ */
+ qsort(IDE_array,
+ trueNumberOfInterfaces,
+ sizeof(XPTInterfaceDirectoryEntry),
+ compare_IDEs_by_IID);
+
+ /* Sort the fix_array to match the IDE_array.
+ */
+ qsort(fix_array,
+ trueNumberOfInterfaces,
+ sizeof(fixElement),
+ compare_fixElements_by_IID);
+
+ /* Iterate through the remaining interfaces (those not deleted)
+ * looking for references to interfaces (such as id->parent_interface)
+ * which need an updated index number.
+ */
+ for (i=0; i<trueNumberOfInterfaces; i++) {
+
+ /* Define id to save some keystrokes.
+ */
+ id = IDE_array[i].interface_descriptor;
+
+ /* Check for unresolved interface.
+ */
+ if (id) {
+
+ /* Fix parent_interface first.
+ */
+ if (id->parent_interface && id->parent_interface != 0) {
+ id->parent_interface =
+ get_new_index(fix_array, totalNumberOfInterfaces,
+ fix_array[i].file_num, id->parent_interface);
+ }
+ /* Iterate through the method descriptors looking for params of
+ * type TD_INTERFACE_TYPE.
+ */
+ for (j=0; j<id->num_methods; j++) {
+ /* Cycle through the params first.
+ */
+ for (k=0; k<id->method_descriptors[j].num_args; k++) {
+ /* Define td to save some keystrokes.
+ */
+ td = &id->method_descriptors[j].params[k].type;
+
+ while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) {
+ td = &id->additional_types[td->type.additional_type];
+ }
+
+ if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_TYPE) {
+ td->type.iface =
+ get_new_index(fix_array,
+ totalNumberOfInterfaces,
+ fix_array[i].file_num,
+ td->type.iface);
+ }
+ }
+
+ /* Check the result param too. Define td again to save
+ * some keystrokes.
+ */
+ td = &id->method_descriptors[j].result->type;
+ if (XPT_TDP_TAG(td->prefix) == TD_INTERFACE_TYPE) {
+ td->type.iface =
+ get_new_index(fix_array, totalNumberOfInterfaces,
+ fix_array[i].file_num,
+ td->type.iface);
+ }
+ }
+ }
+ }
+
+ /* Iterate through the array quickly looking for duplicate IIDS.
+ * This shouldn't happen, i.e. is a failure condition, so bail
+ * if we find a duplicate. If we have more than one entry, start
+ * at one so we don't accidentally grep the ether.
+ */
+ if (trueNumberOfInterfaces>1) {
+ for (i=1; i<trueNumberOfInterfaces; i++) {
+ /* Only complain if the IIDs are identical and nonzero. */
+ if (compare_IIDs(&IDE_array[i-1].iid, &IDE_array[i].iid) == 0 &&
+ compare_IDE_with_zero(&IDE_array[i]) != 0) {
+ fprintf(stderr, "FATAL ERROR:\n"
+ "Duplicate IID detected (");
+ print_IID(&IDE_array[i-1].iid, stderr);
+ fprintf(stderr, ") in\n"
+ "interface %s::%s from %s\n"
+ "and\n"
+ "interface %s::%s from %s\n",
+ IDE_array[i-1].name_space ?
+ IDE_array[i-1].name_space : "",
+ IDE_array[i-1].name,
+ argv[fix_array[i-1].file_num+2],
+ IDE_array[i].name_space ?
+ IDE_array[i].name_space : "",
+ IDE_array[i].name,
+ argv[fix_array[i].file_num+2]);
+ return 1;
+ }
+ }
+ }
+
+ header = XPT_NewHeader(arena, (PRUint16)trueNumberOfInterfaces,
+ major_version, minor_version);
+
+ header->annotations = first_ann;
+ for (i=0; i<trueNumberOfInterfaces; i++) {
+ if (!copy_IDE(&IDE_array[i], &header->interface_directory[i])) {
+ perror("FAILED: 2nd copying of IDE");
+ return 1;
+ }
+ }
+
+ header_sz = XPT_SizeOfHeaderBlock(header);
+
+ state = XPT_NewXDRState(XPT_ENCODE, NULL, 0);
+ if (!state) {
+ perror("FAILED: error creating XDRState");
+ return 1;
+ }
+
+ XPT_SetDataOffset(state, header_sz);
+
+ if (!XPT_MakeCursor(state, XPT_HEADER, header_sz, cursor)) {
+ perror("FAILED: error making cursor");
+ return 1;
+ }
+ oldOffset = cursor->offset;
+ if (!XPT_DoHeader(arena, cursor, &header)) {
+ perror("FAILED: error doing Header");
+ return 1;
+ }
+ newOffset = cursor->offset;
+ XPT_GetXDRDataLength(state, XPT_HEADER, &len);
+ header->file_length = len;
+ XPT_GetXDRDataLength(state, XPT_DATA, &len);
+ header->file_length += len;
+ XPT_SeekTo(cursor, oldOffset);
+ if (!XPT_DoHeaderPrologue(arena, cursor, &header, NULL)) {
+ perror("FAILED: error doing Header");
+ return 1;
+ }
+ XPT_SeekTo(cursor, newOffset);
+ out = fopen(outFileName, "wb");
+ if (!out) {
+ perror("FAILED: fopen");
+ return 1;
+ }
+
+ XPT_GetXDRData(state, XPT_HEADER, &head, &len);
+ fwrite(head, len, 1, out);
+
+ XPT_GetXDRData(state, XPT_DATA, &data, &len);
+ fwrite(data, len, 1, out);
+
+ if (ferror(out) != 0 || fclose(out) != 0) {
+ fprintf(stderr, "Error writing file: %s\n", argv[1]);
+ } else {
+/* fprintf(stderr, "File written: %s\n", argv[1]); */
+ }
+
+ if (state)
+ XPT_DestroyXDRState(state);
+
+ XPT_DestroyArena(arena);
+
+ return 0;
+}
+
+static int
+compare_IDEs_by_IID(const void *ap,
+ const void *bp)
+{
+ const XPTInterfaceDirectoryEntry *ide1 = ap, *ide2 = bp;
+
+ int answer = compare_IIDs(&ide1->iid, &ide2->iid);
+ if(!answer)
+ answer = compare_strings(ide1->name, ide2->name);
+
+ return answer;
+}
+
+/* For detecting unresolved interfaces. */
+const nsID iid_zero = { 0x0, 0x0, 0x0,
+ { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } };
+
+static int
+compare_IDE_with_zero(const void *ap)
+{
+ const XPTInterfaceDirectoryEntry *ide1 = ap;
+
+ return compare_IIDs(&ide1->iid, &iid_zero);
+}
+
+static int
+compare_fixElements_by_IID(const void *ap,
+ const void *bp)
+{
+ const fixElement *fix1 = ap, *fix2 = bp;
+
+ int answer = compare_IIDs(&fix1->iid, &fix2->iid);
+ if(!answer)
+ answer = compare_strings(fix1->name, fix2->name);
+
+ return answer;
+}
+
+static int
+compare_IDEs_by_name(const void *ap,
+ const void *bp)
+{
+ const XPTInterfaceDirectoryEntry *ide1 = ap, *ide2 = bp;
+
+ int answer = compare_strings(ide1->name, ide2->name);
+ if(!answer)
+ answer = compare_pointers(ide1->name, ide2->name);
+
+ return answer;
+}
+
+static int
+compare_IDEs_by_name_space(const void *ap,
+ const void *bp)
+{
+ const XPTInterfaceDirectoryEntry *ide1 = ap, *ide2 = bp;
+
+ return compare_strings(ide1->name_space, ide2->name_space);
+}
+
+static int
+compare_strings(const void *ap, const void *bp)
+{
+ const char *string1 = ap, *string2 = bp;
+
+ if (!string1 && !string2)
+ return 0;
+ if (!string1)
+ return -1;
+ if (!string2)
+ return 1;
+
+ return strcmp(string1, string2);
+}
+
+static int
+compare_pointers(const void *ap, const void *bp)
+{
+ if (ap == bp) {
+#ifdef DEBUG_jband
+ perror("name addresses were equal!");
+#endif
+ return 0;
+ }
+ if (ap > bp)
+ return 1;
+ return -1;
+}
+
+static int
+compare_fixElements_by_name(const void *ap,
+ const void *bp)
+{
+ const fixElement *fix1 = ap, *fix2 = bp;
+
+ int answer= compare_strings(fix1->name, fix2->name);
+ if(!answer)
+ answer = compare_pointers(fix1->name, fix2->name);
+
+ return answer;
+}
+
+static int
+compare_IIDs(const void *ap, const void *bp)
+{
+ const nsID *a = ap, *b = bp;
+ int i;
+#define COMPARE(field) if (a->field > b->field) return 1; \
+ if (b->field > a->field) return -1;
+ COMPARE(m0);
+ COMPARE(m1);
+ COMPARE(m2);
+ for (i = 0; i < 8; i++) {
+ COMPARE(m3[i]);
+ }
+ return 0;
+#undef COMPARE
+}
+
+PRBool
+shrink_IDE_array(XPTInterfaceDirectoryEntry *ide, int element_to_delete,
+ int num_interfaces)
+{
+ int i;
+
+ if (element_to_delete >= num_interfaces) {
+ return PR_FALSE;
+ }
+
+ for (i=element_to_delete+1; i<num_interfaces; i++) {
+ if (!copy_IDE(&ide[i], &ide[i-1])) {
+ return PR_FALSE;
+ }
+ }
+
+ return PR_TRUE;
+}
+
+/* update_fix_array marks a fixElement as deleted, updates its mapping
+ * to point to the "replacement" element, and moves it to the end of
+ * the array.
+ */
+PRBool
+update_fix_array(XPTArena *arena, fixElement *fix, int element_to_delete,
+ int num_interfaces, int replacement)
+{
+ fixElement *deleted;
+ int i;
+
+ if (element_to_delete >= num_interfaces) {
+ return PR_FALSE;
+ }
+
+ deleted = XPT_CALLOC(arena, sizeof(fixElement));
+ if (!copy_fixElement(&fix[element_to_delete], deleted)) {
+ return PR_FALSE;
+ }
+ deleted->is_deleted = PR_TRUE;
+ deleted->maps_to_file_num = fix[replacement].file_num;
+ deleted->maps_to_interface_num = fix[replacement].interface_num;
+
+ for (i=element_to_delete+1; i<num_interfaces; i++) {
+ if (!copy_fixElement(&fix[i], &fix[i-1])) {
+ return PR_FALSE;
+ }
+ }
+
+ if (!copy_fixElement(deleted, &fix[num_interfaces-1])) {
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+}
+
+/* get_new_index returns the new interface index by walking the fix_array
+ * until the file_num and interface_num match the target values. If a match
+ * is found, it checks to see if that element has been deleted. If it has
+ * been deleted, it follows that elements mapping until it gets to the
+ * proper interface (recursion). FYI, Indices are one-based; zero
+ * represents the special case (no parent interface).
+ */
+static int
+get_new_index(const fixElement *fix, int num_elements,
+ int target_file, int target_interface)
+{
+ int i;
+
+ for (i=0; i<num_elements; i++) {
+ if (fix[i].file_num == target_file &&
+ fix[i].interface_num == target_interface) {
+ if (fix[i].is_deleted) {
+ return get_new_index(fix, num_elements,
+ fix[i].maps_to_file_num,
+ fix[i].maps_to_interface_num);
+ }
+ return i+1;
+ }
+ }
+
+ return 0;
+}
+
+PRBool
+copy_IDE(XPTInterfaceDirectoryEntry *from, XPTInterfaceDirectoryEntry *to)
+{
+ if (!from || !to) {
+ return PR_FALSE;
+ }
+
+ to->iid = from->iid;
+ to->name = from->name;
+ to->name_space = from->name_space;
+ to->interface_descriptor = from->interface_descriptor;
+ return PR_TRUE;
+}
+
+PRBool
+copy_fixElement(fixElement *from, fixElement *to)
+{
+ if (!from || !to) {
+ return PR_FALSE;
+ }
+
+ to->iid = from->iid;
+ to->name = from->name;
+ to->file_num = from->file_num;
+ to->interface_num = from->interface_num;
+ to->is_deleted = from->is_deleted;
+ to->maps_to_file_num = from->maps_to_file_num;
+ to->maps_to_interface_num = from->maps_to_interface_num;
+
+ return PR_TRUE;
+}
+
+static void
+print_IID(struct nsID *iid, FILE *file)
+{
+ fprintf(file, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ (PRUint32) iid->m0, (PRUint32) iid->m1,(PRUint32) iid->m2,
+ (PRUint32) iid->m3[0], (PRUint32) iid->m3[1],
+ (PRUint32) iid->m3[2], (PRUint32) iid->m3[3],
+ (PRUint32) iid->m3[4], (PRUint32) iid->m3[5],
+ (PRUint32) iid->m3[6], (PRUint32) iid->m3[7]);
+}
+
+static void
+xpt_link_usage(char *argv[])
+{
+ fprintf(stdout, "Usage: %s [-t version number] outfile file1.xpt file2.xpt ...\n"
+ " Links multiple typelib files into one outfile\n"
+ " -t create a typelib of an older version number\n", argv[0]);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/windbgdlg/.cvsignore b/src/libs/xpcom18a4/xpcom/windbgdlg/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/windbgdlg/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/windbgdlg/Makefile.in b/src/libs/xpcom18a4/xpcom/windbgdlg/Makefile.in
new file mode 100644
index 00000000..da1bcfae
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/windbgdlg/Makefile.in
@@ -0,0 +1,50 @@
+#
+# ***** 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
+
+SIMPLE_PROGRAMS = windbgdlg$(BIN_SUFFIX)
+
+CPPSRCS = windbgdlg.cpp
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/windbgdlg/windbgdlg.cpp b/src/libs/xpcom18a4/xpcom/windbgdlg/windbgdlg.cpp
new file mode 100644
index 00000000..9023ef4d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/windbgdlg/windbgdlg.cpp
@@ -0,0 +1,60 @@
+/* -*- 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 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) 1999
+ * 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 ***** */
+
+/* Windows only app to show a modal debug dialog - launched by nsDebug.cpp */
+
+#include <windows.h>
+
+int WINAPI
+WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
+ LPSTR lpszCmdLine, int nCmdShow)
+{
+ static char msg[4048];
+
+ wsprintf(msg,
+ "%s\n\nClick Abort to exit the Application.\n"
+ "Click Retry to Debug the Application..\n"
+ "Click Ignore to continue running the Application.",
+ lpszCmdLine);
+
+ return MessageBox(NULL, msg, "nsDebug::Assertion",
+ MB_ICONSTOP | MB_SYSTEMMODAL|
+ MB_ABORTRETRYIGNORE | MB_DEFBUTTON3);
+}
diff --git a/src/libs/xpcom18a4/xpcom/xpcom-config.h.in b/src/libs/xpcom18a4/xpcom/xpcom-config.h.in
new file mode 100644
index 00000000..5338a41d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/xpcom-config.h.in
@@ -0,0 +1,65 @@
+/* Global defines needed by xpcom clients */
+
+#ifndef _XPCOM_CONFIG_H_
+#define _XPCOM_CONFIG_H_
+
+/* Define this to throw() if the compiler complains about
+ * constructors returning NULL
+ */
+#undef CPP_THROW_NEW
+
+/* Define if the c++ compiler supports a 2-byte wchar_t */
+#undef HAVE_CPP_2BYTE_WCHAR_T
+
+/* Define if the c++ compiler supports changing access with |using| */
+#undef HAVE_CPP_ACCESS_CHANGING_USING
+
+/* Define if the c++ compiler can resolve ambiguity with |using| */
+#undef HAVE_CPP_AMBIGUITY_RESOLVING_USING
+
+/* Define if the c++ compiler has builtin Bool type */
+#undef HAVE_CPP_BOOL
+
+/* Define if a dyanmic_cast to void* gives the most derived object */
+#undef HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR
+
+/* Define if the c++ compiler supports the |explicit| keyword */
+#undef HAVE_CPP_EXPLICIT
+
+/* Define if the c++ compiler supports the modern template
+ * specialization syntax
+ */
+#undef HAVE_CPP_MODERN_SPECIALIZE_TEMPLATE_SYNTAX
+
+/* Define if the c++ compiler supports the |std| namespace */
+#undef HAVE_CPP_NAMESPACE_STD
+
+/* Define if the c++ compiler supports reinterpret_cast */
+#undef HAVE_CPP_NEW_CASTS
+
+/* Define if the c++ compiler supports partial template specialization */
+#undef HAVE_CPP_PARTIAL_SPECIALIZATION
+
+/* Define if the c++ compiler has trouble comparing a constant
+ * reference to a templatized class to zero
+ */
+#undef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
+
+/* Define if the c++ compiler supports the |typename| keyword */
+#undef HAVE_CPP_TYPENAME
+
+/* Define if the stanard template operator!=() is ambiguous */
+#undef HAVE_CPP_UNAMBIGUOUS_STD_NOTEQUAL
+
+/* Define if statvfs() is available */
+#undef HAVE_STATVFS
+
+/* Define if the c++ compiler requires implementations of
+ * unused virtual methods
+ */
+#undef NEED_CPP_UNUSED_IMPLEMENTATIONS
+
+/* Define to either <new> or <new.h> */
+#undef NEW_H
+
+#endif /* _XPCOM_CONFIG_H_ */
diff --git a/src/libs/xpcom18a4/xpcom/xpcom-private.h.in b/src/libs/xpcom18a4/xpcom/xpcom-private.h.in
new file mode 100644
index 00000000..ae1c4605
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/xpcom-private.h.in
@@ -0,0 +1,31 @@
+/* The following defines are only used by the xpcom implementation */
+
+#ifndef _XPCOM_PRIVATE_H_
+#define _XPCOM_PRIVATE_H_
+
+/* Define to build the static component loader */
+#undef ENABLE_STATIC_COMPONENT_LOADER
+
+/* Define if getpagesize() is available */
+#undef HAVE_GETPAGESIZE
+
+/* Define if iconv() is available */
+#undef HAVE_ICONV
+
+/* Define if iconv() supports const input */
+#undef HAVE_ICONV_WITH_CONST_INPUT
+
+/* Define if mbrtowc() is available */
+#undef HAVE_MBRTOWC
+
+/* Define if <sys/mount.h> is present */
+#undef HAVE_SYS_MOUNT_H
+
+/* Define if <sys/vfs.h> is present */
+#undef HAVE_SYS_VFS_H
+
+/* Define if wcrtomb() is available */
+#undef HAVE_WCRTOMB
+
+#endif /* _XPCOM_PRIVATE_H_ */
+