SharedVariant::SharedVariant(CVarRef source, bool serialized, bool inner /* = false */, bool unserializeObj /* = false */) : m_count (1), m_shouldCache(false), m_flags(0){ ASSERT(!serialized || source.isString()); m_type = source.getType(); switch (m_type) { case KindOfBoolean: { m_data.num = source.toBoolean(); break; } case KindOfByte: case KindOfInt16: case KindOfInt32: case KindOfInt64: { m_type = KindOfInt64; m_data.num = source.toInt64(); break; } case KindOfDouble: { m_data.dbl = source.toDouble(); break; } case KindOfStaticString: case KindOfString: { String s = source.toString(); if (serialized) { m_type = KindOfObject; // It is priming, and there might not be the right class definitions // for unserialization. s = apc_reserialize(s); } m_data.str = s->copy(true); break; } case KindOfArray: { ArrayData *arr = source.getArrayData(); if (!inner) { // only need to call hasInternalReference() on the toplevel array PointerSet seen; if (arr->hasInternalReference(seen)) { setSerializedArray(); m_shouldCache = true; String s = apc_serialize(source); m_data.str = new StringData(s.data(), s.size(), CopyString); break; } } size_t size = arr->size(); if (arr->isVectorData()) { setIsVector(); m_data.vec = new VectorData(size); uint i = 0; for (ArrayIter it(arr); !it.end(); it.next(), i++) { SharedVariant* val = Create(it.secondRef(), false, true, unserializeObj); if (val->m_shouldCache) m_shouldCache = true; m_data.vec->vals[i] = val; } } else { m_data.map = new ImmutableMap(size); for (ArrayIter it(arr); !it.end(); it.next()) { SharedVariant* key = Create(it.first(), false, true, unserializeObj); SharedVariant* val = Create(it.secondRef(), false, true, unserializeObj); if (val->m_shouldCache) m_shouldCache = true; m_data.map->add(key, val); } } break; } case KindOfNull: { m_data.num = 0; break; } default: { ASSERT(source.isObject()); m_shouldCache = true; if (unserializeObj) { // This assumes hasInternalReference(seen, true) is false ImmutableObj* obj = new ImmutableObj(source.getObjectData()); m_data.obj = obj; setIsObj(); } else { String s = apc_serialize(source); m_data.str = new StringData(s.data(), s.size(), CopyString); } break; } } }
SharedVariant::SharedVariant(CVarRef source, bool serialized, bool inner /* = false */, bool unserializeObj /* = false */) : m_shouldCache(false), m_flags(0) { assert(!serialized || source.isString()); m_count = 1; m_type = source.getType(); switch (m_type) { case KindOfBoolean: { m_data.num = source.toBoolean(); break; } case KindOfInt64: { m_type = KindOfInt64; m_data.num = source.toInt64(); break; } case KindOfDouble: { m_data.dbl = source.toDouble(); break; } case KindOfStaticString: { if (serialized) goto StringCase; m_data.str = source.getStringData(); break; } StringCase: case KindOfString: { String s = source.toString(); if (serialized) { m_type = KindOfObject; // It is priming, and there might not be the right class definitions // for unserialization. s = apc_reserialize(s); } StringData* st = StringData::LookupStaticString(s.get()); if (st) { m_data.str = st; m_type = KindOfStaticString; break; } m_data.str = s->copy(true); break; } case KindOfArray: { ArrayData *arr = source.getArrayData(); if (!inner) { // only need to call hasInternalReference() on the toplevel array PointerSet seen; if (arr->hasInternalReference(seen)) { setSerializedArray(); m_shouldCache = true; String s = apc_serialize(source); m_data.str = StringData::MakeMalloced(s.data(), s.size()); break; } } if (arr->isVectorData()) { setIsVector(); m_data.vec = new (arr->size()) VectorData(); for (ArrayIter it(arr); !it.end(); it.next()) { SharedVariant* val = Create(it.secondRef(), false, true, unserializeObj); if (val->m_shouldCache) m_shouldCache = true; m_data.vec->vals()[m_data.vec->m_size++] = val; } } else { m_data.map = ImmutableMap::Create(arr, unserializeObj, m_shouldCache); } break; } case KindOfUninit: case KindOfNull: { break; } case KindOfResource: { // TODO Task #2661075: Here and elsewhere in the runtime, we convert // Resources to the empty array during various serialization operations, // which does not match Zend behavior. We should fix this. m_type = KindOfArray; setIsVector(); m_data.vec = new (0) VectorData(); break; } default: { assert(source.isObject()); m_shouldCache = true; if (unserializeObj) { // This assumes hasInternalReference(seen, true) is false ImmutableObj* obj = new ImmutableObj(source.getObjectData()); m_data.obj = obj; setIsObj(); } else { String s = apc_serialize(source); m_data.str = StringData::MakeMalloced(s.data(), s.size()); } break; } } assert(m_type != KindOfResource); }