typename std::enable_if<
  std::is_base_of<BaseSet, TSet>::value, TSet*>::type
BaseSet::Clone(ObjectData* obj) {
  auto thiz = static_cast<TSet*>(obj);
  auto target = static_cast<TSet*>(TSet::instanceCtor(TSet::classof()));
  if (!thiz->m_size) {
    return target;
  }
  thiz->arrayData()->incRefCount();
  target->m_size = thiz->m_size;
  target->m_arr = thiz->m_arr;
  target->setIntLikeStrKeys(thiz->intLikeStrKeys());
  return target;
}
Exemplo n.º 2
0
typename std::enable_if<
  std::is_base_of<BaseMap, TMap>::value, TMap*>::type
BaseMap::Clone(ObjectData* obj) {
  auto thiz = static_cast<TMap*>(obj);
  auto target = static_cast<TMap*>(obj->cloneImpl());
  if (!thiz->m_size) {
    return target;
  }
  thiz->arrayData()->incRefCount();
  target->m_size = thiz->m_size;
  target->m_arr = thiz->m_arr;
  target->setIntLikeStrKeys(thiz->intLikeStrKeys());
  return target;
}
// This function will create a immutable copy of this Set (if it doesn't
// already exist) and then return it
Object c_Set::getImmutableCopy() {
  if (m_immCopy.isNull()) {
    auto set = req::make<c_ImmSet>();
    set->m_size = m_size;
    set->m_version = m_version;
    set->m_arr = m_arr;
    set->setIntLikeStrKeys(intLikeStrKeys());
    m_immCopy = std::move(set);
    arrayData()->incRefCount();
  }
  assert(!m_immCopy.isNull());
  assert(data() == static_cast<c_ImmSet*>(m_immCopy.get())->data());
  assert(arrayData()->hasMultipleRefs());
  return m_immCopy;
}
Exemplo n.º 4
0
ALWAYS_INLINE
typename std::enable_if<
  std::is_base_of<BaseMap, TMap>::value, Object>::type
BaseMap::php_map(const Variant& callback) const {
  VMRegGuard _;
  CallCtx ctx;
  vm_decode_function(callback, 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)};
  assert(posLimit() != 0);
  assert(hashSize() > 0);
  assert(map->arrayData() == staticEmptyMixedArray());
  map->m_arr = MixedArray::asMixed(MixedArray::MakeReserveMixed(cap()));
  map->setIntLikeStrKeys(intLikeStrKeys());
  wordcpy(map->hashTab(), hashTab(), hashSize());
  {
    uint32_t used = posLimit();
    int32_t version = m_version;
    uint32_t i = 0;
    // When the loop below finishes or when an exception is thrown,
    // make sure that posLimit() get set to the correct value and
    // that m_pos gets set to point to the first element.
    SCOPE_EXIT {
      map->setPosLimit(i);
      map->arrayData()->m_pos = map->nthElmPos(0);
    };
    constexpr int64_t argc = useKey ? 2 : 1;
    TypedValue argv[argc];
    for (; i < used; ++i) {
      const Elm& e = data()[i];
      Elm& ne = map->data()[i];
      if (isTombstone(i)) {
        ne.data.m_type = e.data.m_type;
        continue;
      }
      TypedValue* tv = &ne.data;
      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;
      g_context->invokeFuncFew(tv, ctx, argc, argv);
      if (UNLIKELY(version != m_version)) {
        tvRefcountedDecRef(tv);
        throw_collection_modified();
      }
      if (e.hasStrKey()) {
        e.skey->incRefCount();
      }
      ne.ikey = e.ikey;
      ne.data.hash() = e.data.hash();
      map->incSize();
      // Needed so that the new elements are accounted for when GC scanning.
      map->incPosLimit();
    }
  }
  return Object{std::move(map)};
}