Arquivos
hhvm/hphp/runtime/vm/name_value_table_wrapper.cpp
T
Edwin Smith 7204d561e5 Devirtualize ArrayData part 2
Convert remaining virtual methods to static methods dispatched
by kind.  This makes ArrayData a non-virtual class, so shuffle
fields and adjust static_asserts.
2013-07-22 11:34:09 -07:00

277 linhas
8.5 KiB
C++

/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/runtime/vm/name_value_table_wrapper.h"
#include "hphp/runtime/base/runtime_error.h"
#include "hphp/runtime/base/array_iterator.h"
#include "hphp/runtime/base/array_init.h"
namespace HPHP {
//////////////////////////////////////////////////////////////////////
inline NameValueTableWrapper* NameValueTableWrapper::asNVTW(ArrayData* ad) {
assert(ad->kind() == kNvtwKind);
return static_cast<NameValueTableWrapper*>(ad);
}
inline const NameValueTableWrapper*
NameValueTableWrapper::asNVTW(const ArrayData* ad) {
assert(ad->kind() == kNvtwKind);
return static_cast<const NameValueTableWrapper*>(ad);
}
size_t NameValueTableWrapper::Vsize(const ArrayData* ad) {
// We need to iterate to find out the actual size, since
// KindOfIndirect elements in the array may have been set to
// KindOfUninit.
auto a = asNVTW(ad);
size_t count = 0;
for (auto iter = IterBegin(a);
iter != invalid_index;
iter = IterAdvance(a, iter)) {
++count;
}
return count;
}
void NameValueTableWrapper::NvGetKey(const ArrayData* ad, TypedValue* out,
ssize_t pos) {
auto a = asNVTW(ad);
NameValueTable::Iterator iter(a->m_tab, pos);
if (iter.valid()) {
auto k = iter.curKey();
out->m_data.pstr = const_cast<StringData*>(k);
out->m_type = KindOfString;
k->incRefCount();
} else {
out->m_type = KindOfUninit;
}
}
CVarRef NameValueTableWrapper::GetValueRef(const ArrayData* ad, ssize_t pos) {
auto a = asNVTW(ad);
NameValueTable::Iterator iter(a->m_tab, pos);
return iter.valid() ? tvAsCVarRef(iter.curVal()) : null_variant;
}
bool
NameValueTableWrapper::ExistsInt(const ArrayData* ad, int64_t k) {
return ExistsStr(ad, String(k).get());
}
bool
NameValueTableWrapper::ExistsStr(const ArrayData* ad, const StringData* k) {
return asNVTW(ad)->m_tab->lookup(k) != nullptr;
}
TypedValue*
NameValueTableWrapper::NvGetStr(const ArrayData* ad, const StringData* k) {
return asNVTW(ad)->m_tab->lookup(k);
}
TypedValue* NameValueTableWrapper::NvGetInt(const ArrayData* ad, int64_t k) {
return asNVTW(ad)->m_tab->lookup(String(k).get());
}
ArrayData*
NameValueTableWrapper::LvalInt(ArrayData* ad, int64_t k, Variant*& ret,
bool copy) {
return LvalStr(ad, String(k).get(), ret, copy);
}
ArrayData*
NameValueTableWrapper::LvalStr(ArrayData* ad, StringData* k, Variant*& ret,
bool copy) {
auto a = asNVTW(ad);
TypedValue* tv = a->m_tab->lookup(k);
if (!tv) {
TypedValue nulVal;
tvWriteNull(&nulVal);
tv = a->m_tab->set(k, &nulVal);
}
ret = &tvAsVariant(tv);
return a;
}
ArrayData*
NameValueTableWrapper::AddLvalInt(ArrayData* ad, int64_t k, Variant*& ret,
bool copy) {
return LvalStr(ad, String(k).get(), ret, copy);
}
ArrayData*
NameValueTableWrapper::AddLvalStr(ArrayData* ad, StringData* k, Variant*& ret,
bool copy) {
return LvalStr(ad, k, ret, copy);
}
ArrayData*
NameValueTableWrapper::LvalNew(ArrayData* ad, Variant*& ret, bool copy) {
ret = &Variant::lvalBlackHole();
return ad;
}
ArrayData* NameValueTableWrapper::SetInt(ArrayData* ad, int64_t k,
CVarRef v, bool copy) {
return SetStr(ad, String(k).get(), v, copy);
}
ArrayData* NameValueTableWrapper::SetStr(ArrayData* ad, StringData* k,
CVarRef v, bool copy) {
auto a = asNVTW(ad);
tvAsVariant(a->m_tab->lookupAdd(k)).assignVal(v);
return a;
}
ArrayData* NameValueTableWrapper::SetRefInt(ArrayData* ad, int64_t k,
CVarRef v, bool copy) {
return asNVTW(ad)->setRef(String(k).get(), v, copy);
}
ArrayData* NameValueTableWrapper::SetRefStr(ArrayData* ad, StringData* k,
CVarRef v, bool copy) {
auto a = asNVTW(ad);
tvAsVariant(a->m_tab->lookupAdd(k)).assignRef(v);
return a;
}
ArrayData*
NameValueTableWrapper::RemoveInt(ArrayData* ad, int64_t k, bool copy) {
return RemoveStr(ad, String(k).get(), copy);
}
ArrayData*
NameValueTableWrapper::RemoveStr(ArrayData* ad, const StringData* k,
bool copy) {
auto a = asNVTW(ad);
a->m_tab->unset(k);
return a;
}
/*
* The messages in the user-visible exceptions below claim we are
* $GLOBALS, because the only user-visible NameValueTableWrapper array
* is currently $GLOBALS.
*/
ArrayData*
NameValueTableWrapper::Append(ArrayData*, CVarRef v, bool copy) {
throw NotImplementedException("append on $GLOBALS");
}
ArrayData*
NameValueTableWrapper::AppendRef(ArrayData*, CVarRef v, bool copy) {
throw NotImplementedException("appendRef on $GLOBALS");
}
ArrayData*
NameValueTableWrapper::AppendWithRef(ArrayData*, CVarRef v, bool copy) {
throw NotImplementedException("appendWithRef on $GLOBALS");
}
ArrayData*
NameValueTableWrapper::Plus(ArrayData*, const ArrayData* elems, bool copy) {
throw NotImplementedException("plus on $GLOBALS");
}
ArrayData*
NameValueTableWrapper::Merge(ArrayData*, const ArrayData* elems, bool copy) {
throw NotImplementedException("merge on $GLOBALS");
}
ArrayData*
NameValueTableWrapper::Prepend(ArrayData*, CVarRef v, bool copy) {
throw NotImplementedException("prepend on $GLOBALS");
}
ssize_t NameValueTableWrapper::IterBegin(const ArrayData* ad) {
auto a = asNVTW(ad);
NameValueTable::Iterator iter(a->m_tab);
return iter.toInteger();
}
ssize_t NameValueTableWrapper::IterEnd(const ArrayData* ad) {
auto a = asNVTW(ad);
return NameValueTable::Iterator::getEnd(a->m_tab).toInteger();
}
ssize_t NameValueTableWrapper::IterAdvance(const ArrayData* ad, ssize_t prev) {
auto a = asNVTW(ad);
NameValueTable::Iterator iter(a->m_tab, prev);
iter.next();
return iter.toInteger();
}
ssize_t NameValueTableWrapper::IterRewind(const ArrayData* ad, ssize_t prev) {
auto a = asNVTW(ad);
NameValueTable::Iterator iter(a->m_tab, prev);
iter.prev();
return iter.toInteger();
}
bool
NameValueTableWrapper::ValidFullPos(const ArrayData* ad, const FullPos & fp) {
assert(fp.getContainer() == ad);
auto a = asNVTW(ad);
if (fp.getResetFlag()) return false;
if (fp.m_pos == invalid_index) return false;
NameValueTable::Iterator iter(a->m_tab, fp.m_pos);
return iter.valid();
}
bool NameValueTableWrapper::AdvanceFullPos(ArrayData* ad, FullPos& fp) {
auto a = asNVTW(ad);
bool reset = fp.getResetFlag();
NameValueTable::Iterator iter = reset ?
NameValueTable::Iterator(a->m_tab) :
NameValueTable::Iterator(a->m_tab, fp.m_pos);
if (reset) {
fp.setResetFlag(false);
} else {
if (!iter.valid()) {
return false;
}
iter.next();
}
fp.m_pos = iter.toInteger();
if (!iter.valid()) return false;
// To conform to PHP behavior, we need to set the internal
// cursor to point to the next element.
iter.next();
a->m_pos = iter.toInteger();
return true;
}
ArrayData* NameValueTableWrapper::EscalateForSort(ArrayData* ad) {
raise_warning("Sorting the $GLOBALS array is not supported");
return ad;
}
void NameValueTableWrapper::Ksort(ArrayData*, int sort_flags, bool ascending) {}
void NameValueTableWrapper::Sort(ArrayData*, int sort_flags, bool ascending) {}
void NameValueTableWrapper::Asort(ArrayData*, int sort_flags, bool ascending) {}
void NameValueTableWrapper::Uksort(ArrayData*, CVarRef cmp_function) {}
void NameValueTableWrapper::Usort(ArrayData*, CVarRef cmp_function) {}
void NameValueTableWrapper::Uasort(ArrayData*, CVarRef cmp_function) {}
bool NameValueTableWrapper::IsVectorData(const ArrayData*) {
return false;
}
//////////////////////////////////////////////////////////////////////
}