Учебник РНР
НазадГлава 34. Создание Переменных Вперёд

Массивы

Массивы хранятся с использованием внутренних хэш-таблиц Zend, доступ к которым может быть получен с помощью zend_hash_*() API. Для каждого создаваемого вами массива вам понадобится дескриптор новой хэш таблицы, который хранится в члене ht контейнера zval.value.

Имеется API, предназначенный исключительно для создания массивов.
Для создания нового массива вы вызываете array_init().
zval *new_array;

MAKE_STD_ZVAL(new_array);

if(array_init(new_array) != SUCCESS)
{
    // здесь обработка ошибок
}

Если array_init() не смогла создать новый массив, она возвращает FAILURE.

Для добавления в массив новых элементов вы можете использовать многочисленные функции, в зависимости от того, что нужно сделать. В Таблицах 9.8, 9.9 и 9.10 описаны эти функции. Все функции возвращают FAILURE при неудаче и SUCCESS при успешном выполнении.

Рисунок 34-3. Таблица 9.8. Zend's API для ассоциативных массивов
Примечание: Все функции в Таблице 9.8 работают с массивом "array" с ключом
"key". Строка ключа не должна находиться во внутренней памяти Zend;
она будет дублироваться API.

ФункцияОписание
add_assoc_long(zval *array, char *key, longn);()Добавляет элемент типа long.
add_assoc_unset(zval *array, char *key);()Добавляет unset-элемент.
add_assoc_bool(zval *array, char *key, int b);() Добавляет Булев элемент.
add_assoc_resource(zval *array, char *key,
int r);()
Добавляет ресурс к массиву.
add_assoc_double(zval *array, char *key,
double d);()
Добавляет значение с плавающей точкой.
add_assoc_string(zval *array, char *key,
char *str, int duplicate);()
Добавляет строку к массиву. Флаг duplicate специфицирует, копируется ли содержимое строки во внутреннюю память Zend.
add_assoc_stringl(zval *array, char *key,
char *str, uint length, int duplicate);()
Добавляет строку необходимого размера length к массиву. Иначе поведение как у add_assoc_string()().
Рисунок 34-4. Таблица 9.9. Zend's API для индексированных массивов , Часть 1
Примечание: Все функции в Таблице 9.9 работают с массивом "array" с индексом
"idx". Индекс - всегда integer.

ФункцияОписание
add_index_long(zval *array, uint idx, long n);()Добавляет элемент типа long.
add_index_unset(zval *array, uint idx);()Добавляет unset-элемент.
add_index_bool(zval *array, uint idx, int b);()Добавляет Булев элемент.
add_index_resource(zval *array, uint idx,
int r);()
Добавляет ресурс к массиву.
add_index_double(zval *array, uint idx,
double d);()
Добавляет значение с плавающей точкой.
add_index_string(zval *array, uint idx,
char *str, int duplicate);()
Добавляет строку к массиву. Флаг duplicate специфицирует, копируется ли содержимое строки во внутреннюю память Zend.
add_index_stringl(zval *array, uint idx,
char *str, uint length, int duplicate);()
Добавляет строку необходимого размера length к массиву. Эта функция работает быстрее и безопасна в бинарном режиме. Иначе поведение как у add_index_string()().
Рисунок 34-5. Таблица 9.10. Zend's API для индексированных массивов , Часть 2
Примечание: Все функции в Таблице 9.10 работают с массивом "array".
Эти функции автоматически генерируют новый индекс на основе наибольшего
индекса, найденного в массиве.

ФункцияОписание
add_next_index_long(zval *array, long n);()Добавляет элемент типа long.
add_next_index_unset(zval *array);()Добавляет unset-элемент.
add_next_index_bool(zval *array, int b);()Добавляет Булев элемент.
add_next_index_resource(zval *array, int r);()Добавляет ресурс к массиву.
add_next_index_double(zval *array,
double d);()
Добавляет значение с плавающей точкой.
add_next_index_string(zval *array, char *str, int duplicate);() Добавляет строку к массиву. Флаг duplicate специфицирует, копируется ли содержимое строки во внутреннюю память Zend.
add_next_index_stringl(zval *array, char *str, uint length, int duplicate);() Добавляет строку необходимого размера length к массиву. Эта функция работает быстрее и безопасна в бинарном режиме. Иначе поведение как у add_index_string()().

Все эти функции предоставляют удобную абстракцию API внутреннего хэша Zend. Разумеется, вы можете также использовать функции хэша напрямую - например, если у вас уже есть размещённый zval-контейнер, который вы хотите вставить в массив. Это делается с помощью zend_hash_update()() для ассоциативный массивов (см. Листинг 9.12) и zend_hash_index_update() - для индексированных массивов (см. Листинг 9.13):

Рисунок 34-6. Листинг 9.12. Добавление элемента в ассоциативный массив.
zval *new_array, *new_element;
char *key = "element_key";

MAKE_STD_ZVAL(new_array);
MAKE_STD_ZVAL(new_element);

if(array_init(new_array) == FAILURE)
{
    // здесь обработка ошибок
}

ZVAL_LONG(new_element, 10);

if(zend_hash_update(new_array->value.ht, key, strlen(key) + 1, (void *)&new_element, sizeof(zval *), NULL) == FAILURE)
{
    // здесь обработка ошибок
}
Рисунок 34-7. Листинг 9.13. Добавление элемента в индексированный массив.
zval *new_array, *new_element;
int key = 2;

MAKE_STD_ZVAL(new_array);
MAKE_STD_ZVAL(new_element);

if(array_init(new_array) == FAILURE)
{
    // здесь обработка ошибок
}

ZVAL_LONG(new_element, 10);

if(zend_hash_index_update(new_array->value.ht, key, (void *)&new_element, sizeof(zval *), NULL) == FAILURE)
{
    // здесь обработка ошибок
}

Для эмуляции функциональности add_next_index_*() вы можете использовать:

zend_hash_next_index_insert(ht, zval **new_element, sizeof(zval *), NULL)
Примечание: для возвращения массивов из функций используйте array_init() и все последующие акции с предопределённой переменной return_value (заданной в качестве аргумента в вашей экспортируемой функции; см. ранее обсуждение интерфейса вызова). Вы не должны использовать при этом MAKE_STD_ZVAL.

Подсказка: чтобы исключить необходимость каждый раз записывать new_array->value.ht, вы можете использовать HASH_OF(new_array), что рекомендуется также по соображениям стиля и обеспечения совместимости.


Назад Оглавление Вперёд
Booleans/Булевы Вверх Объекты