Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Private Member Functions | Private Attributes
nsStreamConverterService Class Reference

#include <nsStreamConverterService.h>

Inheritance diagram for nsStreamConverterService:
Inheritance graph
[legend]
Collaboration diagram for nsStreamConverterService:
Collaboration graph
[legend]

List of all members.

Public Member Functions

NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMCONVERTERSERVICE 
nsStreamConverterService ()
virtual ~nsStreamConverterService ()
nsresult Init ()
nsIInputStream convert (in nsIInputStream aFromStream, in string aFromType, in string aToType, in nsISupports aContext)
 SYNCRONOUS VERSION Converts a stream of one type, to a stream of another type.
nsIStreamListener asyncConvertData (in string aFromType, in string aToType, in nsIStreamListener aListener, in nsISupports aContext)
 ASYNCRONOUS VERSION Retrieves a nsIStreamListener that receives the original/raw data via its nsIStreamListener::OnDataAvailable() callback, then converts and pushes the data to aListener.

Private Member Functions

nsresult FindConverter (const char *aContractID, nsCStringArray **aEdgeList)
nsresult BuildGraph (void)
nsresult AddAdjacency (const char *aContractID)
nsresult ParseFromTo (const char *aContractID, nsCString &aFromRes, nsCString &aToRes)

Private Attributes

nsObjectHashtable * mAdjacencyList

Detailed Description

Definition at line 47 of file nsStreamConverterService.h.


Constructor & Destructor Documentation

Definition at line 78 of file nsStreamConverterService.cpp.

Definition at line 81 of file nsStreamConverterService.cpp.

                                                    {
    NS_ASSERTION(mAdjacencyList, "init wasn't called, or the retval was ignored");
    delete mAdjacencyList;
}

Member Function Documentation

nsresult nsStreamConverterService::AddAdjacency ( const char *  aContractID) [private]

Definition at line 160 of file nsStreamConverterService.cpp.

                                                              {
    nsresult rv;
    // first parse out the FROM and TO MIME-types.

    nsCAutoString fromStr, toStr;
    rv = ParseFromTo(aContractID, fromStr, toStr);
    if (NS_FAILED(rv)) return rv;

    // Each MIME-type is a vertex in the graph, so first lets make sure
    // each MIME-type is represented as a key in our hashtable.

    nsCStringKey fromKey(fromStr);
    SCTableData *fromEdges = (SCTableData*)mAdjacencyList->Get(&fromKey);
    if (!fromEdges) {
        // There is no fromStr vertex, create one.

        nsCStringKey *newFromKey = new nsCStringKey(ToNewCString(fromStr), fromStr.Length(), nsCStringKey::OWN);
        if (!newFromKey) return NS_ERROR_OUT_OF_MEMORY;

        SCTableData *data = new SCTableData(newFromKey);
        if (!data) {
            delete newFromKey;
            return NS_ERROR_OUT_OF_MEMORY;
        }

        nsCOMArray<nsIAtom>* edgeArray = new nsCOMArray<nsIAtom>;
        if (!edgeArray) {
            delete newFromKey;
            data->key = nsnull;
            delete data;
            return NS_ERROR_OUT_OF_MEMORY;
        }
        data->data.edges = edgeArray;

        mAdjacencyList->Put(newFromKey, data);
        fromEdges = data;
    }

    nsCStringKey toKey(toStr);
    if (!mAdjacencyList->Get(&toKey)) {
        // There is no toStr vertex, create one.
        nsCStringKey *newToKey = new nsCStringKey(ToNewCString(toStr), toStr.Length(), nsCStringKey::OWN);
        if (!newToKey) return NS_ERROR_OUT_OF_MEMORY;

        SCTableData *data = new SCTableData(newToKey);
        if (!data) {
            delete newToKey;
            return NS_ERROR_OUT_OF_MEMORY;
        }

        nsCOMArray<nsIAtom>* edgeArray = new nsCOMArray<nsIAtom>;
        if (!edgeArray) {
            delete newToKey;
            data->key = nsnull;
            delete data;
            return NS_ERROR_OUT_OF_MEMORY;
        }
        data->data.edges = edgeArray;
        mAdjacencyList->Put(newToKey, data);
    }
    
    // Now we know the FROM and TO types are represented as keys in the hashtable.
    // Let's "connect" the verticies, making an edge.

    nsCOMPtr<nsIAtom> vertex = do_GetAtom(toStr.get()); 
    if (!vertex) return NS_ERROR_OUT_OF_MEMORY;

    NS_ASSERTION(fromEdges, "something wrong in adjacency list construction");
    if (!fromEdges)
        return NS_ERROR_FAILURE;

    nsCOMArray<nsIAtom> *adjacencyList = fromEdges->data.edges;
    return adjacencyList->AppendObject(vertex) ? NS_OK : NS_ERROR_FAILURE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsIStreamListener nsIStreamConverterService::asyncConvertData ( in string  aFromType,
in string  aToType,
in nsIStreamListener  aListener,
in nsISupports  aContext 
) [inherited]

ASYNCRONOUS VERSION Retrieves a nsIStreamListener that receives the original/raw data via its nsIStreamListener::OnDataAvailable() callback, then converts and pushes the data to aListener.

Use this method when you want to proxy (and convert) nsIStreamListener callbacks asynchronously.

Parameters:
aFromTypeThe MIME type of the original/raw data.
aToTypeThe MIME type of the converted data.
aListenerThe listener that receives the converted data.
aCtxtEither an opaque context, or a converter specific context (implementation specific).
Returns:
A nsIStreamListener that receives data via its OnDataAvailable() method.

Definition at line 119 of file nsStreamConverterService.cpp.

                                     {

    nsresult rv;

    nsCOMPtr<nsICategoryManager> catmgr(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv));
    if (NS_FAILED(rv)) return rv;

    nsCOMPtr<nsISimpleEnumerator> entries;
    rv = catmgr->EnumerateCategory(NS_ISTREAMCONVERTER_KEY, getter_AddRefs(entries));
    if (NS_FAILED(rv)) return rv;

    // go through each entry to build the graph
    nsCOMPtr<nsISupportsCString> entry;
    rv = entries->GetNext(getter_AddRefs(entry));
    while (NS_SUCCEEDED(rv)) {

        // get the entry string
        nsCAutoString entryString;
        rv = entry->GetData(entryString);
        if (NS_FAILED(rv)) return rv;
        
        // cobble the entry string w/ the converter key to produce a full contractID.
        nsCAutoString contractID(NS_ISTREAMCONVERTER_KEY);
        contractID.Append(entryString);

        // now we've got the CONTRACTID, let's parse it up.
        rv = AddAdjacency(contractID.get());
        if (NS_FAILED(rv)) return rv;

        rv = entries->GetNext(getter_AddRefs(entry));
    }

    return NS_OK;
}

Here is the call graph for this function:

nsIInputStream nsIStreamConverterService::convert ( in nsIInputStream  aFromStream,
in string  aFromType,
in string  aToType,
in nsISupports  aContext 
) [inherited]

SYNCRONOUS VERSION Converts a stream of one type, to a stream of another type.

Use this method when you have a stream you want to convert.

Parameters:
aFromStreamThe stream representing the original/raw data.
aFromTypeThe MIME type of aFromStream.
aToTypeThe MIME type of the returned stream.
aContextEither an opaque context, or a converter specific context (implementation specific).
Returns:
The converted stream. NOTE: The returned stream may not already be converted. An efficient stream converter implementation will convert data on demand rather than buffering the converted data until it is used.
nsresult nsStreamConverterService::FindConverter ( const char *  aContractID,
nsCStringArray **  aEdgeList 
) [private]

Definition at line 310 of file nsStreamConverterService.cpp.

                                                                                           {
    nsresult rv;
    if (!aEdgeList) return NS_ERROR_NULL_POINTER;
    *aEdgeList = nsnull;

    // walk the graph in search of the appropriate converter.

    PRInt32 vertexCount = mAdjacencyList->Count();
    if (0 >= vertexCount) return NS_ERROR_FAILURE;

    // Create a corresponding color table for each vertex in the graph.
    nsObjectHashtable lBFSTable(nsnull, nsnull, DeleteBFSEntry, nsnull);
    mAdjacencyList->Enumerate(InitBFSTable, &lBFSTable);

    NS_ASSERTION(lBFSTable.Count() == vertexCount, "strmconv BFS table init problem");

    // This is our source vertex; our starting point.
    nsCAutoString fromC, toC;
    rv = ParseFromTo(aContractID, fromC, toC);
    if (NS_FAILED(rv)) return rv;

    nsCStringKey *source = new nsCStringKey(fromC.get());
    if (!source) return NS_ERROR_OUT_OF_MEMORY;

    SCTableData *data = (SCTableData*)lBFSTable.Get(source);
    if (!data) {
        delete source;
        return NS_ERROR_FAILURE;
    }

    BFSState *state = data->data.state;

    state->color = gray;
    state->distance = 0;
    CStreamConvDeallocator *dtorFunc = new CStreamConvDeallocator();
    if (!dtorFunc) {
        delete source;
        return NS_ERROR_OUT_OF_MEMORY;
    }

    nsDeque grayQ(dtorFunc);

    // Now generate the shortest path tree.
    grayQ.Push(source);
    while (0 < grayQ.GetSize()) {
        nsCStringKey *currentHead = (nsCStringKey*)grayQ.PeekFront();
        SCTableData *data2 = (SCTableData*)mAdjacencyList->Get(currentHead);
        if (!data2) return NS_ERROR_FAILURE;

        nsCOMArray<nsIAtom> *edges = data2->data.edges;
        NS_ASSERTION(edges, "something went wrong with BFS strmconv algorithm");
        if (!edges) return NS_ERROR_FAILURE;

        // Get the state of the current head to calculate the distance of each
        // reachable vertex in the loop.
        data2 = (SCTableData*)lBFSTable.Get(currentHead);
        if (!data2) return NS_ERROR_FAILURE;

        BFSState *headVertexState = data2->data.state;
        NS_ASSERTION(headVertexState, "problem with the BFS strmconv algorithm");
        if (!headVertexState) return NS_ERROR_FAILURE;

        PRInt32 edgeCount = edges->Count();

        for (PRInt32 i = 0; i < edgeCount; i++) {
            nsIAtom* curVertexAtom = edges->ObjectAt(i);
            nsAutoString curVertexStr;
            curVertexAtom->ToString(curVertexStr);
            nsCStringKey *curVertex = new nsCStringKey(ToNewCString(curVertexStr), 
                                        curVertexStr.Length(), nsCStringKey::OWN);
            if (!curVertex) return NS_ERROR_OUT_OF_MEMORY;

            SCTableData *data3 = (SCTableData*)lBFSTable.Get(curVertex);
            if (!data3) {
                delete curVertex;
                return NS_ERROR_FAILURE;
            }
            BFSState *curVertexState = data3->data.state;
            NS_ASSERTION(curVertexState, "something went wrong with the BFS strmconv algorithm");
            if (!curVertexState) return NS_ERROR_FAILURE;

            if (white == curVertexState->color) {
                curVertexState->color = gray;
                curVertexState->distance = headVertexState->distance + 1;
                curVertexState->predecessor = (nsCStringKey*)currentHead->Clone();
                if (!curVertexState->predecessor) {
                    delete curVertex;
                    return NS_ERROR_OUT_OF_MEMORY;
                }
                grayQ.Push(curVertex);
            } else {
                delete curVertex; // if this vertex has already been discovered, we don't want
                                  // to leak it. (non-discovered vertex's get cleaned up when
                                  // they're popped).
            }
        }
        headVertexState->color = black;
        nsCStringKey *cur = (nsCStringKey*)grayQ.PopFront();
        delete cur;
        cur = nsnull;
    }
    // The shortest path (if any) has been generated and is represetned by the chain of 
    // BFSState->predecessor keys. Start at the bottom and work our way up.

    // first parse out the FROM and TO MIME-types being registered.

    nsCAutoString fromStr, toStr;
    rv = ParseFromTo(aContractID, fromStr, toStr);
    if (NS_FAILED(rv)) return rv;

    // get the root CONTRACTID
    nsCAutoString ContractIDPrefix(NS_ISTREAMCONVERTER_KEY);
    nsCStringArray *shortestPath = new nsCStringArray();
    if (!shortestPath) return NS_ERROR_OUT_OF_MEMORY;

    nsCStringKey toMIMEType(toStr);
    data = (SCTableData*)lBFSTable.Get(&toMIMEType);
    if (!data) {
        // If this vertex isn't in the BFSTable, then no-one has registered for it,
        // therefore we can't do the conversion.
        delete shortestPath;
        return NS_ERROR_FAILURE;
    }

    while (data) {
        BFSState *curState = data->data.state;

        nsCStringKey *key = data->key;
        
        if (fromStr.Equals(key->GetString())) {
            // found it. We're done here.
            *aEdgeList = shortestPath;
            return NS_OK;
        }

        // reconstruct the CONTRACTID.
        // Get the predecessor.
        if (!curState->predecessor) break; // no predecessor
        SCTableData *predecessorData = (SCTableData*)lBFSTable.Get(curState->predecessor);

        if (!predecessorData) break; // no predecessor, chain doesn't exist.

        // build out the CONTRACTID.
        nsCAutoString newContractID(ContractIDPrefix);
        newContractID.AppendLiteral("?from=");

        nsCStringKey *predecessorKey = predecessorData->key;
        newContractID.Append(predecessorKey->GetString());

        newContractID.AppendLiteral("&to=");
        newContractID.Append(key->GetString());
    
        // Add this CONTRACTID to the chain.
        rv = shortestPath->AppendCString(newContractID) ? NS_OK : NS_ERROR_FAILURE;  // XXX this method incorrectly returns a bool
        NS_ASSERTION(NS_SUCCEEDED(rv), "AppendElement failed");

        // move up the tree.
        data = predecessorData;
    }
    delete shortestPath;
    return NS_ERROR_FAILURE; // couldn't find a stream converter or chain.
}

Here is the call graph for this function:

Definition at line 97 of file nsStreamConverterService.cpp.

                               {
    mAdjacencyList = new nsObjectHashtable(nsnull, nsnull,
                                           DeleteAdjacencyEntry, nsnull);
    if (!mAdjacencyList) return NS_ERROR_OUT_OF_MEMORY;
    return NS_OK;
}

Here is the call graph for this function:

nsresult nsStreamConverterService::ParseFromTo ( const char *  aContractID,
nsCString aFromRes,
nsCString aToRes 
) [private]

Definition at line 236 of file nsStreamConverterService.cpp.

                                                                                                     {

    nsCAutoString ContractIDStr(aContractID);

    PRInt32 fromLoc = ContractIDStr.Find("from=");
    PRInt32 toLoc   = ContractIDStr.Find("to=");
    if (-1 == fromLoc || -1 == toLoc ) return NS_ERROR_FAILURE;

    fromLoc = fromLoc + 5;
    toLoc = toLoc + 3;

    nsCAutoString fromStr, toStr;

    ContractIDStr.Mid(fromStr, fromLoc, toLoc - 4 - fromLoc);
    ContractIDStr.Mid(toStr, toLoc, ContractIDStr.Length() - toLoc);

    aFromRes.Assign(fromStr);
    aToRes.Assign(toStr);

    return NS_OK;
}

Here is the caller graph for this function:


Member Data Documentation

nsObjectHashtable* nsStreamConverterService::mAdjacencyList [private]

Definition at line 74 of file nsStreamConverterService.h.


The documentation for this class was generated from the following files: