~ubuntu-branches/ubuntu/gutsy/virtualbox-ose/gutsy

« back to all changes in this revision

Viewing changes to src/libs/xpcom18a4/xpcom/reflect/xptinfo/src/xptiprivate.h

  • Committer: Bazaar Package Importer
  • Author(s): Steve Kowalik
  • Date: 2007-09-08 16:44:58 UTC
  • Revision ID: james.westby@ubuntu.com-20070908164458-wao29470vqtr8ksy
Tags: upstream-1.5.0-dfsg2
ImportĀ upstreamĀ versionĀ 1.5.0-dfsg2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 
2
/* ***** BEGIN LICENSE BLOCK *****
 
3
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
4
 *
 
5
 * The contents of this file are subject to the Mozilla Public License Version
 
6
 * 1.1 (the "License"); you may not use this file except in compliance with
 
7
 * the License. You may obtain a copy of the License at
 
8
 * http://www.mozilla.org/MPL/
 
9
 *
 
10
 * Software distributed under the License is distributed on an "AS IS" basis,
 
11
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
12
 * for the specific language governing rights and limitations under the
 
13
 * License.
 
14
 *
 
15
 * The Original Code is mozilla.org code.
 
16
 *
 
17
 * The Initial Developer of the Original Code is
 
18
 * Netscape Communications Corporation.
 
19
 * Portions created by the Initial Developer are Copyright (C) 1999
 
20
 * the Initial Developer. All Rights Reserved.
 
21
 *
 
22
 * Contributor(s):
 
23
 *   Mike McCabe <mccabe@netscape.com>
 
24
 *   John Bandhauer <jband@netscape.com>
 
25
 *
 
26
 * Alternatively, the contents of this file may be used under the terms of
 
27
 * either of the GNU General Public License Version 2 or later (the "GPL"),
 
28
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
29
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
30
 * of those above. If you wish to allow use of your version of this file only
 
31
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
32
 * use your version of this file under the terms of the MPL, indicate your
 
33
 * decision by deleting the provisions above and replace them with the notice
 
34
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
35
 * the provisions above, a recipient may use your version of this file under
 
36
 * the terms of any one of the MPL, the GPL or the LGPL.
 
37
 *
 
38
 * ***** END LICENSE BLOCK ***** */
 
39
 
 
40
/* Library-private header for Interface Info system. */
 
41
 
 
42
#ifndef xptiprivate_h___
 
43
#define xptiprivate_h___
 
44
 
 
45
#include "nscore.h"
 
46
#include "nsISupports.h"
 
47
 
 
48
// this after nsISupports, to pick up IID
 
49
// so that xpt stuff doesn't try to define it itself...
 
50
#include "xpt_struct.h"
 
51
#include "xpt_xdr.h"
 
52
 
 
53
#include "nsIInterfaceInfo.h"
 
54
#include "nsIInterfaceInfoManager.h"
 
55
#include "xptinfo.h"
 
56
#include "nsIXPTLoader.h"
 
57
 
 
58
#include "nsIServiceManager.h"
 
59
#include "nsILocalFile.h"
 
60
#include "nsIDirectoryService.h"
 
61
#include "nsDirectoryServiceDefs.h"
 
62
#include "nsAppDirectoryServiceDefs.h"
 
63
#include "nsIWeakReference.h"
 
64
 
 
65
#include "nsCRT.h"
 
66
#include "nsMemory.h"
 
67
 
 
68
#include "nsISupportsArray.h"
 
69
#include "nsSupportsArray.h"
 
70
#include "nsInt64.h"
 
71
 
 
72
#include "nsQuickSort.h"
 
73
 
 
74
#include "nsXPIDLString.h"
 
75
 
 
76
#include "nsIInputStream.h"
 
77
 
 
78
#include "nsAutoLock.h"
 
79
 
 
80
#include "pldhash.h"
 
81
#include "plstr.h"
 
82
#include "prprf.h"
 
83
#include "prio.h"
 
84
#include "prtime.h"
 
85
#include "prenv.h"
 
86
 
 
87
#include <stdio.h>
 
88
#include <stdarg.h>
 
89
 
 
90
/***************************************************************************/
 
91
 
 
92
#if 0 && defined(DEBUG_jband)
 
93
#define LOG_RESOLVE(x) printf x
 
94
#define LOG_LOAD(x)    printf x
 
95
#define LOG_AUTOREG(x) do{printf x; xptiInterfaceInfoManager::WriteToLog x;}while(0)
 
96
#else
 
97
#define LOG_RESOLVE(x) ((void)0)
 
98
#define LOG_LOAD(x)    ((void)0)
 
99
#define LOG_AUTOREG(x) xptiInterfaceInfoManager::WriteToLog x
 
100
#endif
 
101
 
 
102
#if 1 && defined(DEBUG_jband)
 
103
#define SHOW_INFO_COUNT_STATS
 
104
#endif
 
105
 
 
106
/***************************************************************************/
 
107
 
 
108
class xptiFile;
 
109
class xptiInterfaceInfo;
 
110
class xptiInterfaceInfoManager;
 
111
class xptiInterfaceEntry;
 
112
class xptiInterfaceGuts;
 
113
class xptiTypelibGuts;
 
114
class xptiWorkingSet;
 
115
 
 
116
/***************************************************************************/
 
117
 
 
118
class xptiTypelib
 
119
{
 
120
public:
 
121
    // No ctors or dtors so that we can be in a union in xptiInterfaceInfo.
 
122
    // Allow automatic shallow copies.
 
123
 
 
124
    uint16 GetFileIndex()    const {return mFileIndex;}
 
125
    uint16 GetZipItemIndex() const {return mZipItemIndex;}
 
126
 
 
127
    enum {NOT_ZIP = 0xffff};
 
128
 
 
129
    PRBool IsZip() const {return mZipItemIndex != NOT_ZIP;}
 
130
 
 
131
    void Init(uint16 aFileIndex, uint16 aZipItemIndex = NOT_ZIP)
 
132
        {mFileIndex = aFileIndex; mZipItemIndex = aZipItemIndex;}
 
133
 
 
134
    PRBool Equals(const xptiTypelib& r) const
 
135
        {return mFileIndex == r.mFileIndex && 
 
136
                mZipItemIndex == r.mZipItemIndex;}
 
137
 
 
138
private:
 
139
    uint16 mFileIndex;
 
140
    uint16 mZipItemIndex;
 
141
};
 
142
 
 
143
/***************************************************************************/
 
144
 
 
145
// No virtuals.
 
146
// These are always constructed in the struct arena using placement new.
 
147
// dtor need not be called.
 
148
 
 
149
class xptiTypelibGuts
 
150
{
 
151
public:
 
152
    static xptiTypelibGuts* NewGuts(XPTHeader* aHeader,
 
153
                                    xptiWorkingSet* aWorkingSet);
 
154
 
 
155
    XPTHeader*          GetHeader()           {return mHeader;}
 
156
    PRUint16            GetEntryCount() const {return mHeader->num_interfaces;}
 
157
    
 
158
    void                SetEntryAt(PRUint16 i, xptiInterfaceEntry* ptr)
 
159
    {
 
160
        NS_ASSERTION(mHeader,"bad state!");
 
161
        NS_ASSERTION(i < GetEntryCount(),"bad param!");
 
162
        mEntryArray[i] = ptr;
 
163
    }        
 
164
 
 
165
    xptiInterfaceEntry* GetEntryAt(PRUint16 i) const
 
166
    {
 
167
        NS_ASSERTION(mHeader,"bad state!");
 
168
        NS_ASSERTION(i < GetEntryCount(),"bad param!");
 
169
        return mEntryArray[i];
 
170
    }        
 
171
 
 
172
private:
 
173
    xptiTypelibGuts(); // not implemented
 
174
    xptiTypelibGuts(XPTHeader* aHeader);
 
175
    ~xptiTypelibGuts() {}
 
176
    void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
 
177
 
 
178
private:
 
179
    XPTHeader*           mHeader;        // hold pointer into arena
 
180
    xptiInterfaceEntry*  mEntryArray[1]; // Always last. Sized to fit.
 
181
};
 
182
 
 
183
/***************************************************************************/
 
184
 
 
185
class xptiFile
 
186
{
 
187
public:
 
188
    const nsInt64&          GetSize()      const {return mSize;}
 
189
    const nsInt64&          GetDate()      const {return mDate;}
 
190
    const char*             GetName()      const {return mName;}
 
191
    const PRUint32          GetDirectory() const {return mDirectory;}
 
192
          xptiTypelibGuts*  GetGuts()            {return mGuts;}
 
193
 
 
194
    xptiFile();
 
195
 
 
196
    xptiFile(const nsInt64&  aSize,
 
197
             const nsInt64&  aDate,
 
198
             PRUint32        aDirectory,
 
199
             const char*     aName,
 
200
             xptiWorkingSet* aWorkingSet);
 
201
 
 
202
    xptiFile(const xptiFile& r, xptiWorkingSet* aWorkingSet);
 
203
 
 
204
    ~xptiFile();
 
205
 
 
206
    PRBool SetHeader(XPTHeader* aHeader, xptiWorkingSet* aWorkingSet);
 
207
 
 
208
    PRBool Equals(const xptiFile& r) const
 
209
    {
 
210
        return  mDirectory == r.mDirectory &&
 
211
                mSize == r.mSize &&
 
212
                mDate == r.mDate &&
 
213
                0 == PL_strcmp(mName, r.mName);
 
214
    }
 
215
 
 
216
    xptiFile(const xptiFile& r) {CopyFields(r);}
 
217
    xptiFile& operator= (const xptiFile& r)
 
218
    {
 
219
        if(this != &r)
 
220
            CopyFields(r);
 
221
        return *this;
 
222
    }
 
223
 
 
224
private:
 
225
    void CopyFields(const xptiFile& r)
 
226
    {
 
227
#ifdef DEBUG
 
228
        // If 'this' has a workingset then it better match that of the assigner. 
 
229
        NS_ASSERTION(!mDEBUG_WorkingSet || 
 
230
                     mDEBUG_WorkingSet == r.mDEBUG_WorkingSet,
 
231
                     "illegal xptiFile assignment");
 
232
        mDEBUG_WorkingSet = r.mDEBUG_WorkingSet;
 
233
#endif
 
234
 
 
235
        mSize      = r.mSize;
 
236
        mDate      = r.mDate;
 
237
        mName      = r.mName;
 
238
        mDirectory = r.mDirectory;
 
239
        mGuts      = r.mGuts;
 
240
    }
 
241
 
 
242
private:
 
243
#ifdef DEBUG
 
244
    xptiWorkingSet*  mDEBUG_WorkingSet;
 
245
#endif
 
246
    nsInt64          mSize;
 
247
    nsInt64          mDate;
 
248
    const char*      mName; // hold pointer into arena from initializer
 
249
    xptiTypelibGuts* mGuts; // hold pointer into arena
 
250
    PRUint32         mDirectory;
 
251
};
 
252
 
 
253
/***************************************************************************/
 
254
 
 
255
class xptiZipItem
 
256
{
 
257
public:
 
258
    const char*             GetName() const {return mName;}
 
259
          xptiTypelibGuts*  GetGuts()       {return mGuts;}
 
260
 
 
261
    xptiZipItem();
 
262
 
 
263
    xptiZipItem(const char*     aName,
 
264
                xptiWorkingSet* aWorkingSet);
 
265
 
 
266
    xptiZipItem(const xptiZipItem& r, xptiWorkingSet* aWorkingSet);
 
267
 
 
268
    ~xptiZipItem();
 
269
 
 
270
    PRBool SetHeader(XPTHeader* aHeader, xptiWorkingSet* aWorkingSet);
 
271
 
 
272
    PRBool Equals(const xptiZipItem& r) const
 
273
    {
 
274
        return 0 == PL_strcmp(mName, r.mName);
 
275
    }
 
276
 
 
277
    xptiZipItem(const xptiZipItem& r) {CopyFields(r);}
 
278
    xptiZipItem& operator= (const xptiZipItem& r)
 
279
    {
 
280
        if(this != &r)
 
281
            CopyFields(r);
 
282
        return *this;
 
283
    }
 
284
 
 
285
private:
 
286
    void CopyFields(const xptiZipItem& r)
 
287
    {
 
288
#ifdef DEBUG
 
289
        // If 'this' has a workingset then it better match that of the assigner. 
 
290
        NS_ASSERTION(!mDEBUG_WorkingSet || 
 
291
                     mDEBUG_WorkingSet == r.mDEBUG_WorkingSet,
 
292
                     "illegal xptiFile assignment");
 
293
        mDEBUG_WorkingSet = r.mDEBUG_WorkingSet;
 
294
#endif
 
295
 
 
296
        mName = r.mName;
 
297
        mGuts = r.mGuts;
 
298
    }
 
299
 
 
300
private:
 
301
#ifdef DEBUG
 
302
    xptiWorkingSet*  mDEBUG_WorkingSet;
 
303
#endif
 
304
    const char*      mName; // hold pointer into arena from initializer
 
305
    xptiTypelibGuts* mGuts; // hold pointer into arena
 
306
};
 
307
 
 
308
/***************************************************************************/
 
309
 
 
310
class xptiWorkingSet
 
311
{
 
312
public:
 
313
    xptiWorkingSet(); // not implmented
 
314
    xptiWorkingSet(nsISupportsArray* aDirectories);
 
315
    ~xptiWorkingSet();
 
316
    
 
317
    PRBool IsValid() const;
 
318
 
 
319
    void InvalidateInterfaceInfos();
 
320
    void ClearHashTables();
 
321
    void ClearFiles();
 
322
    void ClearZipItems();
 
323
 
 
324
    // utility methods...
 
325
 
 
326
    xptiTypelibGuts* GetTypelibGuts(const xptiTypelib& typelib)
 
327
    { 
 
328
        return typelib.IsZip() ?
 
329
            GetZipItemAt(typelib.GetZipItemIndex()).GetGuts() :
 
330
            GetFileAt(typelib.GetFileIndex()).GetGuts();
 
331
    }
 
332
    
 
333
    enum {NOT_FOUND = 0xffffffff};
 
334
 
 
335
    // FileArray stuff...
 
336
 
 
337
    PRUint32  GetFileCount() const {return mFileCount;}
 
338
    PRUint32  GetFileFreeSpace()
 
339
        {return mFileArray ? mMaxFileCount - mFileCount : 0;} 
 
340
    
 
341
    PRUint32 FindFile(PRUint32 dir, const char* name);
 
342
 
 
343
    PRUint32 GetTypelibDirectoryIndex(const xptiTypelib& typelib)
 
344
    {
 
345
        return GetFileAt(typelib.GetFileIndex()).GetDirectory();
 
346
    }
 
347
 
 
348
    const char* GetTypelibFileName(const xptiTypelib& typelib)
 
349
    {
 
350
        return GetFileAt(typelib.GetFileIndex()).GetName();
 
351
    }
 
352
 
 
353
    xptiFile& GetFileAt(PRUint32 i) const 
 
354
    {
 
355
        NS_ASSERTION(mFileArray, "bad state!");
 
356
        NS_ASSERTION(i < mFileCount, "bad param!");
 
357
        return mFileArray[i];
 
358
    }
 
359
 
 
360
    void SetFileAt(PRUint32 i, const xptiFile& r)
 
361
    { 
 
362
        NS_ASSERTION(mFileArray, "bad state!");
 
363
        NS_ASSERTION(i < mFileCount, "bad param!");
 
364
        mFileArray[i] = r;
 
365
    }
 
366
 
 
367
    void AppendFile(const xptiFile& r)
 
368
    { 
 
369
        NS_ASSERTION(mFileArray, "bad state!");
 
370
        NS_ASSERTION(mFileCount < mMaxFileCount, "bad param!");
 
371
        mFileArray[mFileCount++] = r;
 
372
    }
 
373
 
 
374
    PRBool NewFileArray(PRUint32 count);
 
375
    PRBool ExtendFileArray(PRUint32 count);
 
376
 
 
377
    // ZipItemArray stuff...
 
378
 
 
379
    PRUint32  GetZipItemCount() const {return mZipItemCount;}
 
380
    PRUint32  GetZipItemFreeSpace()
 
381
        {return mZipItemArray ? mMaxZipItemCount - mZipItemCount : 0;} 
 
382
 
 
383
    PRUint32 FindZipItemWithName(const char* name);
 
384
 
 
385
    xptiZipItem& GetZipItemAt(PRUint32 i) const 
 
386
    {
 
387
        NS_ASSERTION(mZipItemArray, "bad state!");
 
388
        NS_ASSERTION(i < mZipItemCount, "bad param!");
 
389
        return mZipItemArray[i];
 
390
    }
 
391
 
 
392
    void SetZipItemAt(PRUint32 i, const xptiZipItem& r)
 
393
    { 
 
394
        NS_ASSERTION(mZipItemArray, "bad state!");
 
395
        NS_ASSERTION(i < mZipItemCount, "bad param!");
 
396
        mZipItemArray[i] = r;
 
397
    }
 
398
 
 
399
    void AppendZipItem(const xptiZipItem& r)
 
400
    { 
 
401
        NS_ASSERTION(mZipItemArray, "bad state!");
 
402
        NS_ASSERTION(mZipItemCount < mMaxZipItemCount, "bad param!");
 
403
        mZipItemArray[mZipItemCount++] = r;
 
404
    }
 
405
 
 
406
    PRBool NewZipItemArray(PRUint32 count);
 
407
    PRBool ExtendZipItemArray(PRUint32 count);
 
408
 
 
409
    // Directory stuff...
 
410
 
 
411
    PRUint32 GetDirectoryCount();
 
412
    nsresult GetCloneOfDirectoryAt(PRUint32 i, nsILocalFile** dir);
 
413
    nsresult GetDirectoryAt(PRUint32 i, nsILocalFile** dir);
 
414
    PRBool   FindDirectory(nsILocalFile* dir, PRUint32* index);
 
415
    PRBool   FindDirectoryOfFile(nsILocalFile* file, PRUint32* index);
 
416
    PRBool   DirectoryAtMatchesPersistentDescriptor(PRUint32 i, const char* desc);
 
417
 
 
418
    // Arena stuff...
 
419
 
 
420
    XPTArena*  GetStringArena() {return mStringArena;}
 
421
    XPTArena*  GetStructArena() {return mStructArena;}
 
422
 
 
423
 
 
424
private:
 
425
    PRUint32        mFileCount;
 
426
    PRUint32        mMaxFileCount;
 
427
    xptiFile*       mFileArray;         // using new[] and delete[]
 
428
 
 
429
    PRUint32        mZipItemCount;
 
430
    PRUint32        mMaxZipItemCount;
 
431
    xptiZipItem*    mZipItemArray;      // using new[] and delete[]
 
432
 
 
433
    XPTArena*       mStringArena;
 
434
    XPTArena*       mStructArena;
 
435
 
 
436
    nsCOMPtr<nsISupportsArray> mDirectories;
 
437
 
 
438
public:
 
439
    // XXX make these private with accessors
 
440
    PLDHashTable*   mNameTable;
 
441
    PLDHashTable*   mIIDTable;
 
442
    PRUint32*       mFileMergeOffsetMap;    // always in an arena
 
443
    PRUint32*       mZipItemMergeOffsetMap; // always in an arena
 
444
};
 
445
 
 
446
/***************************************************************************/
 
447
 
 
448
class xptiInterfaceGuts
 
449
{
 
450
public:
 
451
    uint16                      mMethodBaseIndex;
 
452
    uint16                      mConstantBaseIndex;
 
453
    xptiInterfaceEntry*         mParent;
 
454
    XPTInterfaceDescriptor*     mDescriptor;
 
455
    xptiTypelib                 mTypelib;
 
456
    xptiWorkingSet*             mWorkingSet;
 
457
 
 
458
    static xptiInterfaceGuts* NewGuts(XPTInterfaceDescriptor* aDescriptor,
 
459
                                      const xptiTypelib&      aTypelib,
 
460
                                      xptiWorkingSet*         aWorkingSet)
 
461
    {
 
462
        void* place = XPT_MALLOC(aWorkingSet->GetStructArena(),
 
463
                                 sizeof(xptiInterfaceGuts));
 
464
        if(!place)
 
465
            return nsnull;
 
466
        return new(place) xptiInterfaceGuts(aDescriptor, aTypelib, aWorkingSet);
 
467
    }
 
468
 
 
469
private:
 
470
    void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
 
471
    xptiInterfaceGuts(XPTInterfaceDescriptor* aDescriptor,
 
472
                      const xptiTypelib&      aTypelib,
 
473
                      xptiWorkingSet*         aWorkingSet)
 
474
        :   mMethodBaseIndex(0),
 
475
            mConstantBaseIndex(0),
 
476
            mParent(nsnull),
 
477
            mDescriptor(aDescriptor),
 
478
            mTypelib(aTypelib),
 
479
            mWorkingSet(aWorkingSet) {}
 
480
 
 
481
    ~xptiInterfaceGuts() {}
 
482
};
 
483
 
 
484
/***************************************************************************/
 
485
 
 
486
// This class exists to help xptiInterfaceInfo store a 4-state (2 bit) value 
 
487
// and a set of bitflags in one 8bit value. See below.
 
488
 
 
489
class xptiInfoFlags
 
490
{
 
491
    enum {STATE_MASK = 3};
 
492
public:
 
493
    xptiInfoFlags(uint8 n) : mData(n) {}
 
494
    xptiInfoFlags(const xptiInfoFlags& r) : mData(r.mData) {}
 
495
 
 
496
    static uint8 GetStateMask()
 
497
        {return uint8(STATE_MASK);}
 
498
    
 
499
    void Clear()
 
500
        {mData = 0;}
 
501
 
 
502
    uint8 GetData() const
 
503
        {return mData;}
 
504
 
 
505
    uint8 GetState() const 
 
506
        {return mData & GetStateMask();}
 
507
 
 
508
    void SetState(uint8 state) 
 
509
        {mData &= ~GetStateMask(); mData |= state;}                                   
 
510
 
 
511
    void SetFlagBit(uint8 flag, PRBool on) 
 
512
        {if(on)
 
513
            mData |= ~GetStateMask() & flag;
 
514
         else
 
515
            mData &= GetStateMask() | ~flag;}
 
516
 
 
517
    PRBool GetFlagBit(uint8 flag) const 
 
518
        {return (mData & flag) ? PR_TRUE : PR_FALSE;}
 
519
 
 
520
private:
 
521
    uint8 mData;    
 
522
};
 
523
 
 
524
/****************************************************/
 
525
 
 
526
// No virtual methods.
 
527
// We always create in the struct arena and construct using "placement new".
 
528
// No members need dtor calls.
 
529
 
 
530
class xptiInterfaceEntry
 
531
{
 
532
public:
 
533
    static xptiInterfaceEntry* NewEntry(const char* name,
 
534
                                        int nameLength,
 
535
                                        const nsID& iid,
 
536
                                        const xptiTypelib& typelib,
 
537
                                        xptiWorkingSet* aWorkingSet);
 
538
 
 
539
    static xptiInterfaceEntry* NewEntry(const xptiInterfaceEntry& r,
 
540
                                        const xptiTypelib& typelib,
 
541
                                        xptiWorkingSet* aWorkingSet);
 
542
 
 
543
    enum {
 
544
        NOT_RESOLVED          = 0,
 
545
        PARTIALLY_RESOLVED    = 1,
 
546
        FULLY_RESOLVED        = 2,
 
547
        RESOLVE_FAILED        = 3
 
548
    };
 
549
    
 
550
    // Additional bit flags...
 
551
    enum {SCRIPTABLE = 4};
 
552
 
 
553
    uint8 GetResolveState() const {return mFlags.GetState();}
 
554
    
 
555
    PRBool IsFullyResolved() const 
 
556
        {return GetResolveState() == (uint8) FULLY_RESOLVED;}
 
557
 
 
558
    PRBool HasInterfaceRecord() const
 
559
        {int s = (int) GetResolveState(); 
 
560
         return (s == PARTIALLY_RESOLVED || s == FULLY_RESOLVED) && mInterface;}
 
561
 
 
562
    const xptiTypelib&  GetTypelibRecord() const
 
563
        {return HasInterfaceRecord() ? mInterface->mTypelib : mTypelib;}
 
564
 
 
565
    xptiInterfaceGuts*  GetInterfaceGuts() const
 
566
        {return HasInterfaceRecord() ? mInterface : nsnull;}
 
567
 
 
568
#ifdef DEBUG
 
569
    PRBool DEBUG_ScriptableFlagIsValid() const
 
570
        {int s = (int) GetResolveState(); 
 
571
         if((s == PARTIALLY_RESOLVED || s == FULLY_RESOLVED) && mInterface)
 
572
            {
 
573
                if(XPT_ID_IS_SCRIPTABLE(mInterface->mDescriptor->flags))
 
574
                    return GetScriptableFlag();
 
575
                return !GetScriptableFlag();
 
576
            }
 
577
         return PR_TRUE;
 
578
        }
 
579
#endif
 
580
 
 
581
    void   SetScriptableFlag(PRBool on)
 
582
                {mFlags.SetFlagBit(uint8(SCRIPTABLE),on);}
 
583
    PRBool GetScriptableFlag() const
 
584
                {return mFlags.GetFlagBit(uint8(SCRIPTABLE));}
 
585
 
 
586
    const nsID* GetTheIID()  const {return &mIID;}
 
587
    const char* GetTheName() const {return mName;}
 
588
 
 
589
    PRBool EnsureResolved(xptiWorkingSet* aWorkingSet = nsnull)
 
590
        {return IsFullyResolved() ? PR_TRUE : Resolve(aWorkingSet);}
 
591
 
 
592
    PRBool PartiallyResolveLocked(XPTInterfaceDescriptor*  aDescriptor,
 
593
                                  xptiWorkingSet*          aWorkingSet);
 
594
 
 
595
    nsresult GetInterfaceInfo(xptiInterfaceInfo** info);
 
596
    PRBool   InterfaceInfoEquals(const xptiInterfaceInfo* info) const 
 
597
        {return info == mInfo;}
 
598
    
 
599
    void     LockedInvalidateInterfaceInfo();
 
600
    void     LockedInterfaceInfoDeathNotification() {mInfo = nsnull;}
 
601
 
 
602
    //////////////////////
 
603
    // These non-virtual methods handle the delegated nsIInterfaceInfo methods.
 
604
 
 
605
    nsresult GetName(char * *aName);
 
606
    nsresult GetIID(nsIID * *aIID);
 
607
    nsresult IsScriptable(PRBool *_retval);
 
608
    // Except this one.
 
609
    //nsresult GetParent(nsIInterfaceInfo * *aParent);
 
610
    nsresult GetMethodCount(PRUint16 *aMethodCount);
 
611
    nsresult GetConstantCount(PRUint16 *aConstantCount);
 
612
    nsresult GetMethodInfo(PRUint16 index, const nsXPTMethodInfo * *info);
 
613
    nsresult GetMethodInfoForName(const char *methodName, PRUint16 *index, const nsXPTMethodInfo * *info);
 
614
    nsresult GetConstant(PRUint16 index, const nsXPTConstant * *constant);
 
615
    nsresult GetInfoForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval);
 
616
    nsresult GetIIDForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID * *_retval);
 
617
    nsresult GetTypeForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, nsXPTType *_retval);
 
618
    nsresult GetSizeIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval);
 
619
    nsresult GetLengthIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval);
 
620
    nsresult GetInterfaceIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint8 *_retval);
 
621
    nsresult IsIID(const nsIID * IID, PRBool *_retval);
 
622
    nsresult GetNameShared(const char **name);
 
623
    nsresult GetIIDShared(const nsIID * *iid);
 
624
    nsresult IsFunction(PRBool *_retval);
 
625
    nsresult HasAncestor(const nsIID * iid, PRBool *_retval);
 
626
    nsresult GetIIDForParamNoAlloc(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID *iid);
 
627
 
 
628
    //////////////////////
 
629
 
 
630
private:
 
631
    xptiInterfaceEntry();   // not implemented
 
632
 
 
633
    xptiInterfaceEntry(const char* name,
 
634
                       size_t nameLength,
 
635
                       const nsID& iid,
 
636
                       const xptiTypelib& typelib);
 
637
 
 
638
    xptiInterfaceEntry(const xptiInterfaceEntry& r,
 
639
                       size_t nameLength,
 
640
                       const xptiTypelib& typelib);
 
641
    ~xptiInterfaceEntry();
 
642
 
 
643
    void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
 
644
 
 
645
    void SetResolvedState(int state) 
 
646
        {mFlags.SetState(uint8(state));}
 
647
 
 
648
    PRBool Resolve(xptiWorkingSet* aWorkingSet = nsnull);
 
649
 
 
650
    // We only call these "*Locked" variants after locking. This is done to 
 
651
    // allow reentrace as files are loaded and various interfaces resolved 
 
652
    // without having to worry about the locked state.
 
653
 
 
654
    PRBool EnsureResolvedLocked(xptiWorkingSet* aWorkingSet = nsnull)
 
655
        {return IsFullyResolved() ? PR_TRUE : ResolveLocked(aWorkingSet);}
 
656
    PRBool ResolveLocked(xptiWorkingSet* aWorkingSet = nsnull);
 
657
 
 
658
    // private helpers
 
659
 
 
660
    nsresult GetEntryForParam(PRUint16 methodIndex, 
 
661
                              const nsXPTParamInfo * param,
 
662
                              xptiInterfaceEntry** entry);
 
663
 
 
664
    nsresult GetTypeInArray(const nsXPTParamInfo* param,
 
665
                            uint16 dimension,
 
666
                            const XPTTypeDescriptor** type);
 
667
 
 
668
private:
 
669
    nsID                    mIID;
 
670
    union {
 
671
        xptiTypelib         mTypelib;     // Valid only until resolved.
 
672
        xptiInterfaceGuts*  mInterface;   // Valid only after resolved.
 
673
    };
 
674
    xptiInterfaceInfo*      mInfo;        // May come and go.
 
675
    xptiInfoFlags           mFlags;
 
676
    char                    mName[1];     // Always last. Sized to fit.
 
677
};
 
678
 
 
679
struct xptiHashEntry : public PLDHashEntryHdr
 
680
{
 
681
    xptiInterfaceEntry* value;    
 
682
};
 
683
 
 
684
/****************************************************/
 
685
 
 
686
class xptiInterfaceInfo : public nsIInterfaceInfo
 
687
{
 
688
public:
 
689
    NS_DECL_ISUPPORTS
 
690
 
 
691
    // Use delegation to implement (most!) of nsIInterfaceInfo.
 
692
    NS_IMETHOD GetName(char * *aName) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetName(aName); }
 
693
    NS_IMETHOD GetInterfaceIID(nsIID * *aIID) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIID(aIID); }
 
694
    NS_IMETHOD IsScriptable(PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsScriptable(_retval); }
 
695
    // Except this one.
 
696
    NS_IMETHOD GetParent(nsIInterfaceInfo * *aParent) 
 
697
    {
 
698
        if(!EnsureResolved() || !EnsureParent())
 
699
            return NS_ERROR_UNEXPECTED;
 
700
        NS_IF_ADDREF(*aParent = mParent);
 
701
        return NS_OK;
 
702
    }
 
703
    NS_IMETHOD GetMethodCount(PRUint16 *aMethodCount) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodCount(aMethodCount); }
 
704
    NS_IMETHOD GetConstantCount(PRUint16 *aConstantCount) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstantCount(aConstantCount); }
 
705
    NS_IMETHOD GetMethodInfo(PRUint16 index, const nsXPTMethodInfo * *info) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfo(index, info); }
 
706
    NS_IMETHOD GetMethodInfoForName(const char *methodName, PRUint16 *index, const nsXPTMethodInfo * *info) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetMethodInfoForName(methodName, index, info); }
 
707
    NS_IMETHOD GetConstant(PRUint16 index, const nsXPTConstant * *constant) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetConstant(index, constant); }
 
708
    NS_IMETHOD GetInfoForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInfoForParam(methodIndex, param, _retval); }
 
709
    NS_IMETHOD GetIIDForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID * *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParam(methodIndex, param, _retval); }
 
710
    NS_IMETHOD GetTypeForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, nsXPTType *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetTypeForParam(methodIndex, param, dimension, _retval); }
 
711
    NS_IMETHOD GetSizeIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetSizeIsArgNumberForParam(methodIndex, param, dimension, _retval); }
 
712
    NS_IMETHOD GetLengthIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetLengthIsArgNumberForParam(methodIndex, param, dimension, _retval); }
 
713
    NS_IMETHOD GetInterfaceIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint8 *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetInterfaceIsArgNumberForParam(methodIndex, param, _retval); }
 
714
    NS_IMETHOD IsIID(const nsIID * IID, PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsIID(IID, _retval); }
 
715
    NS_IMETHOD GetNameShared(const char **name) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetNameShared(name); }
 
716
    NS_IMETHOD GetIIDShared(const nsIID * *iid) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDShared(iid); }
 
717
    NS_IMETHOD IsFunction(PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->IsFunction(_retval); }
 
718
    NS_IMETHOD HasAncestor(const nsIID * iid, PRBool *_retval) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->HasAncestor(iid, _retval); }
 
719
    NS_IMETHOD GetIIDForParamNoAlloc(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID *iid) { return !mEntry ? NS_ERROR_UNEXPECTED : mEntry->GetIIDForParamNoAlloc(methodIndex, param, iid); }
 
720
 
 
721
public:
 
722
    xptiInterfaceInfo(xptiInterfaceEntry* entry);
 
723
 
 
724
    void Invalidate() 
 
725
        {NS_IF_RELEASE(mParent); mEntry = nsnull;}
 
726
 
 
727
#ifdef DEBUG
 
728
    static void DEBUG_ShutdownNotification();
 
729
#endif
 
730
 
 
731
private:
 
732
 
 
733
    ~xptiInterfaceInfo();
 
734
 
 
735
    // Note that mParent might still end up as nsnull if we don't have one.
 
736
    PRBool EnsureParent(xptiWorkingSet* aWorkingSet = nsnull)
 
737
    {
 
738
        NS_ASSERTION(mEntry && mEntry->IsFullyResolved(), "bad EnsureParent call");
 
739
        return mParent || !mEntry->GetInterfaceGuts()->mParent || BuildParent();
 
740
    }
 
741
    
 
742
    PRBool EnsureResolved(xptiWorkingSet* aWorkingSet = nsnull)
 
743
    {
 
744
        return mEntry && mEntry->EnsureResolved(aWorkingSet);
 
745
    }
 
746
 
 
747
    PRBool BuildParent()
 
748
    {
 
749
        NS_ASSERTION(mEntry && 
 
750
                     mEntry->IsFullyResolved() && 
 
751
                     !mParent &&
 
752
                     mEntry->GetInterfaceGuts()->mParent,
 
753
                    "bad BuildParent call");
 
754
        return NS_SUCCEEDED(mEntry->GetInterfaceGuts()->mParent->
 
755
                                        GetInterfaceInfo(&mParent));
 
756
    }
 
757
 
 
758
    xptiInterfaceInfo();  // not implemented
 
759
 
 
760
private:
 
761
    xptiInterfaceEntry* mEntry;
 
762
    xptiInterfaceInfo*  mParent;
 
763
};
 
764
 
 
765
/***************************************************************************/
 
766
 
 
767
class xptiManifest
 
768
{
 
769
public:
 
770
    static PRBool Read(xptiInterfaceInfoManager* aMgr,
 
771
                       xptiWorkingSet*           aWorkingSet);
 
772
 
 
773
    static PRBool Write(xptiInterfaceInfoManager* aMgr,
 
774
                        xptiWorkingSet*           aWorkingSet);
 
775
 
 
776
    static PRBool Delete(xptiInterfaceInfoManager* aMgr);
 
777
 
 
778
private:
 
779
    xptiManifest(); // no implementation
 
780
};
 
781
 
 
782
/***************************************************************************/
 
783
 
 
784
class xptiZipLoaderSink : public nsIXPTLoaderSink
 
785
{
 
786
public:
 
787
    xptiZipLoaderSink(xptiInterfaceInfoManager* aMgr,
 
788
                      xptiWorkingSet* aWorkingSet) :
 
789
        mManager(aMgr),
 
790
        mWorkingSet(aWorkingSet) {}
 
791
    
 
792
    NS_DECL_ISUPPORTS
 
793
    NS_DECL_NSIXPTLOADERSINK
 
794
    
 
795
private:
 
796
    ~xptiZipLoaderSink() {}
 
797
 
 
798
    xptiInterfaceInfoManager* mManager;
 
799
    xptiWorkingSet* mWorkingSet;
 
800
 
 
801
};
 
802
 
 
803
class xptiZipLoader
 
804
{
 
805
public:
 
806
    xptiZipLoader();  // not implemented
 
807
 
 
808
    static XPTHeader*
 
809
    ReadXPTFileFromInputStream(nsIInputStream *stream,
 
810
                               xptiWorkingSet* aWorkingSet);
 
811
 
 
812
};
 
813
 
 
814
 
 
815
/***************************************************************************/
 
816
 
 
817
class xptiFileType
 
818
{
 
819
public:
 
820
    enum Type {UNKNOWN = -1, XPT = 0, ZIP = 1 };
 
821
 
 
822
    static Type GetType(const char* name);
 
823
 
 
824
    static PRBool IsUnknown(const char* name)
 
825
        {return GetType(name) == UNKNOWN;}
 
826
 
 
827
    static PRBool IsXPT(const char* name)
 
828
        {return GetType(name) == XPT;}
 
829
 
 
830
    static PRBool IsZip(const char* name)
 
831
        {return GetType(name) == ZIP;}
 
832
private:
 
833
    xptiFileType(); // no implementation
 
834
};
 
835
 
 
836
/***************************************************************************/
 
837
 
 
838
// We use this is as a fancy way to open a logfile to be used within the scope
 
839
// of some given function where it is instantiated.
 
840
 
 
841
class xptiAutoLog
 
842
{
 
843
public:    
 
844
    xptiAutoLog();  // not implemented
 
845
    xptiAutoLog(xptiInterfaceInfoManager* mgr,
 
846
                nsILocalFile* logfile, PRBool append);
 
847
    ~xptiAutoLog();
 
848
private:
 
849
    void WriteTimestamp(PRFileDesc* fd, const char* msg);
 
850
 
 
851
    xptiInterfaceInfoManager* mMgr;
 
852
    PRFileDesc* mOldFileDesc;
 
853
#ifdef DEBUG
 
854
    PRFileDesc* m_DEBUG_FileDesc;
 
855
#endif
 
856
};
 
857
 
 
858
/***************************************************************************/
 
859
 
 
860
class xptiInterfaceInfoManager 
 
861
    : public nsIInterfaceInfoSuperManager
 
862
{
 
863
    NS_DECL_ISUPPORTS
 
864
    NS_DECL_NSIINTERFACEINFOMANAGER
 
865
    NS_DECL_NSIINTERFACEINFOSUPERMANAGER
 
866
 
 
867
    // helper
 
868
    PRBool 
 
869
    FoundZipEntry(const char* entryName,
 
870
                  int index,
 
871
                  XPTHeader* header,
 
872
                  xptiWorkingSet* aWorkingSet);
 
873
 
 
874
public:
 
875
    static xptiInterfaceInfoManager* GetInterfaceInfoManagerNoAddRef();
 
876
    static void FreeInterfaceInfoManager();
 
877
 
 
878
    xptiWorkingSet*  GetWorkingSet() {return &mWorkingSet;}
 
879
    PRFileDesc*      GetOpenLogFile() {return mOpenLogFile;}
 
880
    PRFileDesc*      SetOpenLogFile(PRFileDesc* fd) 
 
881
        {PRFileDesc* temp = mOpenLogFile; mOpenLogFile = fd; return temp;}
 
882
 
 
883
    PRBool LoadFile(const xptiTypelib& aTypelibRecord,
 
884
                    xptiWorkingSet* aWorkingSet = nsnull);
 
885
 
 
886
    PRBool GetApplicationDir(nsILocalFile** aDir);
 
887
    PRBool GetCloneOfManifestLocation(nsILocalFile** aDir);
 
888
 
 
889
    void   GetSearchPath(nsISupportsArray** aSearchPath)
 
890
        {NS_ADDREF(*aSearchPath = mSearchPath);}
 
891
 
 
892
    static PRLock* GetResolveLock(xptiInterfaceInfoManager* self = nsnull) 
 
893
        {if(!self && !(self = GetInterfaceInfoManagerNoAddRef())) 
 
894
            return nsnull;
 
895
         return self->mResolveLock;}
 
896
 
 
897
    static PRLock* GetAutoRegLock(xptiInterfaceInfoManager* self = nsnull) 
 
898
        {if(!self && !(self = GetInterfaceInfoManagerNoAddRef())) 
 
899
            return nsnull;
 
900
         return self->mAutoRegLock;}
 
901
 
 
902
    static PRMonitor* GetInfoMonitor(xptiInterfaceInfoManager* self = nsnull) 
 
903
        {if(!self && !(self = GetInterfaceInfoManagerNoAddRef())) 
 
904
            return nsnull;
 
905
         return self->mInfoMonitor;}
 
906
 
 
907
    static void WriteToLog(const char *fmt, ...);
 
908
 
 
909
private:
 
910
    ~xptiInterfaceInfoManager();
 
911
    xptiInterfaceInfoManager(); // not implmented
 
912
    xptiInterfaceInfoManager(nsISupportsArray* aSearchPath);
 
913
 
 
914
    enum AutoRegMode {
 
915
        NO_FILES_CHANGED = 0,
 
916
        FILES_ADDED_ONLY,
 
917
        FULL_VALIDATION_REQUIRED
 
918
    };
 
919
 
 
920
    PRBool IsValid();
 
921
 
 
922
    PRBool BuildFileList(nsISupportsArray* aSearchPath,
 
923
                         nsISupportsArray** aFileList);
 
924
 
 
925
    nsILocalFile** BuildOrderedFileArray(nsISupportsArray* aSearchPath,
 
926
                                         nsISupportsArray* aFileList,
 
927
                                         xptiWorkingSet* aWorkingSet);
 
928
 
 
929
    XPTHeader* ReadXPTFile(nsILocalFile* aFile, xptiWorkingSet* aWorkingSet);
 
930
    
 
931
    AutoRegMode DetermineAutoRegStrategy(nsISupportsArray* aSearchPath,
 
932
                                         nsISupportsArray* aFileList,
 
933
                                         xptiWorkingSet* aWorkingSet);
 
934
 
 
935
    PRBool AddOnlyNewFilesFromFileList(nsISupportsArray* aSearchPath,
 
936
                                       nsISupportsArray* aFileList,
 
937
                                       xptiWorkingSet* aWorkingSet);
 
938
 
 
939
    PRBool DoFullValidationMergeFromFileList(nsISupportsArray* aSearchPath,
 
940
                                             nsISupportsArray* aFileList,
 
941
                                             xptiWorkingSet* aWorkingSet);
 
942
 
 
943
    PRBool VerifyAndAddEntryIfNew(xptiWorkingSet* aWorkingSet,
 
944
                                  XPTInterfaceDirectoryEntry* iface,
 
945
                                  const xptiTypelib& typelibRecord,
 
946
                                  xptiInterfaceEntry** entryAdded);
 
947
 
 
948
    PRBool MergeWorkingSets(xptiWorkingSet* aDestWorkingSet,
 
949
                            xptiWorkingSet* aSrcWorkingSet);
 
950
 
 
951
    void   LogStats(); 
 
952
 
 
953
    PRBool DEBUG_DumpFileList(nsISupportsArray* aFileList);
 
954
    PRBool DEBUG_DumpFileArray(nsILocalFile** aFileArray, PRUint32 count);
 
955
    PRBool DEBUG_DumpFileListInWorkingSet(xptiWorkingSet* aWorkingSet);
 
956
 
 
957
    static PRBool BuildFileSearchPath(nsISupportsArray** aPath);
 
958
 
 
959
private:
 
960
    xptiWorkingSet               mWorkingSet;
 
961
    nsCOMPtr<nsILocalFile>       mStatsLogFile;
 
962
    nsCOMPtr<nsILocalFile>       mAutoRegLogFile;
 
963
    PRFileDesc*                  mOpenLogFile;
 
964
    PRLock*                      mResolveLock;
 
965
    PRLock*                      mAutoRegLock;
 
966
    PRMonitor*                   mInfoMonitor;
 
967
    PRLock*                      mAdditionalManagersLock;
 
968
    nsSupportsArray              mAdditionalManagers;
 
969
    nsCOMPtr<nsISupportsArray>   mSearchPath;
 
970
};
 
971
 
 
972
/***************************************************************************/
 
973
// utilities...
 
974
 
 
975
nsresult xptiCloneLocalFile(nsILocalFile*  aLocalFile,
 
976
                            nsILocalFile** aCloneLocalFile);
 
977
 
 
978
nsresult xptiCloneElementAsLocalFile(nsISupportsArray* aArray, PRUint32 aIndex,
 
979
                                     nsILocalFile** aLocalFile);
 
980
 
 
981
#endif /* xptiprivate_h___ */