示例#1
0
ArrayData* StructArray::SetStr(
  ArrayData* ad,
  StringData* k,
  Cell v,
  bool copy
) {
  auto structArray = asStructArray(ad);
  auto shape = structArray->shape();
  auto result = structArray;

  auto offset = shape->offsetFor(k);
  bool isNewProperty = offset == PropertyTable::kInvalidOffset;

  auto convertToMixedAndAdd = [&]() {
    auto mixed = copy ? ToMixedCopy(structArray) : ToMixed(structArray);
    return mixed->addValNoAsserts(k, v);
  };

  if (isNewProperty) {
    StringData* staticKey;
    // We don't support adding non-static strings yet.
    if (k->isStatic()) {
      staticKey = k;
    } else {
      staticKey = lookupStaticString(k);
      if (!staticKey) return convertToMixedAndAdd();
    }

    auto newShape = shape->transition(staticKey);
    if (!newShape) return convertToMixedAndAdd();
    result = copy ? CopyAndResizeIfNeeded(structArray, newShape)
                  : ResizeIfNeeded(structArray, newShape);
    offset = result->shape()->offsetFor(staticKey);
    assert(offset != PropertyTable::kInvalidOffset);
    TypedValue* dst = &result->data()[offset];
    // TODO(#3888164): we should restructure things so we don't have to
    // check KindOfUninit here.
    if (UNLIKELY(v.m_type == KindOfUninit)) v = make_tv<KindOfNull>();
    cellDup(v, *dst);
    return result;
  }

  if (copy) {
    result = asStructArray(Copy(structArray));
  }

  assert(offset != PropertyTable::kInvalidOffset);
  TypedValue* dst = &result->data()[offset];
  if (UNLIKELY(v.m_type == KindOfUninit)) v = make_tv<KindOfNull>();
  cellSet(v, *tvToCell(dst));
  return result;
}
示例#2
0
StructArray* StructArray::CopyAndResizeIfNeeded(
  const StructArray* array,
  Shape* newShape
) {
  if (!array->shape()->transitionRequiresGrowth()) {
    auto ret = asStructArray(Copy(array));
    ret->setShape(newShape);
    return ret;
  }
  auto const copy = asStructArray(Copy(array));
  auto const ret = Grow(copy, newShape);
  Release(copy);
  return ret;
}
示例#3
0
void StructArray::NvGetKey(const ArrayData* ad, TypedValue* out, ssize_t pos) {
  const auto structArray = asStructArray(ad);

  auto str = const_cast<StringData*>(structArray->shape()->keyForOffset(pos));
  out->m_type = KindOfPersistentString;
  out->m_data.pstr = str;
}
示例#4
0
void StructArray::OnSetEvalScalar(ArrayData* ad) {
  auto structArray = asStructArray(ad);
  auto ptr = structArray->data();
  auto const stop = ptr + structArray->size();
  for (; ptr != stop; ++ptr) {
    tvAsVariant(ptr).setEvalScalar();
  }
  // All keys are already static strings.
}
示例#5
0
const TypedValue* StructArray::NvGetStr(
  const ArrayData* ad,
  const StringData* property
) {
  const auto structArray = asStructArray(ad);
  auto offset = structArray->shape()->offsetFor(property);
  if (offset == PropertyTable::kInvalidOffset) return nullptr;
  return &structArray->data()[offset];
}
示例#6
0
ArrayData* StructArray::AppendWithRef(
  ArrayData* ad,
  const Variant& v,
  bool copy
) {
  auto structArray = asStructArray(ad);
  auto mixedArray = copy ? ToMixedCopy(structArray) : ToMixed(structArray);
  return MixedArray::AppendWithRef(mixedArray->asArrayData(), v, false);
}
示例#7
0
ArrayData* StructArray::SetRefStr(
  ArrayData* ad,
  StringData* k,
  Variant& v,
  bool copy
) {
  auto structArray = asStructArray(ad);
  auto mixedArray = copy ? ToMixedCopy(structArray) : ToMixed(structArray);
  return MixedArray::SetRefStr(mixedArray->asArrayData(), k, v, false);
}
示例#8
0
ArrayData* StructArray::LvalInt(
  ArrayData* ad,
  int64_t k,
  Variant*& ret,
  bool copy
) {
  auto structArray = asStructArray(ad);
  auto mixedArray = copy ? ToMixedCopy(structArray) : ToMixed(structArray);
  return mixedArray->addLvalImpl(k, ret);
}
示例#9
0
ArrayData* StructArray::LvalStr(
  ArrayData* ad,
  StringData* property,
  Variant*& ret,
  bool copy
) {
  auto structArray = asStructArray(ad);
  auto shape = structArray->shape();
  auto offset = shape->offsetFor(property);
  if (offset != PropertyTable::kInvalidOffset) {
    auto const result = asStructArray(
      copy ? Copy(structArray) : structArray);
    ret = &tvAsVariant(&result->data()[offset]);
    return result;
  }

  auto convertToMixedAndAdd = [&]() {
    auto mixed = copy ? ToMixedCopy(structArray) : ToMixed(structArray);
    return mixed->addLvalImpl(property, ret);
  };

  // We don't support adding non-static strings yet.
  StringData* staticKey;
  if (property->isStatic()) {
    staticKey = property;
  } else {
    staticKey = lookupStaticString(property);
    if (!staticKey) return convertToMixedAndAdd();
  }

  auto newShape = shape->transition(staticKey);
  if (!newShape) return convertToMixedAndAdd();
  auto result = copy ? CopyAndResizeIfNeeded(structArray, newShape)
                     : ResizeIfNeeded(structArray, newShape);

  assert(newShape->hasOffsetFor(staticKey));
  offset = newShape->offsetFor(staticKey);
  tvWriteNull(&result->data()[offset]);
  ret = &tvAsVariant(&result->data()[offset]);
  return result;
}
示例#10
0
ArrayData* StructArray::PlusEq(ArrayData* ad, const ArrayData* elems) {
  auto structArray = asStructArray(ad);
  auto const neededSize = structArray->size() + elems->size();
  auto const mixedArray = ToMixedCopyReserve(structArray, neededSize);
  try {
    auto const ret = MixedArray::PlusEq(mixedArray, elems);
    assert(ret == mixedArray);
    assert(mixedArray->hasExactlyOneRef());
    return ret;
  } catch (...) {
    MixedArray::Release(mixedArray);
    throw;
  }
}
示例#11
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;
}
示例#12
0
ArrayData* StructArray::CopyStatic(const ArrayData* ad) {
  auto structArray = asStructArray(ad);
  auto shape = structArray->shape();
  auto ret = StructArray::createStatic(shape, structArray->size());

  ret->m_pos = structArray->m_pos;

  auto const srcData = structArray->data();
  auto const size    = structArray->size();
  auto const stop    = srcData + size;
  auto targetData    = ret->data();
  for (auto ptr = srcData; ptr != stop; ++ptr, ++targetData) {
    tvDupFlattenVars(ptr, targetData, structArray);
  }

  assert(ret->isStatic());
  return ret;
}
示例#13
0
void StructArray::Release(ArrayData* ad) {
  assert(ad->isRefCounted());
  assert(ad->hasExactlyOneRef());
  auto array = asStructArray(ad);

  auto const size = array->size();
  auto const data = array->data();
  auto const stop = data + size;
  for (auto ptr = data; ptr != stop; ++ptr) {
    tvRefcountedDecRef(ptr);
  }
  if (UNLIKELY(strong_iterators_exist())) {
    free_strong_iterators(ad);
  }

  auto const cap = array->capacity();
  MM().objFree(array, sizeof(StructArray) + sizeof(TypedValue) * cap);
}
示例#14
0
bool StructArray::AdvanceMArrayIter(ArrayData* ad, MArrayIter& fp) {
  auto structArray = asStructArray(ad);
  if (fp.getResetFlag()) {
    fp.setResetFlag(false);
    fp.m_pos = 0;
  } else if (fp.m_pos == structArray->size()) {
    return false;
  } else {
    fp.m_pos = IterAdvance(structArray, fp.m_pos);
  }
  if (fp.m_pos == structArray->size()) {
    return false;
  }
  // We set ad's internal cursor to point to the next element
  // to conform with PHP5 behavior
  structArray->m_pos = IterAdvance(structArray, fp.m_pos);
  return true;
}
示例#15
0
void StructArray::ReleaseUncounted(ArrayData* ad) {
  assert(ad->isUncounted());
  auto structArray = asStructArray(ad);

  auto const data = structArray->data();
  auto const stop = data + structArray->size();
  for (auto ptr = data; ptr != stop; ++ptr) {
    ReleaseUncountedTv(*ptr);
  }

  // We better not have strong iterators associated with uncounted
  // arrays.
  if (debug && UNLIKELY(strong_iterators_exist())) {
    for_each_strong_iterator([&] (const MIterTable::Ent& miEnt) {
      assert(miEnt.array != structArray);
    });
  }

  std::free(structArray);
}
示例#16
0
ArrayData* StructArray::MakeUncounted(ArrayData* array) {
  auto structArray = asStructArray(array);
  // We don't need to copy the full capacity, since the array won't
  // change once it's uncounted.
  auto size = structArray->size();
  StructArray* result = createUncounted(structArray->shape(), size);
  result->m_hdr.init(HeaderKind::Struct, UncountedValue);
  result->m_sizeAndPos = array->m_sizeAndPos;
  auto const srcData = structArray->data();
  auto const stop    = srcData + size;
  auto targetData    = result->data();
  for (auto ptr = srcData; ptr != stop; ++ptr, ++targetData) {
    auto srcVariant = MixedArray::CreateVarForUncountedArray(tvAsCVarRef(ptr));
    tvCopy(*srcVariant.asTypedValue(),
           *targetData);
  }
  assert(result->m_pos == structArray->m_pos);
  assert(result->isUncounted());
  return result;
}
示例#17
0
ArrayData* StructArray::Copy(const ArrayData* ad) {
  auto old = asStructArray(ad);
  auto shape = old->shape();

  auto result = StructArray::createNoCopy(shape, shape->size());
  result->m_pos = old->m_pos;

  assert(result->m_size == result->shape()->size());
  assert(result->size() == old->size());
  auto const srcData = old->data();
  auto const stop = srcData + old->size();
  auto targetData = result->data();
  for (auto ptr = srcData; ptr != stop; ++ptr, ++targetData) {
    tvDupFlattenVars(ptr, targetData, old);
  }

  assert(result->m_size == result->shape()->size());
  assert(result->hasExactlyOneRef());
  return result;
}
示例#18
0
ArrayData* StructArray::ToDict(ArrayData* ad) {
  auto a = asStructArray(ad);
  auto mixed = ad->cowCheck() ? ToMixedCopy(a) : ToMixed(a);
  return MixedArray::ToDictInPlace(mixed);
}
示例#19
0
ArrayData* StructArray::Prepend(ArrayData* ad, const Variant& v, bool copy) {
  return MixedArray::Prepend(ToMixed(asStructArray(ad)), v, copy);
}
示例#20
0
ArrayData* StructArray::Dequeue(ArrayData* ad, Variant& value) {
  return MixedArray::Dequeue(ToMixed(asStructArray(ad))->asArrayData(), value);
}
示例#21
0
ArrayData* StructArray::Merge(ArrayData* ad, const ArrayData* elems) {
  auto structArray = asStructArray(ad);
  auto const neededSize = structArray->m_size + elems->size();
  auto const mixedArray = ToMixedCopyReserve(structArray, neededSize);
  return MixedArray::ArrayMergeGeneric(mixedArray, elems);
}
示例#22
0
ssize_t StructArray::IterEnd(const ArrayData* ad) {
  return asStructArray(ad)->size();
}
示例#23
0
ssize_t StructArray::IterAdvance(const ArrayData* ad, ssize_t pos) {
  if (pos < asStructArray(ad)->size()) {
    ++pos;
  }
  return pos;
}
示例#24
0
ArrayData* StructArray::ZAppend(ArrayData* ad, RefData* v, int64_t* key_ptr) {
  return MixedArray::ZAppend(ToMixedCopy(asStructArray(ad)), v, key_ptr);
}
示例#25
0
ArrayData* StructArray::ZSetStr(ArrayData* ad, StringData* k, RefData* v) {
  return MixedArray::ZSetStr(ToMixedCopy(asStructArray(ad)), k, v);
}
示例#26
0
ArrayData* StructArray::ZSetInt(ArrayData* ad, int64_t k, RefData* v) {
  return MixedArray::ZSetInt(ToMixedCopy(asStructArray(ad)), k, v);
}
示例#27
0
ArrayData* StructArray::EscalateForSort(ArrayData* ad, SortFunction) {
  return ToMixedCopy(asStructArray(ad));
}
示例#28
0
ssize_t StructArray::IterLast(const ArrayData* ad) {
  const auto structArray = asStructArray(ad);
  return structArray->size() ? structArray->size() - 1 : 0;
}
示例#29
0
ArrayData* StructArray::Append(ArrayData* ad, Cell v, bool copy) {
  auto structArray = asStructArray(ad);
  auto mixedArray = copy ? ToMixedCopy(structArray) : ToMixed(structArray);
  return MixedArray::Append(mixedArray->asArrayData(), v, false);
}
示例#30
0
ssize_t StructArray::IterRewind(const ArrayData* ad, ssize_t pos) {
  if (pos > 0) {
    return pos - 1;
  }
  return asStructArray(ad)->size();
}