📄 array.c
字号:
**length, /* How many elements to get */ **entry; /* An array entry */ int offset_val, /* Value of the offset argument */ length_val, /* Value of the length argument */ num_in, /* Number of elements in the input array */ pos, /* Current position in the array */ argc; /* Number of function arguments */ char *string_key; uint string_key_len; ulong num_key; HashPosition hpos; /* Get the arguments and do error-checking */ argc = ZEND_NUM_ARGS(); if (argc < 2 || argc > 3 || zend_get_parameters_ex(argc, &input, &offset, &length)) { WRONG_PARAM_COUNT; } if (Z_TYPE_PP(input) != IS_ARRAY) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "The first argument should be an array"); return; } /* Make sure offset and length are integers and assume we want all entries from offset to the end if length is not passed */ convert_to_long_ex(offset); offset_val = Z_LVAL_PP(offset); if (argc == 3) { convert_to_long_ex(length); length_val = Z_LVAL_PP(length); } else { length_val = zend_hash_num_elements(Z_ARRVAL_PP(input)); } /* Initialize returned array */ array_init(return_value); /* Get number of entries in the input hash */ num_in = zend_hash_num_elements(Z_ARRVAL_PP(input)); /* Clamp the offset.. */ if (offset_val > num_in) return; else if (offset_val < 0 && (offset_val=num_in+offset_val) < 0) offset_val = 0; /* ..and the length */ if (length_val < 0) { length_val = num_in-offset_val+length_val; } else if (((unsigned) offset_val + (unsigned)length_val) > num_in) { length_val = num_in-offset_val; } if (length_val == 0) return; /* Start at the beginning and go until we hit offset */ pos = 0; zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(input), &hpos); while (pos < offset_val && zend_hash_get_current_data_ex(Z_ARRVAL_PP(input), (void **)&entry, &hpos) == SUCCESS) { pos++; zend_hash_move_forward_ex(Z_ARRVAL_PP(input), &hpos); } /* Copy elements from input array to the one that's returned */ while (pos < offset_val+length_val && zend_hash_get_current_data_ex(Z_ARRVAL_PP(input), (void **)&entry, &hpos) == SUCCESS) { (*entry)->refcount++; switch (zend_hash_get_current_key_ex(Z_ARRVAL_PP(input), &string_key, &string_key_len, &num_key, 0, &hpos)) { case HASH_KEY_IS_STRING: zend_hash_update(Z_ARRVAL_P(return_value), string_key, string_key_len, entry, sizeof(zval *), NULL); break; case HASH_KEY_IS_LONG: zend_hash_next_index_insert(Z_ARRVAL_P(return_value), entry, sizeof(zval *), NULL); break; } pos++; zend_hash_move_forward_ex(Z_ARRVAL_PP(input), &hpos); }}/* }}} */PHPAPI int php_array_merge(HashTable *dest, HashTable *src, int recursive TSRMLS_DC){ zval **src_entry, **dest_entry; char *string_key; uint string_key_len; ulong num_key; HashPosition pos; zend_hash_internal_pointer_reset_ex(src, &pos); while (zend_hash_get_current_data_ex(src, (void **)&src_entry, &pos) == SUCCESS) { switch (zend_hash_get_current_key_ex(src, &string_key, &string_key_len, &num_key, 0, &pos)) { case HASH_KEY_IS_STRING: if (recursive && zend_hash_find(dest, string_key, string_key_len, (void **)&dest_entry) == SUCCESS) { if (*src_entry == *dest_entry && ((*dest_entry)->refcount % 2)) { zend_error(E_WARNING, "%s(): recursion detected", get_active_function_name(TSRMLS_C)); return 0; } SEPARATE_ZVAL(dest_entry); SEPARATE_ZVAL(src_entry); convert_to_array_ex(dest_entry); convert_to_array_ex(src_entry); if (!php_array_merge(Z_ARRVAL_PP(dest_entry), Z_ARRVAL_PP(src_entry), recursive TSRMLS_CC)) return 0; } else { (*src_entry)->refcount++; zend_hash_update(dest, string_key, strlen(string_key)+1, src_entry, sizeof(zval *), NULL); } break; case HASH_KEY_IS_LONG: (*src_entry)->refcount++; zend_hash_next_index_insert(dest, src_entry, sizeof(zval *), NULL); break; } zend_hash_move_forward_ex(src, &pos); } return 1;}static void php_array_merge_wrapper(INTERNAL_FUNCTION_PARAMETERS, int recursive){ zval ***args = NULL; int argc, i; /* Get the argument count and check it */ argc = ZEND_NUM_ARGS(); if (argc < 1) { WRONG_PARAM_COUNT; } /* Allocate arguments array and get the arguments, checking for errors. */ args = (zval ***)safe_emalloc(sizeof(zval **), argc, 0); if (zend_get_parameters_array_ex(argc, args) == FAILURE) { efree(args); WRONG_PARAM_COUNT; } array_init(return_value); for (i=0; i<argc; i++) { SEPARATE_ZVAL(args[i]); convert_to_array_ex(args[i]); php_array_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_PP(args[i]), recursive TSRMLS_CC); } efree(args);}/* {{{ proto array array_merge(array arr1, array arr2 [, array ...]) Merges elements from passed arrays into one array */PHP_FUNCTION(array_merge){ php_array_merge_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);}/* }}} *//* {{{ proto array array_merge_recursive(array arr1, array arr2 [, array ...]) Recursively merges elements from passed arrays into one array */PHP_FUNCTION(array_merge_recursive){ php_array_merge_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);}/* }}} *//* {{{ proto array array_keys(array input [, mixed search_value]) Return just the keys from the input array, optionally only for the specified search_value */PHP_FUNCTION(array_keys){ zval **input, /* Input array */ **search_value, /* Value to search for */ **entry, /* An entry in the input array */ res, /* Result of comparison */ *new_val; /* New value */ int add_key; /* Flag to indicate whether a key should be added */ char *string_key; /* String key */ uint string_key_len; ulong num_key; /* Numeric key */ HashPosition pos; search_value = NULL; /* Get arguments and do error-checking */ if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 2 || zend_get_parameters_ex(ZEND_NUM_ARGS(), &input, &search_value) == FAILURE) { WRONG_PARAM_COUNT; } if (Z_TYPE_PP(input) != IS_ARRAY) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "The first argument should be an array"); return; } /* Initialize return array */ array_init(return_value); add_key = 1; /* Go through input array and add keys to the return array */ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(input), &pos); while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(input), (void **)&entry, &pos) == SUCCESS) { if (search_value != NULL) { is_equal_function(&res, *search_value, *entry TSRMLS_CC); add_key = zval_is_true(&res); } if (add_key) { MAKE_STD_ZVAL(new_val); switch (zend_hash_get_current_key_ex(Z_ARRVAL_PP(input), &string_key, &string_key_len, &num_key, 1, &pos)) { case HASH_KEY_IS_STRING: Z_TYPE_P(new_val) = IS_STRING; Z_STRVAL_P(new_val) = string_key; Z_STRLEN_P(new_val) = string_key_len-1; zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &new_val, sizeof(zval *), NULL); break; case HASH_KEY_IS_LONG: Z_TYPE_P(new_val) = IS_LONG; Z_LVAL_P(new_val) = num_key; zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &new_val, sizeof(zval *), NULL); break; } } zend_hash_move_forward_ex(Z_ARRVAL_PP(input), &pos); }}/* }}} *//* {{{ proto array array_values(array input) Return just the values from the input array */PHP_FUNCTION(array_values){ zval **input, /* Input array */ **entry; /* An entry in the input array */ HashPosition pos; /* Get arguments and do error-checking */ if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(ZEND_NUM_ARGS(), &input) == FAILURE) { WRONG_PARAM_COUNT; } if (Z_TYPE_PP(input) != IS_ARRAY) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array"); return; } /* Initialize return array */ array_init(return_value); /* Go through input array and add values to the return array */ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(input), &pos); while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(input), (void **)&entry, &pos) == SUCCESS) { (*entry)->refcount++; zend_hash_next_index_insert(Z_ARRVAL_P(return_value), entry, sizeof(zval *), NULL); zend_hash_move_forward_ex(Z_ARRVAL_PP(input), &pos); }}/* }}} *//* {{{ proto array array_count_values(array input) Return the value as key and the frequency of that value in input as value */PHP_FUNCTION(array_count_values){ zval **input, /* Input array */ **entry; /* An entry in the input array */ zval **tmp; HashTable *myht; HashPosition pos; /* Get arguments and do error-checking */ if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &input) == FAILURE) { WRONG_PARAM_COUNT; } if (Z_TYPE_PP(input) != IS_ARRAY) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array"); return; } /* Initialize return array */ array_init(return_value); /* Go through input array and add values to the return array */ myht = Z_ARRVAL_PP(input); zend_hash_internal_pointer_reset_ex(myht, &pos); while (zend_hash_get_current_data_ex(myht, (void **)&entry, &pos) == SUCCESS) { if (Z_TYPE_PP(entry) == IS_LONG) { if (zend_hash_index_find(Z_ARRVAL_P(return_value), Z_LVAL_PP(entry), (void**)&tmp) == FAILURE) { zval *data; MAKE_STD_ZVAL(data); Z_TYPE_P(data) = IS_LONG; Z_LVAL_P(data) = 1; zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_PP(entry), &data, sizeof(data), NULL); } else { Z_LVAL_PP(tmp)++; } } else if (Z_TYPE_PP(entry) == IS_STRING) { if (zend_hash_find(Z_ARRVAL_P(return_value), Z_STRVAL_PP(entry), Z_STRLEN_PP(entry)+1, (void**)&tmp) == FAILURE) { zval *data; MAKE_STD_ZVAL(data); Z_TYPE_P(data) = IS_LONG; Z_LVAL_P(data) = 1; zend_hash_update(Z_ARRVAL_P(return_value), Z_STRVAL_PP(entry), Z_STRLEN_PP(entry) + 1, &data, sizeof(data), NULL); } else { Z_LVAL_PP(tmp)++; } } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can only count STRING and INTEGER values!"); } zend_hash_move_forward_ex(myht, &pos); }}/* }}} *//* {{{ proto array array_reverse(array input [, bool preserve keys]) Return input as a new array with the order of the entries reversed */PHP_FUNCTION(array_reverse){ zval **input, /* Input array */ **z_preserve_keys, /* Flag: whether to preserve keys */ **entry; /* An entry in the input array */ char *string_key; uint string_key_len; ulong num_key; zend_bool preserve_keys = 0; HashPosition pos; /* Get arguments and do error-checking */ if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 2 || zend_get_parameters_ex(ZEND_NUM_ARGS(), &input, &z_preserve_keys) == FAILURE) { WRONG_PARAM_COUNT; } if (Z_TYPE_PP(input) != IS_ARRAY) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array"); return; } if (ZEND_NUM_ARGS() > 1) { convert_to_boolean_ex(z_preserve_keys); preserve_keys = Z_BVAL_PP(z_preserve_keys); } /* Initialize return array */ array_init(return_value); zend_hash_internal_pointer_end_ex(Z_ARRVAL_PP(input), &pos); while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(input), (void **)&entry, &pos) == SUCCESS) { (*entry)->refcount++; switch (zend_hash_get_current_key_ex(Z_ARRVAL_PP(input), &string_key, &string_key_len, &num_key, 0, &pos)) { case HASH_KEY_IS_STRING: zend_hash_update(Z_ARRVAL_P(return_value), string_key, string_key_len, entry, sizeof(zval *), NULL); break; case HASH_KEY_IS_LONG: if (preserve_keys) zend_hash_index_update(Z_ARRVAL_P(return_value), num_key, entry, sizeof(zval *), NULL); else zend_hash_next_index_insert(Z_ARRVAL_P(return_value), entry, sizeof(zval *), NULL); break; } zend_hash_move_backwards_ex(Z_ARRVAL_PP(input), &pos); }}/* }}} *//* {{{ proto array array_pad(array input, int pad_size, mixed pad_value) Returns a copy of input array padded with pad_value to size pad_size */PHP_FUNCTION(array_pad){ zval **input; /* Input array */ zval **pad_size; /* Size to pad to */ zval **pad_value; /* Padding value obviously */ zval ***pads; /* Array to pass to splice */ HashTable *new_hash; /* Return value from splice */ int input_size; /* Size of the input array */ int pad_size_abs; /* Absolute value of pad_size */ int num_pads; /* How many pads do we need */ int do_pad; /* Whether we should do padding at all */ int i; /* Get arguments and do error-checking */ if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &input, &pad_size, &pad_value) == FAILURE) { WRONG_PARAM_COUNT; } /* Make sure arguments are of the proper type */ if (Z_TYPE_PP(input) != IS_ARRAY) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array"); return; } convert_to_long_ex(pad_size); /* Do some initial calculations */ input_size = zend_hash_num_elements(Z_ARRVAL_PP(input)); pad_size_abs = abs(Z_LVAL_PP(pad_size)); do_pad = (input_size >= pad_size_abs) ? 0 : 1; /* Copy the original array */ *return_value = **input; zval_copy_ctor(return_value); /* If no need to pad, no need to continue */ if (!do_pad) return; /* Populate the pads array */ num_pads = pad_size_abs - input_size; if(num_pads > 1048576) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "You may only pad up to 1048576 elements at a time"); RETURN_FALSE; } pads = (zval ***)safe_emalloc(sizeof(zval **), num_pads, 0); for (i = 0; i < num_pads; i++) pads[i] = pad_value; /* Pad on the right or on the left */ if (Z_LVAL_PP(pad_size) > 0) new_hash = php_splice(Z_ARRVAL_P(return_value), input_size, 0, pads, num_pads, NULL); else new_hash = php_splice(Z_ARRVAL_P(return_value), 0, 0, pads, num_pads, NULL); /* Copy the result hash into return value */ zend_hash_destroy(Z_ARRVAL_P(return_value)); *Z_ARRVAL_P(return_value) = *new_hash; FREE_HASHTABLE(new_hash); /* Clean up */ efree(pads);}/* }}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -