array_slice(): support for collections, remove dead code

A straight-forward delegation to ArrayIter does the job.
 After analysis of the uses of slicing code, it seems that slicing can
 be confined to just the ext_array function, since the other uses for
 func_get_args have been subsumed by special purpose bytecodes. Thus,
 this diff also removes Array::slice, ArrayUtil::Slice, func_get_arg,
 and func_get_args.

Reviewed By: @jdelong

Differential Revision: D1142189
Esse commit está contido em:
Eugene Letuchy
2014-01-24 01:24:54 -08:00
commit de Sara Golemon
commit f58e20caf3
10 arquivos alterados com 181 adições e 113 exclusões
-32
Ver Arquivo
@@ -57,38 +57,6 @@ Variant ArrayUtil::Chunk(CArrRef input, int size,
return ret;
}
Variant ArrayUtil::Slice(CArrRef input, int offset, int64_t length,
bool preserve_keys) {
int num_in = input.size();
if (offset > num_in) {
offset = num_in;
} else if (offset < 0 && (offset = (num_in + offset)) < 0) {
offset = 0;
}
if (length < 0) {
length = num_in - offset + length;
} else if (((unsigned)offset + (unsigned)length) > (unsigned)num_in) {
length = num_in - offset;
}
Array out_hash = Array::Create();
int pos = 0;
ArrayIter iter(input);
for (; pos < offset && iter; ++pos, ++iter) {}
for (; pos < offset + length && iter; ++pos, ++iter) {
Variant key(iter.first());
bool doAppend = !preserve_keys && key.isNumeric();
CVarRef v = iter.secondRef();
if (doAppend) {
out_hash.appendWithRef(v);
} else {
out_hash.setWithRef(key, v, true);
}
}
return out_hash;
}
Variant ArrayUtil::Splice(CArrRef input, int offset, int64_t length /* = 0 */,
CVarRef replacement /* = null_variant */,
Array *removed /* = NULL */) {
-8
Ver Arquivo
@@ -36,14 +36,6 @@ public:
*/
static Variant Chunk(CArrRef input, int size, bool preserve_keys = false);
/**
* Taking a slice. When "preserve_keys" is true, a vector will turn
* into numerically keyed map. When "preserve_keys" is false, a map will
* turn into vectors, unless keys are not numeric.
*/
static Variant Slice(CArrRef input, int offset, int64_t length,
bool preserve_keys);
/**
* Removes the elements designated by offset and length and replace them
* with supplied array.
-5
Ver Arquivo
@@ -296,11 +296,6 @@ Array &Array::mergeImpl(ArrayData *data) {
return *this;
}
Array Array::slice(int offset, int length, bool preserve_keys) const {
if (m_px == nullptr) return Array();
return ArrayUtil::Slice(m_px, offset, length, preserve_keys).toArray();
}
///////////////////////////////////////////////////////////////////////////////
// comparisons
-1
Ver Arquivo
@@ -200,7 +200,6 @@ public:
* into numerically keyed map.
*/
Array& merge(CArrRef arr);
Array slice(int offset, int length, bool preserve_keys) const;
/*
* Sorting.
+47 -4
Ver Arquivo
@@ -619,7 +619,9 @@ Variant f_array_reverse(CVarRef input, bool preserve_keys /* = false */) {
const auto& cell_input = *input.asCell();
if (UNLIKELY(!isContainer(cell_input))) {
throw_expected_array_or_collection_exception();
raise_warning("Invalid operand type was used: %s expects "
"an array or collection as argument 1",
__FUNCTION__+2);
return uninit_null();
}
@@ -641,13 +643,54 @@ Variant f_array_shift(VRefParam array) {
return array.dequeue();
}
Variant f_array_slice(CVarRef array, int offset,
Variant f_array_slice(CVarRef input, int offset,
CVarRef length /* = null_variant */,
bool preserve_keys /* = false */) {
getCheckedArray(array);
const auto& cell_input = *input.asCell();
if (UNLIKELY(!isContainer(cell_input))) {
raise_warning("Invalid operand type was used: %s expects "
"an array or collection as argument 1",
__FUNCTION__+2);
return uninit_null();
}
int64_t len = length.isNull() ? 0x7FFFFFFF : length.toInt64();
return ArrayUtil::Slice(arr_array, offset, len, preserve_keys);
int num_in = getContainerSize(cell_input);
if (offset > num_in) {
offset = num_in;
} else if (offset < 0 && (offset = (num_in + offset)) < 0) {
offset = 0;
}
if (len < 0) {
len = num_in - offset + len;
} else if (((unsigned)offset + (unsigned)len) > (unsigned)num_in) {
len = num_in - offset;
}
if (len <= 0) {
return empty_array;
}
// PackedArrayInit can't be used because non-numeric keys are preserved
// even when preserve_keys is false
Array ret = Array::attach(HphpArray::MakeReserve(len));
int pos = 0;
ArrayIter iter(input);
for (; pos < offset && iter; ++pos, ++iter) {}
for (; pos < (offset + len) && iter; ++pos, ++iter) {
Variant key(iter.first());
bool doAppend = !preserve_keys && key.isNumeric();
CVarRef v = iter.secondRefPlus();
if (doAppend) {
ret.appendWithRef(v);
} else {
ret.setWithRef(key, v, true);
}
}
return ret;
}
Variant f_array_splice(VRefParam input, int offset,
CVarRef length /* = null_variant */,
CVarRef replacement /* = null_variant */) {
-39
Ver Arquivo
@@ -313,25 +313,6 @@ Variant f_func_get_arg(int arg_num) {
return false;
}
Variant func_get_arg(int num_args, CArrRef params, CArrRef args, int pos) {
if (num_args <= params.size()) {
if (pos >= 0 && pos < num_args) {
return params.rvalAt(pos);
}
} else {
if (pos >= 0) {
int index = pos - params.size();
if (index < 0) {
return params.rvalAt(pos);
}
if (index < args.size()) {
return args.rvalAt(index);
}
}
}
return false;
}
Array hhvm_get_frame_args(const ActRec* ar, int offset) {
if (ar == NULL) {
return Array();
@@ -375,26 +356,6 @@ Variant f_func_get_args() {
FUNC_GET_ARGS_IMPL(0);
}
Array func_get_args(int num_args, CArrRef params, CArrRef args) {
if (params.empty() && args.empty()) return Array::Create();
if (args.empty()) {
if (num_args < params.size()) {
return params.slice(0, num_args, false);
}
return params;
}
Array derefArgs;
for (ArrayIter iter(args); iter; ++iter) {
derefArgs.append(iter.second());
}
if (params.empty()) return derefArgs;
assert(num_args > params.size());
Array ret = Array(params).merge(derefArgs);
return ret;
}
Variant f_hphp_func_slice_args(int offset) {
if (offset < 0) {
offset = 0;
-2
Ver Arquivo
@@ -50,7 +50,6 @@ String f_create_function(const String& args, const String& code);
* parameters to help the implementation.
*/
Variant f_func_get_arg(int arg_num);
Variant func_get_arg(int num_args, CArrRef params, CArrRef args, int pos);
/**
* PHP's func_get_args() is transformed to this function with some extra
@@ -58,7 +57,6 @@ Variant func_get_arg(int num_args, CArrRef params, CArrRef args, int pos);
*/
Variant f_func_get_args();
Array hhvm_get_frame_args(const ActRec* ar, int offset);
Array func_get_args(int num_args, CArrRef params, CArrRef args);
/**
* HipHop extension that allows requesting only a subset of function arguments.
-22
Ver Arquivo
@@ -452,28 +452,6 @@ bool TestCppBase::TestArray() {
VS(arr, make_map_array("n0", "s2", "n1", "s3"));
}
// slice
{
Array arr = make_packed_array("test1", "test2");
Array sub = arr.slice(1, 1, true);
VS(sub, make_map_array(1, "test2"));
}
{
Array arr = make_packed_array("test1", "test2");
Array sub = arr.slice(1, 1, false);
VS(sub, make_packed_array("test2"));
}
{
Array arr = make_map_array("n1", "test1", "n2", "test2");
Array sub = arr.slice(1, 1, true);
VS(sub, make_map_array("n2", "test2"));
}
{
Array arr = make_map_array("n1", "test1", "n2", "test2");
Array sub = arr.slice(1, 1, false);
VS(sub, make_map_array("n2", "test2"));
}
// escalation
{
Array arr;
@@ -0,0 +1,34 @@
<?hh
function main() {
$input = Vector {"a", "b", "c", "d", "e"};
var_dump(array_slice($input, 2));
var_dump(array_slice($input, 2, null));
var_dump(array_slice($input, -2, 1));
var_dump(array_slice($input, 0, 3));
// note the differences in the array keys
var_dump(array_slice($input, 2, -1));
var_dump(array_slice($input, 2, -1, true));
var_dump(array_slice(Vector {"a", "b", "c"}, 1, 2, true));
var_dump(array_slice(Vector {"a", "b", "c"}, 1, 2, false));
$m = Map {"a" => "g", 0 => "a", 1 => "b", 2 => "c"};
unset($m['a']);
var_dump(array_slice($m, 1, 2, true));
var_dump(array_slice($m, 1, 2, false));
$m = Map {"a" => 123, 0 => "a", 1 => "b", 2 => "c"};
unset($m['a']);
var_dump(array_slice($m, 1, 2, true));
var_dump(array_slice($m, 1, 2, false));
var_dump(array_slice(FrozenVector{123, "b", "c"}, 1, 2, true));
var_dump(array_slice(FrozenVector{123, "b", "c"}, 1, 2, false));
var_dump(array_slice(Set {"a", "b", "c"}, 1, 2, true));
var_dump(array_slice(FrozenSet {"a", "b", "c"}, 1, 2, false));
}
main();
@@ -0,0 +1,100 @@
array(3) {
[0]=>
string(1) "c"
[1]=>
string(1) "d"
[2]=>
string(1) "e"
}
array(3) {
[0]=>
string(1) "c"
[1]=>
string(1) "d"
[2]=>
string(1) "e"
}
array(1) {
[0]=>
string(1) "d"
}
array(3) {
[0]=>
string(1) "a"
[1]=>
string(1) "b"
[2]=>
string(1) "c"
}
array(2) {
[0]=>
string(1) "c"
[1]=>
string(1) "d"
}
array(2) {
[2]=>
string(1) "c"
[3]=>
string(1) "d"
}
array(2) {
[1]=>
string(1) "b"
[2]=>
string(1) "c"
}
array(2) {
[0]=>
string(1) "b"
[1]=>
string(1) "c"
}
array(2) {
[1]=>
string(1) "b"
[2]=>
string(1) "c"
}
array(2) {
[0]=>
string(1) "b"
[1]=>
string(1) "c"
}
array(2) {
[1]=>
string(1) "b"
[2]=>
string(1) "c"
}
array(2) {
[0]=>
string(1) "b"
[1]=>
string(1) "c"
}
array(2) {
[1]=>
string(1) "b"
[2]=>
string(1) "c"
}
array(2) {
[0]=>
string(1) "b"
[1]=>
string(1) "c"
}
array(2) {
["b"]=>
string(1) "b"
["c"]=>
string(1) "c"
}
array(2) {
["b"]=>
string(1) "b"
["c"]=>
string(1) "c"
}