const nsAttrValue* nsAttrAndChildArray::GetAttr(nsIAtom* aLocalName, PRInt32 aNamespaceID) const { PRUint32 i, slotCount = AttrSlotCount(); if (aNamespaceID == kNameSpaceID_None) { // This should be the common case so lets make an optimized loop for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) { if (ATTRS(mImpl)[i].mName.Equals(aLocalName)) { return &ATTRS(mImpl)[i].mValue; } } if (mImpl && mImpl->mMappedAttrs) { return mImpl->mMappedAttrs->GetAttr(aLocalName); } } else { for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) { if (ATTRS(mImpl)[i].mName.Equals(aLocalName, aNamespaceID)) { return &ATTRS(mImpl)[i].mValue; } } } return nsnull; }
PRInt32 nsAttrAndChildArray::IndexOfAttr(nsIAtom* aLocalName, PRInt32 aNamespaceID) const { PRInt32 idx; if (mImpl && mImpl->mMappedAttrs) { idx = mImpl->mMappedAttrs->IndexOfAttr(aLocalName, aNamespaceID); if (idx >= 0) { return idx; } } PRUint32 i; PRUint32 mapped = MappedAttrCount(); PRUint32 slotCount = AttrSlotCount(); if (aNamespaceID == kNameSpaceID_None) { // This should be the common case so lets make an optimized loop for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) { if (ATTRS(mImpl)[i].mName.Equals(aLocalName)) { return i + mapped; } } } else { for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) { if (ATTRS(mImpl)[i].mName.Equals(aLocalName, aNamespaceID)) { return i + mapped; } } } return -1; }
const nsAttrValue* nsAttrAndChildArray::GetAttr(const nsAString& aName, nsCaseTreatment aCaseSensitive) const { // Check whether someone is being silly and passing non-lowercase // attr names. if (aCaseSensitive == eIgnoreCase && nsContentUtils::StringContainsASCIIUpper(aName)) { // Try again with a lowercased name, but make sure we can't reenter this // block by passing eCaseSensitive for aCaseSensitive. nsAutoString lowercase; nsContentUtils::ASCIIToLower(aName, lowercase); return GetAttr(lowercase, eCaseMatters); } uint32_t i, slotCount = AttrSlotCount(); for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) { if (ATTRS(mImpl)[i].mName.QualifiedNameEquals(aName)) { return &ATTRS(mImpl)[i].mValue; } } if (mImpl && mImpl->mMappedAttrs) { const nsAttrValue* val = mImpl->mMappedAttrs->GetAttr(aName); if (val) { return val; } } return nullptr; }
int main () { char * xml; xml = XMLNode ("a", ATTRS({"href", "#"}, {"class", "plop"}), "%s", XMLNode ("span", ATTRS({"class", "plip"}), "%s%d", "coucou", 42)); printf("%s\n", xml); free(xml); return (0); }
const nsAttrName* nsAttrAndChildArray::GetExistingAttrNameFromQName(const nsAString& aName) const { PRUint32 i, slotCount = AttrSlotCount(); for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) { if (ATTRS(mImpl)[i].mName.QualifiedNameEquals(aName)) { return &ATTRS(mImpl)[i].mName; } } if (mImpl && mImpl->mMappedAttrs) { return mImpl->mMappedAttrs->GetExistingAttrNameFromQName(aName); } return nsnull; }
const nsAttrValue* nsAttrAndChildArray::GetAttr(const nsAString& aLocalName) const { uint32_t i, slotCount = AttrSlotCount(); for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) { if (ATTRS(mImpl)[i].mName.Equals(aLocalName)) { return &ATTRS(mImpl)[i].mValue; } } if (mImpl && mImpl->mMappedAttrs) { return mImpl->mMappedAttrs->GetAttr(aLocalName); } return nullptr; }
nsresult nsAttrAndChildArray::SetAndTakeAttr(nsINodeInfo* aName, nsAttrValue& aValue) { PRInt32 namespaceID = aName->NamespaceID(); nsIAtom* localName = aName->NameAtom(); if (namespaceID == kNameSpaceID_None) { return SetAndTakeAttr(localName, aValue); } PRUint32 i, slotCount = AttrSlotCount(); for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) { if (ATTRS(mImpl)[i].mName.Equals(localName, namespaceID)) { ATTRS(mImpl)[i].mName.SetTo(aName); ATTRS(mImpl)[i].mValue.Reset(); ATTRS(mImpl)[i].mValue.SwapValueWith(aValue); return NS_OK; } } NS_ENSURE_TRUE(i < ATTRCHILD_ARRAY_MAX_ATTR_COUNT, NS_ERROR_FAILURE); if (i == slotCount && !AddAttrSlot()) { return NS_ERROR_OUT_OF_MEMORY; } new (&ATTRS(mImpl)[i].mName) nsAttrName(aName); new (&ATTRS(mImpl)[i].mValue) nsAttrValue(); ATTRS(mImpl)[i].mValue.SwapValueWith(aValue); return NS_OK; }
nsresult nsAttrAndChildArray::SetAndTakeAttr(nsIAtom* aLocalName, nsAttrValue& aValue) { PRUint32 i, slotCount = AttrSlotCount(); for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) { if (ATTRS(mImpl)[i].mName.Equals(aLocalName)) { ATTRS(mImpl)[i].mValue.Reset(); ATTRS(mImpl)[i].mValue.SwapValueWith(aValue); return NS_OK; } } NS_ENSURE_TRUE(i < ATTRCHILD_ARRAY_MAX_ATTR_COUNT, NS_ERROR_FAILURE); if (i == slotCount && !AddAttrSlot()) { return NS_ERROR_OUT_OF_MEMORY; } new (&ATTRS(mImpl)[i].mName) nsAttrName(aLocalName); new (&ATTRS(mImpl)[i].mValue) nsAttrValue(); ATTRS(mImpl)[i].mValue.SwapValueWith(aValue); return NS_OK; }
const nsAttrName* nsAttrAndChildArray::AttrNameAt(PRUint32 aPos) const { NS_ASSERTION(aPos < AttrCount(), "out-of-bounds access in nsAttrAndChildArray"); PRUint32 mapped = MappedAttrCount(); if (aPos < mapped) { return mImpl->mMappedAttrs->NameAt(aPos); } return &ATTRS(mImpl)[aPos - mapped].mName; }
const nsAttrValue* nsAttrAndChildArray::AttrAt(uint32_t aPos) const { NS_ASSERTION(aPos < AttrCount(), "out-of-bounds access in nsAttrAndChildArray"); uint32_t mapped = MappedAttrCount(); if (aPos < mapped) { return mImpl->mMappedAttrs->AttrAt(aPos); } return &ATTRS(mImpl)[aPos - mapped].mValue; }
nsresult nsAttrAndChildArray::RemoveAttrAt(PRUint32 aPos, nsAttrValue& aValue) { NS_ASSERTION(aPos < AttrCount(), "out-of-bounds"); PRUint32 mapped = MappedAttrCount(); if (aPos < mapped) { if (mapped == 1) { // We're removing the last mapped attribute. Can't swap in this // case; have to copy. aValue.SetTo(*mImpl->mMappedAttrs->AttrAt(0)); NS_RELEASE(mImpl->mMappedAttrs); return NS_OK; } nsRefPtr<nsMappedAttributes> mapped; nsresult rv = GetModifiableMapped(nsnull, nsnull, false, getter_AddRefs(mapped)); NS_ENSURE_SUCCESS(rv, rv); mapped->RemoveAttrAt(aPos, aValue); return MakeMappedUnique(mapped); } aPos -= mapped; ATTRS(mImpl)[aPos].mValue.SwapValueWith(aValue); ATTRS(mImpl)[aPos].~InternalAttr(); PRUint32 slotCount = AttrSlotCount(); memmove(&ATTRS(mImpl)[aPos], &ATTRS(mImpl)[aPos + 1], (slotCount - aPos - 1) * sizeof(InternalAttr)); memset(&ATTRS(mImpl)[slotCount - 1], nsnull, sizeof(InternalAttr)); return NS_OK; }
bool nsAttrAndChildArray::AddAttrSlot() { PRUint32 slotCount = AttrSlotCount(); PRUint32 childCount = ChildCount(); // Grow buffer if needed if (!(mImpl && mImpl->mBufferSize >= (slotCount + 1) * ATTRSIZE + childCount) && !GrowBy(ATTRSIZE)) { return false; } void** offset = mImpl->mBuffer + slotCount * ATTRSIZE; if (childCount > 0) { memmove(&ATTRS(mImpl)[slotCount + 1], &ATTRS(mImpl)[slotCount], childCount * sizeof(nsIContent*)); } SetAttrSlotCount(slotCount + 1); offset[0] = nsnull; offset[1] = nsnull; return true; }
size_t nsAttrAndChildArray::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const { size_t n = 0; if (mImpl) { // Don't add the size taken by *mMappedAttrs because it's shared. n += aMallocSizeOf(mImpl); PRUint32 slotCount = AttrSlotCount(); for (PRUint32 i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) { nsAttrValue* value = &ATTRS(mImpl)[i].mValue; n += value->SizeOfExcludingThis(aMallocSizeOf); } } return n; }
void nsAttrAndChildArray::Clear() { if (!mImpl) { return; } if (mImpl->mMappedAttrs) { NS_RELEASE(mImpl->mMappedAttrs); } PRUint32 i, slotCount = AttrSlotCount(); for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) { ATTRS(mImpl)[i].~InternalAttr(); } nsAutoScriptBlocker scriptBlocker; PRUint32 end = slotCount * ATTRSIZE + ChildCount(); for (i = slotCount * ATTRSIZE; i < end; ++i) { nsIContent* child = static_cast<nsIContent*>(mImpl->mBuffer[i]); // making this false so tree teardown doesn't end up being // O(N*D) (number of nodes times average depth of tree). child->UnbindFromTree(false); // XXX is it better to let the owner do this? // Make sure to unlink our kids from each other, since someone // else could stil be holding references to some of them. // XXXbz We probably can't push this assignment down into the |aNullParent| // case of UnbindFromTree because we still need the assignment in // RemoveChildAt. In particular, ContentRemoved fires between // RemoveChildAt and UnbindFromTree, and in ContentRemoved the sibling // chain needs to be correct. Though maybe we could set the prev and next // to point to each other but keep the kid being removed pointing to them // through ContentRemoved so consumers can find where it used to be in the // list? child->mPreviousSibling = child->mNextSibling = nsnull; NS_RELEASE(child); } SetAttrSlotAndChildCount(0, 0); }
PRInt64 nsAttrAndChildArray::SizeOf() const { PRInt64 size = sizeof(*this); if (mImpl) { // Don't add the size taken by *mMappedAttrs because it's shared. // mBuffer cointains InternalAttr and nsIContent* (even if it's void**) // so, we just have to compute the size of *mBuffer given that this object // doesn't own the children list. size += mImpl->mBufferSize * sizeof(*(mImpl->mBuffer)) + NS_IMPL_EXTRA_SIZE; PRUint32 slotCount = AttrSlotCount(); for (PRUint32 i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) { nsAttrValue* value = &ATTRS(mImpl)[i].mValue; size += value->SizeOf() - sizeof(*value); } } return size; }