void Array::unserialize(VariableUnserializer *uns) { int64 size = uns->readInt(); char sep = uns->readChar(); if (sep != ':') { throw Exception("Expected ':' but got '%c'", sep); } sep = uns->readChar(); if (sep != '{') { throw Exception("Expected '{' but got '%c'", sep); } if (size == 0) { operator=(Create()); } else { // Pre-allocate an ArrayData of the given size, to avoid escalation in // the middle, which breaks references. operator=(ArrayInit(size).create()); bool isAPC = (uns->getType() == VariableUnserializer::APCSerialize); for (int64 i = 0; i < size; i++) { Variant key(uns->unserializeKey()); if (!key.isString() && !key.isInteger()) { throw Exception("Invalid key"); } Variant &value = isAPC ? addLval(key, true) : lvalAt(key, AccessFlags::Key); value.unserialize(uns); } } sep = uns->readChar(); if (sep != '}') { throw Exception("Expected '}' but got '%c'", sep); } }
Variant *Array::lvalPtr(CStrRef key, bool forWrite, bool create) { if (create) { if (!m_px) ArrayBase::operator=(ArrayData::Create()); return &lvalAt(key, AccessFlags::Key); } Variant *ret = nullptr; if (m_px) { ArrayData *escalated = m_px->lvalPtr(key, ret, forWrite && m_px->getCount() > 1, false); if (escalated != m_px) ArrayBase::operator=(escalated); } return ret; }
HOT_FUNC_HPHP Variant *Array::lvalPtr(int64 key, bool forWrite, bool create) { if (create) { if (!m_px) { ArrayBase::operator=(ArrayData::Create()); } return &lvalAt(key, AccessFlags::None); } Variant *ret = NULL; if (m_px) { ArrayData *escalated = m_px->lvalPtr(key, ret, forWrite && m_px->getCount() > 1, false); if (escalated) { ArrayBase::operator=(escalated); } } return ret; }
Variant Array::refvalAt(CStrRef key, bool isString /* = false */) { return strongBind(lvalAt(key, AccessFlags::IsKey(isString))); }