mozilla
Your Search Results

    XPCOM array guide

    Introduction

    Array types

    Mozilla has many array classes because each array is optimized for a particular usage pattern. This guide describes the available arrays as well as the enumerator classes that can be used to get to them. In this document the term Array refers to a container for multiple objects with a numeric, zero-based index.

    The standard array classes are:

    • nsIArray - a scriptable container for scriptable XPCOM objects. This array is read-only, and the interface does not provide any methods that will allow adding and removing members.
    • nsIMutableArray - a scriptable container for scriptable XPCOM objects, which allows addition and removal of member objects. This interface actually derives from nsIArray.
    • nsTArray<T> - a C++ class which provides a typesafe container for objects or primitive types (pointers, integers, and so on). The objects must define a default constructor and a copy constructor. To use IndexOf without providing a comparator, they must also define an operator==. For sorting without providing a comparator they must define an operator<. Note that this class differs from the other array types by using unsigned indices.
    • nsCOMArray<T> - a C++ class which provides a typesafe, reference-counted container for pointers to a single type of COM object. This class is more or less a wrapper around nsVoidArray and thus shares most of its semantics.
    • nsAutoTArray<T, N> - a version of nsTArray which includes N entries of internal storage for the array data.
    • nsTPtrArray<T> and nsAutoTPtrArray<T> - similar to using T* with the above arrays, but also provides a SafeElementAt() accessor. As of Gecko 8, SafeElementAt() is now directly available on nsTArray for arrays instantiated with pointer types.
    • nsVoidArray - a C++ class which provides a generic container for any objects using the generic void * type.
    • nsStringArray Obsolete since Gecko 5.0/ nsCStringArray - a set of C++ classes for holding lists of string objects. Derived from nsVoidArray.
    • nsAutoVoidArray - a version of nsVoidArray which includes 8 entries of internal storage for the array data.
    • nsSmallVoidArray - a replacement for nsVoidArray which is optimized to hold zero or one element.
    • Some other arrays: FallibleTArray, AutoFallibleTArray, InfallibleTArray, AutoInfallibleTArray, nsTObserverArray, nsAutoTObserverArray.

    This handy chart may make it easier to understand the different arrays:

    Class Data Type Scriptable? Typesafe? Can be modified? Built in buffer? Ownership
    nsIArray XPCOM object Yes No No No Reference Counted, Weak/Strong
    nsIMutableArray XPCOM object Yes No Yes No Reference Counted, Weak/Strong
    nsCOMArray<T> XPCOM object No Yes Yes* No Reference Counted, Strong
    nsTArray<T> Any that has a default constructor and copy constructor No Yes Yes* No Can hold objects directly, in which case it owns them. When holding pointers, doesn't own the pointer.
    nsAutoTArray<T,N> Any that has a default constructor and copy constructor No Yes Yes* Yes Can hold objects directly, in which case it owns them. When holding pointers, doesn't own the pointer.
    nsVoidArray Any No No Yes* No Weak / None
    nsStringArrayObsolete since Gecko 5.0 nsString No Yes Yes* No Private (copies strings)
    nsCStringArray nsCString
    nsAutoVoidArray Any No No Yes* Yes Weak / None
    nsSmallVoidArray Any No No Yes* No Weak / None
    nsISupportsArray XPCOM Object Yes No Yes* No Reference Counted, Strong

    (*) Note: Concrete C++ arrays can be made read-only by declaring them const. For example:

    // HandleList cannot modify the array because of const
    void HandleList(const nsVoidArray&);
    

    In-place enumeration

    Most of the arrays presented here provide callback-style means to enumerate members of an array. Instead of incrementally accessing each element of the array by its index, the arrays provide a way to pass in a callback function that will be called for each element in the array.

    For most concrete C++ classes like nsVoidArray and nsCOMArray<T>, indexing should be faster than the callback-style enumeration, because accessing an indexed member of such an array is usually very fast, while enumeration has slight function call overhead. In the case of scriptable arrays like nsIArray however, the enumeration mechanism is often preferred because it avoids the AddRef / Release overhead that comes from accessing each object.

    The only functional drawback to in-place enumeration is that you cannot manipulate the array itself during the enumeration. For example, you should not delete elements of an array during the enumeration as this will often confuse the loop which is enumerating the array.

    Enumerators

    Most arrays provide access to an object which is used to enumerate members of the array. These Enumerators maintain state about the current position in the array. Enumerators are used to access the elements in an ordered way, without relying on the underlying array type. These enumerators include:

    • nsISimpleEnumerator - an enumerator for COM objects.
    • nsIStringEnumerator / nsIUTF8StringEnumerator - enumerators for strings

    Obsolete arrays / enumerators

    There are some deprecated classes which should not be used by new code.

    • nsISupportsArray - obsoleted by nsIArray and nsIMutableArray, use those instead.
    • nsIEnumerator - obsoleted by nsISimpleEnumerator, use that instead.
    • nsIBidirectionalEnumerator - obsoleted by nsISimpleEnumerator, use that instead.
    • nsStringArray Obsolete since Gecko 5.0/ nsCStringArray - nsTArray<nsString> / nsTArray<nsCString> is preferred.
    • nsVoidArray - nsTArray<T> is preferred.

    Which Array should I use?

    Do not use nsISupportsArray; it is deprecated.

    Does your array need to be scriptable? If so, use nsIArray.

    Example: an array attribute in an IDL file would be nsIArray.

    Will your array store non-refcounted objects and need automatic resizing? If so, use nsTArray<T>.

    Example: an array of integers or an array of strings.

    Will your array store non-refcounted objects and be a fixed size? If so, just use a native C++ array unless you need the enumeration options on nsTArray<T>.

    Example: an array of error message static const char* pointers.

    Are all the things you are storing interface pointers to instances of the same interface? If so, use nsCOMArray.

    Example: a content node's list of nsIContent children.

    Otherwise use nsIArray and make liberal use of QueryElementAt().

    The point of nsCOMArray is that it's a template, and all the pointers in it must be pointers to the same type; it's nice to be able to use it because you get type-safety and don't have to spend time and code QIing (like you have to with nsIArray).

    Array Guidelines

    Here are a few simple rules which will keep your code clean and your developers happy:

    • Use typesafe arrays like nsCOMArray<T> nsTArray<T> wherever possible.
    • Avoid all obsolete arrays and enumerators.
    • Avoid creating temporary arrays.

    Scriptable Arrays

    nsIArray / nsIMutableArray

    Usage

    nsIArray is useful if you need to pass arrays of COM objects through interfaces or require a scriptable array. It can hold strong or weak references to its container objects. This basic interface only allows querying of existing elements in the array. The methods that modify the array have been broken out into nsIMutableArray.

    An nsIArray implementation can be created from C++ or JavaScript using nsIComponentManager.createInstance() and the contract ID "@mozilla.org/array;1". The created array implements nsIMutableArray and nsIArray. Since nsIMutableArray derives from nsIArray, the resulting array can be cast to a read-only array.

    C++ Example

    void GetList(nsIArray** aResult) {
      nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID);
    
      // append some elements
      ...
    
      // return it to the caller
      *aResult = array;
      NS_ADDREF(*aResult);
    }
    

    JavaScript Example

    function getList() {
      var array = Components.classes["@mozilla.org/array;1"]
                            .createInstance(Components.interfaces.nsIMutableArray);
      // append some elements
      ...
    
      // return it to the caller
      return array;
    }
    

    Access to elements

    Since nsIArray is a regular XPCOM object, its interfaces follows the standard conventions of ownership. Access to specific elements is through QueryElementAt, which is similar to QueryInterface, but it takes a specific index.

    void NotifyObservers(nsIArray* aArray) {
      PRUint32 length;
      aArray->GetLength(&length);
      for (PRUint32 i=0; i<length; ++i) {
        nsCOMPtr<nsIMyObserver> element;
        aArray->QueryElementAt(i, NS_GET_IID(nsIElement), getter_AddRefs(element));
        element->Observe();
      }
    }
    

    A simpler option is to use the helper do_QueryElementAt which is typesafe.

    void NotifyObservers(nsIArray* aArray) {
      PRUint32 length;
      aArray->GetLength(&length);
      for (PRUint32 i=0; i<length; ++i) {
        nsCOMPtr<nsIMyObserver> element = do_QueryElementAt(aArray, i);
        element->Observe();
      }
    }
    

    Passing as a parameter

    Since nsIArray is an XPCOM object, it should be passed as a pointer. To distinguish between read-only arrays and writable arrays, you should make sure to pass a nsIArray or nsIMutableArray as appropriate.

    When the array can or should be modified, then use nsIMutableArray:

    // array is read-only because it uses nsIArray
    void PrintSize(nsIArray* elements) {
      PRUint32 count;
      elements->GetLength(&count);
      printf("There are %d elements.\n", count);
    }
    
    // using nsIMutableArray, so callee may modify
    void TweakArray(nsIMutableArray* elements) {
      elements->RemoveElementAt(0);
      elements->AppendElement(newElement, PR_FALSE);
    }
    

    While it is usually possible to call QueryInterface on an nsIArray to get access to the nsIMutableArray interface, this is against convention and it should be avoided.

    // no need for the double-pointer, and this violates XPCOM rules
    // which expect acess to a new object
    void TweakArray(nsIMutableArray** elements) {
      // ugh, extra indirection!
      *elements->RemoveElementAt(0);
      *elements->AppendElement(newElement, PR_FALSE);
    }
    

    In-place enumeration

    When accessing all members of an nsIArray, in-place enumeration is preferred over indexed access. However, I seem to have forgotten to implement that. Good thing the interface is under review. Sorry!

    Enumerators

    Creating an enumerator from an nsIArray is easy. The method Enumerate() returns a nsISimpleEnumerator which accesses all the elements in the array. Often, simply accessing an array by index, using QueryElementAt is faster. See the section on Enumerators to learn when to properly use enumerators.

    For example, if you need to iterate an array returned from another object, you might use Enumerate().

    ...
    // get the array
    nsCOMPtr<nsIArray> array;
    foo->GetElements(getter_AddRefs(array));
    
    // make an enumerator
    nsCOMPtr<nsISimpleEnumerator> enumerator;
    array->Enumerate(getter_AddRefs(enumerator));
    
    // now enumerate the elements
    ...
    

    Typesafe Arrays

    nsCOMArray<T>

    nsCOMArray<T> is a typesafe wrapper around nsVoidArray, so it has a similar API. It enforces both typesafety and XPCOM reference counting by keeping an owning reference to each element in the array.

    Usage

    It is most often used as a member of a C++ class to store a list of well-typed XPCOM objects. It is also usually declared as an inline member rather than a pointer. As a class member, nsCOMArray<T> is preferred over nsIArray when access to the array is confined to the class itself.

    For example, here is its use in a class:

    class NodeContainer {
    public:
      void AddNode(nsINode* node);
       
    private:
      nsCOMArray<nsINode> mNodes;
    };
    
    // typesafety of mNodes ensures that we only append an nsINode*
    void NodeContainer::AddNode(nsINode* node) {
      mNodes.AppendObject(node);
    }
       
    

    nsCOMArray<T> can also be declared on the stack to collect a temporary list of objects and manipulate them. When the object goes out of scope, all its members are released.

    void ProcessVisibleItems()
    {
      // temporary stack-based nsCOMArray
      nsCOMArray<nsIFoo> fooItems;
      GetCompleteList(fooItems);
       
      // now filter out non visible objects
      // doing this backwards
      PRUint32 i = fooItems.Count();
      while (i > 0) {
        --i;
        PRBool isVisible;
        fooItems[i]->GetIsVisible(&isVisible);
        if (!isVisible) {
          fooItems.RemoveObjectAt(i);
        }
      }
    
      // now deal with the processed list
      ProcessList(fooItems);
    
      // fooItems will release all its members
      // when it goes out of scope
    }
    

    Access to elements

    nsCOMArray<T> is a concrete C++ class, and so the [] operator is used to access its members. When using the [] operator, the reference count is unchanged. This allows direct processing of array elements without worrying about calling Release().

    For example, this code calls the same method on each member:

    void NotifyObservers(const nsCOMArray<nsIMyObserver>& observers) {
      // Using [] doesn't leak!
      for (PRInt32 i = observers.Count() - 1; i >= 0 ; i--)
        observers[i]->Observe();
    }
    

    Be careful with this though, you could end up with a weak pointer if you're converting from non-nsCOMArray code.

    // old version, relied on automatic addref
    // mElements is an nsISupportsArray*
    void GetFirstObject(nsIElement** aResult) {
      // no need to call NS_ADDREF - this does it for you
      mElements->QueryElementAt(0, NS_GET_IID(nsIElement), (void**)aResult);
    }
      
    // new version, make sure to call NS_ADDREF()
    // mElements is now a nsCOMArray<nsIElement>
    void GetFirstObject(nsIElement** aResult) {
      *aResult = mElements[0];
      NS_ADDREF(*aResult);
    }
    

    Passing as a parameter

    When passing nsCOMArray<T> among functions, the convention is to pass by reference. Also be sure to use const if you want to enforce that the array is read-only.

    Here is an example with a read-only and a writable array:

    // array is read-only because of const
    void PrintSize(const nsCOMArray<nsIElements>& elements) {
     printf("There are %d elements.\n", elements.Count());
    }
    
    // no const, so we can modify the array
    void TweakArray(nsCOMArray<nsIElement>& elements, nsIElement* newElement) {
      elements.RemoveObjectAt(0);
      elements.AppendObject(newElement);
    }
    

    In-place enumeration

    The callback-based enumeration in nsCOMArray<T> is about as fast as, if not faster than, standard loop-based iteration. The callback mechanism can be useful when integrating with existing callback-style code however.

    One particularly nice thing about the callback mechanism is that it is typesafe. For instance:

    PR_CALLBACK PRBool getFirstVisible(nsIElement* element, void* closure) {
     PRBool isVisible;
     element->IsVisible(&isVisible);
    
     // stop at first object
     if (isVisible) {
       NS_STATIC_CAST(ClosureObject*,closure)->element = element;
       return PR_FALSE;
     }
     return PR_TRUE;
    }
    
    ...
    // enumerate to find the object
    ClosureObject closureObject = { 0 };
    if (!mElements.EnumerateForwards(getFirstVisible, closureObject))
      processElement(closureObject->element);
    ...
    

    Enumerators

    A nsISimpleEnumerator can be created to provide access to a nsCOMArray<T>. When the enumerator is created, it takes a snapshot of the elements in the array, so that the enumerator can outlive the array.

    To create the enumerator, use NS_NewArrayEnumerator(nsISimpleEnumerator**, const nsCOMArray<T>&).  For example:

    // mElements is an nsCOMArray<nsIElement>
    nsFoo::GetElements(nsISimpleEnumerator** aResult) {
      return NS_NewArrayEnumerator(aResult, mElements);
    }
    

    (Firefox 6.0 / Thunderbird 6.0 / SeaMonkey 2.3)

    Deleting objects

    Gecko 6.0 (Firefox 6.0 / Thunderbird 6.0 / SeaMonkey 2.3) introduces the RemoveObjectsAt() method to nsCOMArray<T>. This lets you delete multiple objects from the array at once by specifying the index to the first item to delete as well as the number of items to delete.

    For example, to remove three objects, starting at the third object in the array (that is, the object with index value 2):

    myArray.RemoveObjectsAt(2, 3);
    

    nsTArray<T>

    nsTArray<T> is a typesafe array for holding various objects. It can be used to hold objects directly, not just pointers to objects.

    Usage

    It is most often used as a member of a C++ class to store a list of well-typed objects. It is also usually declared as an inline member rather than a pointer. As a class member, nsTArray<T> is preferred over nsVoidArray.

    For example, here is its use in a class:

    class MediaList {
    public:
      void AddMedium(const nsString& aMedium);
       
    private:
      nsTArray<nsString> mMedia;
    };
    
    // typesafety of mMedia ensures that we only append an nsString
    void NodeContainer::AddMedium(const nsString& aMedium) {
      mMedia.AppendElement(aMedium);
    }
       
    

    nsTArray<T> can also be declared on the stack to collect a temporary list of objects and manipulate them. When the object goes out of scope, all its members have their destructors called. Note that if the nsTArray<T> holds pointers to objects, the objects will not be deleted (and hence not have their destructors called). You can work around this by using nsTArray<nsAutoPtr<T> > instead.

    void ProcessVisibleItems()
    {
      // temporary stack-based nsTArray
      nsTArray<FooStruct> fooItems;
      GetCompleteList(fooItems);
       
      // now filter out non visible objects
      // doing this backwards
      PRUint32 i = fooItems.Length();
      while (i > 0) {
        --i;
        PRBool isVisible;
        fooItems[i]->GetIsVisible(&isVisible);
        if (!isVisible) {
          fooItems.RemoveElementAt(i);
        }
      }
    
      // now deal with the processed list
      ProcessList(fooItems);
    
      // fooItems will call the destructors of all the FooStruct objects
      // when it goes out of scope
    }
    

    Access to elements

    nsTArray<T> is a concrete C++ class, and so the [] operator is used to access its members.

    For example, this code calls the same method on each member:

    void NotifyObservers(const nsTArray<ObserverClass*>& observers) {
      for (PRUint32 i = observers.Length(); i > 0 ; ) {
        --i;
        observers[i]->Observe();
      }
    }
    

    Bounds-safe access to elements

    You can also access elements in an nsTArray<T> using the SafeElementAt() method. This method is bounds-safe; that is, if you attempt to access an element outside the range of the array, a specified "safe" value is returned. For example:

    var value = myArray.SafeElementAt(idx, defaultValue);
    
    if (value == defaultValue) {
      /* the index idx was out of bounds, or the value at that index was the default value */
    }
    

    Note: As of Gecko 8.0, if the element type is a pointer type, you can use the SafeElementAt() method without providing a default value. It returns a null pointer if the index is out of bounds.

    Note: As of Gecko 10.0, if the element type is a smart pointer type, you can use the SafeElementAt() method without providing a default value. It returns the underlying pointer type or the null pointer if the index is out of bounds.

    Passing as a parameter

    When passing nsTArray<T> among functions, the convention is to pass by reference. Also be sure to use const if you want to enforce that the array is read-only.

    Here is an example with a read-only and a writable array:

    // array is read-only because of const
    void PrintSize(const nsTArray<nsElement>& elements) {
     printf("There are %d elements.\n", elements.Length());
    }
    
    // no const, so we can modify the array
    void TweakArray(nsTArray<nsElement>& elements, 
                    const nsElement& newElement) {
      elements.RemoveElementAt(0);
      elements.AppendElement(newElement);
    }
    

    In-place enumeration

    There are no enumerator objects that work on an nsTArray<T>.

    C++ Arrays

    nsVoidArray, nsAutoVoidArray, nsSmallVoidArray

    nsVoidArray is a concrete C++ class that allows for storage of any arbitrary object. The base type for all objects is void *. When converting to/from a void *, ensure that no const-ness is lost.

    Note that nsVoidArray defines no semantics of ownership of its objects. Depending on its use, the array may either own the objects that it points to, or its member may be pointers to existing objects that are owned by another data structure. Because nsVoidArray itself does not define any ownership rules, it is up to the consumer to know when it is appropriate to free objects out of the array.

    This implies that when an nsVoidArray goes out of scope, seperate code must free any memory that is semantically owned by the array. This should always be documented in the declaration of the array instance.

    An nsAutoVoidArray is almost the same as an nsVoidArray except that it has a built-in buffer of eight void * pointers. This class is designed to be used as a temporary stack-based array for up to about eight items, thus avoiding a heap allocation.

    An nsSmallVoidArray is designed to provide the same interface as an nsVoidArray except that it is optimised to hold a single pointer, and is slightly slower if there are more

    nsCOMArray<T> was designed to eliminate some of the overhead of using nsVoidArray when using COM objects. If your code is using nsVoidArray to keep references to COM objects, consider converting it to nsCOMArray<T>.

    Usage

    nsVoidArray is often used as a member variable in a class. Remember to document ownership!

    struct FooElement {
     ...
    };
    
    class nsFoo : nsIFoo {
     ...
     virtual ~nsFoo();
     ...
     
     private:
     // mElements owns a list of FooElement structs,
     // which must be deleted when this object goes away
     nsVoidArray mElements;
    
     // mVisibleElements contains weak (non-owning) references
     // to elements in mElements, and does not need to be cleaned up
     nsVoidArray mVisibleElements;
    };
    
    nsFoo::~nsFoo() {
     // mVisibleElements is fine, but
     // don't forget to clean up mElements!
     PRUint32 i, count = mElements.Count();
     for (i=0; i<count; ++i)
      delete NS_STATIC_CAST(FooElement*, mElements[i]);
     }
       
    

    As you can see, nsVoidArray has some context-specific overhead to make sure memory is cleaned up appropriately.

    Access to elements

    The [] operator is used to access member variables. Don't forget to use static_cast<>().

    for (i=0; i<count; ++i) {
      FooElement* element = static_cast<FooElement*>(mElements[i]);
      // now manipulate element
    }
    

    Passing as a parameter

    Like other concrete C++ classes, passing by reference using the & syntax is preferred.

    In-place enumeration

    nsVoidArray provides two enumeration methods, EnumerateForwards and EnumerateBackwards. They are equivalent to the appropriate loop-based enumeration.

    Enumerators

    Enumerators are very simple, structure-free objects for visiting each member of a set of objects. The enumerators are used as a generic interface for arrays, hashtables, and other constructs which contain one or more objects. When designing public interfaces, enumerators are the preferred mechanism for accessing these structures because they hide the details of the implementation behind the interface.

    nsISimpleEnumerator

    nsISimpleEnumerator is a generic enumerator for enumerating a list of any XPCOM object. There are many implementations of nsISimpleEnumerator, including one that enumerates nsIArray objects, and another one for nsCOMArray. It is very common for other interfaces which support nsISimpleEnumerator to make their own implementations.

    nsIStringEnumerator

    String enumerators provide an easy way to pass a list of strings around with minimal copying. Both unicode strings and UTF8-encoded strings are supported. For more information about the different types of strings, see the String Guide.

    String enumerators can be created from nsTArray<nsString> or nsTArray<nsCString> objects. The implementation of the string enumerator interfaces for nsTArray<nsString> and nsTArray<nsCString> supports conversion between UTF8 and Unicode, and can be QueryInterface'd back and forth between nsIStringEnumerator and nsIUTF8StringEnumerator.

    To create an nsIStringEnumerator for an nsTArray<nsString>, you can use one of the variations of NS_NewStringEnumerator. There are also corresponding enumerators and helpers for UTF8 strings. In the examples below, NS_NewUTF8StringEnumerator can be used along with nsIUTF8StringEnumerator and nsTArray<nsCString>.

    This first example demonstrates the case where a class which owns an nsTArray<nsString>, and are returns an nsIStringEnumerator to a caller. You can use the variation of NS_NewStringEnumerator that ensures the owner of the array outlives the enumerator. This is necessary because nsStringArray is not reference counted. Without holding a reference to the owner, the enumerator could be left with a dangling pointer to a deleted nsTArray<nsString>.

    class nsFoo : nsIFoo {
    ...
    private:
      nsTArray<nsString> mElementNames;
    };
    
    nsFoo::GetElementNames(nsIStringEnumerator** aResult)
    {
      // pass in "this" to make sure the enumerator
      // holds a reference to "this"
      return NS_NewStringEnumerator(aResult, mElementNames, this);
    }
    

    One variant of NS_NewStringEnumerator does not require an owner, but should only be used when the lifetime of the enumerator is known to be shorter than that of the array. Often this is used when a method must take a nsIStringEnumerator rather than an nsStringArray, due to some sort of interface constraint.

    class nsFoo : nsIFoo {
     ...
     // when ProcessElements returns, the enumerator is at the
     // end of the list, and can be released.
     NS_IMETHODIMP ProcessNames(nsIStringEnumerator*);
     private:
       
     nsTArray<nsString> mElementNames;
    };
    
    ...
    nsCOMPtr<nsIStringEnumerator> enumerator;
    NS_NewStringEnumerator(getter_AddRefs(enumerator), mElementNames);
    
    // now call a method on "this" that has a known behavior
    ProcessNames(enumerator);
    // now enumerator is used up, and can be released
    ...
    

    The last version of nsIStringEnumerator takes ownership of an nsStringArray and is responsible for freeing the array when the enumerator is used up.

    void GetNames(nsIStringEnumerator** aResult)
    {
     nsTArray<nsString> *resultArray = new nsTArray<nsString>;
     resultArray->AppendString(str1);
     resultArray->AppendString(str2);
     
     // enumerator will free resultArray
     return NS_NewAdoptingStringEnumerator(aResult, resultArray);
    }
    

    As noted above, these implementations of nsIStringEnumerator can also be QueryInterface'd between nsIStringEnumerator and nsIUTF8StringEnumerator. The implementations will properly convert back and forth between UTF8 and Unicode. To ensure that you get the right implementation and the conversion is done in the right direction, make sure that you call the version of NS_NewStringEnumerator or NS_NewUTF8StringEnumerator that corresponds to the array type, not the enumerator type.

    For example, if a class has an internal nsTArray<nsCString> of UTF8 strings, but needs to implement an interface which returns an nsIStringEnumerator, it should use NS_NewUTF8StringEnumerator:

    class nsFoo : nsIFoo {
      ...
      NS_IMETHOD GetStrings(nsIStringEnumerator** aResult);
    
      private:
      nsCStringArray mElementNames;
    };
    
    NS_IMETHODIMP
    nsFoo::GetStrings(nsIStringEnumerator** aResult) {
      nsCOMPtr<nsIUTF8StringEnumerator> enumerator;
      nsresult rv = NS_NewUTF8StringEnumerator(getter_AddRefs(enumerator),
                                               mElementNames, this);
      NS_ENSURE_SUCCESS(rv, rv);
      return CallQueryInterface(enumerator, aResult);
    }
    

    Obsolete Arrays and Enumerators

    nsISupportsArray

    nsIEnumerator (includes nsIBidirectionalEnumerator)

    Document Tags and Contributors

    Last updated by: lygstate,