Exemplo n.º 1
0
Array HashCollection::toValuesArray() {
  PackedArrayInit ai(m_size);
  auto* eLimit = elmLimit();
  for (auto* e = firstElm(); e != eLimit; e = nextElm(e, eLimit)) {
    ai.append(tvAsCVarRef(&e->data));
  }
  return ai.toArray();
}
Exemplo n.º 2
0
Variant BaseMap::firstKey() {
  if (!m_size) return null_variant;
  auto* e = firstElm();
  assert(e != elmLimit());
  if (e->hasIntKey()) {
    return e->ikey;
  } else {
    assert(e->hasStrKey());
    return Variant{e->skey};
  }
}
Exemplo n.º 3
0
Array HashCollection::toKeysArray() {
  PackedArrayInit ai(m_size);
  auto* eLimit = elmLimit();
  for (auto* e = firstElm(); e != eLimit; e = nextElm(e, eLimit)) {
    if (e->hasIntKey()) {
      ai.append(int64_t{e->ikey});
    } else {
      assert(e->hasStrKey());
      ai.append(VarNR(e->skey).tv());
    }
  }
  return ai.toArray();
}
bool BaseSet::Equals(const ObjectData* obj1, const ObjectData* obj2) {
  auto st1 = static_cast<const BaseSet*>(obj1);
  auto st2 = static_cast<const BaseSet*>(obj2);
  if (st1->m_size != st2->m_size) return false;

  auto eLimit = st1->elmLimit();
  for (auto e = st1->firstElm(); e != eLimit; e = nextElm(e, eLimit)) {
    if (e->hasIntKey()) {
      if (!st2->contains(e->data.m_data.num)) return false;
    } else {
      assert(e->hasStrKey());
      if (!st2->contains(e->data.m_data.pstr)) return false;
    }
  }
  return true;
}
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;
}
Exemplo n.º 6
0
ALWAYS_INLINE
typename std::enable_if<
  std::is_base_of<BaseMap, TMap>::value, Object>::type
BaseMap::php_skipWhile(const Variant& fn) {
  CallCtx ctx;
  vm_decode_function(fn, nullptr, false, ctx);
  if (!ctx.func) {
    SystemLib::throwInvalidArgumentExceptionObject(
               "Parameter must be a valid callback");
  }
  auto map = req::make<TMap>();
  if (!m_size) return Object{std::move(map)};
  int32_t version;
  if (std::is_same<c_Map, TMap>::value) {
    version = m_version;
  }
  ssize_t pos;
  for (pos = iter_begin(); iter_valid(pos); pos = iter_next(pos)) {
    auto* e = iter_elm(pos);
    bool b = invokeAndCastToBool(ctx, 1, &e->data);
    if (std::is_same<c_Map, TMap>::value) {
      if (UNLIKELY(version != m_version)) {
        throw_collection_modified();
      }
    }
    if (!b) break;
  }
  if (iter_valid(pos)) {
    auto* eLimit = elmLimit();
    auto* e = iter_elm(pos);
    for (; e != eLimit; e = nextElm(e, eLimit)) {
      if (e->hasIntKey()) {
        map->set(e->ikey, &e->data);
      } else {
        assert(e->hasStrKey());
        map->set(e->skey, &e->data);
      }
    }
  }
  return Object{std::move(map)};
}
Exemplo n.º 7
0
NEVER_INLINE
void HashCollection::warnOnStrIntDup() const {
  req::hash_set<int64_t> seenVals;

  auto* eLimit = elmLimit();
  for (auto* e = firstElm(); e != eLimit; e = nextElm(e, eLimit)) {
    int64_t newVal = 0;

    if (e->hasIntKey()) {
      newVal = e->ikey;
    } else {
      assert(e->hasStrKey());
      // isStriclyInteger() puts the int value in newVal as a side effect.
      if (!e->skey->isStrictlyInteger(newVal)) continue;
    }

    if (seenVals.find(newVal) != seenVals.end()) {
      auto cls = getVMClass()->name()->toCppString();
      auto pos = cls.rfind('\\');
      if (pos != std::string::npos) {
        cls = cls.substr(pos + 1);
      }
      raise_warning(
        "%s::toArray() for a %s containing both int(%" PRId64 ") "
        "and string('%" PRId64 "')",
        cls.c_str(),
        toLower(cls).c_str(),
        newVal,
        newVal
      );

      return;
    }

    seenVals.insert(newVal);
  }
  // Do nothing if no 'duplicates' were found.
}
Exemplo n.º 8
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");
  }
}
Exemplo n.º 9
0
ALWAYS_INLINE
typename std::enable_if<
  std::is_base_of<BaseMap, TMap>::value, Object>::type
BaseMap::php_differenceByKey(const Variant& it) {
  if (!it.isObject()) {
    SystemLib::throwInvalidArgumentExceptionObject(
               "Parameter it must be an instance of Iterable");
  }
  ObjectData* obj = it.getObjectData();
  TMap* target = BaseMap::Clone<TMap>(this);
  auto ret = Object::attach(target);
  if (obj->isCollection()) {
    if (isMapCollection(obj->collectionType())) {
      auto map = static_cast<BaseMap*>(obj);
      auto* eLimit = map->elmLimit();
      for (auto* e = map->firstElm(); e != eLimit; e = nextElm(e, eLimit)) {
        if (e->hasIntKey()) {
          target->remove((int64_t)e->ikey);
        } else {
          assert(e->hasStrKey());
          target->remove(e->skey);
        }
      }
      return ret;
    }
  }
  for (ArrayIter iter(obj); iter; ++iter) {
    Variant k = iter.first();
    if (k.isInteger()) {
      target->remove(k.toInt64());
    } else {
      assert(k.isString());
      target->remove(k.getStringData());
    }
  }
  return ret;
}
Exemplo n.º 10
0
Variant BaseSet::firstValue() {
  if (!m_size) return init_null();
  auto e = firstElm();
  assert(e != elmLimit());
  return tvAsCVarRef(&e->data);
}
Exemplo n.º 11
0
Variant BaseMap::firstValue() {
  if (!m_size) return null_variant;
  auto* e = firstElm();
  assert(e != elmLimit());
  return tvAsCVarRef(&e->data);
}