Пример #1
0
ArrayData* ArrayCommon::ToKeyset(ArrayData* a, bool) {
  auto const size = a->size();
  if (!size) return staticEmptyKeysetArray();
  KeysetInit init{size};
  IterateV(
    a,
    [&](const TypedValue* v) {
      if (UNLIKELY(v->m_type == KindOfRef)) {
        if (v->m_data.pref->isReferenced()) {
          throwRefInvalidArrayValueException(init.toArray());
        }
        v = v->m_data.pref->tv();
        assertx(v->m_type != KindOfRef);
      }

      if (LIKELY(isStringType(v->m_type))) {
        init.add(v->m_data.pstr);
      } else if (LIKELY(isIntType(v->m_type))) {
        init.add(v->m_data.num);
      } else {
        throwInvalidArrayKeyException(v, init.toArray().get());
      }
    }
  );
  return init.create();
}
Пример #2
0
ArrayData* ArrayCommon::ToVec(ArrayData* a, bool) {
  auto const size = a->size();
  if (!size) return staticEmptyVecArray();
  VecArrayInit init{size};
  IterateV(
    a,
    [&](const TypedValue* v) {
      if (UNLIKELY(v->m_type == KindOfRef)) {
        if (v->m_data.pref->isReferenced()) {
          throwRefInvalidArrayValueException(init.toArray());
        }
      }
      init.append(tvAsCVarRef(v));
    }
  );
  return init.create();
}
Пример #3
0
ArrayCommon::RefCheckResult
ArrayCommon::CheckForRefs(const ArrayData* ad) {
  auto result = RefCheckResult::Pass;
  IterateV(
    ad,
    [&](const TypedValue* v) {
      if (UNLIKELY(v->m_type == KindOfRef)) {
        auto const ref = v->m_data.pref;
        if (ref->isReferenced() || ref->tv()->m_data.parr == ad) {
          result = RefCheckResult::Fail;
          return true;
        }
        result = RefCheckResult::Collapse;
      }
      return false;
    }
  );
  return result;
}
void BaseSet::addAll(const Variant& t) {
  if (t.isNull()) { return; } // nothing to do

  decltype(cap()) oldCap = 0;
  bool ok = IterateV(
    *t.asTypedValue(),
    [&](ArrayData* adata) {
      auto sz = adata->size();
      if (!sz) return true;
      if (m_size) {
        oldCap = cap(); // assume minimal collisions
      }
      reserve(m_size + sz);
      mutateAndBump();
      return false;
    },
    [this](const TypedValue* value) {
      addRaw(tvAsCVarRef(value));
    },
    [this](ObjectData* coll) {
      if (!m_size && coll->collectionType() == CollectionType::Set) {
        auto hc = static_cast<HashCollection*>(coll);
        replaceArray(hc->arrayData());
        setIntLikeStrKeys(BaseSet::intLikeStrKeys(hc));
        return true;
      }
      if (coll->collectionType() == CollectionType::Pair) {
        mutateAndBump();
      }
      return false;
    },
    [this](const TypedValue* value) {
      add(tvAsCVarRef(value));
    });

  if (UNLIKELY(!ok)) {
    throw_invalid_collection_parameter();
  }
  // ... and shrink back if that was incorrect
  if (oldCap) shrinkIfCapacityTooHigh(oldCap);
}