Variant f_hphp_current_ref(VRefParam array) { if (!array.isArray()) { throw_bad_array_exception(); return false; } return strongBind(array.array_iter_current_ref()); }
bool f_shuffle(VRefParam array) { if (!array.isArray()) { throw_bad_array_exception(); return false; } array = ArrayUtil::Shuffle(array); return true; }
static bool HHVM_METHOD(Collator, sort, VRefParam arr, int64_t sort_flag /* = Collator::SORT_REGULAR */) { FETCH_COL(data, this_, false); if (!arr.isArray()) { throw_expected_array_exception(); return false; } data->clearError(); bool ret = collator_sort(arr, sort_flag, true, data->collator(), data); if (U_FAILURE(data->getErrorCode())) { return false; } return ret; }
bool f_array_walk(VRefParam input, CVarRef funcname, CVarRef userdata /* = null_variant */) { if (!input.isArray()) { throw_bad_array_exception(); return false; } CallCtx ctx; CallerFrame cf; vm_decode_function(funcname, cf(), false, ctx); if (ctx.func == NULL) { return false; } ArrayUtil::Walk(input, walk_func, &ctx, false, NULL, userdata); return true; }
bool f_array_walk_recursive(VRefParam input, CVarRef funcname, CVarRef userdata /* = null_variant */) { if (!input.isArray()) { throw_bad_array_exception(); return false; } CallCtx ctx; CallerFrame cf; vm_decode_function(funcname, cf(), false, ctx); if (ctx.func == NULL) { return uninit_null(); } PointerSet seen; ArrayUtil::Walk(input, walk_func, &ctx, true, &seen, userdata); return true; }
bool c_Collator::t_sort(VRefParam arr, int64_t sort_flag /* = q_Collator$$SORT_REGULAR */) { if (!arr.isArray()) { throw_expected_array_exception(); return false; } if (!m_ucoll) { raise_warning("sort called on uninitialized Collator object"); return false; } m_errcode.clearError(); bool ret = collator_sort(arr, sort_flag, true, m_ucoll, &m_errcode); if (U_FAILURE(m_errcode.getErrorCode())) { return false; } return ret; }
static Variant f_hphp_get_iterator(VRefParam iterable, bool isMutable) { if (iterable.isArray()) { if (isMutable) { return create_object(s_MutableArrayIterator, CREATE_VECTOR1(ref(iterable))); } return create_object(s_ArrayIterator, CREATE_VECTOR1(iterable)); } if (iterable.isObject()) { ObjectData *obj = iterable.getObjectData(); Variant iterator; while (obj->instanceof(SystemLib::s_IteratorAggregateClass)) { iterator = obj->o_invoke(s_getIterator, Array()); if (!iterator.isObject()) break; obj = iterator.getObjectData(); } VM::Class*ctx = g_vmContext->getContextClass(); CStrRef context = ctx ? ctx->nameRef() : empty_string; if (isMutable) { if (obj->instanceof(SystemLib::s_IteratorClass)) { throw FatalErrorException("An iterator cannot be used for " "iteration by reference"); } Array properties = obj->o_toIterArray(context, true); return create_object(s_MutableArrayIterator, CREATE_VECTOR1(ref(properties))); } else { if (obj->instanceof(SystemLib::s_IteratorClass)) { return obj; } return create_object(s_ArrayIterator, CREATE_VECTOR1(obj->o_toIterArray(context))); } } raise_warning("Invalid argument supplied for iteration"); if (isMutable) { return create_object(s_MutableArrayIterator, CREATE_VECTOR1(Array::Create())); } return create_object(s_ArrayIterator, CREATE_VECTOR1(Array::Create())); }
bool c_Collator::t_sort(VRefParam arr, int64_t sort_flag /* = q_Collator$$SORT_REGULAR */) { if (!arr.isArray()) { throw_bad_array_exception(); return false; } if (!m_ucoll) { raise_warning("sort called on uninitialized Collator object"); return false; } m_errcode.clear(); bool ret = collator_sort(arr, sort_flag, true, m_ucoll, &(m_errcode)); s_intl_error->m_error.clear(); s_intl_error->m_error.code = m_errcode.code; s_intl_error->m_error.custom_error_message = m_errcode.custom_error_message; if (U_FAILURE(m_errcode.code)) { return false; } return ret; }
bool c_Collator::t_asort(VRefParam arr, int64 sort_flag /* = q_Collator___SORT_REGULAR */) { INSTANCE_METHOD_INJECTION_BUILTIN(Collator, Collator::asort); if (!arr.isArray()) { throw_bad_array_exception(); return false; } if (!m_ucoll) { raise_warning("asort called on uninitialized Collator object"); return false; } m_errcode.clear(); bool ret = collator_asort(arr, sort_flag, true, m_ucoll, &m_errcode); s_intl_error->m_error.clear(); s_intl_error->m_error.code = m_errcode.code; s_intl_error->m_error.custom_error_message = m_errcode.custom_error_message; if (U_FAILURE(m_errcode.code)) { return false; } return ret; }
bool c_Collator::t_sortwithsortkeys(VRefParam arr) { INSTANCE_METHOD_INJECTION_BUILTIN(Collator, Collator::sortwithsortkeys); char* sortKeyBuf = NULL; /* buffer to store sort keys */ int32_t sortKeyBufSize = DEF_SORT_KEYS_BUF_SIZE; /* buffer size */ ptrdiff_t sortKeyBufOffset = 0; /* pos in buffer to store sort key */ int32_t sortKeyLen = 0; /* the length of currently processing key */ int32_t bufLeft = 0; int32_t bufIncrement = 0; /* buffer to store 'indexes' which will be passed to 'qsort' */ collator_sort_key_index_t* sortKeyIndxBuf = NULL; int32_t sortKeyIndxBufSize = DEF_SORT_KEYS_INDX_BUF_SIZE; int32_t sortKeyIndxSize = sizeof( collator_sort_key_index_t ); int32_t sortKeyCount = 0; int32_t j = 0; /* tmp buffer to hold current processing string in utf-16 */ UChar* utf16_buf = NULL; /* the length of utf16_buf */ int utf16_buf_size = DEF_UTF16_BUF_SIZE; /* length of converted string */ int utf16_len = 0; m_errcode.clear(); s_intl_error->m_error.clear(); /* * Sort specified array. */ if (!arr.isArray()) { return true; } Array hash = arr.toArray(); if (hash.size() == 0) { return true; } /* Create bufers */ sortKeyBuf = (char*)calloc(sortKeyBufSize, sizeof(char)); sortKeyIndxBuf = (collator_sort_key_index_t*)malloc(sortKeyIndxBufSize); utf16_buf = (UChar*)malloc(utf16_buf_size); /* Iterate through input hash and create a sort key for each value. */ for (ssize_t pos = hash->iter_begin(); pos != ArrayData::invalid_index; pos = hash->iter_advance(pos)) { /* Convert current hash item from UTF-8 to UTF-16LE and save the result * to utf16_buf. */ utf16_len = utf16_buf_size; /* Process string values only. */ Variant val(hash->getValue(pos)); if (val.isString()) { String str = val.toString(); intl_convert_utf8_to_utf16(&utf16_buf, &utf16_len, str.data(), str.size(), &(m_errcode.code)); if (U_FAILURE(m_errcode.code)) { m_errcode.custom_error_message = "Sort with sort keys failed"; if (utf16_buf) { free(utf16_buf); } free(sortKeyIndxBuf); free(sortKeyBuf); return false; } } else { /* Set empty string */ utf16_len = 0; utf16_buf[utf16_len] = 0; } if ((utf16_len + 1) > utf16_buf_size) { utf16_buf_size = utf16_len + 1; } /* Get sort key, reallocating the buffer if needed. */ bufLeft = sortKeyBufSize - sortKeyBufOffset; sortKeyLen = ucol_getSortKey(m_ucoll, utf16_buf, utf16_len, (uint8_t*)sortKeyBuf + sortKeyBufOffset, bufLeft); /* check for sortKeyBuf overflow, increasing its size of the buffer if needed */ if (sortKeyLen > bufLeft) { bufIncrement = ( sortKeyLen > DEF_SORT_KEYS_BUF_INCREMENT ) ? sortKeyLen : DEF_SORT_KEYS_BUF_INCREMENT; sortKeyBufSize += bufIncrement; bufLeft += bufIncrement; sortKeyBuf = (char*)realloc(sortKeyBuf, sortKeyBufSize); sortKeyLen = ucol_getSortKey(m_ucoll, utf16_buf, utf16_len, (uint8_t*)sortKeyBuf + sortKeyBufOffset, bufLeft); } /* check sortKeyIndxBuf overflow, increasing its size of the buffer if needed */ if ((sortKeyCount + 1) * sortKeyIndxSize > sortKeyIndxBufSize) { bufIncrement = (sortKeyIndxSize > DEF_SORT_KEYS_INDX_BUF_INCREMENT) ? sortKeyIndxSize : DEF_SORT_KEYS_INDX_BUF_INCREMENT; sortKeyIndxBufSize += bufIncrement; sortKeyIndxBuf = (collator_sort_key_index_t*)realloc(sortKeyIndxBuf, sortKeyIndxBufSize); } sortKeyIndxBuf[sortKeyCount].key = (char*)sortKeyBufOffset; sortKeyIndxBuf[sortKeyCount].valPos = pos; sortKeyBufOffset += sortKeyLen; ++sortKeyCount; } /* update ptrs to point to valid keys. */ for( j = 0; j < sortKeyCount; j++ ) sortKeyIndxBuf[j].key = sortKeyBuf + (ptrdiff_t)sortKeyIndxBuf[j].key; /* sort it */ zend_qsort(sortKeyIndxBuf, sortKeyCount, sortKeyIndxSize, collator_cmp_sort_keys, NULL); /* for resulting hash we'll assign new hash keys rather then reordering */ Array sortedHash = Array::Create(); for (j = 0; j < sortKeyCount; j++) { sortedHash.append(hash->getValue(sortKeyIndxBuf[j].valPos)); } /* Save sorted hash into return variable. */ arr = sortedHash; if (utf16_buf) free(utf16_buf); free(sortKeyIndxBuf); free(sortKeyBuf); return true; }
static bool HHVM_METHOD(Collator, sortWithSortKeys, VRefParam arr) { FETCH_COL(data, this_, false); data->clearError(); if (!arr.isArray()) { return true; } Array hash = arr.toArray(); if (hash.size() == 0) { return true; } // Preallocate sort keys buffer size_t sortKeysOffset = 0; size_t sortKeysLength = DEF_SORT_KEYS_BUF_SIZE; char* sortKeys = (char*)smart_malloc(sortKeysLength); if (!sortKeys) { throw Exception("Out of memory"); } SCOPE_EXIT{ smart_free(sortKeys); }; // Preallocate index buffer size_t sortIndexPos = 0; size_t sortIndexLength = DEF_SORT_KEYS_INDX_BUF_SIZE; auto sortIndex = (collator_sort_key_index_t*)smart_malloc( sortIndexLength * sizeof(collator_sort_key_index_t)); if (!sortIndex) { throw Exception("Out of memory"); } SCOPE_EXIT{ smart_free(sortIndex); }; // Translate input hash to sortable index auto pos_limit = hash->iter_end(); for (ssize_t pos = hash->iter_begin(); pos != pos_limit; pos = hash->iter_advance(pos)) { Variant val(hash->getValue(pos)); // Convert to UTF16 icu::UnicodeString strval; if (val.isString()) { UErrorCode error = U_ZERO_ERROR; strval = u16(val.toString(), error); if (U_FAILURE(error)) { return false; } } // Generate sort key int sortkey_len = ucol_getSortKey(data->collator(), strval.getBuffer(), strval.length(), (uint8_t*)(sortKeys + sortKeysOffset), sortKeysLength - sortKeysOffset); // Check for key buffer overflow if (sortkey_len > (sortKeysLength - sortKeysOffset)) { int32_t inc = (sortkey_len > DEF_SORT_KEYS_BUF_INCREMENT) ? sortkey_len : DEF_SORT_KEYS_BUF_INCREMENT; sortKeysLength += inc; sortKeys = (char*)smart_realloc(sortKeys, sortKeysLength); if (!sortKeys) { throw Exception("Out of memory"); } sortkey_len = ucol_getSortKey(data->collator(), strval.getBuffer(), strval.length(), (uint8_t*)(sortKeys + sortKeysOffset), sortKeysLength - sortKeysOffset); assert(sortkey_len <= (sortKeysLength - sortKeysOffset)); } // Check for index buffer overflow if ((sortIndexPos + 1) > sortIndexLength) { sortIndexLength += DEF_SORT_KEYS_INDX_BUF_INCREMENT; sortIndex = (collator_sort_key_index_t*)smart_realloc(sortIndex, sortIndexLength * sizeof(collator_sort_key_index_t)); if (!sortIndex) { throw Exception("Out of memory"); } } // Initially store offset into buffer, update later to deal with reallocs sortIndex[sortIndexPos].key = (char*)sortKeysOffset; sortKeysOffset += sortkey_len; sortIndex[sortIndexPos].valPos = pos; ++sortIndexPos; } // Update keys to location in realloc'd buffer for (int i = 0; i < sortIndexPos; ++i) { sortIndex[i].key = sortKeys + (ptrdiff_t)sortIndex[i].key; } zend_qsort(sortIndex, sortIndexPos, sizeof(collator_sort_key_index_t), collator_cmp_sort_keys, nullptr); Array ret = Array::Create(); for (int i = 0; i < sortIndexPos; ++i) { ret.append(hash->getValue(sortIndex[i].valPos)); } arr = ret; return true; }