author Mike Hommey <>
Thu, 26 Mar 2015 12:07:17 +0900
changeset 258314 fc1e894eec2fbd34b745cd94f505080427d24705
parent 248684 86924ac6a94a9147bcae518239d7a33b5981062b
child 272011 bd079aadd3feeee3f9b9f73c5e0bc4bd6a870722
permissions -rw-r--r--
Bug 1147207 - Add a ComposedFinder class that acts like a FileFinder proxy over multiple FileFinders. r=gps, a=sledru

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at */

 * Storage of the children and attributes of a DOM node; storage for
 * the two is unified to minimize footprint.

#ifndef nsAttrAndChildArray_h___
#define nsAttrAndChildArray_h___

#include "mozilla/Attributes.h"
#include "mozilla/MemoryReporting.h"

#include "nscore.h"
#include "nsAttrName.h"
#include "nsAttrValue.h"
#include "nsCaseTreatment.h"

class nsINode;
class nsIContent;
class nsMappedAttributes;
class nsHTMLStyleSheet;
class nsRuleWalker;
class nsMappedAttributeElement;






#define ATTRSIZE (sizeof(InternalAttr) / sizeof(void*))

class nsAttrAndChildArray

  uint32_t ChildCount() const
    return mImpl ? (mImpl->mAttrAndChildCount >> ATTRCHILD_ARRAY_ATTR_SLOTS_BITS) : 0;
  nsIContent* ChildAt(uint32_t aPos) const
    NS_ASSERTION(aPos < ChildCount(), "out-of-bounds access in nsAttrAndChildArray");
    return reinterpret_cast<nsIContent*>(mImpl->mBuffer[AttrSlotsSize() + aPos]);
  nsIContent* GetSafeChildAt(uint32_t aPos) const;
  nsIContent * const * GetChildArray(uint32_t* aChildCount) const;
  nsresult AppendChild(nsIContent* aChild)
    return InsertChildAt(aChild, ChildCount());
  nsresult InsertChildAt(nsIContent* aChild, uint32_t aPos);
  void RemoveChildAt(uint32_t aPos);
  // Like RemoveChildAt but hands the reference to the child being
  // removed back to the caller instead of just releasing it.
  already_AddRefed<nsIContent> TakeChildAt(uint32_t aPos);
  int32_t IndexOfChild(const nsINode* aPossibleChild) const;

  bool HasAttrs() const
    return MappedAttrCount() || (AttrSlotCount() && AttrSlotIsTaken(0));

  uint32_t AttrCount() const;
  const nsAttrValue* GetAttr(nsIAtom* aLocalName,
                             int32_t aNamespaceID = kNameSpaceID_None) const;
  // As above but using a string attr name and always using
  // kNameSpaceID_None.  This is always case-sensitive.
  const nsAttrValue* GetAttr(const nsAString& aName) const;
  // Get an nsAttrValue by qualified name.  Can optionally do
  // ASCII-case-insensitive name matching.
  const nsAttrValue* GetAttr(const nsAString& aName,
                             nsCaseTreatment aCaseSensitive) const;
  const nsAttrValue* AttrAt(uint32_t aPos) const;
  nsresult SetAndTakeAttr(nsIAtom* aLocalName, nsAttrValue& aValue);
  nsresult SetAndTakeAttr(mozilla::dom::NodeInfo* aName, nsAttrValue& aValue);

  // Remove the attr at position aPos.  The value of the attr is placed in
  // aValue; any value that was already in aValue is destroyed.
  nsresult RemoveAttrAt(uint32_t aPos, nsAttrValue& aValue);

  // Returns attribute name at given position, *not* out-of-bounds safe
  const nsAttrName* AttrNameAt(uint32_t aPos) const;

  // Returns attribute name at given position or null if aPos is out-of-bounds
  const nsAttrName* GetSafeAttrNameAt(uint32_t aPos) const;

  const nsAttrName* GetExistingAttrNameFromQName(const nsAString& aName) const;
  int32_t IndexOfAttr(nsIAtom* aLocalName, int32_t aNamespaceID = kNameSpaceID_None) const;

  nsresult SetAndTakeMappedAttr(nsIAtom* aLocalName, nsAttrValue& aValue,
                                nsMappedAttributeElement* aContent,
                                nsHTMLStyleSheet* aSheet);
  nsresult SetMappedAttrStyleSheet(nsHTMLStyleSheet* aSheet) {
    if (!mImpl || !mImpl->mMappedAttrs) {
      return NS_OK;
    return DoSetMappedAttrStyleSheet(aSheet);
  void WalkMappedAttributeStyleRules(nsRuleWalker* aRuleWalker);

  void Compact();

  bool CanFitMoreAttrs() const
    return AttrSlotCount() < ATTRCHILD_ARRAY_MAX_ATTR_COUNT ||
           !AttrSlotIsTaken(ATTRCHILD_ARRAY_MAX_ATTR_COUNT - 1);

  size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
  bool HasMappedAttrs() const
    return MappedAttrCount();

  nsAttrAndChildArray(const nsAttrAndChildArray& aOther) = delete;
  nsAttrAndChildArray& operator=(const nsAttrAndChildArray& aOther) = delete;

  void Clear();

  uint32_t NonMappedAttrCount() const;
  uint32_t MappedAttrCount() const;

  // Returns a non-null zero-refcount object.
  GetModifiableMapped(nsMappedAttributeElement* aContent,
                      nsHTMLStyleSheet* aSheet,
                      bool aWillAddAttr);
  nsresult MakeMappedUnique(nsMappedAttributes* aAttributes);

  uint32_t AttrSlotsSize() const
    return AttrSlotCount() * ATTRSIZE;

  uint32_t AttrSlotCount() const
    return mImpl ? mImpl->mAttrAndChildCount & ATTRCHILD_ARRAY_ATTR_SLOTS_COUNT_MASK : 0;

  bool AttrSlotIsTaken(uint32_t aSlot) const
    NS_PRECONDITION(aSlot < AttrSlotCount(), "out-of-bounds");
    return mImpl->mBuffer[aSlot * ATTRSIZE];

  void SetChildCount(uint32_t aCount)
    mImpl->mAttrAndChildCount = 
        (mImpl->mAttrAndChildCount & ATTRCHILD_ARRAY_ATTR_SLOTS_COUNT_MASK) |

  void SetAttrSlotCount(uint32_t aCount)
    mImpl->mAttrAndChildCount =
        (mImpl->mAttrAndChildCount & ~ATTRCHILD_ARRAY_ATTR_SLOTS_COUNT_MASK) |

  void SetAttrSlotAndChildCount(uint32_t aSlotCount, uint32_t aChildCount)
    mImpl->mAttrAndChildCount = aSlotCount |

  bool GrowBy(uint32_t aGrowSize);
  bool AddAttrSlot();

   * Set *aPos to aChild and update sibling pointers as needed.  aIndex is the
   * index at which aChild is actually being inserted.  aChildCount is the
   * number of kids we had before the insertion.
  inline void SetChildAtPos(void** aPos, nsIContent* aChild, uint32_t aIndex,
                            uint32_t aChildCount);

   * Guts of SetMappedAttrStyleSheet for the rare case when we have mapped attrs
  nsresult DoSetMappedAttrStyleSheet(nsHTMLStyleSheet* aSheet);

  struct InternalAttr
    nsAttrName mName;
    nsAttrValue mValue;

  struct Impl {
    uint32_t mAttrAndChildCount;
    uint32_t mBufferSize;
    nsMappedAttributes* mMappedAttrs;
    void* mBuffer[1];

  Impl* mImpl;