diff --git a/mozilla/modules/libreg/xpcom/nsIRegistry.idl b/mozilla/modules/libreg/xpcom/nsIRegistry.idl index da6bd006908..78b3ba67f76 100644 --- a/mozilla/modules/libreg/xpcom/nsIRegistry.idl +++ b/mozilla/modules/libreg/xpcom/nsIRegistry.idl @@ -119,6 +119,47 @@ interface nsIRegistryValue : nsISupports 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/mozilla/modules/libreg/xpcom/nsRegistry.cpp b/mozilla/modules/libreg/xpcom/nsRegistry.cpp index 3e948c6d73d..f9aa856a512 100644 --- a/mozilla/modules/libreg/xpcom/nsRegistry.cpp +++ b/mozilla/modules/libreg/xpcom/nsRegistry.cpp @@ -357,7 +357,7 @@ static void reginfo2Length( const REGINFO &in, PRUint32 &out ) { | This code generates the implementation of the nsISupports member functions | | for each class implemented in this file. | ------------------------------------------------------------------------------*/ -NS_IMPL_THREADSAFE_ISUPPORTS1( nsRegistry, nsIRegistry ) +NS_IMPL_THREADSAFE_ISUPPORTS2(nsRegistry, nsIRegistry, nsIRegistryGetter) NS_IMPL_ISUPPORTS2( nsRegSubtreeEnumerator, nsIEnumerator, nsIRegistryEnumerator) NS_IMPL_ISUPPORTS1( nsRegistryNode, nsIRegistryNode ) @@ -733,7 +733,8 @@ NS_IMETHODIMP nsRegistry::GetStringUTF8( nsRegistryKey baseKey, const char *path // Attempt to get string into our fixed buffer PR_Lock(mregLock); - err = NR_RegGetEntryString( mReg,(RKEY)baseKey,(char*)path, regStr, sizeof regStr ); + err = NR_RegGetEntryString( mReg,(RKEY)baseKey,(char*)path, regStr, + sizeof(regStr) ); PR_Unlock(mregLock); if ( err == REGERR_OK ) @@ -783,6 +784,30 @@ NS_IMETHODIMP nsRegistry::GetStringUTF8( nsRegistryKey baseKey, const char *path 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. | ------------------------------------------------------------------------------*/ @@ -884,6 +909,41 @@ NS_IMETHODIMP nsRegistry::GetBytesUTF8( nsRegistryKey baseKey, const char *path, 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, (unsigned long *)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 | diff --git a/mozilla/modules/libreg/xpcom/nsRegistry.h b/mozilla/modules/libreg/xpcom/nsRegistry.h index 960f9aba3e3..b70cfb4ac0b 100644 --- a/mozilla/modules/libreg/xpcom/nsRegistry.h +++ b/mozilla/modules/libreg/xpcom/nsRegistry.h @@ -43,13 +43,16 @@ #include "nsIRegistry.h" #include "NSReg.h" -struct nsRegistry : public nsIRegistry { +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 + // ctor/dtor nsRegistry(); virtual ~nsRegistry(); diff --git a/mozilla/xpcom/components/nsComponentManager.cpp b/mozilla/xpcom/components/nsComponentManager.cpp index a82974ef695..e0e812906fb 100644 --- a/mozilla/xpcom/components/nsComponentManager.cpp +++ b/mozilla/xpcom/components/nsComponentManager.cpp @@ -736,7 +736,7 @@ nsComponentManagerImpl::PlatformInit(void) // Set larger-than-standard buffer size to speed startup. // This will be re-set at the end of PrePopulateRegistry() - mRegistry->SetBufferSize(500*1024); + ((nsRegistry *)mRegistry)->SetBufferSize(500*1024); // Check the version of registry. Nuke old versions. nsRegistryKey xpcomRoot; @@ -1118,11 +1118,17 @@ nsComponentManagerImpl::PlatformCLSIDToContractID(const nsCID *aClass, nsresult nsComponentManagerImpl::PlatformPrePopulateRegistry() { nsresult rv; + char buf[MAXREGPATHLEN]; + PRUint32 bufLength = sizeof(buf); if (mPrePopulationDone) return NS_OK; - (void)mRegistry->SetBufferSize( 500*1024 ); + (void)((nsRegistry *)mRegistry)->SetBufferSize( 500*1024 ); + + nsCOMPtr regGetter = do_QueryInterface(mRegistry); + if (!regGetter.get()) + return NS_ERROR_FAILURE; // Read in all CID entries and populate the mFactories nsCOMPtr cidEnum; @@ -1148,30 +1154,32 @@ nsresult nsComponentManagerImpl::PlatformPrePopulateRegistry() rv = regEnum->CurrentItemInPlaceUTF8(&cidKey, &cidString); if (NS_FAILED(rv)) continue; - // Create the CID entry - nsXPIDLCString library; - PRUint32 tmp; - rv = mRegistry->GetBytesUTF8(cidKey, inprocServerValueName, - &tmp, (PRUint8**)getter_Copies(library).operator char**()); - if (NS_FAILED(rv)) continue; - nsCID aClass; - - if (!(aClass.Parse(cidString))) continue; - - nsXPIDLCString componentType; - if (NS_FAILED(mRegistry->GetStringUTF8(cidKey, componentTypeValueName, - getter_Copies(componentType)))) + // Figure out the component type + // Use the non allocating registry getter. Our buffer is big enough + // We wont get NS_ERROR_REG_BUFFER_TOO_SMALL + bufLength = sizeof(buf); + rv = regGetter->GetStringUTF8IntoBuffer(cidKey, componentTypeValueName, buf, &bufLength); + if (NS_FAILED(rv)) continue; - int loadertype = GetLoaderType(componentType); + int loadertype = GetLoaderType(buf); if (loadertype < 0) { - loadertype = AddLoaderType(componentType); + loadertype = AddLoaderType(buf); } - nsFactoryEntry* entry = - new nsFactoryEntry(aClass, library, loadertype); - if (!entry) + // Create the CID entry + bufLength = sizeof(buf); + rv = regGetter->GetBytesUTF8IntoBuffer(cidKey, inprocServerValueName, + (PRUint8 *) buf, &bufLength); + if (NS_FAILED(rv)) continue; + nsCID aClass; + if (!(aClass.Parse(cidString))) + continue; + + nsFactoryEntry *entry = new nsFactoryEntry(aClass, buf, loadertype); + if (!entry) + return NS_ERROR_OUT_OF_MEMORY; nsAutoMonitor mon(mMon); @@ -1208,22 +1216,21 @@ nsresult nsComponentManagerImpl::PlatformPrePopulateRegistry() * It is also faster, and less painful in the allocation department. */ rv = regEnum->CurrentItemInPlaceUTF8(&contractidKey, &contractidString); - if (NS_FAILED(rv)) continue; - - nsXPIDLCString cidString; - rv = mRegistry->GetStringUTF8(contractidKey, classIDValueName, - getter_Copies(cidString)); - if (NS_FAILED(rv)) continue; - - nsCID aClass; - if (!(aClass.Parse(cidString))) - { + if (NS_FAILED(rv)) + continue; + + // Use the non allocating registry getter. Our buffer is big enough + // We wont get NS_ERROR_REG_BUFFER_TOO_SMALL + bufLength = sizeof(buf); + rv = regGetter->GetStringUTF8IntoBuffer(contractidKey, classIDValueName, buf, &bufLength); + if (NS_FAILED(rv)) + continue; + nsCID aClass; + if (!aClass.Parse(buf)) continue; - } // put the {contractid, Cid} mapping into our map HashContractID(contractidString, aClass); - // printf("Populating [ %s, %s ]\n", cidString, contractidString); } //(void)mRegistry->SetBufferSize( 10*1024 ); @@ -2830,7 +2837,7 @@ nsresult nsComponentManagerImpl::AutoRegister(PRInt32 when, nsIFile *inDirSpec) { nsresult rv; - mRegistry->SetBufferSize( 500*1024 ); + ((nsRegistry *)mRegistry)->SetBufferSize( 500*1024 ); rv = AutoRegisterImpl(when, inDirSpec); mRegistry->Flush(); //mRegistry->SetBufferSize( 10*1024 ); diff --git a/mozilla/xpcom/components/nsComponentManager.h b/mozilla/xpcom/components/nsComponentManager.h index 95db53e4c92..19e3949277a 100644 --- a/mozilla/xpcom/components/nsComponentManager.h +++ b/mozilla/xpcom/components/nsComponentManager.h @@ -196,7 +196,7 @@ protected: PLDHashTable mFactories; PLDHashTable mContractIDs; PRMonitor* mMon; - nsRegistry* mRegistry; + nsIRegistry* mRegistry; nsRegistryKey mXPCOMKey; nsRegistryKey mClassesKey; nsRegistryKey mCLSIDKey; diff --git a/mozilla/xpcom/components/nsIRegistry.idl b/mozilla/xpcom/components/nsIRegistry.idl index da6bd006908..78b3ba67f76 100644 --- a/mozilla/xpcom/components/nsIRegistry.idl +++ b/mozilla/xpcom/components/nsIRegistry.idl @@ -119,6 +119,47 @@ interface nsIRegistryValue : nsISupports 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/mozilla/xpcom/components/nsRegistry.cpp b/mozilla/xpcom/components/nsRegistry.cpp index 3e948c6d73d..f9aa856a512 100644 --- a/mozilla/xpcom/components/nsRegistry.cpp +++ b/mozilla/xpcom/components/nsRegistry.cpp @@ -357,7 +357,7 @@ static void reginfo2Length( const REGINFO &in, PRUint32 &out ) { | This code generates the implementation of the nsISupports member functions | | for each class implemented in this file. | ------------------------------------------------------------------------------*/ -NS_IMPL_THREADSAFE_ISUPPORTS1( nsRegistry, nsIRegistry ) +NS_IMPL_THREADSAFE_ISUPPORTS2(nsRegistry, nsIRegistry, nsIRegistryGetter) NS_IMPL_ISUPPORTS2( nsRegSubtreeEnumerator, nsIEnumerator, nsIRegistryEnumerator) NS_IMPL_ISUPPORTS1( nsRegistryNode, nsIRegistryNode ) @@ -733,7 +733,8 @@ NS_IMETHODIMP nsRegistry::GetStringUTF8( nsRegistryKey baseKey, const char *path // Attempt to get string into our fixed buffer PR_Lock(mregLock); - err = NR_RegGetEntryString( mReg,(RKEY)baseKey,(char*)path, regStr, sizeof regStr ); + err = NR_RegGetEntryString( mReg,(RKEY)baseKey,(char*)path, regStr, + sizeof(regStr) ); PR_Unlock(mregLock); if ( err == REGERR_OK ) @@ -783,6 +784,30 @@ NS_IMETHODIMP nsRegistry::GetStringUTF8( nsRegistryKey baseKey, const char *path 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. | ------------------------------------------------------------------------------*/ @@ -884,6 +909,41 @@ NS_IMETHODIMP nsRegistry::GetBytesUTF8( nsRegistryKey baseKey, const char *path, 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, (unsigned long *)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 | diff --git a/mozilla/xpcom/components/nsRegistry.h b/mozilla/xpcom/components/nsRegistry.h index 960f9aba3e3..b70cfb4ac0b 100644 --- a/mozilla/xpcom/components/nsRegistry.h +++ b/mozilla/xpcom/components/nsRegistry.h @@ -43,13 +43,16 @@ #include "nsIRegistry.h" #include "NSReg.h" -struct nsRegistry : public nsIRegistry { +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 + // ctor/dtor nsRegistry(); virtual ~nsRegistry();