Back to index

lightning-sunbird  0.9+nobinonly
xptiWorkingSet.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Mike McCabe <mccabe@netscape.com>
00024  *   John Bandhauer <jband@netscape.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 /* Implementation of xptiWorkingSet. */
00041 
00042 #include "xptiprivate.h"
00043 #include "nsString.h"
00044 
00045 #define XPTI_STRING_ARENA_BLOCK_SIZE    (1024 * 1)
00046 #define XPTI_STRUCT_ARENA_BLOCK_SIZE    (1024 * 1)
00047 #define XPTI_HASHTABLE_SIZE             128
00048 
00049 /***************************************************************************/
00050 
00051 PR_STATIC_CALLBACK(const void*)
00052 IIDGetKey(PLDHashTable *table, PLDHashEntryHdr *entry)
00053 {
00054     return ((xptiHashEntry*)entry)->value->GetTheIID();
00055 }
00056 
00057 PR_STATIC_CALLBACK(PLDHashNumber)
00058 IIDHash(PLDHashTable *table, const void *key)
00059 {
00060     return (PLDHashNumber) ((const nsIID*)key)->m0;        
00061 }
00062 
00063 PR_STATIC_CALLBACK(PRBool)
00064 IIDMatch(PLDHashTable *table,
00065          const PLDHashEntryHdr *entry,
00066          const void *key)
00067 {
00068     const nsIID* iid1 = ((xptiHashEntry*)entry)->value->GetTheIID();
00069     const nsIID* iid2 = (const nsIID*)key;
00070     
00071     return iid1 == iid2 || iid1->Equals(*iid2);
00072 }       
00073           
00074 const static struct PLDHashTableOps IIDTableOps =
00075 {
00076     PL_DHashAllocTable,
00077     PL_DHashFreeTable,
00078     IIDGetKey,
00079     IIDHash,
00080     IIDMatch,
00081     PL_DHashMoveEntryStub,
00082     PL_DHashClearEntryStub,
00083     PL_DHashFinalizeStub
00084 };
00085 
00086 /***************************************************************************/
00087 
00088 PR_STATIC_CALLBACK(const void*)
00089 NameGetKey(PLDHashTable *table, PLDHashEntryHdr *entry)
00090 {
00091     return ((xptiHashEntry*)entry)->value->GetTheName();
00092 }
00093 
00094 PR_STATIC_CALLBACK(PRBool)
00095 NameMatch(PLDHashTable *table,
00096           const PLDHashEntryHdr *entry,
00097           const void *key)
00098 {
00099     const char* str1 = ((xptiHashEntry*)entry)->value->GetTheName();
00100     const char* str2 = (const char*) key;
00101     return str1 == str2 || 0 == PL_strcmp(str1, str2);
00102 }       
00103 
00104 static const struct PLDHashTableOps NameTableOps =
00105 {
00106     PL_DHashAllocTable,
00107     PL_DHashFreeTable,
00108     NameGetKey,
00109     PL_DHashStringKey,
00110     NameMatch,
00111     PL_DHashMoveEntryStub,
00112     PL_DHashClearEntryStub,
00113     PL_DHashFinalizeStub
00114 };
00115 
00116 /***************************************************************************/
00117 
00118 MOZ_DECL_CTOR_COUNTER(xptiWorkingSet)
00119 
00120 xptiWorkingSet::xptiWorkingSet(nsISupportsArray* aDirectories)
00121     : mFileCount(0),
00122       mMaxFileCount(0),
00123       mFileArray(nsnull),
00124       mZipItemCount(0),
00125       mMaxZipItemCount(0),
00126       mZipItemArray(nsnull),
00127       mStringArena(XPT_NewArena(XPTI_STRING_ARENA_BLOCK_SIZE, sizeof(char),
00128                                 "xptiWorkingSet strings")),
00129       mStructArena(XPT_NewArena(XPTI_STRUCT_ARENA_BLOCK_SIZE, sizeof(double),
00130                                 "xptiWorkingSet structs")),
00131       mDirectories(aDirectories),
00132       mNameTable(PL_NewDHashTable(&NameTableOps, nsnull, sizeof(xptiHashEntry),
00133                                   XPTI_HASHTABLE_SIZE)),
00134       mIIDTable(PL_NewDHashTable(&IIDTableOps, nsnull, sizeof(xptiHashEntry),
00135                                  XPTI_HASHTABLE_SIZE)),
00136       mFileMergeOffsetMap(nsnull),
00137       mZipItemMergeOffsetMap(nsnull)
00138 {
00139     MOZ_COUNT_CTOR(xptiWorkingSet);
00140     // do nothing else...            
00141 }        
00142 
00143 PRBool 
00144 xptiWorkingSet::IsValid() const
00145 {
00146     return  (mFileCount == 0 || mFileArray) &&
00147             (mZipItemCount == 0 || mZipItemArray) &&
00148             mStringArena &&
00149             mStructArena &&
00150             mNameTable &&
00151             mIIDTable;          
00152 }
00153 
00154 PR_STATIC_CALLBACK(PLDHashOperator)
00155 xpti_Remover(PLDHashTable *table, PLDHashEntryHdr *hdr,
00156              PRUint32 number, void *arg)
00157 {
00158     return PL_DHASH_REMOVE;
00159 }       
00160 
00161 PR_STATIC_CALLBACK(PLDHashOperator)
00162 xpti_Invalidator(PLDHashTable *table, PLDHashEntryHdr *hdr,
00163                  PRUint32 number, void *arg)
00164 {
00165     xptiInterfaceEntry* entry = ((xptiHashEntry*)hdr)->value;
00166     entry->LockedInvalidateInterfaceInfo();
00167     return PL_DHASH_NEXT;
00168 }
00169 
00170 void 
00171 xptiWorkingSet::InvalidateInterfaceInfos()
00172 {
00173     if(mNameTable)
00174     {
00175         nsAutoMonitor lock(xptiInterfaceInfoManager::GetInfoMonitor());
00176         PL_DHashTableEnumerate(mNameTable, xpti_Invalidator, nsnull);
00177     }
00178 }        
00179 
00180 void 
00181 xptiWorkingSet::ClearHashTables()
00182 {
00183     if(mNameTable)
00184         PL_DHashTableEnumerate(mNameTable, xpti_Remover, nsnull);
00185         
00186     if(mIIDTable)
00187         PL_DHashTableEnumerate(mIIDTable, xpti_Remover, nsnull);
00188 }
00189 
00190 void 
00191 xptiWorkingSet::ClearFiles()
00192 {
00193     if(mFileArray)
00194         delete [] mFileArray;
00195     mFileArray = nsnull;
00196     mMaxFileCount = 0;
00197     mFileCount = 0;
00198 }
00199 
00200 void 
00201 xptiWorkingSet::ClearZipItems()
00202 {
00203     if(mZipItemArray)
00204         delete [] mZipItemArray;
00205     mZipItemArray = nsnull;
00206     mMaxZipItemCount = 0;
00207     mZipItemCount = 0;
00208 }
00209 
00210 xptiWorkingSet::~xptiWorkingSet()
00211 {
00212     MOZ_COUNT_DTOR(xptiWorkingSet);
00213 
00214     ClearFiles();
00215     ClearZipItems();
00216     ClearHashTables();
00217 
00218     if(mNameTable)
00219         PL_DHashTableDestroy(mNameTable);
00220         
00221     if(mIIDTable)
00222         PL_DHashTableDestroy(mIIDTable);
00223 
00224     if(mFileArray)
00225         delete [] mFileArray;
00226 
00227     if(mZipItemArray)
00228         delete [] mZipItemArray;
00229 
00230     // Destroy arenas last in case they are referenced in other members' dtors.
00231 
00232     if(mStringArena)
00233     {
00234 #ifdef DEBUG
00235         XPT_DumpStats(mStringArena);
00236 #endif        
00237         XPT_DestroyArena(mStringArena);
00238     }
00239     
00240     if(mStructArena)
00241     {
00242 #ifdef DEBUG
00243         XPT_DumpStats(mStructArena);
00244 #endif        
00245         XPT_DestroyArena(mStructArena);
00246     }
00247 }        
00248 
00249 PRUint32 
00250 xptiWorkingSet::FindFile(PRUint32 dir, const char* name)
00251 {
00252     if(mFileArray)
00253     {
00254         for(PRUint32 i = 0; i < mFileCount;++i)
00255         {
00256             xptiFile& file = mFileArray[i];
00257             if(file.GetDirectory() == dir && 
00258                0 == PL_strcmp(name, file.GetName()))
00259             {
00260                 return i;
00261             }    
00262         }
00263     }
00264     return NOT_FOUND;
00265 }
00266 
00267 PRBool
00268 xptiWorkingSet::NewFileArray(PRUint32 count)
00269 {
00270     if(mFileArray)
00271         delete [] mFileArray;
00272     mFileCount = 0;
00273     mFileArray = new xptiFile[count];
00274     if(!mFileArray)
00275     {
00276         mMaxFileCount = 0;
00277         return PR_FALSE;
00278     }
00279     mMaxFileCount = count;
00280     return PR_TRUE;
00281 }
00282 
00283 PRBool 
00284 xptiWorkingSet::ExtendFileArray(PRUint32 count)
00285 {
00286     if(mFileArray && count < mMaxFileCount)
00287         return PR_TRUE;
00288 
00289     xptiFile* newArray = new xptiFile[count];
00290     if(!newArray)
00291         return PR_FALSE;
00292 
00293     if(mFileArray)
00294     {
00295         for(PRUint32 i = 0; i < mFileCount; ++i)
00296             newArray[i] = mFileArray[i];
00297         delete [] mFileArray;
00298     }
00299     mFileArray = newArray;
00300     mMaxFileCount = count;
00301     return PR_TRUE;
00302 }
00303 
00304 /***************************************************************************/
00305 
00306 PRUint32 
00307 xptiWorkingSet::FindZipItemWithName(const char* name)
00308 {
00309     if(mZipItemArray)
00310     {
00311         for(PRUint32 i = 0; i < mZipItemCount;++i)
00312             if(0 == PL_strcmp(name, mZipItemArray[i].GetName()))
00313                 return i;
00314     }
00315     return NOT_FOUND;
00316 }
00317 
00318 PRBool
00319 xptiWorkingSet::NewZipItemArray(PRUint32 count)
00320 {
00321     if(mZipItemArray)
00322         delete [] mZipItemArray;
00323     mZipItemCount = 0;
00324     mZipItemArray = new xptiZipItem[count];
00325     if(!mZipItemArray)
00326     {
00327         mMaxZipItemCount = 0;
00328         return PR_FALSE;
00329     }
00330     mMaxZipItemCount = count;
00331     return PR_TRUE;
00332 }
00333 
00334 PRBool 
00335 xptiWorkingSet::ExtendZipItemArray(PRUint32 count)
00336 {
00337     if(mZipItemArray && count < mMaxZipItemCount)
00338         return PR_TRUE;
00339 
00340     xptiZipItem* newArray = new xptiZipItem[count];
00341     if(!newArray)
00342         return PR_FALSE;
00343 
00344     if(mZipItemArray)
00345     {
00346         for(PRUint32 i = 0; i < mZipItemCount; ++i)
00347             newArray[i] = mZipItemArray[i];
00348         delete [] mZipItemArray;
00349     }
00350     mZipItemArray = newArray;
00351     mMaxZipItemCount = count;
00352     return PR_TRUE;
00353 }
00354 
00355 /***************************************************************************/
00356 // Directory stuff...
00357 
00358 PRUint32 xptiWorkingSet::GetDirectoryCount()
00359 {
00360     PRUint32 count = 0;
00361     mDirectories->Count(&count);
00362     return count;
00363 }
00364 
00365 nsresult xptiWorkingSet::GetCloneOfDirectoryAt(PRUint32 i, nsILocalFile** dir)
00366 {
00367     return xptiCloneElementAsLocalFile(mDirectories, i, dir);
00368 }
00369 
00370 nsresult xptiWorkingSet::GetDirectoryAt(PRUint32 i, nsILocalFile** dir)
00371 {
00372     return mDirectories->QueryElementAt(i, NS_GET_IID(nsILocalFile), (void**)dir);
00373 }       
00374 
00375 PRBool xptiWorkingSet::FindDirectory(nsILocalFile* dir, PRUint32* index)
00376 {
00377     PRUint32 count;
00378     nsresult rv = mDirectories->Count(&count);
00379     if(NS_FAILED(rv))
00380         return PR_FALSE;
00381 
00382     for(PRUint32 i = 0; i < count; i++)
00383     {
00384         PRBool same;
00385         nsCOMPtr<nsILocalFile> current;
00386         mDirectories->QueryElementAt(i, NS_GET_IID(nsILocalFile), 
00387                                      getter_AddRefs(current));
00388         if(!current || NS_FAILED(current->Equals(dir, &same)))
00389             break;
00390         if(same)
00391         {
00392             *index = i;    
00393             return PR_TRUE;       
00394         }
00395     }
00396     return PR_FALSE;
00397 }
00398 
00399 PRBool xptiWorkingSet::FindDirectoryOfFile(nsILocalFile* file, PRUint32* index)
00400 {
00401     nsCOMPtr<nsIFile> dirAbstract;
00402     file->GetParent(getter_AddRefs(dirAbstract));
00403     if(!dirAbstract)
00404         return PR_FALSE;
00405     nsCOMPtr<nsILocalFile> dir = do_QueryInterface(dirAbstract);
00406     if(!dir)
00407         return PR_FALSE;
00408     return FindDirectory(dir, index);
00409 }
00410 
00411 PRBool xptiWorkingSet::DirectoryAtMatchesPersistentDescriptor(PRUint32 i, 
00412                                                           const char* inDesc)
00413 {
00414     nsCOMPtr<nsILocalFile> dir;
00415     GetDirectoryAt(i, getter_AddRefs(dir));
00416     if(!dir)
00417         return PR_FALSE;
00418 
00419     nsCOMPtr<nsILocalFile> descDir;
00420     nsresult rv = NS_NewNativeLocalFile(EmptyCString(), PR_FALSE, getter_AddRefs(descDir));
00421     if(NS_FAILED(rv))
00422         return PR_FALSE;
00423 
00424     rv = descDir->SetPersistentDescriptor(nsDependentCString(inDesc));
00425     if(NS_FAILED(rv))
00426         return PR_FALSE;
00427     
00428     PRBool matches;
00429     rv = dir->Equals(descDir, &matches);
00430     return NS_SUCCEEDED(rv) && matches;
00431 }
00432