Back to index

lightning-sunbird  0.9+nobinonly
Classes | Public Types | Public Member Functions | Static Protected Member Functions | Protected Attributes | Static Protected Attributes | Static Private Member Functions
nsElementMap Class Reference

#include <nsElementMap.h>

Collaboration diagram for nsElementMap:
Collaboration graph
[legend]

List of all members.

Classes

class  ContentListItem
struct  EnumerateClosure

Public Types

typedef PRIntn(* nsElementMapEnumerator )(const PRUnichar *aID, nsIContent *aElement, void *aClosure)

Public Member Functions

 nsElementMap (void)
virtual ~nsElementMap ()
nsresult Add (const nsAString &aID, nsIContent *aContent)
nsresult Remove (const nsAString &aID, nsIContent *aContent)
nsresult Find (const nsAString &aID, nsISupportsArray *aResults)
nsresult FindFirst (const nsAString &aID, nsIContent **aContent)
nsresult Enumerate (nsElementMapEnumerator aEnumerator, void *aClosure)

Static Protected Member Functions

static PLHashNumber PR_CALLBACK Hash (const void *akey)
static PRIntn PR_CALLBACK Compare (const void *aLeft, const void *aRight)
static PRIntn PR_CALLBACK ReleaseContentList (PLHashEntry *aHashEntry, PRIntn aIndex, void *aClosure)

Protected Attributes

PLHashTablemMap
nsFixedSizeAllocator mPool

Static Protected Attributes

static PLHashAllocOps gAllocOps

Static Private Member Functions

static PRIntn PR_CALLBACK EnumerateImpl (PLHashEntry *aHashEntry, PRIntn aIndex, void *aClosure)

Detailed Description

Definition at line 72 of file nsElementMap.h.


Class Documentation

struct nsElementMap::EnumerateClosure

Definition at line 142 of file nsElementMap.h.

Collaboration diagram for nsElementMap::EnumerateClosure:
Class Members
void * mClosure
nsElementMapEnumerator mEnumerator
nsElementMap * mSelf

Member Typedef Documentation

Definition at line 134 of file nsElementMap.h.


Constructor & Destructor Documentation

Definition at line 91 of file nsElementMap.cpp.

{
    MOZ_COUNT_CTOR(nsElementMap);

    // Create a table for mapping IDs to elements in the content tree.
    static const size_t kBucketSizes[] = {
        sizeof(PLHashEntry), sizeof(ContentListItem)
    };

    static const PRInt32 kNumBuckets = sizeof(kBucketSizes) / sizeof(size_t);

    static const PRInt32 kInitialNumElements = 64;

    // Per news://news.mozilla.org/39BEC105.5090206%40netscape.com
    static const PRInt32 kInitialPoolSize = 512;

    mPool.Init("nsElementMap", kBucketSizes, kNumBuckets, kInitialPoolSize);

    mMap = PL_NewHashTable(kInitialNumElements,
                           Hash,
                           Compare,
                           PL_CompareValues,
                           &gAllocOps,
                           &mPool);

    NS_ASSERTION(mMap != nsnull, "could not create hash table for resources");

#ifdef PR_LOGGING
    if (! gMapLog)
        gMapLog = PR_NewLogModule("nsElementMap");


    PR_LOG(gMapLog, PR_LOG_NOTICE,
           ("xulelemap(%p) created", this));
#endif
}

Here is the call graph for this function:

Definition at line 128 of file nsElementMap.cpp.

{
    MOZ_COUNT_DTOR(nsElementMap);

    if (mMap) {
        PL_HashTableEnumerateEntries(mMap, ReleaseContentList, this);
        PL_HashTableDestroy(mMap);
    }

    PR_LOG(gMapLog, PR_LOG_NOTICE,
           ("xulelemap(%p) destroyed", this));
}

Here is the call graph for this function:


Member Function Documentation

nsresult nsElementMap::Add ( const nsAString &  aID,
nsIContent aContent 
)

Definition at line 166 of file nsElementMap.cpp.

{
    NS_PRECONDITION(mMap != nsnull, "not initialized");
    if (! mMap)
        return NS_ERROR_NOT_INITIALIZED;

    const nsPromiseFlatString& flatID = PromiseFlatString(aID);
    const PRUnichar *id = flatID.get();

    ContentListItem* head =
        NS_STATIC_CAST(ContentListItem*, PL_HashTableLookup(mMap, id));

    if (! head) {
        head = ContentListItem::Create(mPool, aContent);
        if (! head)
            return NS_ERROR_OUT_OF_MEMORY;

        PRUnichar* key = ToNewUnicode(aID);
        if (! key)
            return NS_ERROR_OUT_OF_MEMORY;

        PL_HashTableAdd(mMap, key, head);
    }
    else {
        while (1) {
            if (head->mContent.get() == aContent) {
                // This can happen if an element that was created via
                // frame construction code is then "appended" to the
                // content model with aNotify == PR_TRUE. If you see
                // this warning, it's an indication that you're
                // unnecessarily notifying the frame system, and
                // potentially causing unnecessary reflow.
                //NS_ERROR("element was already in the map");
#ifdef PR_LOGGING
                if (PR_LOG_TEST(gMapLog, PR_LOG_NOTICE)) {
                    const char *tagname;
                    aContent->Tag()->GetUTF8String(&tagname);

                    nsCAutoString aidC; 
                    aidC.AssignWithConversion(id, aID.Length());
                    PR_LOG(gMapLog, PR_LOG_NOTICE,
                           ("xulelemap(%p) dup    %s[%p] <-- %s\n",
                            this,
                            tagname,
                            aContent,
                            aidC.get()));
                }
#endif

                return NS_OK;
            }
            if (! head->mNext)
                break;

            head = head->mNext;
        }

        head->mNext = nsElementMap::ContentListItem::Create(mPool, aContent);
        if (! head->mNext)
            return NS_ERROR_OUT_OF_MEMORY;
    }

#ifdef PR_LOGGING
    if (PR_LOG_TEST(gMapLog, PR_LOG_NOTICE)) {
        const char *tagname;
        aContent->Tag()->GetUTF8String(&tagname);

        nsCAutoString aidC; 
        aidC.AssignWithConversion(id, aID.Length());
        PR_LOG(gMapLog, PR_LOG_NOTICE,
               ("xulelemap(%p) add    %s[%p] <-- %s\n",
                this,
                tagname,
                aContent,
                aidC.get()));
    }
#endif

    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRIntn nsElementMap::Compare ( const void aLeft,
const void aRight 
) [static, protected]

Definition at line 427 of file nsElementMap.cpp.

{
    return 0 == nsCRT::strcmp(NS_REINTERPRET_CAST(const PRUnichar*, aLeft),
                              NS_REINTERPRET_CAST(const PRUnichar*, aRight));
}

Here is the caller graph for this function:

nsresult nsElementMap::Enumerate ( nsElementMapEnumerator  aEnumerator,
void aClosure 
)

Definition at line 359 of file nsElementMap.cpp.

{
    EnumerateClosure closure = { this, aEnumerator, aClosure };
    PL_HashTableEnumerateEntries(mMap, EnumerateImpl, &closure);
    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRIntn nsElementMap::EnumerateImpl ( PLHashEntry aHashEntry,
PRIntn  aIndex,
void aClosure 
) [static, private]

Definition at line 368 of file nsElementMap.cpp.

{
    // This routine will be called once for each key in the
    // hashtable. It will in turn call the enumerator that the user
    // has passed in via Enumerate() once for each element that's been
    // mapped to this ID.
    EnumerateClosure* closure = NS_REINTERPRET_CAST(EnumerateClosure*, aClosure);

    const PRUnichar* id =
        NS_REINTERPRET_CAST(const PRUnichar*, aHashEntry->key);

    // 'link' holds a pointer to the previous element's link field.
    ContentListItem** link = 
        NS_REINTERPRET_CAST(ContentListItem**, &aHashEntry->value);

    ContentListItem* item = *link;

    // Iterate through each content node that's been mapped to this ID
    while (item) {
        ContentListItem* current = item;
        item = item->mNext;
        PRIntn result = (*closure->mEnumerator)(id, current->mContent, closure->mClosure);

        if (result == HT_ENUMERATE_REMOVE) {
            // If the user wants to remove the current, then deal.
            *link = item;
            ContentListItem::Destroy(closure->mSelf->mPool, current);

            if ((! *link) && (link == NS_REINTERPRET_CAST(ContentListItem**, &aHashEntry->value))) {
                // It's the last content node that was mapped to this
                // ID. Unhash it.
                PRUnichar* key = NS_CONST_CAST(PRUnichar*, id);
                nsMemory::Free(key);
                return HT_ENUMERATE_REMOVE;
            }
        }
        else {
            link = &current->mNext;
        }
    }

    return HT_ENUMERATE_NEXT;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsElementMap::Find ( const nsAString &  aID,
nsISupportsArray aResults 
)

Definition at line 319 of file nsElementMap.cpp.

{
    NS_PRECONDITION(mMap != nsnull, "not initialized");
    if (! mMap)
        return NS_ERROR_NOT_INITIALIZED;

    aResults->Clear();
    ContentListItem* item =
        NS_REINTERPRET_CAST(ContentListItem*, PL_HashTableLookup(mMap, (const PRUnichar *)PromiseFlatString(aID).get()));

    while (item) {
        aResults->AppendElement(item->mContent);
        item = item->mNext;
    }
    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsElementMap::FindFirst ( const nsAString &  aID,
nsIContent **  aContent 
)

Definition at line 338 of file nsElementMap.cpp.

{
    NS_PRECONDITION(mMap != nsnull, "not initialized");
    if (! mMap)
        return NS_ERROR_NOT_INITIALIZED;

    ContentListItem* item =
        NS_REINTERPRET_CAST(ContentListItem*, PL_HashTableLookup(mMap, (const PRUnichar *)PromiseFlatString(aID).get()));

    if (item) {
        *aResult = item->mContent;
        NS_ADDREF(*aResult);
    }
    else {
        *aResult = nsnull;
    }

    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PLHashNumber nsElementMap::Hash ( const void akey) [static, protected]

Definition at line 414 of file nsElementMap.cpp.

{
    PLHashNumber result = 0;
    const PRUnichar* s = NS_REINTERPRET_CAST(const PRUnichar*, aKey);
    while (*s != nsnull) {
        result = (result >> 28) ^ (result << 4) ^ *s;
        ++s;
    }
    return result;
}

Here is the caller graph for this function:

PRIntn nsElementMap::ReleaseContentList ( PLHashEntry aHashEntry,
PRIntn  aIndex,
void aClosure 
) [static, protected]

Definition at line 143 of file nsElementMap.cpp.

{
    nsElementMap* self = NS_STATIC_CAST(nsElementMap*, aClosure);

    PRUnichar* id =
        NS_REINTERPRET_CAST(PRUnichar*, NS_CONST_CAST(void*, aHashEntry->key));

    nsMemory::Free(id);
        
    ContentListItem* head =
        NS_REINTERPRET_CAST(ContentListItem*, aHashEntry->value);

    while (head) {
        ContentListItem* doomed = head;
        head = head->mNext;
        ContentListItem::Destroy(self->mPool, doomed);
    }

    return HT_ENUMERATE_NEXT;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsElementMap::Remove ( const nsAString &  aID,
nsIContent aContent 
)

Definition at line 249 of file nsElementMap.cpp.

{
    NS_PRECONDITION(mMap != nsnull, "not initialized");
    if (! mMap)
        return NS_ERROR_NOT_INITIALIZED;

    const nsPromiseFlatString& flatID = PromiseFlatString(aID);
    const PRUnichar *id = flatID.get();

#ifdef PR_LOGGING
    if (PR_LOG_TEST(gMapLog, PR_LOG_NOTICE)) {
        const char *tagname;
        aContent->Tag()->GetUTF8String(&tagname);

        nsCAutoString aidC; 
        aidC.AssignWithConversion(id);
        PR_LOG(gMapLog, PR_LOG_NOTICE,
               ("xulelemap(%p) remove  %s[%p] <-- %s\n",
                this,
                tagname,
                aContent,
                aidC.get()));
    }
#endif

    PLHashEntry** hep = PL_HashTableRawLookup(mMap,
                                              Hash(id),
                                              id);

    // XXX Don't comment out this assert: if you get here, something
    // has gone dreadfully, horribly wrong. Curse. Scream. File a bug
    // against waterson@netscape.com.
    NS_ASSERTION(hep != nsnull && *hep != nsnull, "attempt to remove an element that was never added");
    if (!hep || !*hep)
        return NS_OK;

    ContentListItem* head = NS_REINTERPRET_CAST(ContentListItem*, (*hep)->value);

    if (head->mContent.get() == aContent) {
        ContentListItem* next = head->mNext;
        if (next) {
            (*hep)->value = next;
        }
        else {
            // It was the last reference in the table
            PRUnichar* key = NS_REINTERPRET_CAST(PRUnichar*, NS_CONST_CAST(void*, (*hep)->key));
            PL_HashTableRawRemove(mMap, hep, *hep);
            nsMemory::Free(key);
        }
        ContentListItem::Destroy(mPool, head);
    }
    else {
        ContentListItem* item = head->mNext;
        while (item) {
            if (item->mContent.get() == aContent) {
                head->mNext = item->mNext;
                ContentListItem::Destroy(mPool, item);
                break;
            }
            head = item;
            item = item->mNext;
        }
    }

    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Initial value:

Definition at line 78 of file nsElementMap.h.

Definition at line 75 of file nsElementMap.h.

nsFixedSizeAllocator nsElementMap::mPool [protected]

Definition at line 76 of file nsElementMap.h.


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