ArrayData *VectorArray::prepend(CVarRef v, bool copy) { if (UNLIKELY(m_size == m_capacity)) { ZendArray *a = escalateToNonEmptyZendArray(); ArrayData *aa UNUSED = a->prepend(v, false); assert(!aa); return a; } if (UNLIKELY(copy)) { ArrayData *a = UNLIKELY(m_size >= FixedSize && Util::isPowerOfTwo(m_size)) ? // in this case, we would escalate in the capacity check anyway static_cast<ArrayData*>(escalateToNonEmptyZendArray()) : static_cast<ArrayData*>(NEW(VectorArray)(this)); ArrayData *aa UNUSED = a->prepend(v, false); assert(!aa); return a; } checkSize(); for (uint i = m_size; i > 0; i--) { // copying TV's by value, intentionally not refcounting. m_elems[i] = m_elems[i-1]; } tvAsUninitializedVariant(&m_elems[0]).constructValHelper(v); m_size++; // To match PHP-like semantics, the prepend operation resets the array's // internal iterator m_pos = (ssize_t)0; return nullptr; }
ArrayData *ZendArray::prepend(CVarRef v, bool copy) { if (UNLIKELY(copy)) { ZendArray *a = copyImpl(); a->prepend(v, false); return a; } // To match PHP-like semantics, we invalidate all strong iterators // when an element is added to the beginning of the array if (!m_strongIterators.empty()) { freeStrongIterators(); } nextInsert(v); if (m_nNumOfElements == 1) { return NULL; // only element in array, no need to move it. } // Move the newly inserted element from the tail to the front. Bucket *p = m_pListHead; Bucket *new_elem = m_pListTail; // Remove from end of list m_pListTail = new_elem->pListLast; if (m_pListTail) { m_pListTail->pListNext = NULL; } // Insert before new position (p) new_elem->pListNext = p; new_elem->pListLast = p->pListLast; p->pListLast = new_elem; if (new_elem->pListLast) { new_elem->pListLast->pListNext = new_elem; } else { // no 'last' means we inserted at the front, so fix that pointer ASSERT(m_pListHead == p); m_pListHead = new_elem; } // Rewrite numeric keys to start from 0 and rehash renumber(); // To match PHP-like semantics, the prepend operation resets the array's // internal iterator m_pos = (ssize_t)m_pListHead; return NULL; }