예제 #1
0
void HashCollection::remove(StringData* key) {
  mutateAndBump();
  auto p = findForRemove(key, key->hash());
  if (validPos(p)) {
    erase(p);
  }
}
예제 #2
0
void HashCollection::remove(int64_t key) {
  mutateAndBump();
  auto p = findForRemove(key, hash_int64(key));
  if (validPos(p)) {
    erase(p);
  }
}
예제 #3
0
Object BaseMap::php_retain(const Variant& callback) {
  CallCtx ctx;
  vm_decode_function(callback, nullptr, false, ctx);
  if (!ctx.func) {
    SystemLib::throwInvalidArgumentExceptionObject(
               "Parameter must be a valid callback");
  }
  auto size = m_size;
  if (!size) { return Object{this}; }
  constexpr int64_t argc = useKey ? 2 : 1;
  TypedValue argv[argc];
  for (ssize_t pos = iter_begin(); iter_valid(pos); pos = iter_next(pos)) {
    auto* e = iter_elm(pos);
    if (useKey) {
      if (e->hasIntKey()) {
        argv[0].m_type = KindOfInt64;
        argv[0].m_data.num = e->ikey;
      } else {
        argv[0].m_type = KindOfString;
        argv[0].m_data.pstr = e->skey;
      }
    }
    argv[argc-1] = e->data;
    int32_t version = m_version;
    bool b = invokeAndCastToBool(ctx, argc, argv);
    if (UNLIKELY(version != m_version)) {
      throw_collection_modified();
    }
    if (b) {
      continue;
    }
    mutateAndBump();
    version = m_version;
    e = iter_elm(pos);
    ssize_t pp = (e->hasIntKey()
                   ? findForRemove(e->ikey)
                   : findForRemove(e->skey, e->skey->hash()));
    eraseNoCompact(pp);
    if (UNLIKELY(version != m_version)) {
      throw_collection_modified();
    }
  }

  assert(m_size <= size);
  compactOrShrinkIfDensityTooLow();
  return Object{this};
}
Variant BaseSet::popFront() {
  if (UNLIKELY(m_size == 0)) {
    SystemLib::throwInvalidOperationExceptionObject("Cannot pop empty Set");
  }
  mutateAndBump();
  auto e = data();
  for (;; ++e) {
    assert(e != elmLimit());
    if (!isTombstone(e)) break;
  }
  Variant ret = tvAsCVarRef(&e->data);
  auto h = e->hash();
  auto ei = e->hasIntKey() ? findForRemove(e->ikey, h) :
            findForRemove(e->skey, h);
  erase(ei);
  return ret;
}
예제 #5
0
ArrayData* StructArray::RemoveStr(
  ArrayData* ad,
  const StringData* k,
  bool copy
) {
  auto structArray = asStructArray(ad);
  if (structArray->shape()->hasOffsetFor(k)) {
    auto const mixed = copy ? ToMixedCopy(structArray) : ToMixed(structArray);
    auto pos = mixed->findForRemove(k, k->hash());
    if (validPos(pos)) mixed->erase(pos);
    return mixed;
  }
  return copy ? Copy(structArray) : structArray;
}
예제 #6
0
Variant BaseMap::popFront() {
  if (m_size) {
    mutateAndBump();
    auto* e = data();
    for (;; ++e) {
      assert(e != elmLimit());
      if (!isTombstone(e)) break;
    }
    Variant ret = tvAsCVarRef(&e->data);
    ssize_t ei;
    if (e->hasIntKey()) {
      ei = findForRemove(e->ikey);
    } else {
      assert(e->hasStrKey());
      ei = findForRemove(e->skey, e->skey->hash());
    }
    erase(ei);
    return ret;
  } else {
    SystemLib::throwInvalidOperationExceptionObject(
      "Cannot pop empty Map");
  }
}
예제 #7
0
ArrayData* PackedArray::RemoveInt(ArrayData* adIn, int64_t k, bool copy) {
  assert(checkInvariants(adIn));
  if (size_t(k) < adIn->m_size) {
    // Escalate to mixed for correctness; unset preserves m_nextKI.
    //
    // TODO(#2606310): if we're removing the /last/ element, we
    // probably could stay packed, but this needs to be verified.
    auto const mixed = copy ? ToMixedCopy(adIn) : ToMixed(adIn);
    auto pos = mixed->findForRemove(k, false);
    if (validPos(pos)) mixed->erase(pos);
    return mixed;
  }
  // Key doesn't exist---we're still packed.
  return copy ? Copy(adIn) : adIn;
}