Remove Variant::GetTypedAccessor
This stuff almost is an abstraction layer, but it's in a strange place. Also, the layout of TypedValue isn't something we've been using through an abstraction layer, and if we want to later I think we won't want to do so using this one.
Esse commit está contido em:
@@ -1699,7 +1699,7 @@ void EmitterVisitor::visit(FileScopePtr file) {
|
||||
} else {
|
||||
assert(!IS_REFCOUNTED_TYPE(v.getType()));
|
||||
}
|
||||
mainReturn = *v.getTypedAccessor();
|
||||
mainReturn = *v.asCell();
|
||||
m_ue.returnSeen();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -233,7 +233,7 @@ bool UnaryOpExpression::preCompute(CVarRef value, Variant &result) {
|
||||
case '-':
|
||||
result = value.negate(); break;
|
||||
case '~':
|
||||
result = ~value; break;
|
||||
result = value.bitNot(); break;
|
||||
case '@':
|
||||
result = value; break;
|
||||
case T_INT_CAST:
|
||||
|
||||
@@ -24,18 +24,18 @@ namespace HPHP {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace {
|
||||
typedef Variant::TypedValueAccessor TypedValueAccessor;
|
||||
|
||||
inline bool isIntKey(TypedValueAccessor tva) {
|
||||
return Variant::GetAccessorType(tva) <= KindOfInt64;
|
||||
inline bool isIntKey(const Cell* cell) {
|
||||
return IS_INT_KEY_TYPE(cell->m_type);
|
||||
}
|
||||
|
||||
inline int64_t getIntKey(TypedValueAccessor tva) {
|
||||
return Variant::GetInt64(tva);
|
||||
inline int64_t getIntKey(const Cell* cell) {
|
||||
assert(cell->m_type == KindOfInt64);
|
||||
return cell->m_data.num;
|
||||
}
|
||||
|
||||
inline StringData *getStringKey(TypedValueAccessor tva) {
|
||||
return Variant::GetStringData(tva);
|
||||
inline StringData* getStringKey(const Cell* cell) {
|
||||
assert(IS_STRING_TYPE(cell->m_type));
|
||||
return cell->m_data.pstr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,9 +46,9 @@ inline bool ArrayData::exists(CStrRef k) const {
|
||||
|
||||
inline bool ArrayData::exists(CVarRef k) const {
|
||||
assert(IsValidKey(k));
|
||||
TypedValueAccessor tvk = k.getTypedAccessor();
|
||||
return isIntKey(tvk) ? exists(getIntKey(tvk)) :
|
||||
exists(getStringKey(tvk));
|
||||
auto const cell = k.asCell();
|
||||
return isIntKey(cell) ? exists(getIntKey(cell))
|
||||
: exists(getStringKey(cell));
|
||||
}
|
||||
|
||||
inline CVarRef ArrayData::get(CStrRef k, bool error) const {
|
||||
@@ -58,9 +58,9 @@ inline CVarRef ArrayData::get(CStrRef k, bool error) const {
|
||||
|
||||
inline CVarRef ArrayData::get(CVarRef k, bool error) const {
|
||||
assert(IsValidKey(k));
|
||||
TypedValueAccessor tvk = k.getTypedAccessor();
|
||||
return isIntKey(tvk) ? get(getIntKey(tvk), error) :
|
||||
get(getStringKey(tvk), error);
|
||||
auto const cell = k.asCell();
|
||||
return isIntKey(cell) ? get(getIntKey(cell), error)
|
||||
: get(getStringKey(cell), error);
|
||||
}
|
||||
|
||||
inline ArrayData* ArrayData::lval(CStrRef k, Variant *&ret, bool copy,
|
||||
@@ -72,9 +72,9 @@ inline ArrayData* ArrayData::lval(CStrRef k, Variant *&ret, bool copy,
|
||||
inline ArrayData* ArrayData::lval(CVarRef k, Variant *&ret, bool copy,
|
||||
bool checkExist) {
|
||||
assert(IsValidKey(k));
|
||||
TypedValueAccessor tvk = k.getTypedAccessor();
|
||||
return isIntKey(tvk) ? lval(getIntKey(tvk), ret, copy, checkExist) :
|
||||
lval(getStringKey(tvk), ret, copy, checkExist);
|
||||
auto const cell = k.asCell();
|
||||
return isIntKey(cell) ? lval(getIntKey(cell), ret, copy, checkExist)
|
||||
: lval(getStringKey(cell), ret, copy, checkExist);
|
||||
}
|
||||
|
||||
inline ArrayData *ArrayData::lvalPtr(CStrRef k, Variant *&ret, bool copy,
|
||||
@@ -90,9 +90,9 @@ inline ArrayData* ArrayData::set(CStrRef k, CVarRef v, bool copy) {
|
||||
|
||||
inline ArrayData* ArrayData::set(CVarRef k, CVarRef v, bool copy) {
|
||||
assert(IsValidKey(k));
|
||||
TypedValueAccessor tvk = k.getTypedAccessor();
|
||||
return isIntKey(tvk) ? set(getIntKey(tvk), v, copy) :
|
||||
set(getStringKey(tvk), v, copy);
|
||||
auto const cell = k.asCell();
|
||||
return isIntKey(cell) ? set(getIntKey(cell), v, copy)
|
||||
: set(getStringKey(cell), v, copy);
|
||||
}
|
||||
|
||||
inline ArrayData* ArrayData::setRef(CStrRef k, CVarRef v, bool copy) {
|
||||
@@ -102,9 +102,9 @@ inline ArrayData* ArrayData::setRef(CStrRef k, CVarRef v, bool copy) {
|
||||
|
||||
inline ArrayData* ArrayData::setRef(CVarRef k, CVarRef v, bool copy) {
|
||||
assert(IsValidKey(k));
|
||||
TypedValueAccessor tvk = k.getTypedAccessor();
|
||||
return isIntKey(tvk) ? setRef(getIntKey(tvk), v, copy) :
|
||||
setRef(getStringKey(tvk), v, copy);
|
||||
auto const cell = k.asCell();
|
||||
return isIntKey(cell) ? setRef(getIntKey(cell), v, copy)
|
||||
: setRef(getStringKey(cell), v, copy);
|
||||
}
|
||||
|
||||
inline ArrayData* ArrayData::add(CStrRef k, CVarRef v, bool copy) {
|
||||
@@ -114,9 +114,9 @@ inline ArrayData* ArrayData::add(CStrRef k, CVarRef v, bool copy) {
|
||||
|
||||
inline ArrayData* ArrayData::add(CVarRef k, CVarRef v, bool copy) {
|
||||
assert(IsValidKey(k));
|
||||
TypedValueAccessor tvk = k.getTypedAccessor();
|
||||
return isIntKey(tvk) ? add(getIntKey(tvk), v, copy) :
|
||||
add(getStringKey(tvk), v, copy);
|
||||
auto const cell = k.asCell();
|
||||
return isIntKey(cell) ? add(getIntKey(cell), v, copy)
|
||||
: add(getStringKey(cell), v, copy);
|
||||
}
|
||||
|
||||
inline ArrayData* ArrayData::addLval(CStrRef k, Variant *&ret, bool copy) {
|
||||
@@ -126,9 +126,9 @@ inline ArrayData* ArrayData::addLval(CStrRef k, Variant *&ret, bool copy) {
|
||||
|
||||
inline ArrayData* ArrayData::addLval(CVarRef k, Variant *&ret, bool copy) {
|
||||
assert(IsValidKey(k));
|
||||
TypedValueAccessor tvk = k.getTypedAccessor();
|
||||
return isIntKey(tvk) ? addLval(getIntKey(tvk), ret, copy) :
|
||||
addLval(getStringKey(tvk), ret, copy);
|
||||
auto const cell = k.asCell();
|
||||
return isIntKey(cell) ? addLval(getIntKey(cell), ret, copy)
|
||||
: addLval(getStringKey(cell), ret, copy);
|
||||
}
|
||||
|
||||
inline ArrayData* ArrayData::remove(CStrRef k, bool copy) {
|
||||
@@ -138,9 +138,9 @@ inline ArrayData* ArrayData::remove(CStrRef k, bool copy) {
|
||||
|
||||
inline ArrayData* ArrayData::remove(CVarRef k, bool copy) {
|
||||
assert(IsValidKey(k));
|
||||
TypedValueAccessor tvk = k.getTypedAccessor();
|
||||
return isIntKey(tvk) ? remove(getIntKey(tvk), copy) :
|
||||
remove(getStringKey(tvk), copy);
|
||||
auto const cell = k.asCell();
|
||||
return isIntKey(cell) ? remove(getIntKey(cell), copy)
|
||||
: remove(getStringKey(cell), copy);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1056,10 +1056,10 @@ AutoloadHandler::Result AutoloadHandler::loadFromMap(CStrRef name,
|
||||
assert(!m_map.isNull());
|
||||
while (true) {
|
||||
CVarRef &type_map = m_map.get()->get(kind);
|
||||
Variant::TypedValueAccessor tva = type_map.getTypedAccessor();
|
||||
if (Variant::GetAccessorType(tva) != KindOfArray) return Failure;
|
||||
auto const typeMapCell = type_map.asCell();
|
||||
if (typeMapCell->m_type != KindOfArray) return Failure;
|
||||
String canonicalName = toLower ? StringUtil::ToLower(name) : name;
|
||||
CVarRef &file = Variant::GetArrayData(tva)->get(canonicalName);
|
||||
CVarRef &file = typeMapCell->m_data.parr->get(canonicalName);
|
||||
bool ok = false;
|
||||
if (file.isString()) {
|
||||
String fName = file.toCStrRef().get();
|
||||
@@ -1095,9 +1095,9 @@ AutoloadHandler::Result AutoloadHandler::loadFromMap(CStrRef name,
|
||||
// - false means we should stop applying autoloaders (only affects classes)
|
||||
// - anything else means keep going
|
||||
Variant action = vm_call_user_func(func, CREATE_VECTOR2(kind, name));
|
||||
tva = action.getTypedAccessor();
|
||||
if (Variant::GetAccessorType(tva) == KindOfBoolean) {
|
||||
if (Variant::GetBoolean(tva)) continue;
|
||||
auto const actionCell = action.asCell();
|
||||
if (actionCell->m_type == KindOfBoolean) {
|
||||
if (actionCell->m_data.num) continue;
|
||||
return StopAutoloading;
|
||||
}
|
||||
return ContinueAutoloading;
|
||||
|
||||
@@ -28,10 +28,10 @@ bool same(CVarRef v1, bool v2) {
|
||||
}
|
||||
|
||||
bool same(CVarRef v1, int64_t v2) {
|
||||
auto const acc = v1.getTypedAccessor();
|
||||
switch (acc->m_type) {
|
||||
auto const cell = v1.asCell();
|
||||
switch (cell->m_type) {
|
||||
case KindOfInt64:
|
||||
return v2 == acc->m_data.num;
|
||||
return v2 == cell->m_data.num;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -227,6 +227,10 @@ BOOST_STATIC_ASSERT(KindOfString == 0x14);
|
||||
#define IS_REAL_TYPE(t) \
|
||||
(((t) >= KindOfUninit && (t) < MaxNumDataTypes) || (t) == KindOfClass)
|
||||
|
||||
inline bool IS_INT_KEY_TYPE(DataType t) {
|
||||
return t <= KindOfInt64;
|
||||
}
|
||||
|
||||
// typeReentersOnRelease --
|
||||
// Returns whether the release helper for a given type can
|
||||
// reenter.
|
||||
|
||||
@@ -227,14 +227,14 @@ TypedValue* SharedMap::nvGetValueRef(ssize_t pos) {
|
||||
|
||||
TypedValue* SharedMap::nvGetCell(int64_t k) const {
|
||||
int index = getIndex(k);
|
||||
return index != -1 ? getValueRef(index).getTypedAccessor() :
|
||||
nvGetNotFound(k);
|
||||
return index != -1 ? const_cast<Cell*>(getValueRef(index).asCell())
|
||||
: nvGetNotFound(k);
|
||||
}
|
||||
|
||||
TypedValue* SharedMap::nvGetCell(const StringData* key) const {
|
||||
int index = getIndex(key);
|
||||
return index != -1 ? getValueRef(index).getTypedAccessor() :
|
||||
nvGetNotFound(key);
|
||||
return index != -1 ? const_cast<Cell*>(getValueRef(index).asCell())
|
||||
: nvGetNotFound(key);
|
||||
}
|
||||
|
||||
ArrayData* SharedMap::escalateForSort() {
|
||||
|
||||
@@ -435,9 +435,9 @@ bool Variant::isScalar() const {
|
||||
}
|
||||
|
||||
bool Variant::isResource() const {
|
||||
TypedValueAccessor acc = getTypedAccessor();
|
||||
if (GetAccessorType(acc) == KindOfObject) {
|
||||
return GetObjectData(acc)->isResource();
|
||||
auto const cell = asCell();
|
||||
if (cell->m_type == KindOfObject) {
|
||||
return cell->m_data.pobj->isResource();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1199,16 +1199,16 @@ Variant &Variant::operator%=(double n) {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// bitwise
|
||||
|
||||
Variant Variant::operator~() const {
|
||||
TypedValueAccessor tva = getTypedAccessor();
|
||||
switch (GetAccessorType(tva)) {
|
||||
Variant Variant::bitNot() const {
|
||||
auto const cell = asCell();
|
||||
switch (cell->m_type) {
|
||||
case KindOfInt64:
|
||||
return ~GetInt64(tva);
|
||||
return ~cell->m_data.num;
|
||||
case KindOfDouble:
|
||||
return ~toInt64(GetDouble(tva));
|
||||
return ~toInt64(cell->m_data.dbl);
|
||||
case KindOfStaticString:
|
||||
case KindOfString:
|
||||
return ~GetAsString(tva);
|
||||
return ~String(cell->m_data.pstr);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1377,9 +1377,9 @@ MutableArrayIter Variant::begin(Variant *key, Variant &val,
|
||||
}
|
||||
|
||||
void Variant::escalate() {
|
||||
TypedValueAccessor tva = getTypedAccessor();
|
||||
if (GetAccessorType(tva) == KindOfArray) {
|
||||
ArrayData *arr = GetArrayData(tva);
|
||||
auto const cell = asCell();
|
||||
if (cell->m_type == KindOfArray) {
|
||||
ArrayData *arr = cell->m_data.parr;
|
||||
ArrayData *esc = arr->escalate();
|
||||
if (arr != esc) set(esc);
|
||||
}
|
||||
@@ -1545,109 +1545,25 @@ Variant::operator Object() const {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define UNWRAP(reverse) \
|
||||
TypedValueAccessor acc = getTypedAccessor(); \
|
||||
switch (GetAccessorType(acc)) { \
|
||||
case KindOfUninit: \
|
||||
case KindOfNull: return HPHP::reverse(v2, false); \
|
||||
case KindOfBoolean: return HPHP::reverse(v2, GetBoolean(acc)); \
|
||||
case KindOfInt64: return HPHP::reverse(v2, GetInt64(acc)); \
|
||||
case KindOfDouble: return HPHP::reverse(v2, GetDouble(acc)); \
|
||||
case KindOfStaticString: \
|
||||
case KindOfString: return HPHP::reverse(v2, GetStringData(acc)); \
|
||||
case KindOfArray: return HPHP::reverse(v2, Array(GetArrayData(acc))); \
|
||||
case KindOfObject: return HPHP::reverse(v2, Object(GetObjectData(acc)));\
|
||||
default: \
|
||||
assert(false); \
|
||||
break; \
|
||||
} \
|
||||
return false; \
|
||||
|
||||
// "null" needs to convert to "" before comparing with a string
|
||||
#define UNWRAP_STR(reverse) \
|
||||
TypedValueAccessor acc = getTypedAccessor(); \
|
||||
switch (GetAccessorType(acc)) { \
|
||||
case KindOfUninit: \
|
||||
case KindOfNull: return HPHP::reverse(v2, empty_string); \
|
||||
case KindOfBoolean: return HPHP::reverse(v2, GetBoolean(acc)); \
|
||||
case KindOfInt64: return HPHP::reverse(v2, GetInt64(acc)); \
|
||||
case KindOfDouble: return HPHP::reverse(v2, GetDouble(acc)); \
|
||||
case KindOfStaticString: \
|
||||
case KindOfString: return HPHP::reverse(v2, GetStringData(acc)); \
|
||||
case KindOfArray: return HPHP::reverse(v2, Array(GetArrayData(acc))); \
|
||||
case KindOfObject: return HPHP::reverse(v2, Object(GetObjectData(acc)));\
|
||||
default: \
|
||||
assert(false); \
|
||||
break; \
|
||||
} \
|
||||
return false; \
|
||||
|
||||
// Array needs to convert to "Array" and Object to String
|
||||
#define UNWRAP_STRING(reverse) \
|
||||
TypedValueAccessor acc = getTypedAccessor(); \
|
||||
switch (GetAccessorType(acc)) { \
|
||||
case KindOfUninit: \
|
||||
case KindOfNull: return HPHP::reverse(v2, empty_string); \
|
||||
case KindOfBoolean: return HPHP::reverse(v2, GetBoolean(acc)); \
|
||||
case KindOfInt64: return HPHP::reverse(v2, GetInt64(acc)); \
|
||||
case KindOfDouble: return HPHP::reverse(v2, GetDouble(acc)); \
|
||||
case KindOfStaticString: \
|
||||
case KindOfString: return HPHP::reverse(v2, GetStringData(acc)); \
|
||||
case KindOfArray: return HPHP::reverse(v2, s_array); \
|
||||
case KindOfObject: \
|
||||
return HPHP::reverse(v2, Object(GetObjectData(acc)).toString()); \
|
||||
default: \
|
||||
assert(false); \
|
||||
break; \
|
||||
} \
|
||||
return false; \
|
||||
|
||||
// "null" needs to convert to "" before comparing with a string
|
||||
#define UNWRAP_VAR(forward, reverse) \
|
||||
TypedValueAccessor acc = getTypedAccessor(); \
|
||||
switch (GetAccessorType(acc)) { \
|
||||
case KindOfUninit: \
|
||||
case KindOfNull: \
|
||||
if (v2.isString()) { \
|
||||
return HPHP::reverse(v2.getStringData(), empty_string); \
|
||||
} \
|
||||
return HPHP::reverse(v2, false); \
|
||||
case KindOfBoolean: return HPHP::reverse(v2, GetBoolean(acc)); \
|
||||
case KindOfInt64: return HPHP::reverse(v2, GetInt64(acc)); \
|
||||
case KindOfDouble: return HPHP::reverse(v2, GetDouble(acc)); \
|
||||
case KindOfStaticString: \
|
||||
case KindOfString: return HPHP::reverse(v2, GetStringData(acc)); \
|
||||
case KindOfArray: \
|
||||
if (v2.isArray()) { \
|
||||
return Array(GetArrayData(acc)).forward(Array(v2.getArrayData())); \
|
||||
} \
|
||||
return HPHP::reverse(v2, Array(GetArrayData(acc))); \
|
||||
case KindOfObject: return HPHP::reverse(v2, Object(GetObjectData(acc)));\
|
||||
default: \
|
||||
assert(false); \
|
||||
break; \
|
||||
} \
|
||||
return false; \
|
||||
|
||||
// array comparison is directional when they are uncomparable
|
||||
// also, ">" is implemented as "!<=" in Zend
|
||||
#define UNWRAP_ARR(forward, reverse) \
|
||||
TypedValueAccessor acc = getTypedAccessor(); \
|
||||
switch (GetAccessorType(acc)) { \
|
||||
case KindOfUninit: \
|
||||
case KindOfNull: return HPHP::reverse(v2, false); \
|
||||
case KindOfBoolean: return HPHP::reverse(v2, GetBoolean(acc)); \
|
||||
case KindOfInt64: return HPHP::reverse(v2, GetInt64(acc)); \
|
||||
case KindOfDouble: return HPHP::reverse(v2, GetDouble(acc)); \
|
||||
case KindOfStaticString: \
|
||||
case KindOfString: return HPHP::reverse(v2, GetStringData(acc)); \
|
||||
case KindOfArray: return Array(GetArrayData(acc)).forward(v2); \
|
||||
case KindOfObject: return HPHP::reverse(v2, Object(GetObjectData(acc)));\
|
||||
default: \
|
||||
assert(false); \
|
||||
break; \
|
||||
} \
|
||||
return false; \
|
||||
#define UNWRAP_STRING(reverse) \
|
||||
auto const cell = asCell(); \
|
||||
switch (cell->m_type) { \
|
||||
case KindOfUninit: \
|
||||
case KindOfNull: return HPHP::reverse(v2, empty_string); \
|
||||
case KindOfBoolean: return HPHP::reverse(v2, !!cell->m_data.num); \
|
||||
case KindOfInt64: return HPHP::reverse(v2, cell->m_data.num); \
|
||||
case KindOfDouble: return HPHP::reverse(v2, cell->m_data.dbl); \
|
||||
case KindOfStaticString: \
|
||||
case KindOfString: return HPHP::reverse(v2, cell->m_data.pstr); \
|
||||
case KindOfArray: return HPHP::reverse(v2, s_array); \
|
||||
case KindOfObject: \
|
||||
return HPHP::reverse(v2, Object(cell->m_data.pobj).toString()); \
|
||||
default: \
|
||||
assert(false); \
|
||||
break; \
|
||||
} \
|
||||
return false;
|
||||
|
||||
bool Variant::equalAsStr(bool v2) const { UNWRAP_STRING(equalAsStr);}
|
||||
bool Variant::equalAsStr(int v2) const { UNWRAP_STRING(equalAsStr);}
|
||||
|
||||
@@ -585,7 +585,6 @@ class Variant : private TypedValue {
|
||||
Variant &operator %= (int64_t n);
|
||||
Variant &operator %= (double n);
|
||||
|
||||
Variant operator ~ () const;
|
||||
Variant operator | (CVarRef v) const;
|
||||
Variant &operator |= (CVarRef v);
|
||||
Variant operator & (CVarRef v) const;
|
||||
@@ -600,6 +599,10 @@ class Variant : private TypedValue {
|
||||
Variant &operator -- ();
|
||||
Variant operator -- (int);
|
||||
|
||||
// Return the result of applying the php bitwise not operator to
|
||||
// this value.
|
||||
Variant bitNot() const;
|
||||
|
||||
/**
|
||||
* Iterator functions. See array_iterator.h for end() and next().
|
||||
*/
|
||||
@@ -987,65 +990,6 @@ class Variant : private TypedValue {
|
||||
const Cell* asCell() const { return tvToCell(asTypedValue()); }
|
||||
Cell* asCell() { return tvToCell(asTypedValue()); }
|
||||
|
||||
/**
|
||||
* Based on the order in complex_types.h, TypedValue is defined before.
|
||||
* TypedValue is binary compatible with Variant
|
||||
*/
|
||||
typedef struct TypedValue* TypedValueAccessor;
|
||||
TypedValueAccessor getTypedAccessor() const {
|
||||
const Variant *value = m_type == KindOfRef ? m_data.pref->var() : this;
|
||||
return (TypedValueAccessor)value;
|
||||
}
|
||||
static DataType GetAccessorType(TypedValueAccessor acc) {
|
||||
assert(acc);
|
||||
return acc->m_type;
|
||||
}
|
||||
static bool GetBoolean(TypedValueAccessor acc) {
|
||||
assert(acc && acc->m_type == KindOfBoolean);
|
||||
return acc->m_data.num;
|
||||
}
|
||||
static int64_t GetInt64(TypedValueAccessor acc) {
|
||||
assert(acc);
|
||||
assert(acc->m_type == KindOfInt64);
|
||||
return acc->m_data.num;
|
||||
}
|
||||
static double GetDouble(TypedValueAccessor acc) {
|
||||
assert(acc && acc->m_type == KindOfDouble);
|
||||
return acc->m_data.dbl;
|
||||
}
|
||||
static bool IsString(TypedValueAccessor acc) {
|
||||
return IS_STRING_TYPE(acc->m_type);
|
||||
}
|
||||
static StringData *GetStringData(TypedValueAccessor acc) {
|
||||
assert(acc && IS_STRING_TYPE(acc->m_type));
|
||||
return acc->m_data.pstr;
|
||||
}
|
||||
static ArrayData *GetArrayData(TypedValueAccessor acc) {
|
||||
assert(acc && acc->m_type == KindOfArray);
|
||||
return acc->m_data.parr;
|
||||
}
|
||||
static ObjectData *GetObjectData(TypedValueAccessor acc) {
|
||||
assert(acc && acc->m_type == KindOfObject);
|
||||
return acc->m_data.pobj;
|
||||
}
|
||||
static ObjectData *GetArrayAccess(TypedValueAccessor acc) {
|
||||
assert(acc && acc->m_type == KindOfObject);
|
||||
ObjectData *obj = acc->m_data.pobj;
|
||||
if (!obj->instanceof(SystemLib::s_ArrayAccessClass)) {
|
||||
throw InvalidOperandException("not ArrayAccess objects");
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
static Array& GetAsArray(TypedValueAccessor acc) {
|
||||
assert(acc && acc->m_type == KindOfArray);
|
||||
return *reinterpret_cast<Array*>(&acc->m_data.parr);
|
||||
}
|
||||
|
||||
static String& GetAsString(TypedValueAccessor acc) {
|
||||
assert(IsString(acc));
|
||||
return *reinterpret_cast<String*>(&acc->m_data.pstr);
|
||||
}
|
||||
|
||||
private:
|
||||
bool isPrimitive() const { return !IS_REFCOUNTED_TYPE(m_type); }
|
||||
bool isObjectConvertable() {
|
||||
@@ -1270,9 +1214,11 @@ public:
|
||||
return *const_cast<VRefParamValue*>(this);
|
||||
}
|
||||
operator Variant&() const { return m_var; }
|
||||
Variant *operator&() const { return &m_var; }
|
||||
Variant *operator&() const { return &m_var; } // FIXME
|
||||
Variant *operator->() const { return &m_var; }
|
||||
|
||||
Variant& wrapped() const { return m_var; }
|
||||
|
||||
explicit operator bool () const { return m_var.toBoolean();}
|
||||
operator int () const { return m_var.toInt32();}
|
||||
operator int64_t () const { return m_var.toInt64();}
|
||||
@@ -1316,9 +1262,6 @@ public:
|
||||
Variant array_iter_key() const { return m_var.array_iter_key(); }
|
||||
Variant array_iter_each() const { return m_var.array_iter_each(); }
|
||||
|
||||
Variant::TypedValueAccessor getTypedAccessor() const {
|
||||
return m_var.getTypedAccessor();
|
||||
}
|
||||
private:
|
||||
mutable Variant m_var;
|
||||
};
|
||||
|
||||
@@ -177,12 +177,16 @@ void StringBuffer::append(int64_t n) {
|
||||
}
|
||||
|
||||
void StringBuffer::append(CVarRef v) {
|
||||
Variant::TypedValueAccessor tva = v.getTypedAccessor();
|
||||
if (Variant::IsString(tva)) {
|
||||
append(Variant::GetAsString(tva));
|
||||
} else if (IS_INT_TYPE(Variant::GetAccessorType(tva))) {
|
||||
append(Variant::GetInt64(tva));
|
||||
} else {
|
||||
auto const cell = v.asCell();
|
||||
switch (cell->m_type) {
|
||||
case KindOfStaticString:
|
||||
case KindOfString:
|
||||
append(cell->m_data.pstr);
|
||||
break;
|
||||
case KindOfInt64:
|
||||
append(cell->m_data.num);
|
||||
break;
|
||||
default:
|
||||
append(v.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -670,54 +670,60 @@ void VariableSerializer::writePropertyKey(CStrRef prop) {
|
||||
|
||||
/* key MUST be a non-reference string or int */
|
||||
void VariableSerializer::writeArrayKey(Variant key) {
|
||||
Variant::TypedValueAccessor tva = key.getTypedAccessor();
|
||||
bool skey = Variant::IsString(tva);
|
||||
auto const keyCell = key.asCell();
|
||||
bool const skey = IS_STRING_TYPE(keyCell->m_type);
|
||||
|
||||
if (skey && m_type == APCSerialize) {
|
||||
write(Variant::GetAsString(tva));
|
||||
write(StrNR(keyCell->m_data.pstr).asString());
|
||||
return;
|
||||
}
|
||||
ArrayInfo &info = m_arrayInfos.back();
|
||||
|
||||
switch (m_type) {
|
||||
case DebuggerDump:
|
||||
case PrintR: {
|
||||
indent();
|
||||
m_buf->append('[');
|
||||
if (info.is_object && skey) {
|
||||
writePropertyKey(Variant::GetAsString(tva));
|
||||
writePropertyKey(keyCell->m_data.pstr);
|
||||
} else {
|
||||
m_buf->append(key);
|
||||
}
|
||||
m_buf->append("] => ");
|
||||
break;
|
||||
}
|
||||
|
||||
case VarExport:
|
||||
case PHPOutput:
|
||||
indent();
|
||||
write(key, true);
|
||||
m_buf->append(" => ");
|
||||
break;
|
||||
|
||||
case VarDump:
|
||||
case DebugDump:
|
||||
indent();
|
||||
m_buf->append('[');
|
||||
if (!skey) {
|
||||
m_buf->append(Variant::GetInt64(tva));
|
||||
m_buf->append(keyCell->m_data.num);
|
||||
} else {
|
||||
m_buf->append('"');
|
||||
if (info.is_object) {
|
||||
writePropertyKey(Variant::GetAsString(tva));
|
||||
writePropertyKey(keyCell->m_data.pstr);
|
||||
} else {
|
||||
m_buf->append(Variant::GetAsString(tva));
|
||||
m_buf->append(keyCell->m_data.pstr);
|
||||
m_buf->append('"');
|
||||
}
|
||||
}
|
||||
m_buf->append("]=>\n");
|
||||
break;
|
||||
|
||||
case APCSerialize:
|
||||
case Serialize:
|
||||
case DebuggerSerialize:
|
||||
write(key);
|
||||
break;
|
||||
|
||||
case JSON:
|
||||
if (!info.first_element) {
|
||||
m_buf->append(',');
|
||||
@@ -728,9 +734,9 @@ void VariableSerializer::writeArrayKey(Variant key) {
|
||||
}
|
||||
if (!info.is_vector) {
|
||||
if (skey) {
|
||||
CStrRef s = Variant::GetAsString(tva);
|
||||
const char *k = s.data();
|
||||
int len = s.size();
|
||||
auto const sdata = keyCell->m_data.pstr;
|
||||
const char *k = sdata->data();
|
||||
int len = sdata->size();
|
||||
if (info.is_object && !*k && len) {
|
||||
while (*++k) len--;
|
||||
k++;
|
||||
@@ -739,7 +745,7 @@ void VariableSerializer::writeArrayKey(Variant key) {
|
||||
write(k, len);
|
||||
} else {
|
||||
m_buf->append('"');
|
||||
m_buf->append(Variant::GetInt64(tva));
|
||||
m_buf->append(keyCell->m_data.num);
|
||||
m_buf->append('"');
|
||||
}
|
||||
m_buf->append(':');
|
||||
@@ -748,6 +754,7 @@ void VariableSerializer::writeArrayKey(Variant key) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
|
||||
@@ -65,16 +65,15 @@ const int64_t k_UCOL_NUMERIC_COLLATION = UCOL_NUMERIC_COLLATION;
|
||||
using HPHP::Transl::CallerFrame;
|
||||
using HPHP::Transl::EagerCallerFrame;
|
||||
|
||||
#define getCheckedArrayRetType(input, fail, type) \
|
||||
Variant::TypedValueAccessor tva_##input = input.getTypedAccessor(); \
|
||||
if (UNLIKELY(Variant::GetAccessorType(tva_##input) != KindOfArray)) { \
|
||||
throw_bad_array_exception(); \
|
||||
return fail; \
|
||||
} \
|
||||
type arr_##input = Variant::GetAsArray(tva_##input);
|
||||
#define getCheckedArrayRet(input, fail) \
|
||||
auto const cell_##input = static_cast<CVarRef>(input).asCell(); \
|
||||
if (UNLIKELY(cell_##input->m_type != KindOfArray)) { \
|
||||
throw_bad_array_exception(); \
|
||||
return fail; \
|
||||
} \
|
||||
ArrNR arrNR_##input(cell_##input->m_data.parr); \
|
||||
CArrRef arr_##input = arrNR_##input.asArray();
|
||||
|
||||
#define getCheckedArrayRet(input, fail) \
|
||||
getCheckedArrayRetType(input, fail, CArrRef)
|
||||
#define getCheckedArray(input) getCheckedArrayRet(input, uninit_null())
|
||||
|
||||
Variant f_array_change_key_case(CVarRef input, bool upper /* = false */) {
|
||||
@@ -191,12 +190,12 @@ Variant f_array_flip(CVarRef trans) {
|
||||
HOT_FUNC
|
||||
bool f_array_key_exists(CVarRef key, CVarRef search) {
|
||||
const ArrayData *ad;
|
||||
Variant::TypedValueAccessor sacc = search.getTypedAccessor();
|
||||
DataType saccType = Variant::GetAccessorType(sacc);
|
||||
if (LIKELY(saccType == KindOfArray)) {
|
||||
ad = Variant::GetArrayData(sacc);
|
||||
} else if (saccType == KindOfObject) {
|
||||
ObjectData* obj = Variant::GetObjectData(sacc);
|
||||
|
||||
auto const searchCell = search.asCell();
|
||||
if (LIKELY(searchCell->m_type == KindOfArray)) {
|
||||
ad = searchCell->m_data.parr;
|
||||
} else if (searchCell->m_type == KindOfObject) {
|
||||
ObjectData* obj = searchCell->m_data.pobj;
|
||||
if (obj->isCollection()) {
|
||||
return collectionOffsetContains(obj, key);
|
||||
}
|
||||
@@ -206,19 +205,20 @@ bool f_array_key_exists(CVarRef key, CVarRef search) {
|
||||
"false returned.");
|
||||
return false;
|
||||
}
|
||||
Variant::TypedValueAccessor kacc = key.getTypedAccessor();
|
||||
switch (Variant::GetAccessorType(kacc)) {
|
||||
|
||||
auto const cell = key.asCell();
|
||||
switch (cell->m_type) {
|
||||
case KindOfString:
|
||||
case KindOfStaticString: {
|
||||
int64_t n = 0;
|
||||
StringData *sd = Variant::GetStringData(kacc);
|
||||
StringData *sd = cell->m_data.pstr;
|
||||
if (sd->isStrictlyInteger(n)) {
|
||||
return ad->exists(n);
|
||||
}
|
||||
return ad->exists(StrNR(sd));
|
||||
}
|
||||
case KindOfInt64:
|
||||
return ad->exists(Variant::GetInt64(kacc));
|
||||
return ad->exists(cell->m_data.num);
|
||||
case KindOfUninit:
|
||||
case KindOfNull:
|
||||
return ad->exists(empty_string);
|
||||
@@ -445,7 +445,18 @@ Variant f_array_product(CVarRef array) {
|
||||
}
|
||||
|
||||
Variant f_array_push(int _argc, VRefParam array, CVarRef var, CArrRef _argv /* = null_array */) {
|
||||
getCheckedArrayRetType(array, uninit_null(), Array &);
|
||||
auto const array_cell = array.wrapped().asCell();
|
||||
if (UNLIKELY(array_cell->m_type != KindOfArray)) {
|
||||
throw_bad_array_exception();
|
||||
return uninit_null();
|
||||
}
|
||||
|
||||
/*
|
||||
* Important note: this *must* cast the parr in the inner cell to
|
||||
* the Array&---we can't copy it to the stack or anything because we
|
||||
* might escalate.
|
||||
*/
|
||||
Array& arr_array = *reinterpret_cast<Array*>(&array_cell->m_data.parr);
|
||||
arr_array.append(var);
|
||||
for (ArrayIter iter(_argv); iter; ++iter) {
|
||||
arr_array.append(iter.second());
|
||||
@@ -1086,7 +1097,7 @@ class ArraySortTmp {
|
||||
static bool
|
||||
php_sort(VRefParam array, int sort_flags, bool ascending, bool use_collator) {
|
||||
if (array.isArray()) {
|
||||
Array& arr_array = Variant::GetAsArray(array.getTypedAccessor());
|
||||
Array& arr_array = array.wrapped().toArrRef();
|
||||
if (use_collator && sort_flags != SORT_LOCALE_STRING) {
|
||||
UCollator *coll = s_collator->getCollator();
|
||||
if (coll) {
|
||||
@@ -1114,7 +1125,7 @@ php_sort(VRefParam array, int sort_flags, bool ascending, bool use_collator) {
|
||||
static bool
|
||||
php_asort(VRefParam array, int sort_flags, bool ascending, bool use_collator) {
|
||||
if (array.isArray()) {
|
||||
Array& arr_array = Variant::GetAsArray(array.getTypedAccessor());
|
||||
Array& arr_array = array.wrapped().toArrRef();
|
||||
if (use_collator && sort_flags != SORT_LOCALE_STRING) {
|
||||
UCollator *coll = s_collator->getCollator();
|
||||
if (coll) {
|
||||
@@ -1142,7 +1153,7 @@ php_asort(VRefParam array, int sort_flags, bool ascending, bool use_collator) {
|
||||
static bool
|
||||
php_ksort(VRefParam array, int sort_flags, bool ascending) {
|
||||
if (array.isArray()) {
|
||||
Array& arr_array = Variant::GetAsArray(array.getTypedAccessor());
|
||||
Array& arr_array = array.wrapped().toArrRef();
|
||||
ArraySortTmp ast(arr_array);
|
||||
ast->ksort(sort_flags, ascending);
|
||||
return true;
|
||||
@@ -1201,7 +1212,7 @@ Variant f_natcasesort(VRefParam array) {
|
||||
|
||||
bool f_usort(VRefParam array, CVarRef cmp_function) {
|
||||
if (array.isArray()) {
|
||||
Array& arr_array = Variant::GetAsArray(array.getTypedAccessor());
|
||||
Array& arr_array = array.wrapped().toArrRef();
|
||||
ArraySortTmp ast(arr_array);
|
||||
ast->usort(cmp_function);
|
||||
return true;
|
||||
@@ -1220,7 +1231,7 @@ bool f_usort(VRefParam array, CVarRef cmp_function) {
|
||||
|
||||
bool f_uasort(VRefParam array, CVarRef cmp_function) {
|
||||
if (array.isArray()) {
|
||||
Array& arr_array = Variant::GetAsArray(array.getTypedAccessor());
|
||||
Array& arr_array = array.wrapped().toArrRef();
|
||||
ArraySortTmp ast(arr_array);
|
||||
ast->uasort(cmp_function);
|
||||
return true;
|
||||
@@ -1239,7 +1250,7 @@ bool f_uasort(VRefParam array, CVarRef cmp_function) {
|
||||
|
||||
bool f_uksort(VRefParam array, CVarRef cmp_function) {
|
||||
if (array.isArray()) {
|
||||
Array& arr_array = Variant::GetAsArray(array.getTypedAccessor());
|
||||
Array& arr_array = array.wrapped().toArrRef();
|
||||
ArraySortTmp ast(arr_array);
|
||||
ast->uksort(cmp_function);
|
||||
return true;
|
||||
@@ -1273,8 +1284,8 @@ bool f_array_multisort(int _argc, VRefParam ar1,
|
||||
bool ascending = true;
|
||||
for (int i = 0; i < _argv.size(); i++) {
|
||||
Variant *v = &((Array&)_argv).lvalAt(i);
|
||||
Variant::TypedValueAccessor tva = v->getTypedAccessor();
|
||||
if (Variant::GetAccessorType(tva) == KindOfArray) {
|
||||
auto const cell = v->asCell();
|
||||
if (cell->m_type == KindOfArray) {
|
||||
sd.cmp_func = get_cmp_func(sort_flags, ascending);
|
||||
data.push_back(sd);
|
||||
|
||||
@@ -1282,7 +1293,7 @@ bool f_array_multisort(int _argc, VRefParam ar1,
|
||||
ascending = true;
|
||||
|
||||
sd.original = v;
|
||||
arrays.push_back(Variant::GetAsArray(tva));
|
||||
arrays.push_back(Array(cell->m_data.parr));
|
||||
sd.array = &arrays.back();
|
||||
} else {
|
||||
int n = v->toInt32();
|
||||
|
||||
@@ -74,14 +74,14 @@ bool f_is_callable(CVarRef v, bool syntax /* = false */,
|
||||
if (!name.isReferenced()) return ret;
|
||||
}
|
||||
|
||||
Variant::TypedValueAccessor tv_func = v.getTypedAccessor();
|
||||
if (Variant::IsString(tv_func)) {
|
||||
if (name.isReferenced()) name = Variant::GetStringData(tv_func);
|
||||
auto const tv_func = v.asCell();
|
||||
if (IS_STRING_TYPE(tv_func->m_type)) {
|
||||
if (name.isReferenced()) name = tv_func->m_data.pstr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (Variant::GetAccessorType(tv_func) == KindOfArray) {
|
||||
CArrRef arr = Variant::GetAsArray(tv_func);
|
||||
if (tv_func->m_type == KindOfArray) {
|
||||
CArrRef arr = tv_func->m_data.parr;
|
||||
CVarRef clsname = arr.rvalAtRef(int64_t(0));
|
||||
CVarRef mthname = arr.rvalAtRef(int64_t(1));
|
||||
if (arr.size() != 2 ||
|
||||
@@ -91,28 +91,28 @@ bool f_is_callable(CVarRef v, bool syntax /* = false */,
|
||||
return false;
|
||||
}
|
||||
|
||||
Variant::TypedValueAccessor tv_meth = mthname.getTypedAccessor();
|
||||
if (!Variant::IsString(tv_meth)) {
|
||||
auto const tv_meth = mthname.asCell();
|
||||
if (!IS_STRING_TYPE(tv_meth->m_type)) {
|
||||
if (name.isReferenced()) name = v.toString();
|
||||
return false;
|
||||
}
|
||||
|
||||
Variant::TypedValueAccessor tv_cls = clsname.getTypedAccessor();
|
||||
if (Variant::GetAccessorType(tv_cls) == KindOfObject) {
|
||||
name = Variant::GetObjectData(tv_cls)->o_getClassName();
|
||||
} else if (Variant::IsString(tv_cls)) {
|
||||
name = Variant::GetStringData(tv_cls);
|
||||
auto const tv_cls = clsname.asCell();
|
||||
if (tv_cls->m_type == KindOfObject) {
|
||||
name = tv_cls->m_data.pobj->o_getClassName();
|
||||
} else if (IS_STRING_TYPE(tv_cls->m_type)) {
|
||||
name = tv_cls->m_data.pstr;
|
||||
} else {
|
||||
name = v.toString();
|
||||
return false;
|
||||
}
|
||||
|
||||
name = concat3(name, s_colon2, Variant::GetAsString(tv_meth));
|
||||
name = concat3(name, s_colon2, tv_meth->m_data.pstr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (Variant::GetAccessorType(tv_func) == KindOfObject) {
|
||||
ObjectData *d = Variant::GetObjectData(tv_func);
|
||||
if (tv_func->m_type == KindOfObject) {
|
||||
ObjectData *d = tv_func->m_data.pobj;
|
||||
const Func* invoke = d->getVMClass()->lookupMethod(s__invoke.get());
|
||||
if (name.isReferenced()) {
|
||||
if (d->instanceof(c_Closure::s_cls)) {
|
||||
|
||||
@@ -136,7 +136,7 @@ bool f_define(CStrRef name, CVarRef value,
|
||||
if (case_insensitive) {
|
||||
raise_warning(Strings::CONSTANTS_CASE_SENSITIVE);
|
||||
}
|
||||
return Unit::defCns(name.get(), value.getTypedAccessor());
|
||||
return Unit::defCns(name.get(), value.asCell());
|
||||
}
|
||||
|
||||
bool f_defined(CStrRef name, bool autoload /* = true */) {
|
||||
|
||||
@@ -667,11 +667,11 @@ Variant f_strcspn(CStrRef str1, CStrRef str2, int start /* = 0 */,
|
||||
}
|
||||
|
||||
Variant f_strlen(CVarRef vstr) {
|
||||
Variant::TypedValueAccessor tva = vstr.getTypedAccessor();
|
||||
switch (Variant::GetAccessorType(tva)) {
|
||||
auto const cell = vstr.asCell();
|
||||
switch (cell->m_type) {
|
||||
case KindOfString:
|
||||
case KindOfStaticString:
|
||||
return Variant(Variant::GetStringData(tva)->size());
|
||||
return Variant(cell->m_data.pstr->size());
|
||||
case KindOfArray:
|
||||
raise_warning("strlen() expects parameter 1 to be string, array given");
|
||||
return uninit_null();
|
||||
|
||||
@@ -4185,7 +4185,7 @@ inline void OPTBLD_INLINE VMExecutionContext::iopBitNot(PC& pc) {
|
||||
c1->m_type = KindOfInt64;
|
||||
c1->m_data.num = ~int64_t(c1->m_data.dbl);
|
||||
} else if (IS_STRING_TYPE(c1->m_type)) {
|
||||
tvCellAsVariant(c1) = ~tvCellAsVariant(c1);
|
||||
tvCellAsVariant(c1) = tvCellAsVariant(c1).bitNot();
|
||||
} else {
|
||||
raise_error("Unsupported operand type for ~");
|
||||
}
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário