ArrayData *ZendArray::remove(CVarRef k, bool copy) { TypedValueAccessor tva = k.getTypedAccessor(); if (isIntKey(tva)) { if (UNLIKELY(copy)) { ZendArray *a = copyImpl(); a->prepareBucketHeadsForWrite(); a->erase(a->findForErase(getIntKey(tva))); return a; } prepareBucketHeadsForWrite(); erase(findForErase(getIntKey(tva))); return NULL; } else { ASSERT(k.isString()); StringData *key = getStringKey(tva); int64 prehash = key->hash(); if (UNLIKELY(copy)) { ZendArray *a = copyImpl(); a->prepareBucketHeadsForWrite(); a->erase(a->findForErase(key->data(), key->size(), prehash)); return a; } prepareBucketHeadsForWrite(); erase(findForErase(key->data(), key->size(), prehash)); return NULL; } }
ArrayData *ZendArray::append(const ArrayData *elems, ArrayOp op, bool copy) { if (UNLIKELY(copy)) { ZendArray *a = copyImpl(); a->append(elems, op, false); return a; } if (op == Plus) { for (ArrayIter it(elems); !it.end(); it.next()) { Variant key = it.first(); CVarRef value = it.secondRef(); if (key.isNumeric()) { addValWithRef(key.toInt64(), value); } else { addValWithRef(key.getStringData(), value); } } } else { ASSERT(op == Merge); for (ArrayIter it(elems); !it.end(); it.next()) { Variant key = it.first(); CVarRef value = it.secondRef(); if (key.isNumeric()) { nextInsertWithRef(value); } else { Variant *p; StringData *sd = key.getStringData(); addLvalImpl(sd, sd->hash(), &p, true); p->setWithRef(value); } } } return NULL; }
ArrayData *ZendArray::setRef(CStrRef k, CVarRef v, bool copy) { if (UNLIKELY(copy)) { ZendArray *a = copyImpl(); a->updateRef(k.get(), v); return a; } updateRef(k.get(), v); return NULL; }
ArrayData *ZendArray::appendWithRef(CVarRef v, bool copy) { if (UNLIKELY(copy)) { ZendArray *a = copyImpl(); a->nextInsertWithRef(v); return a; } nextInsertWithRef(v); return NULL; }
ArrayData *ZendArray::set(int64 k, CVarRef v, bool copy) { if (UNLIKELY(copy)) { ZendArray *a = copyImpl(); a->update(k, v); return a; } update(k, v); return NULL; }
HOT_FUNC_HPHP ArrayData *ZendArray::append(CVarRef v, bool copy) { if (UNLIKELY(copy)) { ZendArray *a = copyImpl(); a->nextInsert(v); return a; } nextInsert(v); return NULL; }
HOT_FUNC_HPHP ArrayData *ZendArray::remove(int64 k, bool copy) { if (UNLIKELY(copy)) { ZendArray *a = copyImpl(); a->erase(a->findForErase(k)); return a; } erase(findForErase(k)); return NULL; }
ArrayData *ZendArray::remove(CStrRef k, bool copy) { int64 prehash = k->hash(); if (UNLIKELY(copy)) { ZendArray *a = copyImpl(); a->erase(a->findForErase(k.data(), k.size(), prehash)); return a; } erase(findForErase(k.data(), k.size(), prehash)); return NULL; }
ArrayData *ZendArray::addLval(CStrRef k, Variant *&ret, bool copy) { ASSERT(!exists(k)); if (UNLIKELY(copy)) { ZendArray *result = copyImpl(); result->addLvalImpl(k.get(), k->hash(), &ret, false); return result; } addLvalImpl(k.get(), k->hash(), &ret, false); return NULL; }
ArrayData *ZendArray::addLval(int64 k, Variant *&ret, bool copy) { ASSERT(!exists(k)); if (UNLIKELY(copy)) { ZendArray *result = copyImpl(); result->addLvalImpl(k, &ret, false); return result; } addLvalImpl(k, &ret, false); return NULL; }
ArrayData *ZendArray::remove(int64 k, bool copy) { if (UNLIKELY(copy)) { ZendArray *a = copyImpl(); a->prepareBucketHeadsForWrite(); a->erase(a->findForErase(k)); return a; } prepareBucketHeadsForWrite(); erase(findForErase(k)); return NULL; }
ArrayData *ZendArray::lval(int64 k, Variant *&ret, bool copy, bool checkExist /* = false */) { if (!copy) { addLvalImpl(k, &ret); return NULL; } if (!checkExist) { ZendArray *a = copyImpl(); a->addLvalImpl(k, &ret); return a; } Bucket *p = find(k); if (p && (p->data.isReferenced() || p->data.isObject())) { ret = &p->data; return NULL; } ZendArray *a = copyImpl(); a->addLvalImpl(k, &ret, p); return a; }
ArrayData *ZendArray::set(CVarRef k, CVarRef v, bool copy) { TypedValueAccessor tva = k.getTypedAccessor(); if (isIntKey(tva)) { if (UNLIKELY(copy)) { ZendArray *a = copyImpl(); a->update(getIntKey(tva), v); return a; } update(getIntKey(tva), v); return NULL; } else { ASSERT(k.isString()); StringData *sd = getStringKey(tva); if (UNLIKELY(copy)) { ZendArray *a = copyImpl(); a->update(sd, v); return a; } update(sd, v); return NULL; } }
ArrayData *ZendArray::lval(CStrRef k, Variant *&ret, bool copy, bool checkExist /* = false */) { StringData *key = k.get(); int64 prehash = key->hash(); if (!copy) { addLvalImpl(key, prehash, &ret); return NULL; } if (!checkExist) { ZendArray *a = copyImpl(); a->addLvalImpl(key, prehash, &ret); return a; } Bucket *p = find(key->data(), key->size(), prehash); if (p && (p->data.isReferenced() || p->data.isObject())) { ret = &p->data; return NULL; } ZendArray *a = copyImpl(); a->addLvalImpl(key, prehash, &ret, p); return a; }
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; }
ArrayData *ZendArray::pop(Variant &value) { if (getCount() > 1) { ZendArray *a = copyImpl(); a->pop(value); return a; } if (m_pListTail) { value = m_pListTail->data; erase(findForErase(m_pListTail), true); } else { value = null; } // To match PHP-like semantics, the pop operation resets the array's // internal iterator m_pos = (ssize_t)m_pListHead; return NULL; }
ArrayData *ZendArray::lvalPtr(int64 k, Variant *&ret, bool copy, bool create) { ZendArray *a = 0, *t = this; if (UNLIKELY(copy)) { a = t = copyImpl(); } if (create) { t->addLvalImpl(k, &ret); } else { Bucket *p = t->find(k); if (p) { ret = &p->data; } else { ret = NULL; } } return a; }
ArrayData *ZendArray::lvalNew(Variant *&ret, bool copy) { if (UNLIKELY(copy)) { ZendArray *a = copyImpl(); if (!a->nextInsert(null)) { ret = &(Variant::lvalBlackHole()); return a; } ASSERT(a->m_pListTail); ret = &a->m_pListTail->data; return a; } if (!nextInsert(null)) { ret = &(Variant::lvalBlackHole()); return NULL; } ASSERT(m_pListTail); ret = &m_pListTail->data; return NULL; }
HOT_FUNC_HPHP ArrayData *ZendArray::add(CStrRef k, CVarRef v, bool copy) { ASSERT(!exists(k)); if (UNLIKELY(copy)) { ZendArray *result = copyImpl(); result->add(k, v, false); return result; } int64 h = k->hash(); Bucket *p = NEW(Bucket)(v); p->setStrKey(k.get(), h); uint nIndex = (h & m_nTableMask); CONNECT_TO_BUCKET_LIST(p, m_arBuckets[nIndex]); SET_ARRAY_BUCKET_HEAD(m_arBuckets, nIndex, p); CONNECT_TO_GLOBAL_DLLIST(p); if (++m_size > tableSize()) { resize(); } return NULL; }
ArrayData *ZendArray::lvalPtr(CStrRef k, Variant *&ret, bool copy, bool create) { StringData *key = k.get(); int64 prehash = key->hash(); ZendArray *a = 0, *t = this; if (UNLIKELY(copy)) { a = t = copyImpl(); } if (create) { t->addLvalImpl(key, prehash, &ret); } else { Bucket *p = t->find(key->data(), key->size(), prehash); if (p) { ret = &p->data; } else { ret = NULL; } } return a; }
ArrayData *ZendArray::add(int64 k, CVarRef v, bool copy) { ASSERT(!exists(k)); if (UNLIKELY(copy)) { ZendArray *result = copyImpl(); result->add(k, v, false); return result; } Bucket *p = NEW(Bucket)(v); p->h = k; uint nIndex = (k & m_nTableMask); CONNECT_TO_BUCKET_LIST(p, m_arBuckets[nIndex]); SET_ARRAY_BUCKET_HEAD(m_arBuckets, nIndex, p); CONNECT_TO_GLOBAL_DLLIST(p); if (k >= m_nNextFreeElement && m_nNextFreeElement >= 0) { m_nNextFreeElement = k + 1; } if (++m_nNumOfElements > m_nTableSize) { resize(); } return NULL; }
ArrayData *ZendArray::add(CStrRef k, CVarRef v, bool copy) { ASSERT(!exists(k)); if (UNLIKELY(copy)) { ZendArray *result = copyImpl(); result->add(k, v, false); return result; } int64 h = k->hash(); Bucket *p = NEW(Bucket)(v); p->key = k.get(); p->key->incRefCount(); p->h = h; uint nIndex = (h & m_nTableMask); CONNECT_TO_BUCKET_LIST(p, m_arBuckets[nIndex]); SET_ARRAY_BUCKET_HEAD(m_arBuckets, nIndex, p); CONNECT_TO_GLOBAL_DLLIST(p); if (++m_nNumOfElements > m_nTableSize) { resize(); } return NULL; }
ArrayData *ZendArray::dequeue(Variant &value) { if (getCount() > 1) { ZendArray *a = copyImpl(); a->dequeue(value); return a; } // To match PHP-like semantics, we invalidate all strong iterators // when an element is removed from the beginning of the array if (!m_strongIterators.empty()) { freeStrongIterators(); } if (m_pListHead) { value = m_pListHead->data; erase(findForErase(m_pListHead)); renumber(); } else { value = null; } // To match PHP-like semantics, the dequeue operation resets the array's // internal iterator m_pos = (ssize_t)m_pListHead; return NULL; }
ArrayData* ZendArray::escalateForSort() { if (getCount() > 1) { return copyImpl(); } return this; }
ArrayData* HphpArray::escalateForSort() { // task #1910931 only do this for refCount() > 1 return copyImpl(); }
ArrayData *ZendArray::copy() const { return copyImpl(); }