Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Typedefs | Functions
nsFastLoadFile.h File Reference
#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"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  nsFastLoadHeader
 Header at the start of a FastLoad file. More...
struct  nsFastLoadFooterPrefix
 Footer prefix structure (footer header, ugh), after which come arrays of structures or strings counted by these members. More...
struct  nsFastLoadSharpObjectInfo
struct  nsFastLoadMuxedDocumentInfo
struct  nsIFastLoadFileReader
class  nsFastLoadFileReader
 Inherit from the concrete class nsBinaryInputStream, which inherits from abstract nsIObjectInputStream but does not implement its direct methods. More...
struct  nsFastLoadFileReader::nsObjectMapEntry
 In-memory representation of an indexed nsFastLoadSharpObjectInfo record. More...
struct  nsFastLoadFileReader::nsFastLoadFooter
 In-memory representation of the FastLoad file footer. More...
class  nsFastLoadFileWriter
 Inherit from the concrete class nsBinaryInputStream, which inherits from abstract nsIObjectInputStream but does not implement its direct methods. More...
class  nsFastLoadFileUpdater
 Subclass of nsFastLoadFileWriter, friend of nsFastLoadFileReader which it wraps when a FastLoad file needs to be updated. More...

Defines

#define MFL_ID_XOR_KEY   0x9E3779B9
 A Mozilla FastLoad file is an untagged (in general) stream of objects and primitive-type data.
#define MFL_OID_XOR_KEY   0x6A09E667
#define MFL_OBJECT_TAG_BITS   3
 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.
#define MFL_OBJECT_TAG_MASK   PR_BITMASK(MFL_OBJECT_TAG_BITS)
#define MFL_OBJECT_DEF_TAG   1U
#define MFL_WEAK_REF_TAG   2U
#define MFL_QUERY_INTERFACE_TAG   4U
#define MFL_DULL_OBJECT_OID   MFL_OBJECT_DEF_TAG
 The dull object identifier introduces the definition of all objects that have only one (necessarily strong) ref in the serialization.
#define MFL_OID_TO_SHARP_INDEX(oid)   (((oid) >> MFL_OBJECT_TAG_BITS) - 1)
 Convert an OID to an index into nsFastLoadFooter::mObjectMap.
#define MFL_SHARP_INDEX_TO_OID(index)   (((index) + 1) << MFL_OBJECT_TAG_BITS)
#define MFL_FILE_MAGIC   "XPCOM\nMozFASL\r\n\032"
 Magic "number" at start of a FastLoad file.
#define MFL_FILE_MAGIC_SIZE   16
#define MFL_FILE_VERSION_0   0
#define MFL_FILE_VERSION_1   1000
#define MFL_FILE_VERSION   5
#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)
#define NS_FASTLOADFILEREADER_IID   {0x7d37d1bb,0xcef3,0x4c5f,{0x97,0x68,0x0f,0x89,0x7f,0x1a,0xe1,0x40}}

Typedefs

typedef PRUint32 NSFastLoadID
 Mozilla FastLoad file format and helper types.
typedef PRUint32 NSFastLoadOID

Functions

 NS_AccumulateFastLoadChecksum (PRUint32 *aChecksum, const PRUint8 *aBuffer, PRUint32 aLength, PRBool aLastBuffer)
 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.
 NS_AddFastLoadChecksums (PRUint32 sum1, PRUint32 sum2, PRUint32 sum2ByteCount)
NS_COM nsresult NS_NewFastLoadFileReader (nsIObjectInputStream **aResult, nsIInputStream *aSrcStream)
NS_COM nsresult NS_NewFastLoadFileWriter (nsIObjectOutputStream **aResult, nsIOutputStream *aDestStream, nsIFastLoadFileIO *aFileIO)
NS_COM nsresult NS_NewFastLoadFileUpdater (nsIObjectOutputStream **aResult, nsIOutputStream *aOutputStream, nsIObjectInputStream *aReaderAsStream)

Class Documentation

struct nsFastLoadHeader

Header at the start of a FastLoad file.

Definition at line 194 of file nsFastLoadFile.h.

Class Members
PRUint32 mChecksum
PRUint32 mFileSize
PRUint32 mFooterOffset
char mMagic
PRUint32 mVersion
struct nsFastLoadMuxedDocumentInfo

Definition at line 233 of file nsFastLoadFile.h.

Class Members
PRUint32 mInitialSegmentOffset
const char * mURISpec

Define Documentation

#define MFL_BUMP_WEAK_REFCNT (   ip)    (++(ip)->mWeakRefCnt)

Definition at line 230 of file nsFastLoadFile.h.

#define MFL_DROP_WEAK_REFCNT (   ip)    (--(ip)->mWeakRefCnt)

Definition at line 231 of file nsFastLoadFile.h.

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.

Definition at line 125 of file nsFastLoadFile.h.

#define MFL_FILE_MAGIC   "XPCOM\nMozFASL\r\n\032"

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.

Definition at line 139 of file nsFastLoadFile.h.

Definition at line 140 of file nsFastLoadFile.h.

Definition at line 144 of file nsFastLoadFile.h.

Definition at line 142 of file nsFastLoadFile.h.

Definition at line 143 of file nsFastLoadFile.h.

#define MFL_GET_SINGLETON_FLAG (   ip)    ((ip)->mWeakRefCnt & MFL_SINGLETON_FLAG)

Definition at line 222 of file nsFastLoadFile.h.

#define MFL_GET_WEAK_REFCNT (   ip)    ((ip)->mWeakRefCnt & MFL_WEAK_REFCNT_MASK)

Definition at line 223 of file nsFastLoadFile.h.

#define MFL_ID_XOR_KEY   0x9E3779B9

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.

Definition at line 95 of file nsFastLoadFile.h.

Definition at line 114 of file nsFastLoadFile.h.

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.

Definition at line 111 of file nsFastLoadFile.h.

Definition at line 112 of file nsFastLoadFile.h.

#define MFL_OID_TO_SHARP_INDEX (   oid)    (((oid) >> MFL_OBJECT_TAG_BITS) - 1)

Convert an OID to an index into nsFastLoadFooter::mObjectMap.

Definition at line 130 of file nsFastLoadFile.h.

#define MFL_OID_XOR_KEY   0x6A09E667

Definition at line 96 of file nsFastLoadFile.h.

Definition at line 117 of file nsFastLoadFile.h.

#define MFL_SET_SINGLETON_FLAG (   ip)    ((ip)->mWeakRefCnt |= MFL_SINGLETON_FLAG)

Definition at line 225 of file nsFastLoadFile.h.

#define MFL_SET_WEAK_REFCNT (   ip,
  rc 
)    ((ip)->mWeakRefCnt = (((ip)->mWeakRefCnt & MFL_SINGLETON_FLAG) | (rc)))

Definition at line 227 of file nsFastLoadFile.h.

Definition at line 131 of file nsFastLoadFile.h.

#define MFL_SINGLETON_FLAG   0x8000

Definition at line 219 of file nsFastLoadFile.h.

Definition at line 115 of file nsFastLoadFile.h.

Definition at line 220 of file nsFastLoadFile.h.

#define NS_FASTLOADFILEREADER_IID   {0x7d37d1bb,0xcef3,0x4c5f,{0x97,0x68,0x0f,0x89,0x7f,0x1a,0xe1,0x40}}

Definition at line 244 of file nsFastLoadFile.h.


Typedef Documentation

Mozilla FastLoad file format and helper types.

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.

Definition at line 80 of file nsFastLoadFile.h.

Definition at line 81 of file nsFastLoadFile.h.


Function Documentation

NS_AccumulateFastLoadChecksum ( PRUint32 aChecksum,
const PRUint8 aBuffer,
PRUint32  aLength,
PRBool  aLastBuffer 
)

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.

Definition at line 107 of file nsFastLoadFile.cpp.

{
    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;
}

Here is the caller graph for this function:

NS_AddFastLoadChecksums ( PRUint32  sum1,
PRUint32  sum2,
PRUint32  sum2ByteCount 
)

Definition at line 228 of file nsFastLoadFile.cpp.

{
    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;
}

Definition at line 1218 of file nsFastLoadFile.cpp.

{
    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;
}

Here is the call graph for this function:

NS_COM nsresult NS_NewFastLoadFileUpdater ( nsIObjectOutputStream **  aResult,
nsIOutputStream aOutputStream,
nsIObjectInputStream aReaderAsStream 
)

Definition at line 2569 of file nsFastLoadFile.cpp.

{
    // 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;
}

Here is the call graph for this function:

Definition at line 2311 of file nsFastLoadFile.cpp.

{
    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;
}

Here is the call graph for this function: