Variant ArrayUtil::RandomValues(CArrRef input, int num_req /* = 1 */) { int count = input.size(); if (num_req <= 0 || num_req > count) { return uninit_null(); } std::vector<ssize_t> indices; indices.reserve(count); for (ssize_t pos = input->iter_begin(); pos != ArrayData::invalid_index; pos = input->iter_advance(pos)) { indices.push_back(pos); } php_array_data_shuffle(indices); if (num_req == 1) { return input->getValue(indices[0]); } Array ret = Array::Create(); for (int i = 0; i < num_req; i++) { ssize_t pos = indices[i]; ret.append(input->getValueRef(pos)); } return ret; }
void Array::SortImpl(vector<int> &indices, CArrRef source, Array::SortData &opaque, Array::PFUNC_CMP cmp_func, bool by_key, const void *data /* = NULL */) { ASSERT(cmp_func); int count = source.size(); if (count == 0) { return; } indices.reserve(count); for (int i = 0; i < count; i++) { indices.push_back(i); } opaque.array = &source; opaque.by_key = by_key; opaque.cmp_func = cmp_func; opaque.data = data; opaque.positions.reserve(count); for (ssize_t pos = source->iter_begin(); pos != ArrayData::invalid_index; pos = source->iter_advance(pos)) { opaque.positions.push_back(pos); } zend_qsort(&indices[0], count, sizeof(int), array_compare_func, &opaque); }
Variant ArrayUtil::RandomKeys(CArrRef input, int num_req /* = 1 */) { int count = input.size(); if (num_req <= 0 || num_req > count) { raise_warning("Second argument has to be between 1 and the " "number of elements in the array"); return uninit_null(); } std::vector<ssize_t> indices; indices.reserve(count); for (ssize_t pos = input->iter_begin(); pos != ArrayData::invalid_index; pos = input->iter_advance(pos)) { indices.push_back(pos); } php_array_data_shuffle(indices); if (num_req == 1) { return input->getKey(indices[0]); } Array ret = Array::Create(); for (int i = 0; i < num_req; i++) { ssize_t pos = indices[i]; ret.append(input->getKey(pos)); } return ret; }
Variant f_max(int _argc, CVarRef value, CArrRef _argv /* = null_array */) { Variant ret; if (_argv.empty() && value.is(KindOfArray)) { Array v = value.toArray(); if (!v.empty()) { ssize_t pos = v->iter_begin(); if (pos != ArrayData::invalid_index) { ret = v->getValue(pos); while (true) { pos = v->iter_advance(pos); if (pos == ArrayData::invalid_index) break; Variant tmp = v->getValue(pos); if (more(tmp, ret)) { ret = tmp; } } } } } else { ret = value; if (!_argv.empty()) { for (ssize_t pos = _argv->iter_begin(); pos != ArrayData::invalid_index; pos = _argv->iter_advance(pos)) { Variant tmp = _argv->getValue(pos); if (more(tmp, ret)) { ret = tmp; } } } } return ret; }
bool Array::MultiSort(std::vector<SortData> &data, bool renumber) { ASSERT(!data.empty()); int count = -1; for (unsigned int k = 0; k < data.size(); k++) { SortData &opaque = data[k]; ASSERT(opaque.array); ASSERT(opaque.cmp_func); int size = opaque.array->size(); if (count == -1) { count = size; } else if (count != size) { throw_invalid_argument("arrays: (inconsistent sizes)"); return false; } opaque.positions.reserve(size); CArrRef arr = *opaque.array; if (!arr.empty()) { for (ssize_t pos = arr->iter_begin(); pos != ArrayData::invalid_index; pos = arr->iter_advance(pos)) { opaque.positions.push_back(pos); } } } if (count == 0) { return true; } int *indices = (int *)malloc(sizeof(int) * count); for (int i = 0; i < count; i++) { indices[i] = i; } zend_qsort(indices, count, sizeof(int), multi_compare_func, (void *)&data); for (unsigned int k = 0; k < data.size(); k++) { SortData &opaque = data[k]; CArrRef arr = *opaque.array; Array sorted; for (int i = 0; i < count; i++) { ssize_t pos = opaque.positions[indices[i]]; Variant k(arr->getKey(pos)); if (renumber && k.isInteger()) { sorted.append(arr->getValueRef(pos)); } else { sorted.set(k, arr->getValueRef(pos)); } } *opaque.original = sorted; } free(indices); return true; }
Variant ArrayUtil::RandomKeys(CArrRef input, int num_req /* = 1 */) { int count = input.size(); if (num_req <= 0 || num_req > count) { raise_warning("Second argument has to be between 1 and the " "number of elements in the array"); return init_null(); } if (num_req == 1) { // Iterating through the counter is correct but a bit inefficient // compared to being able to access the right offset into array data, // but necessary for this code to be agnostic to the array's internal // representation. Assuming uniform distribution, we'll expect to // iterate through half of the array's data. ssize_t index = f_rand(0, count-1); ssize_t pos = input->iter_begin(); while (index--) { pos = input->iter_advance(pos); } return input->getKey(pos); } std::vector<ssize_t> indices; indices.reserve(count); for (ssize_t pos = input->iter_begin(); pos != ArrayData::invalid_index; pos = input->iter_advance(pos)) { indices.push_back(pos); } php_array_data_shuffle(indices); Array ret = Array::Create(); for (int i = 0; i < num_req; i++) { ssize_t pos = indices[i]; ret.append(input->getKey(pos)); } return ret; }
Variant ArrayUtil::Shuffle(CArrRef input) { int count = input.size(); if (count == 0) { return input; } std::vector<ssize_t> indices; indices.reserve(count); for (ssize_t pos = input->iter_begin(); pos != ArrayData::invalid_index; pos = input->iter_advance(pos)) { indices.push_back(pos); } php_array_data_shuffle(indices); Array ret = Array::Create(); for (int i = 0; i < count; i++) { ssize_t pos = indices[i]; ret.appendWithRef(input->getValueRef(pos)); } return ret; }
int64_t f_array_unshift(int _argc, VRefParam array, CVarRef var, CArrRef _argv /* = null_array */) { if (array.toArray()->isVectorData()) { if (!_argv.empty()) { for (ssize_t pos = _argv->iter_end(); pos != ArrayData::invalid_index; pos = _argv->iter_rewind(pos)) { array.prepend(_argv->getValueRef(pos)); } } array.prepend(var); } else { { Array newArray; newArray.append(var); if (!_argv.empty()) { for (ssize_t pos = _argv->iter_begin(); pos != ArrayData::invalid_index; pos = _argv->iter_advance(pos)) { newArray.append(_argv->getValueRef(pos)); } } for (ArrayIter iter(array); iter; ++iter) { Variant key(iter.first()); CVarRef value(iter.secondRef()); if (key.isInteger()) { newArray.appendWithRef(value); } else { newArray.lvalAt(key, AccessFlags::Key).setWithRef(value); } } array = newArray; } // Reset the array's internal pointer if (array.is(KindOfArray)) { array.array_iter_reset(); } } return array.toArray().size(); }