nsresult nsAttrAndChildArray::InsertChildAt(nsIContent* aChild, PRUint32 aPos) { NS_ASSERTION(aChild, "nullchild"); NS_ASSERTION(aPos <= ChildCount(), "out-of-bounds"); PRUint32 offset = AttrSlotsSize(); PRUint32 childCount = ChildCount(); NS_ENSURE_TRUE(childCount < ATTRCHILD_ARRAY_MAX_CHILD_COUNT, NS_ERROR_FAILURE); // First try to fit new child in existing childlist if (mImpl && offset + childCount < mImpl->mBufferSize) { void** pos = mImpl->mBuffer + offset + aPos; if (childCount != aPos) { memmove(pos + 1, pos, (childCount - aPos) * sizeof(nsIContent*)); } SetChildAtPos(pos, aChild, aPos, childCount); SetChildCount(childCount + 1); return NS_OK; } // Try to fit new child in existing buffer by compressing attrslots if (offset && !mImpl->mBuffer[offset - ATTRSIZE]) { // Compress away all empty slots while we're at it. This might not be the // optimal thing to do. PRUint32 attrCount = NonMappedAttrCount(); void** newStart = mImpl->mBuffer + attrCount * ATTRSIZE; void** oldStart = mImpl->mBuffer + offset; memmove(newStart, oldStart, aPos * sizeof(nsIContent*)); memmove(&newStart[aPos + 1], &oldStart[aPos], (childCount - aPos) * sizeof(nsIContent*)); SetChildAtPos(newStart + aPos, aChild, aPos, childCount); SetAttrSlotAndChildCount(attrCount, childCount + 1); return NS_OK; } // We can't fit in current buffer, Realloc time! if (!GrowBy(1)) { return NS_ERROR_OUT_OF_MEMORY; } void** pos = mImpl->mBuffer + offset + aPos; if (childCount != aPos) { memmove(pos + 1, pos, (childCount - aPos) * sizeof(nsIContent*)); } SetChildAtPos(pos, aChild, aPos, childCount); SetChildCount(childCount + 1); return NS_OK; }
void nsAttrAndChildArray::RemoveChildAt(PRUint32 aPos) { NS_ASSERTION(aPos < ChildCount(), "out-of-bounds"); PRUint32 childCount = ChildCount(); void** pos = mImpl->mBuffer + AttrSlotsSize() + aPos; nsIContent* child = static_cast<nsIContent*>(*pos); if (child->mPreviousSibling) { child->mPreviousSibling->mNextSibling = child->mNextSibling; } if (child->mNextSibling) { child->mNextSibling->mPreviousSibling = child->mPreviousSibling; } child->mPreviousSibling = child->mNextSibling = nsnull; NS_RELEASE(child); memmove(pos, pos + 1, (childCount - aPos - 1) * sizeof(nsIContent*)); SetChildCount(childCount - 1); }
already_AddRefed<nsIContent> nsAttrAndChildArray::TakeChildAt(uint32_t aPos) { NS_ASSERTION(aPos < ChildCount(), "out-of-bounds"); uint32_t childCount = ChildCount(); void** pos = mImpl->mBuffer + AttrSlotsSize() + aPos; nsIContent* child = static_cast<nsIContent*>(*pos); if (child->mPreviousSibling) { child->mPreviousSibling->mNextSibling = child->mNextSibling; } if (child->mNextSibling) { child->mNextSibling->mPreviousSibling = child->mPreviousSibling; } child->mPreviousSibling = child->mNextSibling = nullptr; memmove(pos, pos + 1, (childCount - aPos - 1) * sizeof(nsIContent*)); SetChildCount(childCount - 1); return dont_AddRef(child); }
PRInt32 nsAttrAndChildArray::IndexOfChild(nsINode* aPossibleChild) const { if (!mImpl) { return -1; } void** children = mImpl->mBuffer + AttrSlotsSize(); // Use signed here since we compare count to cursor which has to be signed PRInt32 i, count = ChildCount(); if (count >= CACHE_CHILD_LIMIT) { PRInt32 cursor = GetIndexFromCache(this); // Need to compare to count here since we may have removed children since // the index was added to the cache. // We're also relying on that GetIndexFromCache returns -1 if no cached // index was found. if (cursor >= count) { cursor = -1; } // Seek outward from the last found index. |inc| will change sign every // run through the loop. |sign| just exists to make sure the absolute // value of |inc| increases each time through. PRInt32 inc = 1, sign = 1; while (cursor >= 0 && cursor < count) { if (children[cursor] == aPossibleChild) { AddIndexToCache(this, cursor); return cursor; } cursor += inc; inc = -inc - sign; sign = -sign; } // We ran into one 'edge'. Add inc to cursor once more to get back to // the 'side' where we still need to search, then step in the |sign| // direction. cursor += inc; if (sign > 0) { for (; cursor < count; ++cursor) { if (children[cursor] == aPossibleChild) { AddIndexToCache(this, cursor); return static_cast<PRInt32>(cursor); } } } else { for (; cursor >= 0; --cursor) { if (children[cursor] == aPossibleChild) { AddIndexToCache(this, cursor); return static_cast<PRInt32>(cursor); } } } // The child wasn't even in the remaining children return -1; } for (i = 0; i < count; ++i) { if (children[i] == aPossibleChild) { return static_cast<PRInt32>(i); } } return -1; }