package.xml0000644000076500000240000002642013065035057013435 0ustar rtheunissenstaff ds pecl.php.net Data Structures Data Structures for PHP 7 Rudi Theunissen rtheunissen rtheunissen@php.net yes Joe Watkins krakjoe krakjoe@php.net yes 2017-03-23 1.1.8 1.1.0 stable stable MIT License - PriorityQueue automatic truncate bug #78 - Bugs related to unserialization. #77 7.0.0 1.4.0b1 ds ds-1.1.8/src/ds/ds_deque.c0000644000076500000240000005307313065035057015527 0ustar rtheunissenstaff#include "../common.h" #include "../php/iterators/php_deque_iterator.h" #include "../php/handlers/php_deque_handlers.h" #include "../php/classes/php_deque_ce.h" #include "ds_deque.h" #define ds_deque_increment_head(_d) (_d)->head = ((_d)->head + 1) & ((_d)->capacity - 1) #define ds_deque_decrement_head(_d) (_d)->head = ((_d)->head - 1) & ((_d)->capacity - 1) #define ds_deque_increment_tail(_d) (_d)->tail = ((_d)->tail + 1) & ((_d)->capacity - 1) #define ds_deque_decrement_tail(_d) (_d)->tail = ((_d)->tail - 1) & ((_d)->capacity - 1) static inline void _memmove( ds_deque_t *deque, zend_long dst, zend_long src, zend_long length ) { memmove(&deque->buffer[dst], &deque->buffer[src], length * sizeof(zval)); } static zend_long ds_deque_required_capacity(zend_long n) { // We have to allocate an extra element for the tail, so a requested power // of two would need to round to the next. // n--; n |= n >> 1; n |= n >> 2; n |= n >> 4; n |= n >> 8; n |= n >> 16; return MAX(DS_DEQUE_MIN_CAPACITY, n + 1); } ds_deque_t *ds_deque() { ds_deque_t *deque = ecalloc(1, sizeof(ds_deque_t)); deque->buffer = ALLOC_ZVAL_BUFFER(DS_DEQUE_MIN_CAPACITY); deque->capacity = DS_DEQUE_MIN_CAPACITY; deque->head = 0; deque->tail = 0; deque->size = 0; return deque; } static ds_deque_t *ds_deque_from_buffer_ex( zval *buffer, zend_long size, zend_long capacity ) { ds_deque_t *deque = ecalloc(1, sizeof(ds_deque_t)); deque->buffer = buffer; deque->capacity = capacity; deque->head = 0; deque->tail = size; deque->size = size; return deque; } ds_deque_t *ds_deque_from_buffer(zval *buffer, zend_long size) { zend_long capacity = ds_deque_required_capacity(size); return ds_deque_from_buffer_ex(buffer, size, capacity); } ds_deque_t *ds_deque_clone(ds_deque_t *deque) { zval *source; zval *buffer = ALLOC_ZVAL_BUFFER(deque->capacity); zval *target = buffer; DS_DEQUE_FOREACH(deque, source) { ZVAL_COPY(target, source); target++; } DS_DEQUE_FOREACH_END(); return ds_deque_from_buffer_ex(buffer, deque->size, deque->capacity); } static inline bool ds_deque_valid_index(ds_deque_t *deque, zend_long index) { if (index < 0 || index >= deque->size) { INDEX_OUT_OF_RANGE(index, deque->size); return false; } return true; } // Makes sure that the deque's head is at index 0. void ds_deque_reset_head(ds_deque_t *deque) { if (deque->head == 0) { return; } if (deque->head < deque->tail) { _memmove(deque, 0, deque->head, deque->size); } else { zend_long h = deque->head; zend_long t = deque->tail; zend_long r = deque->capacity - h; // Number of values on the right. // Check if there's enough room to push the left partition forward and // the wrapped values (right partition) to the front. if (r < (h - t)) { _memmove(deque, r, 0, t); _memmove(deque, 0, h, r); } else { // We don't have enough temporary space to work with, so create // a new buffer, copy to it, then replace the current buffer. zval *buffer = ALLOC_ZVAL_BUFFER(deque->capacity); memcpy(&buffer[0], &deque->buffer[h], r * sizeof(zval)); memcpy(&buffer[r], &deque->buffer[0], t * sizeof(zval)); FREE_AND_REPLACE(deque->buffer, buffer); } } deque->head = 0; deque->tail = deque->size; } static void ds_deque_reallocate(ds_deque_t *deque, zend_long capacity) { ds_deque_reset_head(deque); REALLOC_ZVAL_BUFFER(deque->buffer, capacity); deque->capacity = capacity; deque->head = 0; deque->tail = deque->size; } static inline void ds_deque_double_capacity(ds_deque_t *deque) { ds_deque_reallocate(deque, deque->capacity * 2); } static inline void ds_deque_ensure_capacity(ds_deque_t *deque, zend_long size) { if (size >= deque->capacity) { ds_deque_reallocate(deque, ds_deque_required_capacity(size)); } } void ds_deque_allocate(ds_deque_t *deque, zend_long capacity) { // -1 because an extra slot will be allocated for the tail. ds_deque_ensure_capacity(deque, capacity - 1); } static inline void ds_deque_auto_truncate(ds_deque_t *deque) { // Automatically truncate if the size of the deque is less than a quarter. if (deque->size < deque->capacity / 4) { // Truncate to half the capacity, but only if greater than the minimum. if ((deque->capacity / 2) > DS_DEQUE_MIN_CAPACITY) { ds_deque_reallocate(deque, deque->capacity / 2); } } } static void ds_deque_clear_buffer(ds_deque_t *deque) { zval *value; DS_DEQUE_FOREACH(deque, value) { DTOR_AND_UNDEF(value); } DS_DEQUE_FOREACH_END(); deque->head = 0; deque->tail = 0; deque->size = 0; } void ds_deque_clear(ds_deque_t *deque) { if (deque->size > 0) { ds_deque_clear_buffer(deque); if (deque->capacity > DS_DEQUE_MIN_CAPACITY) { REALLOC_ZVAL_BUFFER(deque->buffer, DS_DEQUE_MIN_CAPACITY); deque->capacity = DS_DEQUE_MIN_CAPACITY; } } } void ds_deque_free(ds_deque_t *deque) { ds_deque_clear(deque); efree(deque->buffer); efree(deque); } /** * Translates a positional index into a buffer pointer. */ static inline zend_long ds_deque_lookup_index(ds_deque_t *deque, zend_long index) { return (deque->head + index) & (deque->capacity - 1); } /** * Translates a positional index into a buffer index. */ static inline zval *ds_deque_lookup(ds_deque_t *deque, zend_long index) { return deque->buffer + ds_deque_lookup_index(deque, index); } zval *ds_deque_get(ds_deque_t *deque, zend_long index) { if ( ! ds_deque_valid_index(deque, index)) { return NULL; } return ds_deque_lookup(deque, index); } void ds_deque_set(ds_deque_t *deque, zend_long index, zval *value) { if (ds_deque_valid_index(deque, index)) { zval *ptr = ds_deque_lookup(deque, index); zval_ptr_dtor(ptr); ZVAL_COPY(ptr, value); } } void ds_deque_reverse(ds_deque_t *deque) { if (deque->head < deque->tail) { ds_reverse_zval_range( deque->buffer + deque->head, deque->buffer + deque->tail ); } else { zend_long head = deque->head; zend_long tail = deque->tail; zend_long mask = deque->capacity - 1; while (head != tail) { tail = (tail - 1) & mask; SWAP_ZVAL( deque->buffer[head], deque->buffer[tail] ); head = (head + 1) & mask; } } } ds_deque_t *ds_deque_reversed(ds_deque_t *deque) { zval *src; zval *buf = ALLOC_ZVAL_BUFFER(deque->capacity); zval *dst = &buf[deque->size - 1]; DS_DEQUE_FOREACH(deque, src) { ZVAL_COPY(dst, src); dst--; } DS_DEQUE_FOREACH_END(); return ds_deque_from_buffer_ex(buf, deque->size, deque->capacity); } void ds_deque_shift(ds_deque_t *deque, zval *return_value) { SET_AS_RETURN_AND_UNDEF(&deque->buffer[deque->head]); ds_deque_increment_head(deque); deque->size--; ds_deque_auto_truncate(deque); } void ds_deque_shift_throw(ds_deque_t *deque, zval *return_value) { if (deque->size == 0) { NOT_ALLOWED_WHEN_EMPTY(); return; } ds_deque_shift(deque, return_value); } void ds_deque_pop(ds_deque_t *deque, zval *return_value) { ds_deque_decrement_tail(deque); SET_AS_RETURN_AND_UNDEF(&deque->buffer[deque->tail]); deque->size--; ds_deque_auto_truncate(deque); } void ds_deque_pop_throw(ds_deque_t *deque, zval *return_value) { if (deque->size == 0) { NOT_ALLOWED_WHEN_EMPTY(); return; } ds_deque_pop(deque, return_value); } void ds_deque_remove(ds_deque_t *deque, zend_long index, zval *return_value) { if ( ! ds_deque_valid_index(deque, index)) { return; } // Basic shift if it's the first element in the sequence. if (index == 0) { ds_deque_shift(deque, return_value); return; } // Basic pop if it's the last element in the sequence. if (index == deque->size - 1) { ds_deque_pop(deque, return_value); return; } // Translate the positional index to a buffer index. index = ds_deque_lookup_index(deque, index); // Copy the value into the return value, then destruct. SET_AS_RETURN_AND_UNDEF(&deque->buffer[index]); if (index < deque->tail) { // Shift all values between the index and the tail. _memmove(deque, index, index + 1, deque->tail - index); deque->tail--; } else { // Index comes after tail, and we know at this point that the index // is valid, so it must be after the head which has wrapped around. // Unshift all values between the head and the index. _memmove(deque, deque->head + 1, deque->head, index - deque->head); deque->head++; } deque->size--; ds_deque_auto_truncate(deque); } void ds_deque_unshift_va(ds_deque_t *deque, VA_PARAMS) { ds_deque_ensure_capacity(deque, deque->size + argc); deque->size += argc; while (argc--) { ds_deque_decrement_head(deque); ZVAL_COPY(&deque->buffer[deque->head], &argv[argc]); } } void ds_deque_push(ds_deque_t *deque, zval *value) { ZVAL_COPY(&deque->buffer[deque->tail], value); ds_deque_increment_tail(deque); if ((++deque->size) == deque->capacity) { ds_deque_double_capacity(deque); } } void ds_deque_push_va(ds_deque_t *deque, VA_PARAMS) { ds_deque_ensure_capacity(deque, deque->size + argc); while (argc--) { ZVAL_COPY(&deque->buffer[deque->tail], argv++); ds_deque_increment_tail(deque); deque->size++; } } static void _ds_deque_insert_va(ds_deque_t *deque, zend_long position, VA_PARAMS) { zval *dst; zend_long index; // No op if no values. if (argc <= 0) { return; } // Make sure that we have enough room for the new values. ds_deque_ensure_capacity(deque, deque->size + argc); // Translate the positional index to a buffer index. index = ds_deque_lookup_index(deque, position); if (index <= deque->tail) { // The deque is either contiguous or we're inserting in between the // start of the buffer and the tail, where the head has wrapped around. // Check for overflow, which is possible because the head won't // always be at the start of the buffer. if ((deque->tail + argc) > deque->capacity) { // There isn't enough free space to the right of the tail, // so move the entire sequence all the way to the left. _memmove(deque, 0, deque->head, deque->size); index -= deque->head; deque->head = 0; deque->tail = deque->size; } // Move the subsequence after the insertion point to the right // to make room for the new values. _memmove(deque, (index + argc), index, (deque->tail - index)); deque->tail += argc; dst = &deque->buffer[index]; } else { // We're inserting between a wrapped around head and the end of the // buffer, and it's guaranteed that there's enough free space. _memmove(deque, (deque->head - argc), deque->head, (index - deque->head)); deque->head -= argc; dst = &deque->buffer[index - argc]; } deque->size += argc; // Copy the new values into place. while (argc--) { ZVAL_COPY(dst++, argv++); } } void ds_deque_insert_va(ds_deque_t *deque, zend_long position, VA_PARAMS) { // Basic push if inserting at the back. if (position == deque->size) { ds_deque_push_va(deque, VA_ARGS); return; } // Basic unshift if inserting at the front. if (position == 0) { ds_deque_unshift_va(deque, VA_ARGS); return; } if (ds_deque_valid_index(deque, position)) { _ds_deque_insert_va(deque, position, VA_ARGS); } } static zend_long ds_deque_find_index(ds_deque_t *deque, zval *value) { zend_long head = deque->head; zend_long mask = deque->capacity - 1; zend_long index; for (index = 0; index < deque->size; index++, head++) { if (zend_is_identical(value, &deque->buffer[head & mask])) { return index; } } return FAILURE; } void ds_deque_join(ds_deque_t *deque, char *str, size_t len, zval *return_value) { ds_deque_reset_head(deque); ZVAL_STR( return_value, ds_join_zval_buffer(deque->buffer, deque->size, str, len) ); } void ds_deque_find(ds_deque_t *deque, zval *value, zval *return_value) { zend_long index = ds_deque_find_index(deque, value); if (index >= 0) { ZVAL_LONG(return_value, index); } else { ZVAL_FALSE(return_value); } } bool ds_deque_contains_va(ds_deque_t *deque, VA_PARAMS) { while (argc-- > 0) { if (ds_deque_find_index(deque, argv++) == FAILURE) { return false; } } return true; } void ds_deque_rotate(ds_deque_t *deque, zend_long n) { if (deque->size < 2) { return; } if (n < 0) { for (n = llabs(n) % deque->size; n > 0; n--) { // Pop, unshift ds_deque_decrement_head(deque); ds_deque_decrement_tail(deque); // Tail is now at last value, head is before the first. SWAP_ZVAL(deque->buffer[deque->tail], deque->buffer[deque->head]); } } else if (n > 0) { for (n = n % deque->size; n > 0; n--) { // Tail is one past the last value, head is at first value. SWAP_ZVAL(deque->buffer[deque->tail], deque->buffer[deque->head]); // Shift, push ds_deque_increment_head(deque); ds_deque_increment_tail(deque); } } } void ds_deque_to_array(ds_deque_t *deque, zval *array) { if (deque->size == 0) { array_init(array); return; } else { zval *value; array_init_size(array, deque->size); DS_DEQUE_FOREACH(deque, value) { add_next_index_zval(array, value); Z_TRY_ADDREF_P(value); } DS_DEQUE_FOREACH_END(); } } int ds_deque_index_exists(ds_deque_t *deque, zend_long index) { return index >= 0 && index < deque->size; } bool ds_deque_isset(ds_deque_t *deque, zend_long index, int check_empty) { if (index < 0 || index >= deque->size) { return false; } return ds_zval_isset(ds_deque_lookup(deque, index), check_empty); } zval *ds_deque_get_last(ds_deque_t *deque) { return &deque->buffer[(deque->tail - 1) & (deque->capacity - 1)]; } zval *ds_deque_get_last_throw(ds_deque_t *deque) { if (deque->size == 0) { NOT_ALLOWED_WHEN_EMPTY(); return NULL; } return ds_deque_get_last(deque); } zval *ds_deque_get_first(ds_deque_t *deque) { return &deque->buffer[deque->head]; } zval *ds_deque_get_first_throw(ds_deque_t *deque) { if (deque->size == 0) { NOT_ALLOWED_WHEN_EMPTY(); return NULL; } return ds_deque_get_first(deque); } static int iterator_add(zend_object_iterator *iterator, void *puser) { ds_deque_push((ds_deque_t *) puser, iterator->funcs->get_current_data(iterator)); return ZEND_HASH_APPLY_KEEP; } static void add_traversable_to_deque(ds_deque_t *deque, zval *obj) { spl_iterator_apply(obj, iterator_add, deque); } static void add_array_to_deque(ds_deque_t *deque, HashTable *arr) { zval *value; ZEND_HASH_FOREACH_VAL(arr, value) { ds_deque_push(deque, value); } ZEND_HASH_FOREACH_END(); } void ds_deque_push_all(ds_deque_t *deque, zval *values) { if ( ! values) { return; } if (ds_is_array(values)) { add_array_to_deque(deque, Z_ARRVAL_P(values)); return; } if (ds_is_traversable(values)) { add_traversable_to_deque(deque, values); return; } ARRAY_OR_TRAVERSABLE_REQUIRED(); } ds_deque_t *ds_deque_merge(ds_deque_t *deque, zval *values) { if (values && (ds_is_array(values) || ds_is_traversable(values))) { ds_deque_t *merged = ds_deque_clone(deque); ds_deque_push_all(merged, values); return merged; } ARRAY_OR_TRAVERSABLE_REQUIRED(); return NULL; } void ds_deque_sort_callback(ds_deque_t *deque) { ds_deque_reset_head(deque); ds_user_sort_zval_buffer(deque->buffer, deque->size); } void ds_deque_sort(ds_deque_t *deque) { ds_deque_reset_head(deque); ds_sort_zval_buffer(deque->buffer, deque->size); } void ds_deque_apply(ds_deque_t *deque, FCI_PARAMS) { zval *value; zval retval; DS_DEQUE_FOREACH(deque, value) { fci.param_count = 1; fci.params = value; fci.retval = &retval; if (zend_call_function(&fci, &fci_cache) == FAILURE || Z_ISUNDEF(retval)) { return; } zval_ptr_dtor(value); ZVAL_COPY_VALUE(value, &retval); } DS_DEQUE_FOREACH_END(); } ds_deque_t *ds_deque_map(ds_deque_t *deque, FCI_PARAMS) { zval retval; zval *value; zval *buffer = ALLOC_ZVAL_BUFFER(deque->capacity); zval *target = buffer; DS_DEQUE_FOREACH(deque, value) { fci.param_count = 1; fci.params = value; fci.retval = &retval; if (zend_call_function(&fci, &fci_cache) == FAILURE || Z_ISUNDEF(retval)) { // Release the values copied into the buffer on failure. for (; target > buffer; target--) { zval_ptr_dtor(target - 1); } zval_ptr_dtor(&retval); efree(buffer); return NULL; } ZVAL_COPY(target++, &retval); zval_ptr_dtor(&retval); } DS_DEQUE_FOREACH_END(); return ds_deque_from_buffer_ex(buffer, deque->size, deque->capacity); } ds_deque_t *ds_deque_filter_callback(ds_deque_t *deque, FCI_PARAMS) { if (deque->size == 0) { return ds_deque(); } else { zval retval; zval *value; zval *buffer = ALLOC_ZVAL_BUFFER(deque->capacity); zval *target = buffer; DS_DEQUE_FOREACH(deque, value) { fci.param_count = 1; fci.params = value; fci.retval = &retval; // Catch potential exceptions or other errors during comparison. if (zend_call_function(&fci, &fci_cache) == FAILURE || Z_ISUNDEF(retval)) { // Release the values copied into the buffer on failure. for (; target > buffer; target--) { zval_ptr_dtor(target - 1); } zval_ptr_dtor(&retval); efree(buffer); return NULL; } // Copy the value into the buffer if the callback returned true. if (zend_is_true(&retval)) { ZVAL_COPY(target++, value); } zval_ptr_dtor(&retval); } DS_DEQUE_FOREACH_END(); return ds_deque_from_buffer(buffer, target - buffer); } } ds_deque_t *ds_deque_filter(ds_deque_t *deque) { if (deque->size == 0) { return ds_deque(); } else { zval *buf = ALLOC_ZVAL_BUFFER(deque->capacity); zval *dst = buf; zval *src = NULL; DS_DEQUE_FOREACH(deque, src) { if (zend_is_true(src)) { ZVAL_COPY(dst++, src); } } DS_DEQUE_FOREACH_END(); return ds_deque_from_buffer(buf, dst - buf); } } void ds_deque_reduce(ds_deque_t *deque, zval *initial, zval *return_value, FCI_PARAMS) { zval *value; zval carry; zval params[2]; if (initial == NULL) { ZVAL_NULL(&carry); } else { ZVAL_COPY_VALUE(&carry, initial); } DS_DEQUE_FOREACH(deque, value) { ZVAL_COPY_VALUE(¶ms[0], &carry); ZVAL_COPY_VALUE(¶ms[1], value); fci.param_count = 2; fci.params = params; fci.retval = &carry; if (zend_call_function(&fci, &fci_cache) == FAILURE || Z_ISUNDEF(carry)) { zval_ptr_dtor(&carry); ZVAL_NULL(return_value); return; } Z_TRY_DELREF_P(&carry); } DS_DEQUE_FOREACH_END(); ZVAL_COPY(return_value, &carry); } ds_deque_t *ds_deque_slice(ds_deque_t *deque, zend_long index, zend_long length) { ds_normalize_slice_args(&index, &length, deque->size); if (length == 0) { return ds_deque(); } else { zend_long capacity = ds_deque_required_capacity(length); zval *buffer = ALLOC_ZVAL_BUFFER(capacity); zval *src = deque->buffer; // Read from the source deque's buffer zval *dst = buffer; // Pointer to allocated destination buffer zval *end = buffer + length; // Position at which to stop writing. // If the head comes before the tail, we don't need to mod because we // know that no values have wrapped around the end of the buffer. if (deque->head < deque->tail) { src += deque->head + index; for (; dst != end; ++src, ++dst) { ZVAL_COPY(dst, src); } } else { zend_long mask = capacity - 1; zend_long head = deque->head + index; for (; dst != end; ++head, ++dst) { ZVAL_COPY(dst, &src[head & mask]); } } return ds_deque_from_buffer_ex(buffer, length, capacity); } } void ds_deque_sum(ds_deque_t *deque, zval *return_value) { zval *value; ZVAL_LONG(return_value, 0); DS_DEQUE_FOREACH(deque, value) { DS_ADD_TO_SUM(value, return_value); } DS_DEQUE_FOREACH_END(); } ds-1.1.8/src/ds/ds_deque.h0000644000076500000240000000653413065035057015534 0ustar rtheunissenstaff#ifndef DS_DEQUE_H #define DS_DEQUE_H #include "../common.h" #define DS_DEQUE_MIN_CAPACITY 8 // Must be a power of 2 #define DS_DEQUE_SIZE(d) ((d)->size) #define DS_DEQUE_IS_EMPTY(d) ((d)->size == 0) #define DS_DEQUE_FOREACH(_d, _v) \ do { \ ds_deque_t *_deque = _d; \ zval *_buffer = _deque->buffer; \ zend_long _tail = _deque->tail; \ zend_long _mask = _deque->capacity - 1; \ zend_long _head = _deque->head; \ \ for (; _head != _tail; _head = (_head + 1) & _mask) { \ _v = _buffer + _head; #define DS_DEQUE_FOREACH_END() \ } \ } while (0) typedef struct _ds_deque_t { zval *buffer; zend_long capacity; zend_long head; zend_long tail; zend_long size; } ds_deque_t; ds_deque_t *ds_deque(); ds_deque_t *ds_deque_ex(zend_long capacity); ds_deque_t *ds_deque_clone(ds_deque_t *src); ds_deque_t *ds_deque_from_buffer(zval *buffer, zend_long size); void ds_deque_clear(ds_deque_t *deque); void ds_deque_free(ds_deque_t *deque); void ds_deque_allocate(ds_deque_t *deque, zend_long capacity); void ds_deque_reset_head(ds_deque_t *deque); void ds_deque_push(ds_deque_t *deque, zval *value); void ds_deque_push_va(ds_deque_t *deque, VA_PARAMS); void ds_deque_push_all(ds_deque_t *deque, zval *values); void ds_deque_set(ds_deque_t *deque, zend_long index, zval *value); void ds_deque_pop(ds_deque_t *deque, zval *return_value); void ds_deque_pop_throw(ds_deque_t *deque, zval *return_value); void ds_deque_shift(ds_deque_t *deque, zval *return_value); void ds_deque_shift_throw(ds_deque_t *deque, zval *return_value); void ds_deque_find(ds_deque_t *deque, zval *value, zval *return_value); void ds_deque_remove(ds_deque_t *deque, zend_long index, zval *return_value); void ds_deque_insert_va(ds_deque_t *deque, zend_long index, VA_PARAMS); void ds_deque_unshift_va(ds_deque_t *deque, VA_PARAMS); zval *ds_deque_get(ds_deque_t *deque, zend_long index); zval *ds_deque_get_last(ds_deque_t *deque); zval *ds_deque_get_last_throw(ds_deque_t *deque); zval *ds_deque_get_first(ds_deque_t *deque); zval *ds_deque_get_first_throw(ds_deque_t *deque); bool ds_deque_contains_va(ds_deque_t *deque, VA_PARAMS); bool ds_deque_isset(ds_deque_t *deque, zend_long index, int check_empty); ds_deque_t *ds_deque_map(ds_deque_t *deque, FCI_PARAMS); ds_deque_t *ds_deque_filter(ds_deque_t *deque); ds_deque_t *ds_deque_filter_callback(ds_deque_t *deque, FCI_PARAMS); ds_deque_t *ds_deque_slice(ds_deque_t *deque, zend_long index, zend_long length); ds_deque_t *ds_deque_merge(ds_deque_t *deque, zval *values); ds_deque_t *ds_deque_reversed(ds_deque_t *deque); void ds_deque_join(ds_deque_t *deque, char *str, size_t len, zval *return_value); void ds_deque_reduce(ds_deque_t *deque, zval *initial, zval *return_value, FCI_PARAMS); void ds_deque_rotate(ds_deque_t *deque, zend_long rotations); void ds_deque_sort_callback(ds_deque_t *deque); void ds_deque_sort(ds_deque_t *deque); void ds_deque_reverse(ds_deque_t *deque); void ds_deque_to_array(ds_deque_t *deque, zval *return_value); void ds_deque_apply(ds_deque_t *deque, FCI_PARAMS); void ds_deque_sum(ds_deque_t *deque, zval *return_value); #endif ds-1.1.8/src/ds/ds_htable.c0000644000076500000240000007541213065035057015664 0ustar rtheunissenstaff#include "../common.h" #include "ds_pair.h" #include "ds_htable.h" #include "ds_set.h" #include "ds_vector.h" #include "../php/classes/php_hashable_ce.h" static uint32_t next_power_of_2(uint32_t size) { uint32_t c = MAX(size, DS_HTABLE_MIN_CAPACITY); c--; c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8; c |= c >> 16; c++; return c; } static inline ds_htable_bucket_t *ds_htable_allocate_buckets(uint32_t capacity) { return ecalloc(capacity, sizeof(ds_htable_bucket_t)); } static inline ds_htable_bucket_t *ds_htable_reallocate_buckets(ds_htable_t *table, uint32_t capacity) { return erealloc(table->buckets, capacity * sizeof(ds_htable_bucket_t)); } static inline uint32_t *ds_htable_allocate_lookup(uint32_t capacity) { return emalloc(capacity * sizeof(uint32_t)); } static inline uint32_t *ds_htable_reallocate_lookup(uint32_t *lookup, uint32_t capacity) { return erealloc(lookup, capacity * sizeof(uint32_t)); } static inline void ds_htable_reset_lookup(ds_htable_t *table) { memset(table->lookup, DS_HTABLE_INVALID_INDEX, table->capacity * sizeof(uint32_t)); } static inline void ds_htable_realloc(ds_htable_t *table, uint32_t capacity) { table->buckets = ds_htable_reallocate_buckets(table, capacity); table->lookup = ds_htable_reallocate_lookup(table->lookup, capacity); table->capacity = capacity; } static void ds_htable_rehash(ds_htable_t *table) { const uint32_t mask = table->capacity - 1; ds_htable_reset_lookup(table); // Rehash removes all deleted buckets, so we can reset min deleted. table->min_deleted = table->capacity; // No need to rehash if the table is empty. if (table->size == 0) { table->next = 0; return; } else { uint32_t index = 0; ds_htable_bucket_t *bucket = table->buckets; if (DS_HTABLE_IS_PACKED(table)) { // No deleted buckets do { DS_HTABLE_BUCKET_REHASH(table, bucket, mask, index); bucket++; } while (++index < table->next); } else { // There are deleted buckets do { if (DS_HTABLE_BUCKET_DELETED(bucket)) { uint32_t j = index; ds_htable_bucket_t *q = bucket; while (++index < table->next) { if ( ! DS_HTABLE_BUCKET_DELETED(++bucket)) { *q = *bucket; DS_HTABLE_BUCKET_REHASH(table, q, mask, j); q++; j++; } } table->next = j; break; } DS_HTABLE_BUCKET_REHASH(table, bucket, mask, index); bucket++; } while (++index < table->next); } } } static void ds_htable_pack(ds_htable_t *table) { if ( ! DS_HTABLE_IS_PACKED(table)) { ds_htable_bucket_t *end = table->buckets + table->next; ds_htable_bucket_t *src = table->buckets + table->min_deleted; ds_htable_bucket_t *dst = src; while (++src != end) { if ( ! DS_HTABLE_BUCKET_DELETED(src)) { if (dst != src) *dst = *src; dst++; } } table->next = table->size; table->min_deleted = table->capacity; } } static inline void ds_htable_auto_truncate(ds_htable_t *table) { const uint32_t capacity = table->capacity; if (table->size <= capacity / 4 && capacity > DS_HTABLE_MIN_CAPACITY) { ds_htable_pack(table); ds_htable_realloc(table, capacity / 2); ds_htable_rehash(table); } } ds_htable_t *ds_htable_ex(uint32_t capacity) { ds_htable_t *table = ecalloc(1, sizeof(ds_htable_t)); table->buckets = ds_htable_allocate_buckets(capacity); table->lookup = ds_htable_allocate_lookup(capacity); table->capacity = capacity; table->min_deleted = capacity; table->size = 0; table->next = 0; ds_htable_reset_lookup(table); return table; } ds_htable_t *ds_htable() { return ds_htable_ex(DS_HTABLE_MIN_CAPACITY); } static void ds_htable_copy(ds_htable_t *_src, ds_htable_t *_dst) { ds_htable_bucket_t *src = _src->buckets; ds_htable_bucket_t *end = _src->buckets + _src->next; ds_htable_bucket_t *dst = _dst->buckets; memcpy(_dst->lookup, _src->lookup, _src->capacity * sizeof(uint32_t)); for (; src != end; ++src, ++dst) { if ( ! DS_HTABLE_BUCKET_DELETED(src)) { DS_HTABLE_BUCKET_COPY(dst, src); } else { DS_HTABLE_BUCKET_DELETE(dst); } } } ds_htable_t *ds_htable_clone(ds_htable_t *src) { ds_htable_t *dst = ecalloc(1, sizeof(ds_htable_t)); dst->buckets = ds_htable_allocate_buckets(src->capacity); dst->lookup = ds_htable_allocate_lookup(src->capacity); dst->capacity = src->capacity; dst->size = src->size; dst->next = src->next; dst->min_deleted = src->min_deleted; ds_htable_copy(src, dst); return dst; } static inline bool implements_hashable(zval *key) { return instanceof_function(Z_OBJCE_P(key), hashable_ce); } static inline bool user_hashable_equals(zval *a, zval *b) { if (Z_OBJCE_P(a) != Z_OBJCE_P(b)) { return false; } else { zval equals; zend_call_method_with_1_params(a, Z_OBJCE_P(a), NULL, "equals", &equals, b); return Z_TYPE(equals) == IS_TRUE; } } static inline bool key_is_identical(zval *a, zval *b) { if (Z_TYPE_P(a) == IS_OBJECT && implements_hashable(a)) { return Z_TYPE_P(b) == IS_OBJECT && user_hashable_equals(a, b); } return zend_is_identical(a, b); } static inline bool ds_htable_bucket_key_match(ds_htable_bucket_t *bucket, zval *key) { return key_is_identical(&bucket->key, key); } static inline uint32_t get_string_hash(zend_string *str) { return ZSTR_HASH(str); } static inline uint32_t get_string_zval_hash(zval *value) { return get_string_hash(Z_STR_P(value)); } static uint32_t get_array_hash(zval *arr) { uint32_t hash; php_serialize_data_t var_hash; smart_str buffer = {0}; PHP_VAR_SERIALIZE_INIT(var_hash); php_var_serialize(&buffer, arr, &var_hash); PHP_VAR_SERIALIZE_DESTROY(var_hash); smart_str_0(&buffer); if (buffer.s) { hash = get_string_hash(buffer.s); zend_string_free(buffer.s); } else { hash = 0; } return hash; } static inline uint32_t get_spl_object_hash(zval *obj) { zend_string *s = php_spl_object_hash(obj); uint32_t hash = get_string_hash(s); zend_string_free(s); return hash; } static inline uint32_t get_resource_hash(zval *resource) { return Z_RES_HANDLE_P(resource); } static uint32_t get_object_hash(zval *obj) { if (implements_hashable(obj)) { zval hash; zend_call_method_with_0_params(obj, Z_OBJCE_P(obj), NULL, "hash", &hash); switch (Z_TYPE(hash)) { case IS_LONG: return Z_LVAL(hash); case IS_DOUBLE: return zval_get_long(&hash); case IS_STRING: return get_string_zval_hash(&hash); case IS_TRUE: return 1; case IS_FALSE: case IS_NULL: return 0; default: OBJ_HASH_MUST_BE_SCALAR(&hash); return 0; } } // Not instance of Hashable, so use spl_object_hash return get_spl_object_hash(obj); } static uint32_t get_hash(zval *value) { switch (Z_TYPE_P(value)) { case IS_LONG: return Z_LVAL_P(value); case IS_DOUBLE: return zval_get_long(value); case IS_STRING: return get_string_zval_hash(value); case IS_TRUE: return 1; case IS_FALSE: case IS_NULL: return 0; case IS_OBJECT: return get_object_hash(value); case IS_ARRAY: return get_array_hash(value); case IS_RESOURCE: return get_resource_hash(value); case IS_REFERENCE: return get_hash(Z_REFVAL_P(value)); default: return 0; } } static ds_htable_bucket_t *ds_htable_lookup_bucket_by_hash( ds_htable_t *table, zval *key, const uint32_t hash ) { ds_htable_bucket_t *bucket; uint32_t index; // Begin by finding the start of the collision chain by using the lookup // array and the hash to determine the first bucket's buffer index. // Follow the chain until the next bucket in the chain is invalid. for ( index = DS_HTABLE_BUCKET_LOOKUP(table, hash); index != DS_HTABLE_INVALID_INDEX; index = DS_HTABLE_BUCKET_NEXT(bucket) ) { bucket = &table->buckets[index]; if (DS_HTABLE_BUCKET_HASH(bucket) == hash) { if (ds_htable_bucket_key_match(bucket, key)) { return bucket; } } } return NULL; } ds_htable_bucket_t *ds_htable_lookup_by_key(ds_htable_t *table, zval *key) { return ds_htable_lookup_bucket_by_hash(table, key, get_hash(key)); } ds_htable_bucket_t *ds_htable_lookup_by_position(ds_htable_t *table, uint32_t position) { if (table->size == 0 || position >= table->size) { return NULL; } else if (DS_HTABLE_IS_PACKED(table) || position < table->min_deleted) { return &table->buckets[position]; } else { ds_htable_bucket_t *bucket; uint32_t index; // Determine from which end to traverse the buffer if (position > table->size / 2) { // Start at the back index = table->size - 1; DS_HTABLE_FOREACH_BUCKET_REVERSED(table, bucket) { if (index-- == position) { return bucket; } } DS_HTABLE_FOREACH_END(); } else { // Start at the front index = 0; DS_HTABLE_FOREACH_BUCKET(table, bucket) { if (index++ == position) { return bucket; } } DS_HTABLE_FOREACH_END(); } } return NULL; } ds_htable_bucket_t *ds_htable_lookup_by_value(ds_htable_t *table, zval *value) { ds_htable_bucket_t *bucket; DS_HTABLE_FOREACH_BUCKET(table, bucket) { if (zend_is_identical(value, &bucket->value)) { return bucket; } } DS_HTABLE_FOREACH_END(); return NULL; } bool ds_htable_isset(ds_htable_t *table, zval *key, bool check_empty) { ds_htable_bucket_t *bucket = ds_htable_lookup_by_key(table, key); return bucket && ds_zval_isset(&bucket->value, check_empty); } zval *ds_htable_get(ds_htable_t *table, zval *key) { ds_htable_bucket_t *bucket = ds_htable_lookup_by_key(table, key); return bucket ? &bucket->value : NULL; } bool ds_htable_has_key(ds_htable_t *table, zval *key) { return ds_htable_lookup_by_key(table, key) != NULL; } bool ds_htable_has_keys(ds_htable_t *table, VA_PARAMS) { while (argc-- > 0) { if ( ! ds_htable_has_key(table, argv++)) { return false; } } return true; } bool ds_htable_has_value(ds_htable_t *table, zval *value) { return ds_htable_lookup_by_value(table, value) != NULL; } bool ds_htable_has_values(ds_htable_t *table, VA_PARAMS) { while (argc-- > 0) { if ( ! ds_htable_lookup_by_value(table, argv++)) { return false; } } return true; } static void ds_htable_clear_buffer(ds_htable_t *table) { ds_htable_bucket_t *bucket; if (table->size == 0) { return; } DS_HTABLE_FOREACH_BUCKET(table, bucket) { DS_HTABLE_BUCKET_DELETE(bucket); } DS_HTABLE_FOREACH_END(); table->size = 0; table->next = 0; table->min_deleted = table->capacity; } void ds_htable_clear(ds_htable_t *table) { ds_htable_clear_buffer(table); if (table->capacity > DS_HTABLE_MIN_CAPACITY) { ds_htable_realloc(table, DS_HTABLE_MIN_CAPACITY); } table->min_deleted = table->capacity; } void ds_htable_free(ds_htable_t *table) { ds_htable_clear_buffer(table); efree(table->buckets); efree(table->lookup); efree(table); } static inline void ds_htable_sort_ex(ds_htable_t *table, compare_func_t compare_func) { ds_htable_pack(table); qsort(table->buckets, table->size, sizeof(ds_htable_bucket_t), compare_func); ds_htable_rehash(table); } void ds_htable_sort(ds_htable_t *table, compare_func_t compare_func) { ds_htable_sort_ex(table, compare_func); } static int user_compare_by_value(const void *a, const void *b) { zval params[2]; zval retval; ds_htable_bucket_t *x = ((ds_htable_bucket_t*)a); ds_htable_bucket_t *y = ((ds_htable_bucket_t*)b); ZVAL_COPY_VALUE(¶ms[0], &x->value); ZVAL_COPY_VALUE(¶ms[1], &y->value); DSG(user_compare_fci).param_count = 2; DSG(user_compare_fci).params = params; DSG(user_compare_fci).retval = &retval; if (zend_call_function(&DSG(user_compare_fci), &DSG(user_compare_fci_cache)) == SUCCESS) { return zval_get_long(&retval); } return 0; } static int user_compare_by_key(const void *a, const void *b) { zval params[2]; zval retval; ZVAL_COPY_VALUE(¶ms[0], (zval*) a); ZVAL_COPY_VALUE(¶ms[1], (zval*) b); DSG(user_compare_fci).param_count = 2; DSG(user_compare_fci).params = params; DSG(user_compare_fci).retval = &retval; if (zend_call_function(&DSG(user_compare_fci), &DSG(user_compare_fci_cache)) == SUCCESS) { return zval_get_long(&retval); } return 0; } static int compare_by_key(const void *a, const void *b) { zval retval; if (compare_function(&retval, (zval*) a, (zval*) b) == SUCCESS) { return zval_get_long(&retval); } return 0; } static int compare_by_value(const void *a, const void *b) { zval retval; ds_htable_bucket_t *x = (ds_htable_bucket_t*) a; ds_htable_bucket_t *y = (ds_htable_bucket_t*) b; if (compare_function(&retval, &x->value, &y->value) == SUCCESS) { return zval_get_long(&retval); } return 0; } void ds_htable_sort_by_key(ds_htable_t *table) { ds_htable_sort(table, compare_by_key); } void ds_htable_sort_by_value(ds_htable_t *table) { ds_htable_sort(table, compare_by_value); } void ds_htable_sort_callback_by_key(ds_htable_t *table) { ds_htable_sort(table, user_compare_by_key); } void ds_htable_sort_callback_by_value(ds_htable_t *table) { ds_htable_sort(table, user_compare_by_value); } static inline void ds_htable_increase_capacity(ds_htable_t *table) { if (table->next > table->size + (table->size >> 5)) { ds_htable_rehash(table); return; } ds_htable_realloc(table, table->capacity << 1); ds_htable_rehash(table); } void ds_htable_ensure_capacity(ds_htable_t *table, uint32_t capacity) { if (capacity > table->capacity) { ds_htable_realloc(table, next_power_of_2(capacity)); ds_htable_rehash(table); } } /** * Adds a bucket to the table knowing that its key doesn't already exist. */ static void ds_htable_put_distinct_bucket(ds_htable_t *table, ds_htable_bucket_t *bucket) { ds_htable_bucket_t *next = &table->buckets[table->next]; DS_HTABLE_BUCKET_COPY(next, bucket); DS_HTABLE_BUCKET_REHASH(table, next, table->capacity - 1, table->next); table->next++; table->size++; if (table->next == table->capacity) { ds_htable_increase_capacity(table); } } static ds_htable_bucket_t *ds_htable_init_next_bucket( ds_htable_t *table, zval *key, zval *value, const uint32_t hash ) { ds_htable_bucket_t *bucket = &table->buckets[table->next]; DS_HTABLE_BUCKET_HASH(bucket) = hash; DS_HTABLE_BUCKET_REHASH(table, bucket, table->capacity - 1, table->next); ZVAL_COPY(&bucket->key, key); // Only attempt to copy the value if provided. if (value) { ZVAL_COPY(&bucket->value, value); } else { ZVAL_NULL(&bucket->value); } table->next++; table->size++; return bucket; } bool ds_htable_lookup_or_next(ds_htable_t *table, zval *key, ds_htable_bucket_t **bucket) { const uint32_t hash = get_hash(key); // Attempt to find the bucket if ((*bucket = ds_htable_lookup_bucket_by_hash(table, key, hash))) { return true; } if (table->next == table->capacity) { ds_htable_increase_capacity(table); } // Bucket couldn't be found, so create as new bucket in the buffer. *bucket = ds_htable_init_next_bucket(table, key, NULL, hash); return false; } void ds_htable_put(ds_htable_t *table, zval *key, zval *value) { ds_htable_bucket_t *bucket; // Attempt to find the bucket or initialize it as a new bucket. bool found = ds_htable_lookup_or_next(table, key, &bucket); // If found, destruct the current value so that we can replace it. if (found) { zval_ptr_dtor(&bucket->value); } if (value) { ZVAL_COPY(&bucket->value, value); } } zval *ds_htable_values(ds_htable_t *table) { zval *buffer = ALLOC_ZVAL_BUFFER(table->size); zval *target = buffer; zval *value; DS_HTABLE_FOREACH_VALUE(table, value) { ZVAL_COPY(target++, value); } DS_HTABLE_FOREACH_END(); return buffer; } ds_htable_bucket_t *ds_htable_last(ds_htable_t *table) { if (table->size == 0) { return NULL; } else { ds_htable_bucket_t *bucket = &table->buckets[table->next - 1]; while (DS_HTABLE_BUCKET_DELETED(bucket)) { bucket--; } return bucket; } } ds_htable_bucket_t *ds_htable_first(ds_htable_t *table) { if (table->size == 0) { return NULL; } else { ds_htable_bucket_t *bucket = table->buckets; while (DS_HTABLE_BUCKET_DELETED(bucket)) { bucket++; } return bucket; } } zend_string *ds_htable_join_keys(ds_htable_t *table, const char* glue, const size_t len) { smart_str str = {0}; if (table->size == 0) { return ZSTR_EMPTY_ALLOC(); } if (table->size == 1) { return zval_get_string(&ds_htable_last(table)->key); } if (glue && len) { ds_htable_bucket_t *pos = table->buckets; ds_htable_bucket_t *end = ds_htable_last(table); do { if ( ! DS_HTABLE_BUCKET_DELETED(pos)) { smart_str_appendz(&str, &pos->key); smart_str_appendl(&str, glue, len); } } while (++pos != end); // Append last keys smart_str_appendz(&str, &end->key); } else { // No glue, so just append the keys. zval *key; DS_HTABLE_FOREACH_KEY(table, key) { smart_str_appendz(&str, key); } DS_HTABLE_FOREACH_END(); } smart_str_0(&str); return str.s; } int ds_htable_remove(ds_htable_t *table, zval *key, zval *return_value) { uint32_t hash = get_hash(key); uint32_t index = DS_HTABLE_BUCKET_LOOKUP(table, hash); ds_htable_bucket_t *bucket = NULL; ds_htable_bucket_t *prev = NULL; for (; index != DS_HTABLE_INVALID_INDEX; index = DS_HTABLE_BUCKET_NEXT(bucket)) { bucket = &table->buckets[index]; if (DS_HTABLE_BUCKET_HASH(bucket) != hash || ! ds_htable_bucket_key_match(bucket, key)) { prev = bucket; continue; } if (return_value) { ZVAL_COPY(return_value, &bucket->value); } // Clear the lookup if there wasn't a collision chain, // otherwise remove the link in the chain. if (prev == NULL) { DS_HTABLE_BUCKET_LOOKUP(table, hash) = DS_HTABLE_BUCKET_NEXT(bucket); } else { DS_HTABLE_BUCKET_NEXT(prev) = DS_HTABLE_BUCKET_NEXT(bucket); } DS_HTABLE_BUCKET_DELETE(bucket); // If we're removing the last bucket, we might be able to move the // next open slot back if preceeding buckets are also deleted. if (index == table->next - 1 && table->size > 1) { do { table->next--; bucket--; } while (DS_HTABLE_BUCKET_DELETED(bucket)); } // Update the left-most deleted index. if (index < table->min_deleted) { table->min_deleted = index; } table->size--; // Check whether the buffer should be truncated. ds_htable_auto_truncate(table); return SUCCESS; } if (return_value) { ZVAL_NULL(return_value); } return FAILURE; } ds_htable_t *ds_htable_slice(ds_htable_t *table, zend_long index, zend_long length) { ds_normalize_slice_args(&index, &length, table->size); if (length == 0) { return ds_htable(); } else { ds_htable_t *slice = ds_htable_ex(length); /** * If the table doesn't have any deleted buckets or if the first deleted * bucket comes after the slice we're after, we can safely seek * to the index and copy each bucket. */ if (DS_HTABLE_IS_PACKED(table) || ((uint32_t) (index + length)) <= table->min_deleted) { ds_htable_bucket_t *src = &table->buckets[index]; for (; length-- > 0; src++) { ds_htable_init_next_bucket( slice, &src->key, &src->value, DS_HTABLE_BUCKET_HASH(src)); } /** * If the table does have deleted buckets but the first one comes after * the index of the slice, we can safely seek to the index. */ } else if ((uint32_t) index < table->min_deleted) { ds_htable_bucket_t *src = &table->buckets[index]; for (;;) { ds_htable_init_next_bucket( slice, &src->key, &src->value, DS_HTABLE_BUCKET_HASH(src)); if (--length == 0) { break; } // Skip deleted buckets while (DS_HTABLE_BUCKET_DELETED(++src)); } /** * Otherwise there are deleted buckets but they're in the slice range. * The best we can do is just skip any deleted buckets we encounter. */ } else { zend_long seek = 0; ds_htable_bucket_t *src = table->buckets; // We have to seek iteratively until we reach the index for (; seek < index; ++src) { if ( ! DS_HTABLE_BUCKET_DELETED(src)) { seek++; } } // We're at the index, so gather across. for (; length > 0; src++) { if (DS_HTABLE_BUCKET_DELETED(src)) { continue; } ds_htable_init_next_bucket( slice, &src->key, &src->value, DS_HTABLE_BUCKET_HASH(src)); length--; } } return slice; } } void ds_htable_apply(ds_htable_t *table, FCI_PARAMS) { zval retval; ds_htable_bucket_t *bucket; DS_HTABLE_FOREACH_BUCKET(table, bucket) { fci.param_count = 2; fci.params = (zval*) bucket; fci.retval = &retval; if (zend_call_function(&fci, &fci_cache) == FAILURE || Z_ISUNDEF(retval)) { return; } zval_ptr_dtor(&bucket->value); ZVAL_COPY_VALUE(&bucket->value, &retval); } DS_HTABLE_FOREACH_END(); } ds_htable_t *ds_htable_map(ds_htable_t *table, FCI_PARAMS) { ds_htable_bucket_t *bucket; zval retval; ds_htable_t *mapped = ds_htable_ex(table->capacity); DS_HTABLE_FOREACH_BUCKET(table, bucket) { fci.param_count = 2; fci.params = (zval*) bucket; fci.retval = &retval; if (zend_call_function(&fci, &fci_cache) == FAILURE || Z_ISUNDEF(retval)) { ds_htable_free(mapped); zval_ptr_dtor(&retval); return NULL; } ds_htable_init_next_bucket( mapped, &bucket->key, &retval, DS_HTABLE_BUCKET_HASH(bucket)); zval_ptr_dtor(&retval); } DS_HTABLE_FOREACH_END(); return mapped; } ds_htable_t *ds_htable_filter(ds_htable_t *table) { ds_htable_bucket_t *bucket; ds_htable_t *filtered = ds_htable_ex(table->capacity); DS_HTABLE_FOREACH_BUCKET(table, bucket) { if (zend_is_true(&bucket->value)) { ds_htable_init_next_bucket( filtered, &bucket->key, &bucket->value, DS_HTABLE_BUCKET_HASH(bucket)); } } DS_HTABLE_FOREACH_END(); return filtered; } ds_htable_t *ds_htable_filter_callback(ds_htable_t *table, FCI_PARAMS) { ds_htable_bucket_t *src; zval retval; ds_htable_t *filtered = ds_htable_ex(table->capacity); DS_HTABLE_FOREACH_BUCKET(table, src) { fci.param_count = 2; fci.params = (zval*) src; fci.retval = &retval; if (zend_call_function(&fci, &fci_cache) == FAILURE || Z_ISUNDEF(retval)) { ds_htable_free(filtered); zval_ptr_dtor(&retval); return NULL; } // Add as next key => value if the return value is true if (zend_is_true(&retval)) { ds_htable_init_next_bucket( filtered, &src->key, &src->value, DS_HTABLE_BUCKET_HASH(src)); } zval_ptr_dtor(&retval); } DS_HTABLE_FOREACH_END(); return filtered; } void ds_htable_reduce(ds_htable_t *table, FCI_PARAMS, zval *initial, zval *return_value) { zval *key, *value; zval carry; zval params[3]; if (initial == NULL) { ZVAL_NULL(&carry); } else { ZVAL_COPY_VALUE(&carry, initial); } DS_HTABLE_FOREACH_KEY_VALUE(table, key, value) { ZVAL_COPY_VALUE(¶ms[0], &carry); ZVAL_COPY_VALUE(¶ms[1], key); ZVAL_COPY_VALUE(¶ms[2], value); fci.param_count = 3; fci.params = params; fci.retval = &carry; if (zend_call_function(&fci, &fci_cache) == FAILURE || Z_ISUNDEF(carry)) { ZVAL_NULL(return_value); return; } Z_TRY_DELREF_P(&carry); } DS_HTABLE_FOREACH_END(); ZVAL_COPY(return_value, &carry); } ds_htable_t *ds_htable_xor(ds_htable_t *table, ds_htable_t *other) { ds_htable_bucket_t *bucket; ds_htable_t *xor = ds_htable(); DS_HTABLE_FOREACH_BUCKET(table, bucket) { if ( ! ds_htable_has_key(other, &bucket->key)) { ds_htable_put_distinct_bucket(xor, bucket); } } DS_HTABLE_FOREACH_END(); DS_HTABLE_FOREACH_BUCKET(other, bucket) { if ( ! ds_htable_has_key(table, &bucket->key)) { ds_htable_put_distinct_bucket(xor, bucket); } } DS_HTABLE_FOREACH_END(); return xor; } ds_htable_t *ds_htable_diff(ds_htable_t *table, ds_htable_t *other) { ds_htable_bucket_t *bucket; ds_htable_t *diff = ds_htable(); DS_HTABLE_FOREACH_BUCKET(table, bucket) { if ( ! ds_htable_has_key(other, &bucket->key)) { ds_htable_put_distinct_bucket(diff, bucket); } } DS_HTABLE_FOREACH_END(); return diff; } ds_htable_t *ds_htable_intersect(ds_htable_t *table, ds_htable_t *other) { ds_htable_bucket_t *bucket; ds_htable_t *intersection = ds_htable(); DS_HTABLE_FOREACH_BUCKET(table, bucket) { if (ds_htable_has_key(other, &bucket->key)) { ds_htable_put_distinct_bucket(intersection, bucket); } } DS_HTABLE_FOREACH_END(); return intersection; } ds_htable_t *ds_htable_merge(ds_htable_t *table, ds_htable_t *other) { ds_htable_bucket_t *bucket; ds_htable_t *merged = ds_htable_clone(table); DS_HTABLE_FOREACH_BUCKET(other, bucket) { ds_htable_put(merged, &bucket->key, &bucket->value); } DS_HTABLE_FOREACH_END(); return merged; } void ds_htable_reverse(ds_htable_t *table) { ds_htable_pack(table); { ds_htable_bucket_t *a = table->buckets; ds_htable_bucket_t *b = table->buckets + table->size - 1; for (; a < b; ++a, --b) { ds_htable_bucket_t c = *a; *a = *b; *b = c; } } ds_htable_rehash(table); } ds_htable_t *ds_htable_reversed(ds_htable_t *table) { ds_htable_t *reversed = ds_htable_ex(table->capacity); ds_htable_bucket_t *src = NULL; ds_htable_bucket_t *dst = reversed->buckets; const uint32_t mask = reversed->capacity - 1; DS_HTABLE_FOREACH_BUCKET_REVERSED(table, src) { uint32_t *lookup = &reversed->lookup[DS_HTABLE_BUCKET_HASH(src) & mask]; DS_HTABLE_BUCKET_COPY(dst, src); DS_HTABLE_BUCKET_NEXT(dst) = *lookup; *lookup = reversed->next++; dst++; } DS_HTABLE_FOREACH_END(); reversed->size = table->size; return reversed; } void ds_htable_to_array(ds_htable_t *table, zval *return_value) { HashTable *array; zval *key; zval *val; array_init_size(return_value, table->size); array = Z_ARR_P(return_value); DS_HTABLE_FOREACH_KEY_VALUE(table, key, val) { array_set_zval_key(array, key, val); } DS_HTABLE_FOREACH_END(); } int ds_htable_serialize(ds_htable_t *table, unsigned char **buffer, size_t *length, zend_serialize_data *data) { php_serialize_data_t serialize_data = (php_serialize_data_t) data; PHP_VAR_SERIALIZE_INIT(serialize_data); if (table->size == 0) { SERIALIZE_SET_ZSTR(ZSTR_EMPTY_ALLOC()); } else { zval *key, *value; smart_str buf = {0}; DS_HTABLE_FOREACH_KEY_VALUE(table, key, value) { php_var_serialize(&buf, key, &serialize_data); php_var_serialize(&buf, value, &serialize_data); } DS_HTABLE_FOREACH_END(); smart_str_0(&buf); SERIALIZE_SET_ZSTR(buf.s); zend_string_release(buf.s); } PHP_VAR_SERIALIZE_DESTROY(serialize_data); return SUCCESS; } int ds_htable_unserialize(ds_htable_t *table, const unsigned char *buffer, size_t length, zend_unserialize_data *data) { php_unserialize_data_t unserialize_data = (php_unserialize_data_t) data; const unsigned char *pos = buffer; const unsigned char *end = buffer + length; PHP_VAR_UNSERIALIZE_INIT(unserialize_data); while (*pos != '}') { zval *key = var_tmp_var(&unserialize_data); zval *value = var_tmp_var(&unserialize_data); if (php_var_unserialize(key, &pos, end, &unserialize_data)) { var_push_dtor(&unserialize_data, key); } else { goto error; } if (php_var_unserialize(value, &pos, end, &unserialize_data)) { var_push_dtor(&unserialize_data, value); } else { goto error; } ds_htable_put(table, key, value); } if (pos != end) { goto error; } PHP_VAR_UNSERIALIZE_DESTROY(unserialize_data); return SUCCESS; error: PHP_VAR_UNSERIALIZE_DESTROY(unserialize_data); UNSERIALIZE_ERROR(); return FAILURE; } ds-1.1.8/src/ds/ds_htable.h0000644000076500000240000002167013065035057015666 0ustar rtheunissenstaff#ifndef DS_HTABLE_H #define DS_HTABLE_H #include "../common.h" #define DS_HTABLE_MIN_CAPACITY 16 // Must be a power of 2 /** * Marker to indicate an invalid index in the buffer. */ #define DS_HTABLE_INVALID_INDEX ((uint32_t) -1) /** * Determines the calculated hash of a bucket, before mod. */ #define DS_HTABLE_BUCKET_HASH(_bucket) (Z_NEXT((_bucket)->key)) /** * Determines the buffer index of the next bucket in the collision chain. * An invalid index indicates that it's the last bucket in the chain. */ #define DS_HTABLE_BUCKET_NEXT(_bucket) (Z_NEXT((_bucket)->value)) /** * Determines if a bucket has been deleted. */ #define DS_HTABLE_BUCKET_DELETED(_bucket) (Z_ISUNDEF((_bucket)->key)) /** * Finds the start of the collision chain for a given hash. * An invalid index indicates that a chain doesn't exist. */ #define DS_HTABLE_BUCKET_LOOKUP(t, h) ((t)->lookup[h & ((t)->capacity - 1)]) /** * Determines if a table is packed, ie. doesn't have deleted buckets. */ #define DS_HTABLE_IS_PACKED(t) ((t)->size == (t)->next) /** * Rehashes a bucket into a table. * * 1. Determine where the bucket's chain would start. * 2. Set the bucket's next bucket to be the start of the chain. * 3. Set the start of the chain to the bucket's position in the buffer. * * This means that the next bucket can come before another in the buffer, * because a rehash unshifts the bucket into the chain. */ #define DS_HTABLE_BUCKET_REHASH(table, bucket, mask, idx) \ do { \ ds_htable_bucket_t *_bucket = bucket; \ ds_htable_t *_table = table; \ \ uint32_t hash = DS_HTABLE_BUCKET_HASH(_bucket); \ uint32_t *head = &_table->lookup[hash & (mask)]; \ \ DS_HTABLE_BUCKET_NEXT(_bucket) = *head; \ *head = idx; \ } while (0) /** * Copies a bucket's state into another, including: key, value, hash and next. */ #define DS_HTABLE_BUCKET_COPY(dst, src) \ do { \ ds_htable_bucket_t *_src = src; \ ds_htable_bucket_t *_dst = dst; \ ZVAL_COPY(&_dst->key, &_src->key); \ ZVAL_COPY(&_dst->value, &_src->value); \ DS_HTABLE_BUCKET_NEXT(_dst) = DS_HTABLE_BUCKET_NEXT(_src); \ DS_HTABLE_BUCKET_HASH(_dst) = DS_HTABLE_BUCKET_HASH(_src); \ } while (0) /** * Marks a bucket as deleted, destructing both the key and the value. */ #define DS_HTABLE_BUCKET_DELETE(b) \ DTOR_AND_UNDEF(&(b)->value); \ DTOR_AND_UNDEF(&(b)->key); \ DS_HTABLE_BUCKET_NEXT((b)) = DS_HTABLE_INVALID_INDEX #define DS_HTABLE_FOREACH_BUCKET(h, b) \ do { \ ds_htable_t *_h = h; \ ds_htable_bucket_t *_x = _h->buckets; \ ds_htable_bucket_t *_y = _h->buckets + _h->next; \ for (; _x < _y; ++_x) { \ if (DS_HTABLE_BUCKET_DELETED(_x)) continue; \ b = _x; #define DS_HTABLE_FOREACH_BUCKET_REVERSED(h, b) \ do { \ ds_htable_t *_h = h; \ ds_htable_bucket_t *_x = _h->buckets; \ ds_htable_bucket_t *_y = _x + _h->next - 1; \ for (; _y >= _x; --_y) { \ if (DS_HTABLE_BUCKET_DELETED(_y)) continue; \ b = _y; #define DS_HTABLE_FOREACH(h, i, k, v) \ do { \ uint32_t _i; \ uint32_t _n = (h)->size; \ ds_htable_bucket_t *_b = (h)->buckets; \ \ for (_i = 0; _i < _n; ++_b) { \ if (DS_HTABLE_BUCKET_DELETED(_b)) continue; \ k = &_b->key; \ v = &_b->value; \ i = _i++; #define DS_HTABLE_FOREACH_KEY(h, k) \ do { \ ds_htable_t *_h = h; \ ds_htable_bucket_t *_x = _h->buckets; \ ds_htable_bucket_t *_y = _h->buckets + _h->next; \ for (; _x < _y; ++_x) { \ if (DS_HTABLE_BUCKET_DELETED(_x)) continue; \ k = &_x->key; #define DS_HTABLE_FOREACH_VALUE(h, v) \ do { \ ds_htable_t *_h = h; \ ds_htable_bucket_t *_x = _h->buckets; \ ds_htable_bucket_t *_y = _h->buckets + _h->next; \ for (; _x < _y; ++_x) { \ if (DS_HTABLE_BUCKET_DELETED(_x)) continue; \ v = &_x->value; #define DS_HTABLE_FOREACH_KEY_VALUE(h, k, v) \ do { \ ds_htable_t *_h = h; \ ds_htable_bucket_t *_x = _h->buckets; \ ds_htable_bucket_t *_y = _h->buckets + _h->next; \ for (; _x < _y; ++_x) { \ if (DS_HTABLE_BUCKET_DELETED(_x)) continue; \ k = &_x->key; \ v = &_x->value; #define DS_HTABLE_FOREACH_END() \ } \ } while (0) typedef struct _ds_htable_bucket_t { zval key; zval value; } ds_htable_bucket_t; typedef struct _ds_htable_t { ds_htable_bucket_t *buckets; // Buffer for the buckets uint32_t *lookup; // Separated hash lookup table uint32_t next; // Next open index in the bucket buffer uint32_t size; // Number of active pairs in the table uint32_t capacity; // Number of buckets in the table uint32_t min_deleted; // Lowest deleted bucket buffer index } ds_htable_t; ds_htable_t *ds_htable(); zval *ds_htable_values(ds_htable_t *table); void ds_htable_ensure_capacity(ds_htable_t *table, uint32_t capacity); void ds_htable_sort(ds_htable_t *table, compare_func_t compare_func); void ds_htable_sort_by_key(ds_htable_t *table); void ds_htable_sort_by_value(ds_htable_t *table); void ds_htable_sort_by_pair(ds_htable_t *table); void ds_htable_sort_callback_by_key(ds_htable_t *table); void ds_htable_sort_callback_by_value(ds_htable_t *table); ds_htable_bucket_t *ds_htable_lookup_by_value(ds_htable_t *h, zval *key); ds_htable_bucket_t *ds_htable_lookup_by_key(ds_htable_t *h, zval *key); ds_htable_bucket_t *ds_htable_lookup_by_position(ds_htable_t *table, uint32_t position); bool ds_htable_lookup_or_next(ds_htable_t *table, zval *key, ds_htable_bucket_t **return_value); bool ds_htable_has_keys(ds_htable_t *h, VA_PARAMS); bool ds_htable_has_key(ds_htable_t *table, zval *key); bool ds_htable_has_values(ds_htable_t *h, VA_PARAMS); bool ds_htable_has_value(ds_htable_t *h, zval *value); int ds_htable_remove(ds_htable_t *h, zval *key, zval *return_value); void ds_htable_put(ds_htable_t *h, zval *key, zval *value); void ds_htable_to_array(ds_htable_t *h, zval *arr); void ds_htable_free(ds_htable_t *h); zval *ds_htable_get(ds_htable_t *h, zval *key); ds_htable_t *ds_htable_slice(ds_htable_t *table, zend_long index, zend_long length); void ds_htable_clear(ds_htable_t *h); ds_htable_t *ds_htable_clone(ds_htable_t *source); bool ds_htable_isset(ds_htable_t *h, zval *key, bool check_empty); zend_string *ds_htable_join_keys(ds_htable_t *table, const char* glue, const size_t len); void ds_htable_reverse(ds_htable_t *table); ds_htable_t *ds_htable_reversed(ds_htable_t *table); ds_htable_bucket_t *ds_htable_first(ds_htable_t *table); ds_htable_bucket_t *ds_htable_last(ds_htable_t *table); ds_htable_t *ds_htable_map(ds_htable_t *table, FCI_PARAMS); ds_htable_t *ds_htable_filter(ds_htable_t *table); ds_htable_t *ds_htable_filter_callback(ds_htable_t *table, FCI_PARAMS); void ds_htable_apply(ds_htable_t *table, FCI_PARAMS); void ds_htable_reduce(ds_htable_t *table, FCI_PARAMS, zval *initial, zval *return_value); ds_htable_t *ds_htable_xor(ds_htable_t *table, ds_htable_t *other); ds_htable_t *ds_htable_diff(ds_htable_t *table, ds_htable_t *other); ds_htable_t *ds_htable_intersect(ds_htable_t *table, ds_htable_t *other); ds_htable_t *ds_htable_merge(ds_htable_t *table, ds_htable_t *other); int ds_htable_serialize(ds_htable_t *table, unsigned char **buffer, size_t *buf_len, zend_serialize_data *data); int ds_htable_unserialize(ds_htable_t *table, const unsigned char *buffer, size_t length, zend_unserialize_data *data); #endif ds-1.1.8/src/ds/ds_map.c0000644000076500000240000001637413065035057015204 0ustar rtheunissenstaff#include "../common.h" #include "../php/handlers/php_map_handlers.h" #include "../php/classes/php_map_ce.h" #include "../php/classes/php_set_ce.h" #include "ds_htable.h" #include "ds_vector.h" #include "ds_map.h" #include "ds_set.h" #include "ds_pair.h" static ds_map_t *ds_map_ex(ds_htable_t *table) { ds_map_t *map = ecalloc(1, sizeof(ds_map_t)); map->table = table; return map; } ds_map_t *ds_map() { return ds_map_ex(ds_htable()); } ds_map_t *ds_map_clone(ds_map_t *map) { return ds_map_ex(ds_htable_clone(map->table)); } void ds_map_allocate(ds_map_t *map, zend_long capacity) { ds_htable_ensure_capacity(map->table, capacity); } zend_long ds_map_capacity(ds_map_t *map) { return map->table->capacity; } void ds_map_reverse(ds_map_t *map) { ds_htable_reverse(map->table); } ds_map_t *ds_map_reversed(ds_map_t *map) { return ds_map_ex(ds_htable_reversed(map->table)); } void ds_map_put(ds_map_t *map, zval *key, zval *value) { ds_htable_put(map->table, key, value); } void ds_map_reduce(ds_map_t *map, FCI_PARAMS, zval *initial, zval *return_value) { ds_htable_reduce(map->table, FCI_ARGS, initial, return_value); } void ds_map_apply(ds_map_t *map, FCI_PARAMS) { ds_htable_apply(map->table, FCI_ARGS); } ds_map_t *ds_map_map(ds_map_t *map, FCI_PARAMS) { ds_htable_t *table = ds_htable_map(map->table, FCI_ARGS); if (table) { return ds_map_ex(table); } return NULL; } ds_map_t *ds_map_filter(ds_map_t *map) { return ds_map_ex(ds_htable_filter(map->table)); } ds_map_t *ds_map_filter_callback(ds_map_t *map, FCI_PARAMS) { ds_htable_t *table = ds_htable_filter_callback(map->table, FCI_ARGS); if (table) { return ds_map_ex(table); } return NULL; } zval *ds_map_get(ds_map_t *map, zval *key, zval *def) { zval *value = ds_htable_get(map->table, key); if (value) { return value; } if (def) { return def; } KEY_NOT_FOUND(); return NULL; } void ds_map_remove(ds_map_t *map, zval *key, zval *def, zval *return_value) { int removed = ds_htable_remove(map->table, key, return_value); if (removed == FAILURE) { // Failed to remove value if ( ! def) { // Did not specify a default value KEY_NOT_FOUND(); ZVAL_NULL(return_value); return; } // Default value was provided ZVAL_COPY(return_value, def); } } bool ds_map_has_key(ds_map_t *map, zval *key) { return ds_htable_has_key(map->table, key); } bool ds_map_has_value(ds_map_t *map, zval *value) { return ds_htable_has_value(map->table, value); } bool ds_map_has_keys(ds_map_t *map, VA_PARAMS) { return ds_htable_has_keys(map->table, argc, argv); } bool ds_map_has_values(ds_map_t *map, VA_PARAMS) { return ds_htable_has_values(map->table, argc, argv); } void ds_map_clear(ds_map_t *map) { ds_htable_clear(map->table); } void ds_map_sort_by_value_callback(ds_map_t *map) { ds_htable_sort_callback_by_value(map->table); } void ds_map_sort_by_value(ds_map_t *map) { ds_htable_sort_by_value(map->table); } void ds_map_sort_by_key_callback(ds_map_t *map) { ds_htable_sort_callback_by_key(map->table); } void ds_map_sort_by_key(ds_map_t *map) { ds_htable_sort_by_key(map->table); } ds_map_t *ds_map_sorted_by_value_callback(ds_map_t *map) { ds_map_t *sorted = ds_map_clone(map); ds_htable_sort_callback_by_value(sorted->table); return sorted; } ds_map_t *ds_map_sorted_by_value(ds_map_t *map) { ds_map_t *sorted = ds_map_clone(map); ds_htable_sort_by_value(sorted->table); return sorted; } ds_map_t *ds_map_sorted_by_key_callback(ds_map_t *map) { ds_map_t *sorted = ds_map_clone(map); ds_htable_sort_callback_by_key(sorted->table); return sorted; } ds_map_t *ds_map_sorted_by_key(ds_map_t *map) { ds_map_t *sorted = ds_map_clone(map); ds_htable_sort_by_key(sorted->table); return sorted; } void ds_map_to_array(ds_map_t *map, zval *return_value) { ds_htable_to_array(map->table, return_value); } zval *ds_map_values(ds_map_t *map) { return ds_htable_values(map->table); } ds_map_t *ds_map_slice(ds_map_t *map, zend_long index, zend_long length) { return ds_map_ex(ds_htable_slice(map->table, index, length)); } ds_map_t *ds_map_merge(ds_map_t *map, zval *values) { if (ds_is_array(values) || ds_is_traversable(values)) { ds_map_t *merged = ds_map_clone(map); ds_map_put_all(merged, values); return merged; } ARRAY_OR_TRAVERSABLE_REQUIRED(); return NULL; } ds_map_t *ds_map_xor(ds_map_t *map, ds_map_t *other) { return ds_map_ex(ds_htable_xor(map->table, other->table)); } ds_map_t *ds_map_diff(ds_map_t *map, ds_map_t *other) { return ds_map_ex(ds_htable_diff(map->table, other->table)); } ds_map_t *ds_map_intersect(ds_map_t *map, ds_map_t *other) { return ds_map_ex(ds_htable_intersect(map->table, other->table)); } ds_map_t *ds_map_union(ds_map_t *map, ds_map_t *other) { return ds_map_ex(ds_htable_merge(map->table, other->table)); } ds_pair_t *ds_map_first(ds_map_t *map) { ds_htable_bucket_t *bucket = ds_htable_first(map->table); if ( ! bucket) { NOT_ALLOWED_WHEN_EMPTY(); return NULL; } return ds_pair_ex(&bucket->key, &bucket->value); } ds_pair_t *ds_map_last(ds_map_t *map) { ds_htable_bucket_t *bucket = ds_htable_last(map->table); if ( ! bucket) { NOT_ALLOWED_WHEN_EMPTY(); return NULL; } return ds_pair_ex(&bucket->key, &bucket->value); } ds_pair_t *ds_map_skip(ds_map_t *map, zend_long position) { ds_htable_bucket_t *bucket = ds_htable_lookup_by_position(map->table, position); if ( ! bucket) { INDEX_OUT_OF_RANGE(position, map->table->size); return NULL; } return ds_pair_ex(&bucket->key, &bucket->value); } static int iterator_add(zend_object_iterator *iterator, void *puser) { zval key; zval *value = iterator->funcs->get_current_data(iterator); iterator->funcs->get_current_key(iterator, &key); ds_map_put((ds_map_t *) puser, &key, value); zval_ptr_dtor(&key); return ZEND_HASH_APPLY_KEEP; } static inline void add_traversable_to_map(ds_map_t *map, zval *obj) { spl_iterator_apply(obj, iterator_add, (void*) map); } static inline void add_ht_to_map(ds_map_t *map, HashTable *ht) { uint32_t index; zend_string *key; zval *value; zval temp; ZEND_HASH_FOREACH_KEY_VAL(ht, index, key, value) { if (key) { ZVAL_STR(&temp, key); } else { ZVAL_LONG(&temp, index); } ds_map_put(map, &temp, value); } ZEND_HASH_FOREACH_END(); } void ds_map_put_all(ds_map_t *map, zval *values) { if ( ! values) { return; } if (ds_is_array(values)) { add_ht_to_map(map, Z_ARRVAL_P(values)); return; } if (ds_is_traversable(values)) { add_traversable_to_map(map, values); return; } ARRAY_OR_TRAVERSABLE_REQUIRED(); } void ds_map_sum(ds_map_t *map, zval *return_value) { zval *value; ZVAL_LONG(return_value, 0); DS_HTABLE_FOREACH_VALUE(map->table, value) { DS_ADD_TO_SUM(value, return_value); } DS_HTABLE_FOREACH_END(); } void ds_map_free(ds_map_t *map) { ds_htable_free(map->table); efree(map); } ds-1.1.8/src/ds/ds_map.h0000644000076500000240000000442613065035057015204 0ustar rtheunissenstaff#ifndef DS_MAP_H #define DS_MAP_H #include "../common.h" #include "ds_htable.h" #include "ds_pair.h" typedef struct _ds_map_t { ds_htable_t *table; } ds_map_t; #define DS_MAP_SIZE(m) ((m)->table->size) #define DS_MAP_IS_EMPTY(m) (DS_MAP_SIZE(m) == 0) ds_map_t *ds_map(); ds_map_t *ds_map_clone(ds_map_t *map); void ds_map_clear(ds_map_t *map); void ds_map_free(ds_map_t *map); void ds_map_reverse(ds_map_t *map); ds_map_t *ds_map_reversed(ds_map_t *map); zval *ds_map_get(ds_map_t *map, zval *key, zval *def); void ds_map_put(ds_map_t *map, zval *key, zval *value); void ds_map_remove(ds_map_t *map, zval *key, zval *def, zval *return_value); bool ds_map_has_key(ds_map_t *map, zval *key); bool ds_map_has_value(ds_map_t *map, zval *value); bool ds_map_has_keys(ds_map_t *map, VA_PARAMS); bool ds_map_has_values(ds_map_t *map, VA_PARAMS); void ds_map_to_array(ds_map_t *map, zval *return_value); void ds_map_put_all(ds_map_t *map, zval *values); ds_map_t *ds_map_slice(ds_map_t *map, zend_long index, zend_long length); zval *ds_map_values(ds_map_t *map); ds_map_t *ds_map_map(ds_map_t *map, FCI_PARAMS); ds_map_t *ds_map_filter(ds_map_t *map); ds_map_t *ds_map_filter_callback(ds_map_t *map, FCI_PARAMS); void ds_map_allocate(ds_map_t *map, zend_long capacity); zend_long ds_map_capacity(ds_map_t *map); void ds_map_sort_by_value_callback(ds_map_t *map); void ds_map_sort_by_value(ds_map_t *map); void ds_map_sort_by_key_callback(ds_map_t *map); void ds_map_sort_by_key(ds_map_t *map); ds_map_t *ds_map_sorted_by_value_callback(ds_map_t *map); ds_map_t *ds_map_sorted_by_value(ds_map_t *map); ds_map_t *ds_map_sorted_by_key_callback(ds_map_t *map); ds_map_t *ds_map_sorted_by_key(ds_map_t *map); ds_map_t *ds_map_merge(ds_map_t *map, zval *values); ds_map_t *ds_map_xor(ds_map_t *map, ds_map_t *other); ds_map_t *ds_map_diff(ds_map_t *map, ds_map_t *other); ds_map_t *ds_map_intersect(ds_map_t *map, ds_map_t *other); ds_map_t *ds_map_union(ds_map_t *map, ds_map_t *other); ds_pair_t *ds_map_first(ds_map_t *map); ds_pair_t *ds_map_last(ds_map_t *map); ds_pair_t *ds_map_skip(ds_map_t *map, zend_long position); void ds_map_sum(ds_map_t *map, zval *return_value); void ds_map_reduce(ds_map_t *map, FCI_PARAMS, zval *initial, zval *return_value); void ds_map_apply(ds_map_t *map, FCI_PARAMS); #endif ds-1.1.8/src/ds/ds_pair.c0000644000076500000240000000200013065035057015337 0ustar rtheunissenstaff#include "../common.h" #include "../php/handlers/php_pair_handlers.h" #include "../php/classes/php_pair_ce.h" #include "ds_pair.h" ds_pair_t *ds_pair() { ds_pair_t *pair = ecalloc(1, sizeof(ds_pair_t)); ZVAL_UNDEF(&pair->key); ZVAL_UNDEF(&pair->value); return pair; } ds_pair_t *ds_pair_ex(zval *key, zval *value) { ds_pair_t *pair = ds_pair(); ZVAL_COPY(&pair->key, key); ZVAL_COPY(&pair->value, value); return pair; } ds_pair_t *ds_pair_clone(ds_pair_t *pair) { ds_pair_t *clone = ds_pair(); ZVAL_COPY(&clone->key, &pair->key); ZVAL_COPY(&clone->value, &pair->value); return clone; } void ds_pair_to_array(ds_pair_t *pair, zval *array) { array_init_size(array, 2); add_assoc_zval(array, "key", &pair->key); add_assoc_zval(array, "value", &pair->value); Z_TRY_ADDREF_P(&pair->key); Z_TRY_ADDREF_P(&pair->value); } void ds_pair_free(ds_pair_t *pair) { DTOR_AND_UNDEF(&pair->key); DTOR_AND_UNDEF(&pair->value); efree(pair); } ds-1.1.8/src/ds/ds_pair.h0000644000076500000240000000053613065035057015360 0ustar rtheunissenstaff#ifndef DS_PAIR_H #define DS_PAIR_H #include "../common.h" typedef struct _ds_pair_t { zval key; zval value; } ds_pair_t; ds_pair_t *ds_pair(); ds_pair_t *ds_pair_ex(zval *key, zval *value); ds_pair_t *ds_pair_clone(ds_pair_t *pair); void ds_pair_to_array(ds_pair_t *pair, zval *return_value); void ds_pair_free(ds_pair_t *pair); #endif ds-1.1.8/src/ds/ds_priority_queue.c0000644000076500000240000001504413065035057017505 0ustar rtheunissenstaff#include "../common.h" #include "../php/iterators/php_priority_queue_iterator.h" #include "../php/handlers/php_priority_queue_handlers.h" #include "../php/classes/php_priority_queue_ce.h" #include "ds_priority_queue.h" #define LEFT(x) (((x) << 1) + 1) #define RIGHT(x) (((x) << 1) + 2) #define PARENT(x) ((x - 1) >> 1) // Insertion stamp, for equal priority comparison fallback. #define STAMP(n) (Z_NEXT((n).value)) static uint32_t capacity_for_size(uint32_t size) { uint32_t c = MAX(size, DS_PRIORITY_QUEUE_MIN_CAPACITY); c--; c |= c >> 1; c |= c >> 2; c |= c >> 4; c |= c >> 8; c |= c >> 16; c++; return c; } // Priority comparison, with insertion stamp fallback. static inline int compare(ds_priority_queue_node_t a, ds_priority_queue_node_t b) { return ((a.priority == b.priority) ? (STAMP(a) < STAMP(b) ? 1 : -1) : (a.priority > b.priority) ? 1 : -1); } static inline ds_priority_queue_node_t *reallocate_nodes(ds_priority_queue_node_t *nodes, uint32_t capacity) { return erealloc(nodes, capacity * sizeof(ds_priority_queue_node_t)); } static inline ds_priority_queue_node_t *allocate_nodes(uint32_t capacity) { return ecalloc(capacity, sizeof(ds_priority_queue_node_t)); } static inline void reallocate_to_capacity(ds_priority_queue_t *queue, uint32_t capacity) { queue->nodes = reallocate_nodes(queue->nodes, capacity); queue->capacity = capacity; } static inline void increase_capacity(ds_priority_queue_t *queue) { reallocate_to_capacity(queue, queue->capacity << 1); } void ds_priority_queue_allocate(ds_priority_queue_t *queue, uint32_t capacity) { if (capacity > queue->capacity) { reallocate_to_capacity(queue, capacity_for_size(capacity)); } } ds_priority_queue_t *ds_priority_queue() { ds_priority_queue_t *queue = ecalloc(1, sizeof(ds_priority_queue_t)); queue->nodes = allocate_nodes(DS_PRIORITY_QUEUE_MIN_CAPACITY); queue->capacity = DS_PRIORITY_QUEUE_MIN_CAPACITY; queue->size = 0; queue->next = 0; return queue; } uint32_t ds_priority_queue_capacity(ds_priority_queue_t *queue) { return queue->capacity; } void ds_priority_queue_push(ds_priority_queue_t *queue, zval *value, zend_long priority) { uint32_t parent; uint32_t index; ds_priority_queue_node_t *nodes; ds_priority_queue_node_t *node; if (queue->size == queue->capacity) { increase_capacity(queue); } nodes = queue->nodes; for (index = queue->size; index > 0; index = parent) { // Move up the heap parent = PARENT(index); if (priority <= nodes[parent].priority) { break; } nodes[index] = nodes[parent]; } node = &queue->nodes[index]; // Initialize the new node STAMP(*node) = ++queue->next; ZVAL_COPY(&node->value, value); node->priority = priority; queue->size++; } static inline void ds_priority_queue_compact(ds_priority_queue_t *queue) { if (queue->size < (queue->capacity / 4) && (queue->capacity / 2) > DS_PRIORITY_QUEUE_MIN_CAPACITY) { reallocate_to_capacity(queue, queue->capacity / 2); } } void ds_priority_queue_pop(ds_priority_queue_t *queue, zval *return_value) { uint32_t index, swap; ds_priority_queue_node_t bottom; ds_priority_queue_node_t *nodes = queue->nodes; const uint32_t size = queue->size; const uint32_t half = (size - 1) / 2; if (size == 0) { NOT_ALLOWED_WHEN_EMPTY(); ZVAL_NULL(return_value); return; } if (return_value) { ZVAL_COPY(return_value, &(nodes[0].value)); } bottom = nodes[size - 1]; DTOR_AND_UNDEF(&(nodes[0].value)); queue->size--; for (index = 0; index < half; index = swap) { swap = LEFT(index); if (swap < queue->size && compare(nodes[swap], nodes[swap + 1]) < 0) { swap++; } if (compare(nodes[swap], bottom) < 0) { break; } nodes[index] = nodes[swap]; } nodes[index] = bottom; // Reduce the size of the buffer if the size has dropped below a threshold. ds_priority_queue_compact(queue); } static ds_priority_queue_node_t *copy_nodes(ds_priority_queue_t *queue) { ds_priority_queue_node_t *copies = allocate_nodes(queue->capacity); ds_priority_queue_node_t *src = queue->nodes; ds_priority_queue_node_t *end = queue->nodes + queue->size; ds_priority_queue_node_t *dst = copies; for (; src < end; ++src, ++dst) { ZVAL_COPY(&dst->value, &src->value); // Also copies stamp dst->priority = src->priority; } return copies; } ds_priority_queue_t *ds_priority_queue_clone(ds_priority_queue_t * queue) { ds_priority_queue_t *clone = ecalloc(1, sizeof(ds_priority_queue_t)); clone->nodes = copy_nodes(queue); clone->capacity = queue->capacity; clone->size = queue->size; clone->next = queue->next; return clone; } zval *ds_priority_queue_peek(ds_priority_queue_t *queue) { if (queue->size == 0) { NOT_ALLOWED_WHEN_EMPTY(); return NULL; } return &queue->nodes[0].value; } static int priority_sort(const void *a, const void *b) { return compare(*((ds_priority_queue_node_t *) b), *((ds_priority_queue_node_t *) a)); } ds_priority_queue_node_t* ds_priority_queue_create_sorted_buffer(ds_priority_queue_t *queue) { ds_priority_queue_node_t *buffer = allocate_nodes(queue->size); memcpy(buffer, queue->nodes, queue->size * sizeof(ds_priority_queue_node_t)); qsort(buffer, queue->size, sizeof(ds_priority_queue_node_t), priority_sort); return buffer; } void ds_priority_queue_to_array(ds_priority_queue_t *queue, zval *array) { if (DS_PRIORITY_QUEUE_IS_EMPTY(queue)) { array_init(array); } else { ds_priority_queue_node_t *pos, *end, *buf; buf = ds_priority_queue_create_sorted_buffer(queue); pos = buf; end = buf + queue->size; array_init_size(array, queue->size); for (; pos < end; ++pos) { add_next_index_zval(array, &pos->value); Z_TRY_ADDREF_P(&pos->value); } efree(buf); } } void ds_priority_queue_clear(ds_priority_queue_t *queue) { ds_priority_queue_node_t *pos = queue->nodes; ds_priority_queue_node_t *end = pos + queue->size; for (; pos < end; ++pos) { DTOR_AND_UNDEF(&pos->value); } queue->size = 0; reallocate_to_capacity(queue, DS_PRIORITY_QUEUE_MIN_CAPACITY); } void ds_priority_queue_free(ds_priority_queue_t *queue) { ds_priority_queue_clear(queue); efree(queue->nodes); efree(queue); } ds-1.1.8/src/ds/ds_priority_queue.h0000644000076500000240000000527413065035057017516 0ustar rtheunissenstaff#ifndef DS_PRIORITY_QUEUE_H #define DS_PRIORITY_QUEUE_H #include "../common.h" typedef struct _ds_priority_queue_node_t { zval value; zend_long priority; } ds_priority_queue_node_t; typedef struct _ds_priority_queue_t { ds_priority_queue_node_t *nodes; uint32_t capacity; uint32_t size; uint32_t next; } ds_priority_queue_t; #define DS_PRIORITY_QUEUE_MIN_CAPACITY 8 #define DS_PRIORITY_QUEUE_FOREACH_NODE(queue, node) \ do { \ ds_priority_queue_t *_queue = queue; \ ds_priority_queue_node_t *_node = &_queue->nodes[0]; \ ds_priority_queue_node_t *_last = &_queue->nodes[queue->size - 1]; \ \ for (; _node <= _last; ++_node) { \ node = _node; #define DS_PRIORITY_QUEUE_FOREACH_VALUE(queue, value) \ ds_priority_queue_node_t *__node = NULL; \ DS_PRIORITY_QUEUE_FOREACH_NODE(queue, __node) \ value = &__node->value; #define DS_PRIORITY_QUEUE_FOREACH(queue, value, priority) \ ds_priority_queue_node_t *__node = NULL; \ DS_PRIORITY_QUEUE_FOREACH_NODE(queue, __node) \ value = &__node->value; \ priority = __node->priority; #define DS_PRIORITY_QUEUE_FOREACH_END() \ } \ } while (0) \ /** * Has to exist because of the uint32_t insertion order stamp. */ #define DS_PRIORITY_QUEUE_MAX_CAPACITY (1 << 31) #define DS_PRIORITY_QUEUE_SIZE(queue) ((queue)->size) #define DS_PRIORITY_QUEUE_IS_EMPTY(queue) (DS_PRIORITY_QUEUE_SIZE(queue) == 0) ds_priority_queue_t *ds_priority_queue(); void ds_priority_queue_allocate(ds_priority_queue_t *queue, uint32_t capacity); uint32_t ds_priority_queue_capacity(ds_priority_queue_t *queue); zval *ds_priority_queue_peek(ds_priority_queue_t *queue); void ds_priority_queue_pop(ds_priority_queue_t *queue, zval *return_value); void ds_priority_queue_push(ds_priority_queue_t *queue, zval *value, zend_long priority); void ds_priority_queue_to_array(ds_priority_queue_t *queue, zval *array); void ds_priority_queue_free(ds_priority_queue_t *queue); void ds_priority_queue_clear(ds_priority_queue_t *queue); ds_priority_queue_t *ds_priority_queue_clone(ds_priority_queue_t * queue); ds_priority_queue_node_t* ds_priority_queue_create_sorted_buffer(ds_priority_queue_t *queue); #endif ds-1.1.8/src/ds/ds_queue.c0000644000076500000240000000400613065035057015540 0ustar rtheunissenstaff#include "../common.h" #include "../php/iterators/php_queue_iterator.h" #include "../php/handlers/php_queue_handlers.h" #include "../php/classes/php_queue_ce.h" #include "ds_deque.h" #include "ds_queue.h" ds_queue_t *ds_queue_ex(ds_deque_t *deque) { ds_queue_t *queue = ecalloc(1, sizeof(ds_queue_t)); queue->deque = deque; return queue; } ds_queue_t *ds_queue() { return ds_queue_ex(ds_deque()); } ds_queue_t *ds_queue_clone(ds_queue_t *queue) { return ds_queue_ex(ds_deque_clone(queue->deque)); } void ds_queue_free(ds_queue_t *queue) { ds_deque_free(queue->deque); efree(queue); } void ds_queue_allocate(ds_queue_t *queue, zend_long capacity) { ds_deque_allocate(queue->deque, capacity); } zend_long ds_queue_capacity(ds_queue_t *queue) { return queue->deque->capacity; } void ds_queue_push(ds_queue_t *queue, VA_PARAMS) { ds_deque_push_va(queue->deque, argc, argv); } void ds_queue_push_one(ds_queue_t *queue, zval *value) { ds_deque_push(queue->deque, value); } void ds_queue_clear(ds_queue_t *queue) { ds_deque_clear(queue->deque); } void ds_queue_push_all(ds_queue_t *queue, zval *value) { ds_deque_push_all(queue->deque, value); } void ds_queue_to_array(ds_queue_t *queue, zval *return_value) { zend_long size = QUEUE_SIZE(queue); if (size == 0) { array_init(return_value); } else { zval *value; array_init_size(return_value, size); DS_DEQUE_FOREACH(queue->deque, value) { add_next_index_zval(return_value, value); Z_TRY_ADDREF_P(value); } DS_DEQUE_FOREACH_END(); } } void ds_queue_pop_throw(ds_queue_t *queue, zval *return_value) { ds_deque_shift_throw(queue->deque, return_value); } void ds_queue_pop(ds_queue_t *queue, zval *return_value) { ds_deque_shift(queue->deque, return_value); } zval *ds_queue_peek_throw(ds_queue_t *queue) { return ds_deque_get_first_throw(queue->deque); } zval *ds_queue_peek(ds_queue_t *queue) { return ds_deque_get_first(queue->deque); } ds-1.1.8/src/ds/ds_queue.h0000644000076500000240000000321713065035057015550 0ustar rtheunissenstaff#ifndef DS_QUEUE_H #define DS_QUEUE_H #include "../common.h" #include "ds_deque.h" #define QUEUE_SIZE(q) ((q)->deque->size) #define QUEUE_IS_EMPTY(q) ((q)->deque->size == 0) #define QUEUE_FOREACH(queue, value) \ do { \ zval _tmp; \ while ( ! DS_DEQUE_IS_EMPTY(queue->deque)) { \ ds_deque_shift(queue->deque, &_tmp); \ value = &_tmp; #define QUEUE_FOREACH_END() \ } \ zval_ptr_dtor(&_tmp); \ } while (0) \ typedef struct _ds_queue_t { ds_deque_t *deque; } ds_queue_t; ds_queue_t *ds_queue_ex(ds_deque_t *deque); ds_queue_t *ds_queue(); ds_queue_t *ds_queue_clone(ds_queue_t *queue); void ds_queue_allocate(ds_queue_t *queue, zend_long capacity); zend_long ds_queue_capacity(ds_queue_t *queue); void ds_queue_push(ds_queue_t *queue, VA_PARAMS); void ds_queue_push_one(ds_queue_t *queue, zval *value); void ds_queue_clear(ds_queue_t *queue); void ds_queue_pop(ds_queue_t *queue, zval *return_value); void ds_queue_pop_throw(ds_queue_t *queue, zval *return_value); zval *ds_queue_peek(ds_queue_t *queue); zval *ds_queue_peek_throw(ds_queue_t *queue); void ds_queue_push_all(ds_queue_t *queue, zval *value); void ds_queue_to_array(ds_queue_t *queue, zval *return_value); void ds_queue_free(ds_queue_t *queue); int ds_queue_serialize(zval *object, unsigned char **buffer, size_t *length, zend_serialize_data *data); int ds_queue_unserialize(zval *object, zend_class_entry *ce, const unsigned char *buffer, size_t length, zend_unserialize_data *data); #endif ds-1.1.8/src/ds/ds_set.c0000644000076500000240000002003713065035057015211 0ustar rtheunissenstaff#include "../common.h" #include "../php/iterators/php_set_iterator.h" #include "../php/handlers/php_set_handlers.h" #include "../php/classes/php_set_ce.h" #include "ds_set.h" #include "ds_htable.h" ds_set_t *ds_set_ex(ds_htable_t *table) { ds_set_t *set = ecalloc(1, sizeof(ds_set_t)); set->table = table; return set; } ds_set_t *ds_set() { return ds_set_ex(ds_htable()); } ds_set_t *ds_set_clone(ds_set_t *set) { return ds_set_ex(ds_htable_clone(set->table)); } void ds_set_allocate(ds_set_t *set, zend_long capacity) { ds_htable_ensure_capacity(set->table, capacity); } void ds_set_sort_callback(ds_set_t *set) { ds_htable_sort_callback_by_key(set->table); } void ds_set_sort(ds_set_t *set) { ds_htable_sort_by_key(set->table); } ds_set_t *ds_set_sorted_callback(ds_set_t *set) { ds_set_t *sorted = ds_set_clone(set); ds_set_sort_callback(sorted); return sorted; } ds_set_t *ds_set_sorted(ds_set_t *set) { ds_set_t *sorted = ds_set_clone(set); ds_set_sort(sorted); return sorted; } void ds_set_add(ds_set_t *set, zval *value) { ds_htable_put(set->table, value, NULL); } void ds_set_add_va(ds_set_t *set, VA_PARAMS) { for (; argc != 0; argc--, argv++) { ds_set_add(set, argv); } } static int iterator_add(zend_object_iterator *iterator, void *puser) { ds_set_add((ds_set_t *) puser, iterator->funcs->get_current_data(iterator)); return SUCCESS; } static inline void add_traversable_to_set(ds_set_t *set, zval *obj) { spl_iterator_apply(obj, iterator_add, set); } static inline void add_array_to_set(ds_set_t *set, HashTable *array) { zval *value; ZEND_HASH_FOREACH_VAL(array, value) { ds_set_add(set, value); } ZEND_HASH_FOREACH_END(); } void ds_set_add_all(ds_set_t *set, zval *values) { if (values == NULL) { return; } if (ds_is_array(values)) { add_array_to_set(set, Z_ARRVAL_P(values)); return; } if (ds_is_traversable(values)) { add_traversable_to_set(set, values); return; } ARRAY_OR_TRAVERSABLE_REQUIRED(); } bool ds_set_contains(ds_set_t *set, zval *value) { return ds_htable_has_key(set->table, value); } bool ds_set_contains_va(ds_set_t *set, VA_PARAMS) { return ds_htable_has_keys(set->table, argc, argv); } static inline void ds_set_remove(ds_set_t *set, zval *value) { ds_htable_remove(set->table, value, NULL); } void ds_set_remove_va(ds_set_t *set, VA_PARAMS) { while (argc--) { ds_set_remove(set, argv++); } } zval *ds_set_get(ds_set_t *set, zend_long index) { ds_htable_bucket_t *bucket = ds_htable_lookup_by_position(set->table, index); if (bucket) { return &bucket->key; } INDEX_OUT_OF_RANGE(index, set->table->size); return NULL; } zval *ds_set_get_first(ds_set_t *set) { ds_htable_bucket_t *bucket = ds_htable_lookup_by_position(set->table, 0); if ( ! bucket) { NOT_ALLOWED_WHEN_EMPTY(); return NULL; } return &bucket->key; } zval *ds_set_get_last(ds_set_t *set) { ds_htable_bucket_t *bucket = ds_htable_lookup_by_position(set->table, DS_SET_SIZE(set) - 1); if ( ! bucket) { NOT_ALLOWED_WHEN_EMPTY(); return NULL; } return &bucket->key; } void ds_set_join(ds_set_t *set, const char *glue, const size_t len, zval *return_value) { zend_string *str = ds_htable_join_keys(set->table, glue, len); ZVAL_STR(return_value, str); } ds_set_t *ds_set_slice(ds_set_t *set, zend_long index, zend_long length) { return ds_set_ex(ds_htable_slice(set->table, index, length)); } ds_set_t *ds_set_diff(ds_set_t *set, ds_set_t *other) { return ds_set_ex(ds_htable_diff(set->table, other->table)); } void ds_set_assign_diff(ds_set_t *set, ds_set_t *other) { zval *value; DS_SET_FOREACH(other, value) { ds_set_remove(set, value); } DS_SET_FOREACH_END(); } ds_set_t *ds_set_intersect(ds_set_t *set, ds_set_t *other) { return ds_set_ex(ds_htable_intersect(set->table, other->table)); } void ds_set_assign_intersect(ds_set_t *set, ds_set_t *other) { zval *value; DS_SET_FOREACH(set, value) { if ( ! ds_set_contains(other, value)) { ds_set_remove(set, value); } } DS_SET_FOREACH_END(); } // Returns a new ds_set_t with buffer in either A or B but not both ds_set_t *ds_set_xor(ds_set_t *set, ds_set_t *other) { return ds_set_ex(ds_htable_xor(set->table, other->table)); } // Elements in either A or B but not both void ds_set_assign_xor(ds_set_t *set, ds_set_t *other) { zval *value; DS_SET_FOREACH(set, value) { if (ds_set_contains(other, value)) { ds_set_remove(set, value); } } DS_SET_FOREACH_END(); DS_SET_FOREACH(other, value) { ds_set_remove(set, value); } DS_SET_FOREACH_END(); } ds_set_t *ds_set_union(ds_set_t *set, ds_set_t *other) { return ds_set_ex(ds_htable_merge(set->table, other->table)); } ds_set_t *ds_set_merge(ds_set_t *set, zval *values) { if (values && (ds_is_array(values) || ds_is_traversable(values))) { ds_set_t *merged = ds_set_clone(set); ds_set_add_all(merged, values); return merged; } ARRAY_OR_TRAVERSABLE_REQUIRED(); return NULL; } void ds_set_assign_union(ds_set_t *set, ds_set_t *other) { zval *value; DS_SET_FOREACH(other, value) { ds_set_add(set, value); } DS_SET_FOREACH_END(); } void ds_set_clear(ds_set_t *set) { ds_htable_clear(set->table); } void ds_set_free(ds_set_t *set) { ds_htable_free(set->table); efree(set); } void ds_set_reduce(ds_set_t *set, FCI_PARAMS, zval *initial, zval *return_value) { zval *value; zval carry; zval params[2]; if (initial == NULL) { ZVAL_NULL(&carry); } else { ZVAL_COPY_VALUE(&carry, initial); } DS_SET_FOREACH(set, value) { ZVAL_COPY_VALUE(¶ms[0], &carry); ZVAL_COPY_VALUE(¶ms[1], value); fci.param_count = 2; fci.params = params; fci.retval = &carry; if (zend_call_function(&fci, &fci_cache) == FAILURE || Z_ISUNDEF(carry)) { ZVAL_NULL(return_value); return; } Z_TRY_DELREF_P(&carry); } DS_SET_FOREACH_END(); ZVAL_COPY(return_value, &carry); } ds_set_t *ds_set_filter_callback(ds_set_t *set, FCI_PARAMS) { if (DS_SET_IS_EMPTY(set)) { return ds_set(); } else { zval *value; zval param; zval retval; ds_set_t *filtered = ds_set(); DS_SET_FOREACH(set, value) { ZVAL_COPY_VALUE(¶m, value); fci.param_count = 1; fci.params = ¶m; fci.retval = &retval; if (zend_call_function(&fci, &fci_cache) == FAILURE || Z_ISUNDEF(retval)) { ds_set_free(filtered); return NULL; } if (zend_is_true(&retval)) { ds_set_add(filtered, value); } zval_ptr_dtor(&retval); } DS_SET_FOREACH_END(); return filtered; } } ds_set_t *ds_set_filter(ds_set_t *set) { if (DS_SET_IS_EMPTY(set)) { return ds_set(); } else { zval *value; ds_set_t *filtered = ds_set(); DS_SET_FOREACH(set, value) { if (zend_is_true(value)) { ds_set_add(filtered, value); } } DS_SET_FOREACH_END(); return filtered; } } void ds_set_reverse(ds_set_t *set) { ds_htable_reverse(set->table); } ds_set_t *ds_set_reversed(ds_set_t *set) { return ds_set_ex(ds_htable_reversed(set->table)); } void ds_set_to_array(ds_set_t *set, zval *arr) { zval *value; array_init_size(arr, set->table->size); DS_HTABLE_FOREACH_KEY(set->table, value) { add_next_index_zval(arr, value); Z_TRY_ADDREF_P(value); } DS_HTABLE_FOREACH_END(); } void ds_set_sum(ds_set_t *set, zval *return_value) { zval *value; ZVAL_LONG(return_value, 0); DS_SET_FOREACH(set, value) { DS_ADD_TO_SUM(value, return_value); } DS_SET_FOREACH_END(); } ds-1.1.8/src/ds/ds_set.h0000644000076500000240000000437013065035057015220 0ustar rtheunissenstaff#ifndef DS_SET_H #define DS_SET_H #include "../common.h" #include "ds_htable.h" #define DS_SET_SIZE(s) ((s)->table->size) #define DS_SET_CAPACITY(s) ((s)->table->capacity) #define DS_SET_IS_EMPTY(s) (DS_SET_SIZE(s) == 0) #define DS_SET_FOREACH(set, value) DS_HTABLE_FOREACH_KEY(set->table, value) #define DS_SET_FOREACH_END() DS_HTABLE_FOREACH_END() typedef struct _ds_set_t { ds_htable_t *table; } ds_set_t; ds_set_t *ds_set(); ds_set_t *ds_set_ex(ds_htable_t *table); ds_set_t *ds_set_clone(ds_set_t *set); void ds_set_free(ds_set_t *set); void ds_set_clear(ds_set_t *set); void ds_set_allocate(ds_set_t *set, zend_long capacity); void ds_set_add(ds_set_t *set, zval *value); void ds_set_add_va(ds_set_t *set, VA_PARAMS); bool ds_set_contains_va(ds_set_t *set, VA_PARAMS); bool ds_set_contains(ds_set_t *set, zval *value); void ds_set_remove_va(ds_set_t *set, VA_PARAMS); void ds_set_to_array(ds_set_t *set, zval *arr); void ds_set_add_all(ds_set_t *set, zval *value); zval *ds_set_get(ds_set_t *set, zend_long index); zval *ds_set_get_first(ds_set_t *set); zval *ds_set_get_last(ds_set_t *set); ds_set_t *ds_set_slice(ds_set_t *set, zend_long index, zend_long length); void ds_set_sort_callback(ds_set_t *set); void ds_set_sort(ds_set_t *set); ds_set_t *ds_set_sorted_callback(ds_set_t *set); ds_set_t *ds_set_sorted(ds_set_t *set); void ds_set_join (ds_set_t *set, const char *glue, const size_t len, zval *return_value); void ds_set_reduce(ds_set_t *set, FCI_PARAMS, zval *initial, zval *return_value); ds_set_t *ds_set_filter_callback(ds_set_t *set, FCI_PARAMS); ds_set_t *ds_set_filter(ds_set_t *set); void ds_set_reverse (ds_set_t *set); ds_set_t *ds_set_reversed(ds_set_t *set); ds_set_t *ds_set_diff(ds_set_t *set, ds_set_t *other); ds_set_t *ds_set_intersect(ds_set_t *set, ds_set_t *other); ds_set_t *ds_set_xor(ds_set_t *set, ds_set_t *other); ds_set_t *ds_set_union(ds_set_t *set, ds_set_t *other); ds_set_t *ds_set_merge(ds_set_t *set, zval *values); void ds_set_assign_diff(ds_set_t *set, ds_set_t *other); void ds_set_assign_intersect(ds_set_t *set, ds_set_t *other); void ds_set_assign_xor(ds_set_t *set, ds_set_t *other); void ds_set_assign_union(ds_set_t *set, ds_set_t *other); void ds_set_sum(ds_set_t *set, zval *return_value); #endif ds-1.1.8/src/ds/ds_stack.c0000644000076500000240000000367413065035057015533 0ustar rtheunissenstaff#include "../common.h" #include "../php/iterators/php_stack_iterator.h" #include "../php/handlers/php_stack_handlers.h" #include "../php/classes/php_stack_ce.h" #include "ds_stack.h" ds_stack_t *ds_stack_ex(ds_vector_t *vector) { ds_stack_t *stack = ecalloc(1, sizeof(ds_stack_t)); stack->vector = vector; return stack; } ds_stack_t *ds_stack() { return ds_stack_ex(ds_vector()); } ds_stack_t *ds_stack_clone(ds_stack_t *stack) { return ds_stack_ex(ds_vector_clone(stack->vector)); } void ds_stack_free(ds_stack_t *stack) { ds_vector_free(stack->vector); efree(stack); } void ds_stack_allocate(ds_stack_t *stack, zend_long capacity) { ds_vector_allocate(stack->vector, capacity); } void ds_stack_push_va(ds_stack_t *stack, VA_PARAMS) { ds_vector_push_va(stack->vector, argc, argv); } void ds_stack_push(ds_stack_t *stack, zval *value) { ds_vector_push(stack->vector, value); } void ds_stack_clear(ds_stack_t *stack) { ds_vector_clear(stack->vector); } void ds_stack_push_all(ds_stack_t *stack, zval *value) { ds_vector_push_all(stack->vector, value); } void ds_stack_to_array(ds_stack_t *stack, zval *return_value) { zend_long size = DS_STACK_SIZE(stack); if (size == 0) { array_init(return_value); } else { zval *value; array_init_size(return_value, size); DS_VECTOR_FOREACH_REVERSED(stack->vector, value) { add_next_index_zval(return_value, value); Z_TRY_ADDREF_P(value); } DS_VECTOR_FOREACH_END(); } } void ds_stack_pop_throw(ds_stack_t *stack, zval *return_value) { ds_vector_pop_throw(stack->vector, return_value); } void ds_stack_pop(ds_stack_t *stack, zval *return_value) { ds_vector_pop(stack->vector, return_value); } zval *ds_stack_peek(ds_stack_t *stack) { return ds_vector_get_last(stack->vector); } zval *ds_stack_peek_throw(ds_stack_t *stack) { return ds_vector_get_last_throw(stack->vector); } ds-1.1.8/src/ds/ds_stack.h0000644000076500000240000000337213065035057015533 0ustar rtheunissenstaff#ifndef DS_STACK_H #define DS_STACK_H #include "../common.h" #include "ds_vector.h" #define DS_STACK_SIZE(s) ((s)->vector->size) #define DS_STACK_CAPACITY(s) ((s)->vector->capacity) #define DS_STACK_IS_EMPTY(s) (DS_STACK_SIZE(s) == 0) #define DS_STACK_FOREACH(stack, value) \ do { \ zval _tmp; \ \ ds_vector_t *_v = stack->vector; \ zval *_end = _v->buffer; \ zval *_pos = _end + _v->size - 1; \ \ for (; _pos >= _end; --_pos, --_v->size) { \ ZVAL_COPY(&_tmp, _pos); \ zval_ptr_dtor(_pos); \ value = &_tmp; #define DS_STACK_FOREACH_END() \ } \ zval_ptr_dtor(&_tmp); \ } while (0) \ typedef struct _ds_stack_t { ds_vector_t *vector; } ds_stack_t; ds_stack_t *ds_stack(); ds_stack_t *ds_stack_ex(ds_vector_t *vector); ds_stack_t *ds_stack_clone(ds_stack_t *stack); void ds_stack_push(ds_stack_t *stack, zval *value); void ds_stack_push_va(ds_stack_t *stack, VA_PARAMS); void ds_stack_allocate(ds_stack_t *stack, zend_long capacity); void ds_stack_clear(ds_stack_t *stack); void ds_stack_pop(ds_stack_t *stack, zval *return_value); void ds_stack_pop_throw(ds_stack_t *stack, zval *return_value); zval *ds_stack_peek(ds_stack_t *stack); zval *ds_stack_peek_throw(ds_stack_t *stack); void ds_stack_push_all(ds_stack_t *stack, zval *value); void ds_stack_to_array(ds_stack_t *stack, zval *return_value); void ds_stack_free(ds_stack_t *stack); #endif ds-1.1.8/src/ds/ds_vector.c0000644000076500000240000004157613065035057015733 0ustar rtheunissenstaff// #include "../common.h" #include "../php/iterators/php_vector_iterator.h" #include "../php/handlers/php_vector_handlers.h" #include "../php/classes/php_vector_ce.h" #include "ds_vector.h" static inline bool index_out_of_range(zend_long index, zend_long max) { if (index < 0 || index >= max) { INDEX_OUT_OF_RANGE(index, max); return true; } return false; } static inline void ds_vector_reallocate(ds_vector_t *vector, zend_long capacity) { REALLOC_ZVAL_BUFFER(vector->buffer, capacity); vector->capacity = capacity; } ds_vector_t *ds_vector_ex(zend_long capacity) { ds_vector_t *vector = ecalloc(1, sizeof(ds_vector_t)); // Make sure that capacity is valid. capacity = MAX(capacity, DS_VECTOR_MIN_CAPACITY); vector->buffer = ALLOC_ZVAL_BUFFER(capacity); vector->capacity = capacity; vector->size = 0; return vector; } ds_vector_t *ds_vector() { return ds_vector_ex(DS_VECTOR_MIN_CAPACITY); } static ds_vector_t *ds_vector_from_buffer_ex( zval *buffer, zend_long size, zend_long capacity ) { ds_vector_t *vector = ecalloc(1, sizeof(ds_vector_t)); vector->buffer = buffer; vector->capacity = capacity; vector->size = size; return vector; } ds_vector_t *ds_vector_clone(ds_vector_t *vector) { if (DS_VECTOR_IS_EMPTY(vector)) { return ds_vector(); } else { ds_vector_t *clone = ecalloc(1, sizeof(ds_vector_t)); clone->buffer = ALLOC_ZVAL_BUFFER(vector->capacity); clone->capacity = vector->capacity; clone->size = vector->size; COPY_ZVAL_BUFFER(clone->buffer, vector->buffer, vector->size); return clone; } } ds_vector_t *ds_vector_from_buffer(zval *buffer, zend_long size) { zend_long capacity = size; if (size < DS_VECTOR_MIN_CAPACITY) { capacity = DS_VECTOR_MIN_CAPACITY; REALLOC_ZVAL_BUFFER(buffer, capacity); } return ds_vector_from_buffer_ex(buffer, size, capacity); } void ds_vector_allocate(ds_vector_t *vector, zend_long capacity) { if (capacity > vector->capacity) { ds_vector_reallocate(vector, capacity); } } static inline void ds_vector_increase_capacity(ds_vector_t *vector) { ds_vector_reallocate(vector, vector->capacity + (vector->capacity / 2)); } static inline void ds_vector_ensure_capacity(ds_vector_t *vector, zend_long capacity) { if (capacity > vector->capacity) { zend_long boundary = vector->capacity + (vector->capacity / 2); ds_vector_reallocate(vector, MAX(capacity, boundary)); } } static inline void ds_vector_check_compact(ds_vector_t *vector) { const zend_long c = vector->capacity; const zend_long n = vector->size; if (n < c / 4 && c / 2 > DS_VECTOR_MIN_CAPACITY) { ds_vector_reallocate(vector, c / 2); } } void ds_vector_remove(ds_vector_t *vector, zend_long index, zval *return_value) { if (index_out_of_range(index, vector->size)) { return; } if (index == vector->size - 1) { ds_vector_pop(vector, return_value); } else { zval *pos = vector->buffer + index; if (return_value) { ZVAL_COPY(return_value, pos); } if ( ! Z_ISUNDEF_P(pos)) { zval_ptr_dtor(pos); } memmove(pos, pos + 1, sizeof(zval) * (vector->size - index)); vector->size--; ds_vector_check_compact(vector); } } zval *ds_vector_get(ds_vector_t *vector, zend_long index) { if (index_out_of_range(index, vector->size)) { return NULL; } return vector->buffer + index; } static inline void increase_capacity_if_full(ds_vector_t *vector) { if (vector->size == vector->capacity) { ds_vector_increase_capacity(vector); } } static inline void ds_vector_clear_buffer(ds_vector_t *vector) { zval *pos = vector->buffer; zval *end = vector->buffer + vector->size; for (; pos != end; ++pos) { DTOR_AND_UNDEF(pos); } vector->size = 0; } void ds_vector_clear(ds_vector_t *vector) { if (vector->size > 0) { ds_vector_clear_buffer(vector); if (vector->capacity > DS_VECTOR_MIN_CAPACITY) { ds_vector_reallocate(vector, DS_VECTOR_MIN_CAPACITY); } } } void ds_vector_set(ds_vector_t *vector, zend_long index, zval *value) { if ( ! index_out_of_range(index, vector->size)) { zval *ptr = vector->buffer + index; zval_ptr_dtor(ptr); ZVAL_COPY(ptr, value); } } /** * */ void ds_vector_to_array(ds_vector_t *vector, zval *return_value) { zend_long size = vector->size; if (size == 0) { array_init(return_value); } else { zval *pos = vector->buffer; zval *end = pos + size; array_init_size(return_value, size); for (; pos != end; ++pos) { add_next_index_zval(return_value, pos); Z_TRY_ADDREF_P(pos); } } } static inline zend_long ds_vector_find_index(ds_vector_t *vector, zval *value) { zval *pos = vector->buffer; zval *end = vector->buffer + vector->size; for (; pos != end; ++pos) { if (zend_is_identical(value, pos)) { return pos - vector->buffer; } } return FAILURE; } void ds_vector_find(ds_vector_t *vector, zval *value, zval *return_value) { zend_long index = ds_vector_find_index(vector, value); if (index >= 0) { ZVAL_LONG(return_value, index); return; } ZVAL_FALSE(return_value); } bool ds_vector_contains(ds_vector_t *vector, zval *value) { return ds_vector_find_index(vector, value) != FAILURE; } bool ds_vector_contains_va(ds_vector_t *vector, VA_PARAMS) { while (argc-- > 0) { if ( ! ds_vector_contains(vector, argv++)) { return false; } } return true; } void ds_vector_join(ds_vector_t *vector, char *str, size_t len, zval *return_value) { zend_string *s; s = ds_join_zval_buffer(vector->buffer, DS_VECTOR_SIZE(vector), str, len); ZVAL_STR(return_value, s); } void ds_vector_insert_va(ds_vector_t *vector, zend_long index, VA_PARAMS) { if ( ! index_out_of_range(index, vector->size + 1) && argc > 0) { zend_long len; zval *src; zval *dst; zval *end; ds_vector_ensure_capacity(vector, vector->size + argc); src = argv; dst = vector->buffer + index; end = dst + argc; len = vector->size - index; if (len > 0) { memmove(end, dst, (vector->size - index) * sizeof(zval)); } for (; dst != end; ++dst, ++src) { ZVAL_COPY(dst, src); } vector->size += argc; } } void ds_vector_insert(ds_vector_t *vector, zend_long index, zval *value) { ds_vector_insert_va(vector, index, 1, value); } void ds_vector_push(ds_vector_t *vector, zval *value) { increase_capacity_if_full(vector); ZVAL_COPY(&vector->buffer[vector->size++], value); } void ds_vector_push_va(ds_vector_t *vector, VA_PARAMS) { if (argc == 1) { ds_vector_push(vector, argv); return; } if (argc > 0) { zval *src, *dst, *end; ds_vector_ensure_capacity(vector, vector->size + argc); src = argv; dst = &vector->buffer[vector->size]; end = dst + argc; while (dst != end) { ZVAL_COPY(dst++, src++); } vector->size += argc; } } void ds_vector_unshift(ds_vector_t *vector, zval *value) { ds_vector_insert(vector, 0, value); } void ds_vector_unshift_va(ds_vector_t *vector, VA_PARAMS) { if (argc == 1) { ds_vector_unshift(vector, argv); return; } if (argc > 0) { zval *dst, *src, *end; ds_vector_ensure_capacity(vector, vector->size + argc); src = argv; dst = vector->buffer; end = dst + argc; memmove(end, dst, vector->size * sizeof(zval)); while (dst != end) { ZVAL_COPY(dst++, src++); } vector->size += argc; } } void ds_vector_sort_callback(ds_vector_t *vector) { ds_user_sort_zval_buffer(vector->buffer, vector->size); } void ds_vector_sort(ds_vector_t *vector) { ds_sort_zval_buffer(vector->buffer, vector->size); } bool ds_vector_isset(ds_vector_t *vector, zend_long index, int check_empty) { if (index < 0 || index >= vector->size) { return 0; } return ds_zval_isset(vector->buffer + index, check_empty); } bool ds_vector_index_exists(ds_vector_t *vector, zend_long index) { return index >= 0 && index < vector->size; } static int iterator_add(zend_object_iterator *iterator, void *puser) { ds_vector_push((ds_vector_t *) puser, iterator->funcs->get_current_data(iterator)); return ZEND_HASH_APPLY_KEEP; } static inline void add_traversable_to_vector(ds_vector_t *vector, zval *obj) { spl_iterator_apply(obj, iterator_add, (void*) vector); } static inline void add_array_to_vector(ds_vector_t *vector, HashTable *array) { zval *value; ds_vector_ensure_capacity(vector, vector->size + array->nNumOfElements); ZEND_HASH_FOREACH_VAL(array, value) { ds_vector_push(vector, value); } ZEND_HASH_FOREACH_END(); } void ds_vector_rotate(ds_vector_t *vector, zend_long r) { zval *a, *b, *c; zend_long n = vector->size; if (n < 2) { return; } // Negative rotation should rotate in the opposite direction if (r < 0) r = n - (llabs(r) % n); else if (r > n) r = r % n; // There's no need to rotate if the sequence won't be affected. if (r == 0 || r == n) return; a = vector->buffer; // Start of buffer b = a + r; // Pivot c = a + n; // End of buffer // [a..b....c] ds_reverse_zval_range(a, b); ds_reverse_zval_range(b, c); ds_reverse_zval_range(a, c); } void ds_vector_push_all(ds_vector_t *vector, zval *values) { if ( ! values) { return; } if (ds_is_array(values)) { add_array_to_vector(vector, Z_ARRVAL_P(values)); return; } if (ds_is_traversable(values)) { add_traversable_to_vector(vector, values); return; } ARRAY_OR_TRAVERSABLE_REQUIRED(); } ds_vector_t *ds_vector_merge(ds_vector_t *vector, zval *values) { if (values && (ds_is_array(values) || ds_is_traversable(values))) { ds_vector_t *merged = ds_vector_clone(vector); ds_vector_push_all(merged, values); return merged; } ARRAY_OR_TRAVERSABLE_REQUIRED(); return NULL; } void ds_vector_pop(ds_vector_t *vector, zval *return_value) { SET_AS_RETURN_AND_UNDEF(&vector->buffer[--vector->size]); ds_vector_check_compact(vector); } void ds_vector_pop_throw(ds_vector_t *vector, zval *return_value) { if (DS_VECTOR_IS_EMPTY(vector)) { NOT_ALLOWED_WHEN_EMPTY(); return; } ds_vector_pop(vector, return_value); } void ds_vector_shift(ds_vector_t *vector, zval *return_value) { zval *first = vector->buffer; SET_AS_RETURN_AND_UNDEF(first); vector->size--; memmove(first, first + 1, vector->size * sizeof(zval)); ds_vector_check_compact(vector); } void ds_vector_shift_throw(ds_vector_t *vector, zval *return_value) { if (DS_VECTOR_IS_EMPTY(vector)) { NOT_ALLOWED_WHEN_EMPTY(); return; } ds_vector_shift(vector, return_value); } zval *ds_vector_get_last(ds_vector_t *vector) { return &vector->buffer[vector->size - 1]; } zval *ds_vector_get_last_throw(ds_vector_t *vector) { if (DS_VECTOR_IS_EMPTY(vector)) { NOT_ALLOWED_WHEN_EMPTY(); return NULL; } return ds_vector_get_last(vector); } zval *ds_vector_get_first(ds_vector_t *vector) { return &vector->buffer[0]; } zval *ds_vector_get_first_throw(ds_vector_t *vector) { if (DS_VECTOR_IS_EMPTY(vector)) { NOT_ALLOWED_WHEN_EMPTY(); return NULL; } return ds_vector_get_first(vector); } void ds_vector_reverse(ds_vector_t *vector) { ds_reverse_zval_range(vector->buffer, vector->buffer + vector->size); } ds_vector_t *ds_vector_reversed(ds_vector_t *vector) { zval *value; zval *buffer = ALLOC_ZVAL_BUFFER(vector->capacity); zval *target = &buffer[vector->size - 1]; DS_VECTOR_FOREACH(vector, value) { ZVAL_COPY(target--, value); } DS_VECTOR_FOREACH_END(); return ds_vector_from_buffer_ex(buffer, vector->size, vector->capacity); } void ds_vector_apply(ds_vector_t *vector, FCI_PARAMS) { zval retval; zval *value; DS_VECTOR_FOREACH(vector, value) { fci.param_count = 1; fci.params = value; fci.retval = &retval; if (zend_call_function(&fci, &fci_cache) == FAILURE || Z_ISUNDEF(retval)) { return; } zval_ptr_dtor(value); ZVAL_COPY_VALUE(value, &retval); } DS_VECTOR_FOREACH_END(); } ds_vector_t *ds_vector_map(ds_vector_t *vector, FCI_PARAMS) { zval retval; zval *value; zval *buffer = ALLOC_ZVAL_BUFFER(vector->size); zval *target = buffer; DS_VECTOR_FOREACH(vector, value) { fci.param_count = 1; fci.params = value; fci.retval = &retval; if (zend_call_function(&fci, &fci_cache) == FAILURE || Z_ISUNDEF(retval)) { // Release the values copied into the buffer on failure. for (; target > buffer; target--) { zval_ptr_dtor(target - 1); } zval_ptr_dtor(&retval); efree(buffer); return NULL; } ZVAL_COPY(target++, &retval); zval_ptr_dtor(&retval); } DS_VECTOR_FOREACH_END(); return ds_vector_from_buffer_ex(buffer, vector->size, vector->capacity); } ds_vector_t *ds_vector_filter(ds_vector_t *vector) { if (DS_VECTOR_IS_EMPTY(vector)) { return ds_vector(); } else { zval *value; zval *buffer = ALLOC_ZVAL_BUFFER(vector->size); zval *target = buffer; DS_VECTOR_FOREACH(vector, value) { if (zend_is_true(value)) { ZVAL_COPY(target++, value); } } DS_VECTOR_FOREACH_END(); return ds_vector_from_buffer_ex(buffer, target - buffer, vector->size); } } ds_vector_t *ds_vector_filter_callback(ds_vector_t *vector, FCI_PARAMS) { if (DS_VECTOR_IS_EMPTY(vector)) { return ds_vector(); } else { zval retval; zval *value; zval *buffer = ALLOC_ZVAL_BUFFER(vector->size); zval *target = buffer; DS_VECTOR_FOREACH(vector, value) { fci.param_count = 1; fci.params = value; fci.retval = &retval; // Catch potential exceptions or other errors during comparison. if (zend_call_function(&fci, &fci_cache) == FAILURE || Z_ISUNDEF(retval)) { // Release the values copied into the buffer on failure. for (; target > buffer; target--) { zval_ptr_dtor(target - 1); } zval_ptr_dtor(&retval); efree(buffer); return NULL; } // Copy the value into the buffer if the callback returned true. if (zend_is_true(&retval)) { ZVAL_COPY(target++, value); } zval_ptr_dtor(&retval); } DS_VECTOR_FOREACH_END(); return ds_vector_from_buffer_ex(buffer, (target - buffer), vector->size); } } void ds_vector_reduce(ds_vector_t *vector, zval *initial, zval *return_value, FCI_PARAMS) { zval *value; zval carry; zval params[2]; if (initial == NULL) { ZVAL_NULL(&carry); } else { ZVAL_COPY_VALUE(&carry, initial); } DS_VECTOR_FOREACH(vector, value) { ZVAL_COPY_VALUE(¶ms[0], &carry); ZVAL_COPY_VALUE(¶ms[1], value); fci.param_count = 2; fci.params = params; fci.retval = &carry; if (zend_call_function(&fci, &fci_cache) == FAILURE || Z_ISUNDEF(carry)) { zval_ptr_dtor(&carry); ZVAL_NULL(return_value); return; } Z_TRY_DELREF_P(&carry); } DS_VECTOR_FOREACH_END(); ZVAL_COPY(return_value, &carry); } ds_vector_t *ds_vector_slice(ds_vector_t *vector, zend_long index, zend_long length) { ds_normalize_slice_args(&index, &length, vector->size); if (length == 0) { return ds_vector(); } else { zval *src, *dst, *end; zval *buffer = ALLOC_ZVAL_BUFFER(length); src = vector->buffer + index; end = src + length; dst = buffer; for (; src < end; ++src, ++dst) { ZVAL_COPY(dst, src); } return ds_vector_from_buffer(buffer, length); } } void ds_vector_sum(ds_vector_t *vector, zval *return_value) { zval *value; ZVAL_LONG(return_value, 0); DS_VECTOR_FOREACH(vector, value) { DS_ADD_TO_SUM(value, return_value); } DS_VECTOR_FOREACH_END(); } void ds_vector_free(ds_vector_t *vector) { ds_vector_clear_buffer(vector); efree(vector->buffer); efree(vector); } ds-1.1.8/src/ds/ds_vector.h0000644000076500000240000000712713065035057015732 0ustar rtheunissenstaff#ifndef DS_VECTOR_H #define DS_VECTOR_H #include "../common.h" typedef struct ds_vector { zval *buffer; zend_long capacity; // Buffer length zend_long size; // Number of values in the buffer } ds_vector_t; #define DS_VECTOR_MIN_CAPACITY 10 // Does not have to be a power of 2 #define DS_VECTOR_SIZE(v) ((v)->size) #define DS_VECTOR_IS_EMPTY(v) (DS_VECTOR_SIZE(v) == 0) /** * */ #define DS_VECTOR_FOREACH(v, z) \ do { \ zval *x = v->buffer; \ zval *y = x + v->size; \ for (; x < y; ++x) { \ z = x; /** * */ #define DS_VECTOR_FOREACH_REVERSED(v, z) \ do { \ zval *y = v->buffer; \ zval *x = y + v->size - 1; \ for (; x >= y; --x) { \ z = x; /** * */ #define DS_VECTOR_FOREACH_END() \ } \ } while (0) ds_vector_t *ds_vector_clone(ds_vector_t *src); ds_vector_t *ds_vector(); ds_vector_t *ds_vector_ex(zend_long capacity); ds_vector_t *ds_vector_from_buffer(zval *buffer, zend_long size); void ds_vector_allocate(ds_vector_t *vector, zend_long capacity); void ds_vector_clear(ds_vector_t *vector); void ds_vector_free(ds_vector_t *vector); void ds_vector_set(ds_vector_t *vector, zend_long index, zval *value); void ds_vector_pop(ds_vector_t *vector, zval *return_value); void ds_vector_pop_throw(ds_vector_t *vector, zval *return_value); void ds_vector_shift(ds_vector_t *vector, zval *return_value); void ds_vector_shift_throw(ds_vector_t *vector, zval *return_value); void ds_vector_find(ds_vector_t *vector, zval *value, zval *return_value); void ds_vector_remove(ds_vector_t *vector, zend_long index, zval *return_value); void ds_vector_insert(ds_vector_t *vector, zend_long index, zval *value); void ds_vector_insert_va(ds_vector_t *vector, zend_long index, VA_PARAMS); void ds_vector_unshift(ds_vector_t *vector, zval *value); void ds_vector_unshift_va(ds_vector_t *vector, VA_PARAMS); bool ds_vector_contains(ds_vector_t *vector, zval *value); bool ds_vector_contains_va(ds_vector_t *vector, VA_PARAMS); void ds_vector_push(ds_vector_t *vector, zval *value); void ds_vector_push_va(ds_vector_t *vector, VA_PARAMS); void ds_vector_push_all(ds_vector_t *vector, zval *values); zval *ds_vector_get(ds_vector_t *vector, zend_long index); zval *ds_vector_get_last(ds_vector_t *vector); zval *ds_vector_get_first(ds_vector_t *vector); zval *ds_vector_get_last_throw(ds_vector_t *vector); zval *ds_vector_get_first_throw(ds_vector_t *vector); ds_vector_t *ds_vector_map(ds_vector_t *vector, FCI_PARAMS); ds_vector_t *ds_vector_slice(ds_vector_t *vector, zend_long index, zend_long length); ds_vector_t *ds_vector_filter(ds_vector_t *vector); ds_vector_t *ds_vector_filter_callback(ds_vector_t *vector, FCI_PARAMS); ds_vector_t *ds_vector_merge(ds_vector_t *vector, zval *values); ds_vector_t *ds_vector_reversed(ds_vector_t *vector); void ds_vector_reduce(ds_vector_t *vector, zval *initial, zval *return_value, FCI_PARAMS); void ds_vector_reverse(ds_vector_t *vector); void ds_vector_rotate(ds_vector_t *vector, zend_long rotations); void ds_vector_join(ds_vector_t *vector, char *str, size_t len, zval *return_value); void ds_vector_apply(ds_vector_t *vector, FCI_PARAMS); void ds_vector_sum(ds_vector_t *vector, zval *return_value); void ds_vector_sort(ds_vector_t *vector); void ds_vector_sort_callback(ds_vector_t *vector); void ds_vector_to_array(ds_vector_t *vector, zval *return_value); bool ds_vector_index_exists(ds_vector_t *vector, zend_long index); bool ds_vector_isset(ds_vector_t *vector, zend_long index, int check_empty); #endif ds-1.1.8/src/php/classes/php_collection_ce.c0000644000076500000240000000144113065035057021215 0ustar rtheunissenstaff#include "../../common.h" #include "php_collection_ce.h" zend_class_entry *collection_ce; #define COLLECTION_ABSTRACT_ME(name) \ PHP_ABSTRACT_ME(Collection, name, arginfo_Collection_##name) void php_ds_register_collection() { zend_class_entry ce; zend_function_entry methods[] = { COLLECTION_ABSTRACT_ME(clear) COLLECTION_ABSTRACT_ME(copy) COLLECTION_ABSTRACT_ME(isEmpty) COLLECTION_ABSTRACT_ME(toArray) PHP_FE_END }; INIT_CLASS_ENTRY(ce, PHP_DS_NS(Collection), methods); collection_ce = zend_register_internal_interface(&ce); zend_class_implements(collection_ce, 3, zend_ce_traversable, // Traversable spl_ce_Countable, // Countable php_json_serializable_ce // Serializable ); } ds-1.1.8/src/php/classes/php_collection_ce.h0000644000076500000240000000154213065035057021224 0ustar rtheunissenstaff#ifndef DS_COLLECTION_CE_H #define DS_COLLECTION_CE_H #include "../../common.h" #include "../arginfo.h" extern zend_class_entry *collection_ce; #define PHP_DS_COLLECTION_ME(cls, name) \ PHP_ME(cls, name, arginfo_Collection_##name, ZEND_ACC_PUBLIC) #define PHP_DS_COLLECTION_ME_LIST(cls) \ PHP_DS_COLLECTION_ME(cls, clear) \ PHP_DS_COLLECTION_ME(cls, copy) \ PHP_DS_COLLECTION_ME(cls, count) \ PHP_DS_COLLECTION_ME(cls, isEmpty) \ PHP_DS_COLLECTION_ME(cls, jsonSerialize) \ PHP_DS_COLLECTION_ME(cls, toArray) ARGINFO_NONE_RETURN_DS( Collection_copy, Collection); ARGINFO_NONE( Collection_clear); ARGINFO_NONE_RETURN_LONG( Collection_count); ARGINFO_NONE_RETURN_BOOL( Collection_isEmpty); ARGINFO_NONE( Collection_jsonSerialize); ARGINFO_NONE_RETURN_ARRAY( Collection_toArray); void php_ds_register_collection(); #endif ds-1.1.8/src/php/classes/php_deque_ce.c0000644000076500000240000001260013065035057020164 0ustar rtheunissenstaff#include "../../common.h" #include "../parameters.h" #include "../arginfo.h" #include "../objects/php_deque.h" #include "../iterators/php_deque_iterator.h" #include "../handlers/php_deque_handlers.h" #include "php_collection_ce.h" #include "php_sequence_ce.h" #include "php_deque_ce.h" #define METHOD(name) PHP_METHOD(Deque, name) zend_class_entry *php_ds_deque_ce; METHOD(__construct) { PARSE_OPTIONAL_ZVAL(values); if (values) { ds_deque_push_all(THIS_DS_DEQUE(), values); } } METHOD(join) { if (ZEND_NUM_ARGS()) { PARSE_STRING(); ds_deque_join(THIS_DS_DEQUE(), str, len, return_value); } else { ds_deque_join(THIS_DS_DEQUE(), NULL, 0, return_value); } } METHOD(allocate) { PARSE_LONG(capacity); ds_deque_allocate(THIS_DS_DEQUE(), capacity); } METHOD(apply) { PARSE_CALLABLE(); ds_deque_apply(THIS_DS_DEQUE(), FCI_ARGS); } METHOD(capacity) { PARSE_NONE; RETURN_LONG((THIS_DS_DEQUE())->capacity); } METHOD(pushAll) { PARSE_ZVAL(values); ds_deque_push_all(THIS_DS_DEQUE(), values); } METHOD(map) { PARSE_CALLABLE(); RETURN_DS_DEQUE(ds_deque_map(THIS_DS_DEQUE(), FCI_ARGS)); } METHOD(merge) { PARSE_ZVAL(values); RETURN_DS_DEQUE(ds_deque_merge(THIS_DS_DEQUE(), values)); } METHOD(reduce) { PARSE_CALLABLE_AND_OPTIONAL_ZVAL(initial); ds_deque_reduce(THIS_DS_DEQUE(), initial, return_value, FCI_ARGS); } METHOD(filter) { if (ZEND_NUM_ARGS()) { PARSE_CALLABLE(); RETURN_DS_DEQUE(ds_deque_filter_callback(THIS_DS_DEQUE(), FCI_ARGS)); } else { PARSE_NONE; RETURN_DS_DEQUE(ds_deque_filter(THIS_DS_DEQUE())); } } METHOD(slice) { ds_deque_t *deque = THIS_DS_DEQUE(); if (ZEND_NUM_ARGS() > 1) { PARSE_LONG_AND_LONG(index, length); RETURN_DS_DEQUE(ds_deque_slice(deque, index, length)); } else { PARSE_LONG(index); RETURN_DS_DEQUE(ds_deque_slice(deque, index, deque->size)); } } METHOD(sort) { ds_deque_t *sorted = THIS_DS_DEQUE(); if (ZEND_NUM_ARGS()) { PARSE_COMPARE_CALLABLE(); ds_deque_sort_callback(sorted); } else { ds_deque_sort(sorted); } } METHOD(sorted) { ds_deque_t *sorted = ds_deque_clone(THIS_DS_DEQUE()); if (ZEND_NUM_ARGS()) { PARSE_COMPARE_CALLABLE(); ds_deque_sort_callback(sorted); } else { ds_deque_sort(sorted); } RETURN_DS_DEQUE(sorted); } METHOD(push) { PARSE_VARIADIC_ZVAL(); if (argc == 1) { ds_deque_push(THIS_DS_DEQUE(), argv); } else { ds_deque_push_va(THIS_DS_DEQUE(), argc, argv); } } METHOD(unshift) { PARSE_VARIADIC_ZVAL(); ds_deque_unshift_va(THIS_DS_DEQUE(), argc, argv); } METHOD(pop) { PARSE_NONE; ds_deque_pop_throw(THIS_DS_DEQUE(), return_value); } METHOD(shift) { PARSE_NONE; ds_deque_shift_throw(THIS_DS_DEQUE(), return_value); } METHOD(first) { PARSE_NONE; RETURN_ZVAL_COPY(ds_deque_get_first_throw(THIS_DS_DEQUE())); } METHOD(last) { PARSE_NONE; RETURN_ZVAL_COPY(ds_deque_get_last_throw(THIS_DS_DEQUE())); } METHOD(count) { ds_deque_t *deque = THIS_DS_DEQUE(); PARSE_NONE; RETURN_LONG(deque->size); } METHOD(clear) { PARSE_NONE; ds_deque_clear(THIS_DS_DEQUE()); } METHOD(contains) { PARSE_VARIADIC_ZVAL(); RETURN_BOOL(ds_deque_contains_va(THIS_DS_DEQUE(), argc, argv)); } METHOD(sum) { PARSE_NONE; ds_deque_sum(THIS_DS_DEQUE(), return_value); } METHOD(toArray) { PARSE_NONE; ds_deque_to_array(THIS_DS_DEQUE(), return_value); } METHOD(get) { PARSE_LONG(index); RETURN_ZVAL_COPY(ds_deque_get(THIS_DS_DEQUE(), index)); } METHOD(set) { PARSE_LONG_AND_ZVAL(index, value); ds_deque_set(THIS_DS_DEQUE(), index, value); } METHOD(find) { PARSE_ZVAL(value); ds_deque_find(THIS_DS_DEQUE(), value, return_value); } METHOD(remove) { PARSE_LONG(index); ds_deque_remove(THIS_DS_DEQUE(), index, return_value); } METHOD(insert) { PARSE_LONG_AND_VARIADIC_ZVAL(index); ds_deque_insert_va(THIS_DS_DEQUE(), index, argc, argv); } METHOD(reverse) { PARSE_NONE; ds_deque_reverse(THIS_DS_DEQUE()); } METHOD(reversed) { PARSE_NONE; RETURN_DS_DEQUE(ds_deque_reversed(THIS_DS_DEQUE())); } METHOD(rotate) { PARSE_LONG(rotations); ds_deque_rotate(THIS_DS_DEQUE(), rotations); } METHOD(isEmpty) { PARSE_NONE; RETURN_BOOL(DS_DEQUE_IS_EMPTY(THIS_DS_DEQUE())); } METHOD(copy) { PARSE_NONE; RETURN_OBJ(php_ds_deque_create_clone(THIS_DS_DEQUE())); } METHOD(jsonSerialize) { PARSE_NONE; ds_deque_to_array(THIS_DS_DEQUE(), return_value); } void php_ds_register_deque() { zend_class_entry ce; zend_function_entry methods[] = { PHP_DS_COLLECTION_ME_LIST(Deque) PHP_DS_SEQUENCE_ME_LIST(Deque) PHP_FE_END }; INIT_CLASS_ENTRY(ce, PHP_DS_NS(Deque), methods); php_ds_deque_ce = zend_register_internal_class(&ce); php_ds_deque_ce->ce_flags |= ZEND_ACC_FINAL; php_ds_deque_ce->create_object = php_ds_deque_create_object; php_ds_deque_ce->get_iterator = php_ds_deque_get_iterator; php_ds_deque_ce->serialize = php_ds_deque_serialize; php_ds_deque_ce->unserialize = php_ds_deque_unserialize; zend_declare_class_constant_long(php_ds_deque_ce, STR_AND_LEN("MIN_CAPACITY"), DS_DEQUE_MIN_CAPACITY); zend_class_implements(php_ds_deque_ce, 1, sequence_ce); php_ds_register_deque_handlers(); } ds-1.1.8/src/php/classes/php_deque_ce.h0000644000076500000240000000022013065035057020164 0ustar rtheunissenstaff#ifndef DS_DEQUE_CE_H #define DS_DEQUE_CE_H #include "php.h" extern zend_class_entry *php_ds_deque_ce; void php_ds_register_deque(); #endif ds-1.1.8/src/php/classes/php_hashable_ce.c0000644000076500000240000000102313065035057020625 0ustar rtheunissenstaff#include "../../common.h" #include "../arginfo.h" #include "php_hashable_ce.h" zend_class_entry *hashable_ce; ARGINFO_NONE(hash); ARGINFO_ZVAL_RETURN_BOOL(equals, obj); static zend_function_entry hashable_methods[] = { PHP_ABSTRACT_ME(Hashable, hash, arginfo_hash) PHP_ABSTRACT_ME(Hashable, equals, arginfo_equals) PHP_FE_END }; void php_ds_register_hashable() { zend_class_entry ce; INIT_CLASS_ENTRY(ce, PHP_DS_NS(Hashable), hashable_methods); hashable_ce = zend_register_internal_interface(&ce); } ds-1.1.8/src/php/classes/php_hashable_ce.h0000644000076500000240000000022513065035057020635 0ustar rtheunissenstaff#ifndef DS_HASHABLE_CE_H #define DS_HASHABLE_CE_H #include "php.h" extern zend_class_entry *hashable_ce; void php_ds_register_hashable(); #endif ds-1.1.8/src/php/classes/php_map_ce.c0000644000076500000240000001525213065035057017644 0ustar rtheunissenstaff#include "../../common.h" #include "../parameters.h" #include "../arginfo.h" #include "../objects/php_vector.h" #include "../objects/php_map.h" #include "../objects/php_pair.h" #include "../objects/php_set.h" #include "../iterators/php_map_iterator.h" #include "../handlers/php_map_handlers.h" #include "php_collection_ce.h" #include "php_map_ce.h" #define METHOD(name) PHP_METHOD(Map, name) zend_class_entry *php_ds_map_ce; METHOD(__construct) { PARSE_OPTIONAL_ZVAL(values); if (values) { ds_map_put_all(THIS_DS_MAP(), values); } } METHOD(allocate) { PARSE_LONG(capacity); ds_map_allocate(THIS_DS_MAP(), capacity); } METHOD(apply) { PARSE_CALLABLE(); ds_map_apply(THIS_DS_MAP(), FCI_ARGS); } METHOD(capacity) { PARSE_NONE; RETURN_LONG(ds_map_capacity(THIS_DS_MAP())); } METHOD(put) { PARSE_ZVAL_ZVAL(key, value); ds_map_put(THIS_DS_MAP(), key, value); } METHOD(putAll) { PARSE_ZVAL(values); ds_map_put_all(THIS_DS_MAP(), values); } METHOD(get) { PARSE_ZVAL_OPTIONAL_ZVAL(key, def); RETURN_ZVAL_COPY(ds_map_get(THIS_DS_MAP(), key, def)); } METHOD(intersect) { PARSE_OBJ(obj, php_ds_map_ce); RETURN_DS_MAP(ds_map_intersect(THIS_DS_MAP(), Z_DS_MAP_P(obj))); } METHOD(remove) { PARSE_ZVAL_OPTIONAL_ZVAL(key, def); ds_map_remove(THIS_DS_MAP(), key, def, return_value); } METHOD(hasKey) { PARSE_ZVAL(key); RETURN_BOOL(ds_map_has_key(THIS_DS_MAP(), key)); } METHOD(hasValue) { PARSE_ZVAL(value); RETURN_BOOL(ds_map_has_value(THIS_DS_MAP(), value)); } METHOD(diff) { PARSE_OBJ(obj, php_ds_map_ce); RETURN_DS_MAP(ds_map_diff(THIS_DS_MAP(), Z_DS_MAP_P(obj))); } METHOD(clear) { PARSE_NONE; ds_map_clear(THIS_DS_MAP()); } METHOD(sort) { if (ZEND_NUM_ARGS()) { PARSE_COMPARE_CALLABLE(); ds_map_sort_by_value_callback(THIS_DS_MAP()); } else { ds_map_sort_by_value(THIS_DS_MAP()); } } METHOD(sorted) { if (ZEND_NUM_ARGS()) { PARSE_COMPARE_CALLABLE(); RETURN_DS_MAP(ds_map_sorted_by_value_callback(THIS_DS_MAP())); } else { RETURN_DS_MAP(ds_map_sorted_by_value(THIS_DS_MAP())); } } METHOD(ksort) { if (ZEND_NUM_ARGS()) { PARSE_COMPARE_CALLABLE(); ds_map_sort_by_key_callback(THIS_DS_MAP()); } else { ds_map_sort_by_key(THIS_DS_MAP()); } } METHOD(ksorted) { if (ZEND_NUM_ARGS()) { PARSE_COMPARE_CALLABLE(); RETURN_DS_MAP(ds_map_sorted_by_key_callback(THIS_DS_MAP())); } else { RETURN_DS_MAP(ds_map_sorted_by_key(THIS_DS_MAP())); } } METHOD(keys) { PARSE_NONE; RETURN_DS_SET(ds_set_ex(ds_htable_clone(THIS_DS_MAP()->table))); } METHOD(last) { PARSE_NONE; RETURN_DS_PAIR(ds_map_last(THIS_DS_MAP())); } METHOD(merge) { PARSE_ZVAL(values); RETURN_DS_MAP(ds_map_merge(THIS_DS_MAP(), values)); } METHOD(pairs) { ds_map_t *map = THIS_DS_MAP(); PARSE_NONE; RETURN_DS_VECTOR( ds_vector_from_buffer(ds_map_pairs(map), DS_MAP_SIZE(map))); } METHOD(toArray) { PARSE_NONE; ds_map_to_array(THIS_DS_MAP(), return_value); } METHOD(count) { PARSE_NONE; RETURN_LONG(DS_MAP_SIZE(THIS_DS_MAP())); } METHOD(isEmpty) { PARSE_NONE; RETURN_BOOL(DS_MAP_IS_EMPTY(THIS_DS_MAP())); } METHOD(copy) { PARSE_NONE; RETURN_OBJ(php_ds_map_create_clone(THIS_DS_MAP())); } METHOD(jsonSerialize) { PARSE_NONE; ds_map_to_array(THIS_DS_MAP(), return_value); } METHOD(filter) { if (ZEND_NUM_ARGS()) { PARSE_CALLABLE(); RETURN_DS_MAP(ds_map_filter_callback(THIS_DS_MAP(), FCI_ARGS)); } else { RETURN_DS_MAP(ds_map_filter(THIS_DS_MAP())); } } METHOD(first) { PARSE_NONE; RETURN_DS_PAIR(ds_map_first(THIS_DS_MAP())); } METHOD(reduce) { PARSE_CALLABLE_AND_OPTIONAL_ZVAL(initial); ds_map_reduce(THIS_DS_MAP(), FCI_ARGS, initial, return_value); } METHOD(reverse) { PARSE_NONE; ds_map_reverse(THIS_DS_MAP()); } METHOD(reversed) { PARSE_NONE; RETURN_DS_MAP(ds_map_reversed(THIS_DS_MAP())); } METHOD(skip) { PARSE_LONG(position); RETURN_DS_PAIR(ds_map_skip(THIS_DS_MAP(), position)); } METHOD(map) { PARSE_CALLABLE(); RETURN_DS_MAP(ds_map_map(THIS_DS_MAP(), FCI_ARGS)); } METHOD(slice) { ds_map_t *map = THIS_DS_MAP(); if (ZEND_NUM_ARGS() > 1) { PARSE_LONG_AND_LONG(index, length); RETURN_DS_MAP(ds_map_slice(map, index, length)); } else { PARSE_LONG(index); RETURN_DS_MAP(ds_map_slice(map, index, DS_MAP_SIZE(map))); } } METHOD(sum) { PARSE_NONE; ds_map_sum(THIS_DS_MAP(), return_value); } METHOD(union) { PARSE_OBJ(obj, php_ds_map_ce); RETURN_DS_MAP(ds_map_union(THIS_DS_MAP(), Z_DS_MAP_P(obj))); } METHOD(values) { ds_map_t *map = THIS_DS_MAP(); PARSE_NONE; RETURN_DS_VECTOR( ds_vector_from_buffer(ds_map_values(map), DS_MAP_SIZE(map))); } METHOD(xor) { PARSE_OBJ(obj, php_ds_map_ce); RETURN_DS_MAP(ds_map_xor(THIS_DS_MAP(), Z_DS_MAP_P(obj))); } void php_ds_register_map() { zend_class_entry ce; zend_function_entry methods[] = { PHP_DS_ME(Map, __construct) PHP_DS_ME(Map, allocate) PHP_DS_ME(Map, apply) PHP_DS_ME(Map, capacity) PHP_DS_ME(Map, diff) PHP_DS_ME(Map, filter) PHP_DS_ME(Map, first) PHP_DS_ME(Map, get) PHP_DS_ME(Map, hasKey) PHP_DS_ME(Map, hasValue) PHP_DS_ME(Map, intersect) PHP_DS_ME(Map, keys) PHP_DS_ME(Map, ksort) PHP_DS_ME(Map, ksorted) PHP_DS_ME(Map, last) PHP_DS_ME(Map, map) PHP_DS_ME(Map, merge) PHP_DS_ME(Map, pairs) PHP_DS_ME(Map, put) PHP_DS_ME(Map, putAll) PHP_DS_ME(Map, reduce) PHP_DS_ME(Map, remove) PHP_DS_ME(Map, reverse) PHP_DS_ME(Map, reversed) PHP_DS_ME(Map, skip) PHP_DS_ME(Map, slice) PHP_DS_ME(Map, sort) PHP_DS_ME(Map, sorted) PHP_DS_ME(Map, sum) PHP_DS_ME(Map, union) PHP_DS_ME(Map, values) PHP_DS_ME(Map, xor) PHP_DS_COLLECTION_ME_LIST(Map) PHP_FE_END }; INIT_CLASS_ENTRY(ce, PHP_DS_NS(Map), methods); php_ds_map_ce = zend_register_internal_class(&ce); php_ds_map_ce->ce_flags |= ZEND_ACC_FINAL; php_ds_map_ce->create_object = php_ds_map_create_object; php_ds_map_ce->get_iterator = php_ds_map_get_iterator; php_ds_map_ce->serialize = php_ds_map_serialize; php_ds_map_ce->unserialize = php_ds_map_unserialize; zend_declare_class_constant_long( php_ds_map_ce, STR_AND_LEN("MIN_CAPACITY"), DS_HTABLE_MIN_CAPACITY ); zend_class_implements(php_ds_map_ce, 1, collection_ce); php_ds_register_map_handlers(); } ds-1.1.8/src/php/classes/php_map_ce.h0000644000076500000240000000454213065035057017651 0ustar rtheunissenstaff#ifndef DS_MAP_CE_H #define DS_MAP_CE_H #include "php.h" #include "../../common.h" #include "../arginfo.h" extern zend_class_entry *php_ds_map_ce; ARGINFO_OPTIONAL_ZVAL( Map___construct, values); ARGINFO_LONG( Map_allocate, capacity); ARGINFO_CALLABLE( Map_apply, callback); ARGINFO_NONE_RETURN_LONG( Map_capacity); ARGINFO_ZVAL_ZVAL( Map_put, key, value); ARGINFO_ZVAL( Map_putAll, values); ARGINFO_ZVAL_OPTIONAL_ZVAL( Map_get, key, default); ARGINFO_DS_RETURN_DS( Map_intersect, map, Map, Map); ARGINFO_ZVAL_OPTIONAL_ZVAL( Map_remove, key, default); ARGINFO_ZVAL_RETURN_BOOL( Map_hasKey, key); ARGINFO_ZVAL_RETURN_BOOL( Map_hasValue, value); ARGINFO_DS_RETURN_DS( Map_diff, map, Map, Map); ARGINFO_OPTIONAL_CALLABLE( Map_sort, comparator); ARGINFO_OPTIONAL_CALLABLE_RETURN_DS( Map_sorted, comparator, Map); ARGINFO_OPTIONAL_CALLABLE( Map_ksort, comparator); ARGINFO_OPTIONAL_CALLABLE_RETURN_DS( Map_ksorted, comparator, Map); ARGINFO_NONE_RETURN_DS( Map_keys, Set); ARGINFO_NONE_RETURN_DS( Map_last, Pair); ARGINFO_ZVAL_RETURN_DS( Map_merge, values, Map); ARGINFO_NONE_RETURN_DS( Map_pairs, Sequence); ARGINFO_NONE( Map_jsonSerialize); ARGINFO_OPTIONAL_CALLABLE_RETURN_DS( Map_filter, callback, Map); ARGINFO_NONE_RETURN_DS( Map_first, Pair); ARGINFO_CALLABLE_OPTIONAL_ZVAL( Map_reduce, callback, initial); ARGINFO_NONE( Map_reverse); ARGINFO_NONE_RETURN_DS( Map_reversed, Map); ARGINFO_LONG_RETURN_DS( Map_skip, position, Pair); ARGINFO_CALLABLE_RETURN_DS( Map_map, callback, Map); ARGINFO_LONG_OPTIONAL_LONG_RETURN_DS( Map_slice, index, length, Map); ARGINFO_NONE( Map_sum); ARGINFO_ZVAL_RETURN_DS( Map_union, map, Map); ARGINFO_NONE_RETURN_DS( Map_values, Sequence); ARGINFO_DS_RETURN_DS( Map_xor, map, Map, Map); void php_ds_register_map(); #endif ds-1.1.8/src/php/classes/php_pair_ce.c0000644000076500000240000000315513065035057020021 0ustar rtheunissenstaff#include "../../common.h" #include "../parameters.h" #include "../arginfo.h" #include "../objects/php_pair.h" #include "../handlers/php_pair_handlers.h" #include "php_pair_ce.h" #define METHOD(name) PHP_METHOD(Pair, name) zend_class_entry *php_ds_pair_ce; METHOD(__construct) { PARSE_OPTIONAL_ZVAL_OPTIONAL_ZVAL(key, value); { ds_pair_t *pair = THIS_DS_PAIR(); if (key) { ZVAL_COPY(&pair->key, key); } else { ZVAL_NULL(&pair->key); } if (value) { ZVAL_COPY(&pair->value, value); } else { ZVAL_NULL(&pair->value); } } } METHOD(copy) { PARSE_NONE; RETURN_DS_PAIR(ds_pair_clone(THIS_DS_PAIR())); } METHOD(toArray) { PARSE_NONE; ds_pair_to_array(THIS_DS_PAIR(), return_value); } METHOD(jsonSerialize) { PARSE_NONE; ds_pair_to_array(THIS_DS_PAIR(), return_value); } void php_ds_register_pair() { zend_class_entry ce; zend_function_entry methods[] = { PHP_DS_ME(Pair, __construct) PHP_DS_ME(Pair, copy) PHP_DS_ME(Pair, jsonSerialize) PHP_DS_ME(Pair, toArray) PHP_FE_END }; INIT_CLASS_ENTRY(ce, PHP_DS_NS(Pair), methods); php_ds_pair_ce = zend_register_internal_class(&ce); php_ds_pair_ce->ce_flags |= ZEND_ACC_FINAL; php_ds_pair_ce->create_object = php_ds_pair_create_object; php_ds_pair_ce->serialize = php_ds_pair_serialize; php_ds_pair_ce->unserialize = php_ds_pair_unserialize; zend_class_implements(php_ds_pair_ce, 1, php_json_serializable_ce); php_ds_register_pair_handlers(); } ds-1.1.8/src/php/classes/php_pair_ce.h0000644000076500000240000000066413065035057020030 0ustar rtheunissenstaff#ifndef DS_PAIR_CE_H #define DS_PAIR_CE_H #include "php.h" #include "../../common.h" #include "../arginfo.h" extern zend_class_entry *php_ds_pair_ce; ARGINFO_OPTIONAL_ZVAL_OPTIONAL_ZVAL( Pair___construct, key, value); ARGINFO_NONE_RETURN_DS( Pair_copy, Pair); ARGINFO_NONE_RETURN_ARRAY( Pair_toArray); ARGINFO_NONE( Pair_jsonSerialize); void php_ds_register_pair(); #endif ds-1.1.8/src/php/classes/php_priority_queue_ce.c0000644000076500000240000000545113065035057022154 0ustar rtheunissenstaff#include "../../common.h" #include "../parameters.h" #include "../arginfo.h" #include "../iterators/php_priority_queue_iterator.h" #include "../handlers/php_priority_queue_handlers.h" #include "../objects/php_priority_queue.h" #include "php_collection_ce.h" #include "php_priority_queue_ce.h" #define METHOD(name) PHP_METHOD(PriorityQueue, name) zend_class_entry *php_ds_priority_queue_ce; METHOD(__construct) { PARSE_NONE; } METHOD(allocate) { PARSE_LONG(capacity); ds_priority_queue_allocate(THIS_DS_PRIORITY_QUEUE(), capacity); } METHOD(capacity) { PARSE_NONE; RETURN_LONG(ds_priority_queue_capacity(THIS_DS_PRIORITY_QUEUE())); } METHOD(copy) { PARSE_NONE; RETURN_OBJ(php_ds_priority_queue_create_clone(THIS_DS_PRIORITY_QUEUE())); } METHOD(push) { PARSE_ZVAL_LONG(value, priority); ds_priority_queue_push(THIS_DS_PRIORITY_QUEUE(), value, priority); } METHOD(pop) { PARSE_NONE; ds_priority_queue_pop(THIS_DS_PRIORITY_QUEUE(), return_value); } METHOD(peek) { PARSE_NONE; RETURN_ZVAL_COPY(ds_priority_queue_peek(THIS_DS_PRIORITY_QUEUE())); } METHOD(isEmpty) { PARSE_NONE; RETURN_BOOL(DS_PRIORITY_QUEUE_IS_EMPTY(THIS_DS_PRIORITY_QUEUE())); } METHOD(toArray) { PARSE_NONE; ds_priority_queue_to_array(THIS_DS_PRIORITY_QUEUE(), return_value); } METHOD(count) { PARSE_NONE; RETURN_LONG(DS_PRIORITY_QUEUE_SIZE(THIS_DS_PRIORITY_QUEUE())); } METHOD(clear) { PARSE_NONE; ds_priority_queue_clear(THIS_DS_PRIORITY_QUEUE()); } METHOD(jsonSerialize) { PARSE_NONE; ds_priority_queue_to_array(THIS_DS_PRIORITY_QUEUE(), return_value); } void php_ds_register_priority_queue() { zend_class_entry ce; zend_function_entry methods[] = { PHP_DS_ME(PriorityQueue, __construct) PHP_DS_ME(PriorityQueue, allocate) PHP_DS_ME(PriorityQueue, capacity) PHP_DS_ME(PriorityQueue, peek) PHP_DS_ME(PriorityQueue, pop) PHP_DS_ME(PriorityQueue, push) PHP_DS_COLLECTION_ME_LIST(PriorityQueue) PHP_FE_END }; INIT_CLASS_ENTRY(ce, PHP_DS_NS(PriorityQueue), methods); php_ds_priority_queue_ce = zend_register_internal_class(&ce); php_ds_priority_queue_ce->ce_flags |= ZEND_ACC_FINAL; php_ds_priority_queue_ce->create_object = php_ds_priority_queue_create_object; php_ds_priority_queue_ce->get_iterator = php_ds_priority_queue_get_iterator; php_ds_priority_queue_ce->serialize = php_ds_priority_queue_serialize; php_ds_priority_queue_ce->unserialize = php_ds_priority_queue_unserialize; zend_declare_class_constant_long( php_ds_priority_queue_ce, STR_AND_LEN("MIN_CAPACITY"), DS_PRIORITY_QUEUE_MIN_CAPACITY ); zend_class_implements(php_ds_priority_queue_ce, 1, collection_ce); php_ds_register_priority_queue_handlers(); } ds-1.1.8/src/php/classes/php_priority_queue_ce.h0000644000076500000240000000122213065035057022151 0ustar rtheunissenstaff#ifndef DS_PRIORITY_QUEUE_CE_H #define DS_PRIORITY_QUEUE_CE_H #include "php.h" #include "../../common.h" #include "../arginfo.h" extern zend_class_entry *php_ds_priority_queue_ce; ARGINFO_NONE( PriorityQueue___construct); ARGINFO_LONG( PriorityQueue_allocate, capacity); ARGINFO_NONE_RETURN_LONG( PriorityQueue_capacity); ARGINFO_NONE_RETURN_DS( PriorityQueue_copy, PriorityQueue); ARGINFO_ZVAL_LONG( PriorityQueue_push, value, priority); ARGINFO_NONE( PriorityQueue_pop); ARGINFO_NONE( PriorityQueue_peek); void php_ds_register_priority_queue(); #endif ds-1.1.8/src/php/classes/php_queue_ce.c0000644000076500000240000000463613065035057020217 0ustar rtheunissenstaff#include "../../common.h" #include "../parameters.h" #include "../arginfo.h" #include "../iterators/php_queue_iterator.h" #include "../handlers/php_queue_handlers.h" #include "../objects/php_queue.h" #include "php_collection_ce.h" #include "php_queue_ce.h" #define METHOD(name) PHP_METHOD(Queue, name) zend_class_entry *php_ds_queue_ce; METHOD(__construct) { PARSE_OPTIONAL_ZVAL(values); if (values) { ds_queue_push_all(THIS_DS_QUEUE(), values); } } METHOD(allocate) { PARSE_LONG(capacity); ds_queue_allocate(THIS_DS_QUEUE(), capacity); } METHOD(capacity) { PARSE_NONE; RETURN_LONG(ds_queue_capacity(THIS_DS_QUEUE())); } METHOD(push) { PARSE_VARIADIC_ZVAL(); ds_queue_push(THIS_DS_QUEUE(), argc, argv); } METHOD(pop) { PARSE_NONE; ds_queue_pop_throw(THIS_DS_QUEUE(), return_value); } METHOD(peek) { PARSE_NONE; RETURN_ZVAL_COPY(ds_queue_peek_throw(THIS_DS_QUEUE())); } METHOD(copy) { PARSE_NONE; RETURN_OBJ(php_ds_queue_create_clone(THIS_DS_QUEUE())); } METHOD(count) { PARSE_NONE; RETURN_LONG(QUEUE_SIZE(THIS_DS_QUEUE())); } METHOD(clear) { PARSE_NONE; ds_queue_clear(THIS_DS_QUEUE()); } METHOD(toArray) { PARSE_NONE; ds_queue_to_array(THIS_DS_QUEUE(), return_value); } METHOD(isEmpty) { PARSE_NONE; RETURN_BOOL(QUEUE_SIZE(THIS_DS_QUEUE()) == 0); } METHOD(jsonSerialize) { PARSE_NONE; ds_queue_to_array(THIS_DS_QUEUE(), return_value); } void php_ds_register_queue() { zend_class_entry ce; zend_function_entry methods[] = { PHP_DS_ME(Queue, __construct) PHP_DS_ME(Queue, allocate) PHP_DS_ME(Queue, capacity) PHP_DS_ME(Queue, peek) PHP_DS_ME(Queue, pop) PHP_DS_ME(Queue, push) PHP_DS_COLLECTION_ME_LIST(Queue) PHP_FE_END }; INIT_CLASS_ENTRY(ce, PHP_DS_NS(Queue), methods); php_ds_queue_ce = zend_register_internal_class(&ce); php_ds_queue_ce->ce_flags |= ZEND_ACC_FINAL; php_ds_queue_ce->create_object = php_ds_queue_create_object; php_ds_queue_ce->get_iterator = php_ds_queue_get_iterator; php_ds_queue_ce->serialize = php_ds_queue_serialize; php_ds_queue_ce->unserialize = php_ds_queue_unserialize; zend_declare_class_constant_long(php_ds_queue_ce, STR_AND_LEN("MIN_CAPACITY"), DS_DEQUE_MIN_CAPACITY); zend_class_implements(php_ds_queue_ce, 1, collection_ce); php_ds_register_queue_handlers(); } ds-1.1.8/src/php/classes/php_queue_ce.h0000644000076500000240000000077113065035057020220 0ustar rtheunissenstaff#ifndef DS_QUEUE_CE_H #define DS_QUEUE_CE_H #include "php.h" #include "../../common.h" #include "../arginfo.h" extern zend_class_entry *php_ds_queue_ce; ARGINFO_OPTIONAL_ZVAL( Queue___construct, values); ARGINFO_LONG( Queue_allocate, capacity); ARGINFO_NONE_RETURN_LONG( Queue_capacity); ARGINFO_VARIADIC_ZVAL( Queue_push, values); ARGINFO_NONE( Queue_pop); ARGINFO_NONE( Queue_peek); void php_ds_register_queue(); #endif ds-1.1.8/src/php/classes/php_sequence_ce.c0000644000076500000240000000255213065035057020676 0ustar rtheunissenstaff#include "../../common.h" #include "php_collection_ce.h" #include "php_sequence_ce.h" zend_class_entry *sequence_ce; #define SEQUENCE_ABSTRACT_ME(name) PHP_ABSTRACT_ME(Sequence, name, arginfo_Sequence_##name) void php_ds_register_sequence() { zend_class_entry ce; zend_function_entry methods[] = { SEQUENCE_ABSTRACT_ME(__construct) SEQUENCE_ABSTRACT_ME(allocate) SEQUENCE_ABSTRACT_ME(capacity) SEQUENCE_ABSTRACT_ME(contains) SEQUENCE_ABSTRACT_ME(filter) SEQUENCE_ABSTRACT_ME(find) SEQUENCE_ABSTRACT_ME(first) SEQUENCE_ABSTRACT_ME(get) SEQUENCE_ABSTRACT_ME(insert) SEQUENCE_ABSTRACT_ME(join) SEQUENCE_ABSTRACT_ME(last) SEQUENCE_ABSTRACT_ME(map) SEQUENCE_ABSTRACT_ME(merge) SEQUENCE_ABSTRACT_ME(pop) SEQUENCE_ABSTRACT_ME(push) SEQUENCE_ABSTRACT_ME(reduce) SEQUENCE_ABSTRACT_ME(remove) SEQUENCE_ABSTRACT_ME(reverse) SEQUENCE_ABSTRACT_ME(rotate) SEQUENCE_ABSTRACT_ME(set) SEQUENCE_ABSTRACT_ME(shift) SEQUENCE_ABSTRACT_ME(slice) SEQUENCE_ABSTRACT_ME(sort) SEQUENCE_ABSTRACT_ME(unshift) PHP_FE_END }; INIT_CLASS_ENTRY(ce, PHP_DS_NS(Sequence), methods); sequence_ce = zend_register_internal_interface(&ce); zend_class_implements(sequence_ce, 1, collection_ce); } ds-1.1.8/src/php/classes/php_sequence_ce.h0000644000076500000240000000605013065035057020700 0ustar rtheunissenstaff#ifndef PHP_DS_SEQUENCE_CE_H #define PHP_DS_SEQUENCE_CE_H #include "php.h" extern zend_class_entry *sequence_ce; #define PHP_DS_SEQUENCE_ME(cls, name) \ PHP_ME(cls, name, arginfo_Sequence_##name, ZEND_ACC_PUBLIC) #define PHP_DS_SEQUENCE_ME_LIST(cls) \ PHP_DS_SEQUENCE_ME(cls, __construct) \ PHP_DS_SEQUENCE_ME(cls, allocate) \ PHP_DS_SEQUENCE_ME(cls, apply) \ PHP_DS_SEQUENCE_ME(cls, capacity) \ PHP_DS_SEQUENCE_ME(cls, contains) \ PHP_DS_SEQUENCE_ME(cls, filter) \ PHP_DS_SEQUENCE_ME(cls, find) \ PHP_DS_SEQUENCE_ME(cls, first) \ PHP_DS_SEQUENCE_ME(cls, get) \ PHP_DS_SEQUENCE_ME(cls, insert) \ PHP_DS_SEQUENCE_ME(cls, join) \ PHP_DS_SEQUENCE_ME(cls, last) \ PHP_DS_SEQUENCE_ME(cls, map) \ PHP_DS_SEQUENCE_ME(cls, merge) \ PHP_DS_SEQUENCE_ME(cls, pop) \ PHP_DS_SEQUENCE_ME(cls, push) \ PHP_DS_SEQUENCE_ME(cls, reduce) \ PHP_DS_SEQUENCE_ME(cls, remove) \ PHP_DS_SEQUENCE_ME(cls, reverse) \ PHP_DS_SEQUENCE_ME(cls, reversed) \ PHP_DS_SEQUENCE_ME(cls, rotate) \ PHP_DS_SEQUENCE_ME(cls, set) \ PHP_DS_SEQUENCE_ME(cls, shift) \ PHP_DS_SEQUENCE_ME(cls, slice) \ PHP_DS_SEQUENCE_ME(cls, sort) \ PHP_DS_SEQUENCE_ME(cls, sorted) \ PHP_DS_SEQUENCE_ME(cls, sum) \ PHP_DS_SEQUENCE_ME(cls, unshift) ARGINFO_OPTIONAL_ZVAL( Sequence___construct, values); ARGINFO_LONG( Sequence_allocate, capacity); ARGINFO_CALLABLE( Sequence_apply, callback); ARGINFO_NONE_RETURN_LONG( Sequence_capacity); ARGINFO_VARIADIC_ZVAL_RETURN_BOOL( Sequence_contains, values); ARGINFO_OPTIONAL_CALLABLE_RETURN_DS( Sequence_filter, callback, Sequence); ARGINFO_ZVAL( Sequence_find, value); ARGINFO_NONE( Sequence_first); ARGINFO_OPTIONAL_STRING_RETURN_STRING( Sequence_join, glue); ARGINFO_LONG( Sequence_get, index); ARGINFO_LONG_VARIADIC_ZVAL( Sequence_insert, index, values); ARGINFO_NONE( Sequence_last); ARGINFO_CALLABLE_RETURN_DS( Sequence_map, callback, Sequence); ARGINFO_ZVAL_RETURN_DS( Sequence_merge, values, Sequence); ARGINFO_NONE( Sequence_pop); ARGINFO_VARIADIC_ZVAL( Sequence_push, values); ARGINFO_CALLABLE_OPTIONAL_ZVAL( Sequence_reduce, callback, initial); ARGINFO_LONG( Sequence_remove, index); ARGINFO_NONE( Sequence_reverse); ARGINFO_NONE_RETURN_DS( Sequence_reversed, Sequence); ARGINFO_LONG( Sequence_rotate, rotations); ARGINFO_LONG_ZVAL( Sequence_set, index, value); ARGINFO_NONE( Sequence_shift); ARGINFO_LONG_OPTIONAL_LONG_RETURN_DS( Sequence_slice, index, length, Sequence); ARGINFO_OPTIONAL_CALLABLE( Sequence_sort, comparator); ARGINFO_OPTIONAL_CALLABLE_RETURN_DS( Sequence_sorted, comparator, Sequence); ARGINFO_NONE( Sequence_sum); ARGINFO_VARIADIC_ZVAL( Sequence_unshift, values); void php_ds_register_sequence(); #endif ds-1.1.8/src/php/classes/php_set_ce.c0000644000076500000240000001225213065035057017657 0ustar rtheunissenstaff#include "../../common.h" #include "../parameters.h" #include "../arginfo.h" #include "../objects/php_set.h" #include "../iterators/php_set_iterator.h" #include "../handlers/php_set_handlers.h" #include "php_collection_ce.h" #include "php_set_ce.h" #define METHOD(name) PHP_METHOD(Set, name) zend_class_entry *php_ds_set_ce; METHOD(__construct) { PARSE_OPTIONAL_ZVAL(values); if (values) { ds_set_add_all(THIS_DS_SET(), values); } } METHOD(join) { if (ZEND_NUM_ARGS()) { PARSE_STRING(); ds_set_join(THIS_DS_SET(), str, len, return_value); } else { ds_set_join(THIS_DS_SET(), NULL, 0, return_value); } } METHOD(allocate) { PARSE_LONG(capacity); ds_set_allocate(THIS_DS_SET(), capacity); } METHOD(capacity) { PARSE_NONE; RETURN_LONG(DS_SET_CAPACITY(THIS_DS_SET())); } METHOD(add) { PARSE_VARIADIC_ZVAL(); ds_set_add_va(THIS_DS_SET(), argc, argv); } METHOD(remove) { PARSE_VARIADIC_ZVAL(); ds_set_remove_va(THIS_DS_SET(), argc, argv); } METHOD(get) { PARSE_LONG(index); RETURN_ZVAL_COPY(ds_set_get(THIS_DS_SET(), index)); } METHOD(contains) { PARSE_VARIADIC_ZVAL(); RETURN_BOOL(ds_set_contains_va(THIS_DS_SET(), argc, argv)); } METHOD(diff) { PARSE_OBJ(obj, php_ds_set_ce); RETURN_DS_SET(ds_set_diff(THIS_DS_SET(), Z_DS_SET_P(obj))); } METHOD(intersect) { PARSE_OBJ(obj, php_ds_set_ce); RETURN_DS_SET(ds_set_intersect(THIS_DS_SET(), Z_DS_SET_P(obj))); } METHOD(xor) { PARSE_OBJ(obj, php_ds_set_ce); RETURN_DS_SET(ds_set_xor(THIS_DS_SET(), Z_DS_SET_P(obj))); } METHOD(first) { PARSE_NONE; RETURN_ZVAL_COPY(ds_set_get_first(THIS_DS_SET())); } METHOD(last) { PARSE_NONE; RETURN_ZVAL_COPY(ds_set_get_last(THIS_DS_SET())); } METHOD(merge) { PARSE_ZVAL(values); RETURN_DS_SET(ds_set_merge(THIS_DS_SET(), values)); } METHOD(union) { PARSE_OBJ(obj, php_ds_set_ce); RETURN_DS_SET(ds_set_union(THIS_DS_SET(), Z_DS_SET_P(obj))); } METHOD(clear) { PARSE_NONE; ds_set_clear(THIS_DS_SET()); } METHOD(toArray) { PARSE_NONE; ds_set_to_array(THIS_DS_SET(), return_value); } METHOD(count) { PARSE_NONE; RETURN_LONG(DS_SET_SIZE(THIS_DS_SET())); } METHOD(isEmpty) { PARSE_NONE; RETURN_BOOL(DS_SET_IS_EMPTY(THIS_DS_SET())); } METHOD(sort) { if (ZEND_NUM_ARGS()) { PARSE_COMPARE_CALLABLE(); ds_set_sort_callback(THIS_DS_SET()); } else { ds_set_sort(THIS_DS_SET()); } } METHOD(sorted) { if (ZEND_NUM_ARGS()) { PARSE_COMPARE_CALLABLE(); RETURN_DS_SET(ds_set_sorted_callback(THIS_DS_SET())); } else { RETURN_DS_SET(ds_set_sorted(THIS_DS_SET())); } } METHOD(copy) { PARSE_NONE; RETURN_OBJ(php_ds_set_create_clone(THIS_DS_SET())); } METHOD(reduce) { PARSE_CALLABLE_AND_OPTIONAL_ZVAL(initial); ds_set_reduce(THIS_DS_SET(), FCI_ARGS, initial, return_value); } METHOD(slice) { ds_set_t *set = THIS_DS_SET(); if (ZEND_NUM_ARGS() > 1) { PARSE_LONG_AND_LONG(index, length); RETURN_DS_SET(ds_set_slice(set, index, length)); } else { PARSE_LONG(index); RETURN_DS_SET(ds_set_slice(set, index, DS_SET_SIZE(set))); } } METHOD(filter) { if (ZEND_NUM_ARGS()) { PARSE_CALLABLE(); RETURN_DS_SET(ds_set_filter_callback(THIS_DS_SET(), FCI_ARGS)); } else { RETURN_DS_SET(ds_set_filter(THIS_DS_SET())); } } METHOD(reverse) { PARSE_NONE; ds_set_reverse(THIS_DS_SET()); } METHOD(reversed) { PARSE_NONE; RETURN_DS_SET(ds_set_reversed(THIS_DS_SET())); } METHOD(sum) { PARSE_NONE; ds_set_sum(THIS_DS_SET(), return_value); } METHOD(jsonSerialize) { PARSE_NONE; ds_set_to_array(THIS_DS_SET(), return_value); } void php_ds_register_set() { zend_class_entry ce; zend_function_entry methods[] = { PHP_DS_ME(Set, __construct) PHP_DS_ME(Set, add) PHP_DS_ME(Set, allocate) PHP_DS_ME(Set, capacity) PHP_DS_ME(Set, contains) PHP_DS_ME(Set, diff) PHP_DS_ME(Set, filter) PHP_DS_ME(Set, first) PHP_DS_ME(Set, get) PHP_DS_ME(Set, intersect) PHP_DS_ME(Set, join) PHP_DS_ME(Set, last) PHP_DS_ME(Set, merge) PHP_DS_ME(Set, reduce) PHP_DS_ME(Set, remove) PHP_DS_ME(Set, reverse) PHP_DS_ME(Set, reversed) PHP_DS_ME(Set, slice) PHP_DS_ME(Set, sort) PHP_DS_ME(Set, sorted) PHP_DS_ME(Set, sum) PHP_DS_ME(Set, union) PHP_DS_ME(Set, xor) PHP_DS_COLLECTION_ME_LIST(Set) PHP_FE_END }; INIT_CLASS_ENTRY(ce, PHP_DS_NS(Set), methods); php_ds_set_ce = zend_register_internal_class(&ce); php_ds_set_ce->ce_flags |= ZEND_ACC_FINAL; php_ds_set_ce->create_object = php_ds_set_create_object; php_ds_set_ce->get_iterator = php_ds_set_get_iterator; php_ds_set_ce->serialize = php_ds_set_serialize; php_ds_set_ce->unserialize = php_ds_set_unserialize; zend_declare_class_constant_long( php_ds_set_ce, STR_AND_LEN("MIN_CAPACITY"), DS_HTABLE_MIN_CAPACITY ); zend_class_implements(php_ds_set_ce, 1, collection_ce); php_ds_register_set_handlers(); } ds-1.1.8/src/php/classes/php_set_ce.h0000644000076500000240000000325313065035057017665 0ustar rtheunissenstaff#ifndef DS_SET_CE_H #define DS_SET_CE_H #include "php.h" #include "../../common.h" #include "../arginfo.h" extern zend_class_entry *php_ds_set_ce; ARGINFO_OPTIONAL_ZVAL( Set___construct, values); ARGINFO_OPTIONAL_STRING( Set_join, glue); ARGINFO_LONG( Set_allocate, capacity); ARGINFO_NONE_RETURN_LONG( Set_capacity); ARGINFO_VARIADIC_ZVAL( Set_add, values); ARGINFO_VARIADIC_ZVAL( Set_remove, values); ARGINFO_LONG( Set_get, index); ARGINFO_VARIADIC_ZVAL_RETURN_BOOL( Set_contains, values); ARGINFO_DS_RETURN_DS( Set_diff, set, Set, Set); ARGINFO_DS_RETURN_DS( Set_intersect, set, Set, Set); ARGINFO_DS_RETURN_DS( Set_xor, set, Set, Set); ARGINFO_NONE( Set_first); ARGINFO_NONE( Set_last); ARGINFO_ZVAL_RETURN_DS( Set_merge, values, Set); ARGINFO_DS_RETURN_DS( Set_union, set, Set, Set); ARGINFO_OPTIONAL_CALLABLE( Set_sort, comparator); ARGINFO_OPTIONAL_CALLABLE_RETURN_DS( Set_sorted, comparator, Set); ARGINFO_CALLABLE_OPTIONAL_ZVAL( Set_reduce, callback, initial); ARGINFO_LONG_OPTIONAL_LONG_RETURN_DS( Set_slice, index, length, Set); ARGINFO_OPTIONAL_CALLABLE_RETURN_DS( Set_filter, callback, Set); ARGINFO_NONE( Set_reverse); ARGINFO_NONE_RETURN_DS( Set_reversed, Set); ARGINFO_NONE( Set_sum); void php_ds_register_set(); #endif ds-1.1.8/src/php/classes/php_stack_ce.c0000644000076500000240000000447313065035057020177 0ustar rtheunissenstaff#include "../../common.h" #include "../parameters.h" #include "../arginfo.h" #include "../objects/php_stack.h" #include "../iterators/php_stack_iterator.h" #include "../handlers/php_stack_handlers.h" #include "php_collection_ce.h" #include "php_stack_ce.h" #define METHOD(name) PHP_METHOD(Stack, name) zend_class_entry *php_ds_stack_ce; METHOD(__construct) { PARSE_OPTIONAL_ZVAL(values); if (values) { ds_stack_push_all(THIS_DS_STACK(), values); } } METHOD(allocate) { PARSE_LONG(capacity); ds_stack_allocate(THIS_DS_STACK(), capacity); } METHOD(capacity) { PARSE_NONE; RETURN_LONG(DS_STACK_CAPACITY(THIS_DS_STACK())); } METHOD(push) { PARSE_VARIADIC_ZVAL(); ds_stack_push_va(THIS_DS_STACK(), argc, argv); } METHOD(pop) { PARSE_NONE; ds_stack_pop_throw(THIS_DS_STACK(), return_value); } METHOD(peek) { PARSE_NONE; RETURN_ZVAL_COPY(ds_stack_peek_throw(THIS_DS_STACK())); } METHOD(count) { PARSE_NONE; RETURN_LONG(DS_STACK_SIZE(THIS_DS_STACK())); } METHOD(copy) { PARSE_NONE; RETURN_OBJ(php_ds_stack_create_clone(THIS_DS_STACK())); } METHOD(clear) { PARSE_NONE; ds_stack_clear(THIS_DS_STACK()); } METHOD(toArray) { PARSE_NONE; ds_stack_to_array(THIS_DS_STACK(), return_value); } METHOD(isEmpty) { PARSE_NONE; RETURN_BOOL(DS_STACK_IS_EMPTY(THIS_DS_STACK())); } METHOD(jsonSerialize) { PARSE_NONE; ds_stack_to_array(THIS_DS_STACK(), return_value); } void php_ds_register_stack() { zend_class_entry ce; zend_function_entry methods[] = { PHP_DS_ME(Stack, __construct) PHP_DS_ME(Stack, allocate) PHP_DS_ME(Stack, capacity) PHP_DS_ME(Stack, peek) PHP_DS_ME(Stack, pop) PHP_DS_ME(Stack, push) PHP_DS_COLLECTION_ME_LIST(Stack) PHP_FE_END }; INIT_CLASS_ENTRY(ce, PHP_DS_NS(Stack), methods); php_ds_stack_ce = zend_register_internal_class(&ce); php_ds_stack_ce->ce_flags |= ZEND_ACC_FINAL; php_ds_stack_ce->create_object = php_ds_stack_create_object; php_ds_stack_ce->get_iterator = php_ds_stack_get_iterator; php_ds_stack_ce->serialize = php_ds_stack_serialize; php_ds_stack_ce->unserialize = php_ds_stack_unserialize; zend_class_implements(php_ds_stack_ce, 1, collection_ce); php_register_ds_stack_handlers(); } ds-1.1.8/src/php/classes/php_stack_ce.h0000644000076500000240000000100113065035057020164 0ustar rtheunissenstaff#ifndef PHP_DS_STACK_CE_H #define PHP_DS_STACK_CE_H #include "php.h" #include "../../common.h" #include "../arginfo.h" extern zend_class_entry *php_ds_stack_ce; ARGINFO_OPTIONAL_ZVAL( Stack___construct, values); ARGINFO_LONG( Stack_allocate, capacity); ARGINFO_NONE_RETURN_LONG( Stack_capacity); ARGINFO_VARIADIC_ZVAL( Stack_push, values); ARGINFO_NONE( Stack_pop); ARGINFO_NONE( Stack_peek); void php_ds_register_stack(); #endif ds-1.1.8/src/php/classes/php_vector_ce.c0000644000076500000240000001255013065035057020367 0ustar rtheunissenstaff#include "../../common.h" #include "../parameters.h" #include "../arginfo.h" #include "../objects/php_vector.h" #include "../iterators/php_vector_iterator.h" #include "../handlers/php_vector_handlers.h" #include "php_collection_ce.h" #include "php_sequence_ce.h" #include "php_vector_ce.h" #define METHOD(name) PHP_METHOD(Vector, name) zend_class_entry *php_ds_vector_ce; METHOD(__construct) { PARSE_OPTIONAL_ZVAL(values); if (values) { ds_vector_push_all(THIS_DS_VECTOR(), values); } } METHOD(allocate) { PARSE_LONG(capacity); ds_vector_allocate(THIS_DS_VECTOR(), capacity); } METHOD(apply) { PARSE_CALLABLE(); ds_vector_apply(THIS_DS_VECTOR(), FCI_ARGS); } METHOD(capacity) { PARSE_NONE; RETURN_LONG((THIS_DS_VECTOR())->capacity); } METHOD(clear) { PARSE_NONE; ds_vector_clear(THIS_DS_VECTOR()); } METHOD(contains) { PARSE_VARIADIC_ZVAL(); RETURN_BOOL(ds_vector_contains_va(THIS_DS_VECTOR(), argc, argv)); } METHOD(copy) { PARSE_NONE; RETURN_OBJ(php_ds_vector_create_clone(THIS_DS_VECTOR())); } METHOD(count) { PARSE_NONE; RETURN_LONG(DS_VECTOR_SIZE(THIS_DS_VECTOR())); } METHOD(filter) { if (ZEND_NUM_ARGS()) { PARSE_CALLABLE(); RETURN_DS_VECTOR(ds_vector_filter_callback(THIS_DS_VECTOR(), FCI_ARGS)); } else { RETURN_DS_VECTOR(ds_vector_filter(THIS_DS_VECTOR())); } } METHOD(find) { PARSE_ZVAL(value); ds_vector_find(THIS_DS_VECTOR(), value, return_value); } METHOD(first) { PARSE_NONE; RETURN_ZVAL_COPY(ds_vector_get_first_throw(THIS_DS_VECTOR())); } METHOD(get) { PARSE_LONG(index); RETURN_ZVAL_COPY(ds_vector_get(THIS_DS_VECTOR(), index)); } METHOD(insert) { PARSE_LONG_AND_VARIADIC_ZVAL(index); ds_vector_insert_va(THIS_DS_VECTOR(), index, argc, argv); } METHOD(isEmpty) { PARSE_NONE; RETURN_BOOL(DS_VECTOR_IS_EMPTY(THIS_DS_VECTOR())); } METHOD(join) { if (ZEND_NUM_ARGS()) { PARSE_STRING(); ds_vector_join(THIS_DS_VECTOR(), str, len, return_value); } else { ds_vector_join(THIS_DS_VECTOR(), NULL, 0, return_value); } } METHOD(jsonSerialize) { PARSE_NONE; ds_vector_to_array(THIS_DS_VECTOR(), return_value); } METHOD(last) { PARSE_NONE; RETURN_ZVAL_COPY(ds_vector_get_last_throw(THIS_DS_VECTOR())); } METHOD(map) { PARSE_CALLABLE(); RETURN_DS_VECTOR(ds_vector_map(THIS_DS_VECTOR(), FCI_ARGS)); } METHOD(merge) { PARSE_ZVAL(values); RETURN_DS_VECTOR(ds_vector_merge(THIS_DS_VECTOR(), values)); } METHOD(pop) { PARSE_NONE; ds_vector_pop_throw(THIS_DS_VECTOR(), return_value); } METHOD(push) { PARSE_VARIADIC_ZVAL(); ds_vector_push_va(THIS_DS_VECTOR(), argc, argv); } METHOD(push_one) { PARSE_ZVAL(value); ds_vector_push(THIS_DS_VECTOR(), value); } METHOD(reduce) { PARSE_CALLABLE_AND_OPTIONAL_ZVAL(initial); ds_vector_reduce(THIS_DS_VECTOR(), initial, return_value, FCI_ARGS); } METHOD(remove) { PARSE_LONG(index); ds_vector_remove(THIS_DS_VECTOR(), index, return_value); } METHOD(reverse) { PARSE_NONE; ds_vector_reverse(THIS_DS_VECTOR()); } METHOD(reversed) { PARSE_NONE; RETURN_DS_VECTOR(ds_vector_reversed(THIS_DS_VECTOR())); } METHOD(rotate) { PARSE_LONG(rotations); ds_vector_rotate(THIS_DS_VECTOR(), rotations); } METHOD(set) { PARSE_LONG_AND_ZVAL(index, value); ds_vector_set(THIS_DS_VECTOR(), index, value); } METHOD(shift) { PARSE_NONE; ds_vector_shift_throw(THIS_DS_VECTOR(), return_value); } METHOD(slice) { ds_vector_t *vector = THIS_DS_VECTOR(); if (ZEND_NUM_ARGS() > 1) { PARSE_LONG_AND_LONG(index, length); RETURN_DS_VECTOR(ds_vector_slice(vector, index, length)); } else { PARSE_LONG(index); RETURN_DS_VECTOR(ds_vector_slice(vector, index, vector->size)); } } METHOD(sort) { ds_vector_t *vector = THIS_DS_VECTOR(); if (ZEND_NUM_ARGS()) { PARSE_COMPARE_CALLABLE(); ds_vector_sort_callback(vector); } else { ds_vector_sort(vector); } } METHOD(sorted) { ds_vector_t *vector = ds_vector_clone(THIS_DS_VECTOR()); if (ZEND_NUM_ARGS()) { PARSE_COMPARE_CALLABLE(); ds_vector_sort_callback(vector); } else { ds_vector_sort(vector); } RETURN_DS_VECTOR(vector); } METHOD(sum) { PARSE_NONE; ds_vector_sum(THIS_DS_VECTOR(), return_value); } METHOD(toArray) { PARSE_NONE; ds_vector_to_array(THIS_DS_VECTOR(), return_value); } METHOD(unshift) { PARSE_VARIADIC_ZVAL(); ds_vector_unshift_va(THIS_DS_VECTOR(), argc, argv); } void php_ds_register_vector() { zend_class_entry ce; zend_function_entry methods[] = { PHP_DS_SEQUENCE_ME_LIST(Vector) PHP_DS_COLLECTION_ME_LIST(Vector) PHP_FE_END }; INIT_CLASS_ENTRY(ce, PHP_DS_NS(Vector), methods); php_ds_vector_ce = zend_register_internal_class(&ce); php_ds_vector_ce->ce_flags |= ZEND_ACC_FINAL; php_ds_vector_ce->create_object = php_ds_vector_create_object; php_ds_vector_ce->get_iterator = php_ds_vector_get_iterator; php_ds_vector_ce->serialize = php_ds_vector_serialize; php_ds_vector_ce->unserialize = php_ds_vector_unserialize; zend_declare_class_constant_long(php_ds_vector_ce, STR_AND_LEN("MIN_CAPACITY"), DS_VECTOR_MIN_CAPACITY); zend_class_implements(php_ds_vector_ce, 1, sequence_ce); php_register_vector_handlers(); } ds-1.1.8/src/php/classes/php_vector_ce.h0000644000076500000240000000022413065035057020367 0ustar rtheunissenstaff#ifndef DS_VECTOR_CE_H #define DS_VECTOR_CE_H #include "php.h" extern zend_class_entry *php_ds_vector_ce; void php_ds_register_vector(); #endif ds-1.1.8/src/php/handlers/php_common_handlers.c0000644000076500000240000000102013065035057021717 0ustar rtheunissenstaff#include "php_common_handlers.h" #include "zend_smart_str.h" int php_ds_default_cast_object(zval *obj, zval *return_value, int type) { switch (type) { case IS_STRING: { smart_str buffer = {0}; smart_str_appendl(&buffer, "object(", 7); smart_str_append (&buffer, Z_OBJCE_P(obj)->name); smart_str_appendc(&buffer, ')'); smart_str_0(&buffer); ZVAL_STR(return_value, buffer.s); return SUCCESS; } } return FAILURE; } ds-1.1.8/src/php/handlers/php_common_handlers.h0000644000076500000240000000031013065035057021725 0ustar rtheunissenstaff#ifndef PHP_COMMON_HANDLERS_H #define PHP_COMMON_HANDLERS_H #include "php.h" /** * Default object cast handler. */ int php_ds_default_cast_object(zval *obj, zval *return_value, int type); #endif ds-1.1.8/src/php/handlers/php_deque_handlers.c0000644000076500000240000000665313065035057021553 0ustar rtheunissenstaff#include "php_common_handlers.h" #include "php_deque_handlers.h" #include "../objects/php_deque.h" #include "../../ds/ds_deque.h" zend_object_handlers php_deque_handlers; static zval *php_ds_deque_read_dimension(zval *obj, zval *offset, int type, zval *return_value) { if (Z_TYPE_P(offset) != IS_LONG) { INTEGER_INDEX_REQUIRED(offset); return NULL; } else { zval *value = ds_deque_get(Z_DS_DEQUE_P(obj), Z_LVAL_P(offset)); // Create a reference to handle nested array access if (value && type != BP_VAR_R) { ZVAL_MAKE_REF(value); } return value; } } static void php_ds_deque_write_dimension(zval *obj, zval *offset, zval *value) { ds_deque_t *deque = Z_DS_DEQUE_P(obj); if (offset == NULL) { /* $v[] = ... */ ds_deque_push(deque, value); } else if (Z_TYPE_P(offset) != IS_LONG) { INTEGER_INDEX_REQUIRED(offset); } else { ds_deque_set(deque, Z_LVAL_P(offset), value); } } static int php_ds_deque_has_dimension(zval *obj, zval *offset, int check_empty) { if (Z_TYPE_P(offset) != IS_LONG) { return 0; } return ds_deque_isset(Z_DS_DEQUE_P(obj), Z_LVAL_P(offset), check_empty); } static void php_ds_deque_unset_dimension(zval *obj, zval *offset) { if (Z_TYPE_P(offset) != IS_LONG) { return; } else { zend_long index = Z_LVAL_P(offset); ds_deque_t *deque = Z_DS_DEQUE_P(obj); if (index >= 0 && index < deque->size) { ds_deque_remove(deque, index, NULL); } } } static int php_ds_deque_count_elements(zval *obj, zend_long *count) { ds_deque_t *deque = Z_DS_DEQUE_P(obj); *count = deque->size; return SUCCESS; } static void php_ds_deque_free_object(zend_object *object) { php_ds_deque_t *obj = (php_ds_deque_t*) object; zend_object_std_dtor(&obj->std); ds_deque_free(obj->deque); } static HashTable *php_ds_deque_get_debug_info(zval *obj, int *is_temp) { zval return_value; ds_deque_t *deque = Z_DS_DEQUE_P(obj); *is_temp = 1; ds_deque_to_array(deque, &return_value); return Z_ARRVAL(return_value); } static zend_object *php_ds_deque_clone_obj(zval *obj) { ds_deque_t *deque = Z_DS_DEQUE_P(obj); return php_ds_deque_create_clone(deque); } static HashTable *php_ds_deque_get_gc(zval *obj, zval **gc_data, int *gc_count) { ds_deque_t *deque = Z_DS_DEQUE_P(obj); *gc_data = deque->buffer; *gc_count = (int) deque->capacity; return NULL; } void php_ds_register_deque_handlers() { memcpy(&php_deque_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); php_deque_handlers.offset = XtOffsetOf(php_ds_deque_t, std); php_deque_handlers.dtor_obj = zend_objects_destroy_object; php_deque_handlers.free_obj = php_ds_deque_free_object; php_deque_handlers.get_gc = php_ds_deque_get_gc; php_deque_handlers.cast_object = php_ds_default_cast_object; php_deque_handlers.clone_obj = php_ds_deque_clone_obj; php_deque_handlers.get_debug_info = php_ds_deque_get_debug_info; php_deque_handlers.count_elements = php_ds_deque_count_elements; php_deque_handlers.read_dimension = php_ds_deque_read_dimension; php_deque_handlers.write_dimension = php_ds_deque_write_dimension; php_deque_handlers.has_dimension = php_ds_deque_has_dimension; php_deque_handlers.unset_dimension = php_ds_deque_unset_dimension; } ds-1.1.8/src/php/handlers/php_deque_handlers.h0000644000076500000240000000025313065035057021546 0ustar rtheunissenstaff#ifndef DS_DEQUE_HANDLERS_H #define DS_DEQUE_HANDLERS_H #include "php.h" extern zend_object_handlers php_deque_handlers; void php_ds_register_deque_handlers(); #endif ds-1.1.8/src/php/handlers/php_map_handlers.c0000644000076500000240000000600713065035057021216 0ustar rtheunissenstaff#include "php_map_handlers.h" #include "php_common_handlers.h" #include "../../ds/ds_map.h" #include "../objects/php_map.h" zend_object_handlers php_map_handlers; static zval *php_ds_map_read_dimension(zval *obj, zval *offset, int type, zval *return_value) { ds_map_t *map = Z_DS_MAP_P(obj); if (offset == NULL) { ARRAY_ACCESS_PUSH_NOT_SUPPORTED(); return NULL; } else { zval *value = ds_map_get(map, offset, NULL); if (value && type != BP_VAR_R) { ZVAL_MAKE_REF(value); } return value; } } static void php_ds_map_write_dimension(zval *obj, zval *offset, zval *value) { ds_map_t *map = Z_DS_MAP_P(obj); if (offset == NULL) { ARRAY_ACCESS_PUSH_NOT_SUPPORTED(); return; } ds_htable_put(map->table, offset, value); } static int php_ds_map_has_dimension(zval *obj, zval *offset, int check_empty) { ds_map_t *map = Z_DS_MAP_P(obj); return ds_htable_isset(map->table, offset, check_empty); } static void php_ds_map_unset_dimension(zval *obj, zval *offset) { ds_map_t *map = Z_DS_MAP_P(obj); ds_htable_remove(map->table, offset, NULL); } static int php_ds_map_count_elements(zval *obj, zend_long *count) { *count = DS_MAP_SIZE(Z_DS_MAP_P(obj)); return SUCCESS; } static void php_ds_map_free_object(zend_object *object) { php_ds_map_t *intern = (php_ds_map_t*) object; zend_object_std_dtor(&intern->std); ds_map_free(intern->map); } static HashTable *php_ds_map_get_debug_info(zval *obj, int *is_temp) { *is_temp = 1; return ds_map_pairs_to_php_hashtable(Z_DS_MAP_P(obj)); } static zend_object *php_ds_map_clone_obj(zval *obj) { return php_ds_map_create_clone(Z_DS_MAP_P(obj)); } static HashTable *php_ds_map_get_gc(zval *obj, zval **gc_data, int *gc_count) { ds_map_t *map = Z_DS_MAP_P(obj); if (DS_MAP_IS_EMPTY(map)) { *gc_data = NULL; *gc_count = 0; } else { *gc_data = (zval*) map->table->buckets; *gc_count = (int) map->table->next * 2; } return NULL; } void php_ds_register_map_handlers() { memcpy(&php_map_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); php_map_handlers.offset = 0; php_map_handlers.dtor_obj = zend_objects_destroy_object; php_map_handlers.get_gc = php_ds_map_get_gc; php_map_handlers.free_obj = php_ds_map_free_object; php_map_handlers.clone_obj = php_ds_map_clone_obj; php_map_handlers.get_debug_info = php_ds_map_get_debug_info; php_map_handlers.count_elements = php_ds_map_count_elements; php_map_handlers.read_dimension = php_ds_map_read_dimension; php_map_handlers.write_dimension = php_ds_map_write_dimension; php_map_handlers.has_dimension = php_ds_map_has_dimension; php_map_handlers.unset_dimension = php_ds_map_unset_dimension; php_map_handlers.cast_object = php_ds_default_cast_object; // php_map_handlers.get_properties = ds_map_get_properties; } ds-1.1.8/src/php/handlers/php_map_handlers.h0000644000076500000240000000024313065035057021217 0ustar rtheunissenstaff#ifndef DS_MAP_HANDLERS_H #define DS_MAP_HANDLERS_H #include "php.h" extern zend_object_handlers php_map_handlers; void php_ds_register_map_handlers(); #endif ds-1.1.8/src/php/handlers/php_pair_handlers.c0000644000076500000240000001023113065035057021366 0ustar rtheunissenstaff#include "php_pair_handlers.h" #include "php_common_handlers.h" #include "../../ds/ds_pair.h" #include "../objects/php_pair.h" zend_object_handlers php_pair_handlers; static zval *get_property(ds_pair_t *pair, zval *offset) { if (offset && Z_TYPE_P(offset) == IS_STRING) { if (ZVAL_EQUALS_STRING(offset, "key")) { return &pair->key; } if (ZVAL_EQUALS_STRING(offset, "value")) { return &pair->value; } } return NULL; } static zval *php_ds_pair_get_property_ptr_ptr(zval *object, zval *offset, int type, void **cache_slot) { zval *property = get_property(Z_DS_PAIR_P(object), offset); if ( ! property) { return &EG(uninitialized_zval); } return property; } static zval *php_ds_pair_read_property(zval *object, zval *offset, int type, void **cache_slot, zval *rv) { zval *property = get_property(Z_DS_PAIR_P(object), offset); if ( ! property) { OFFSET_OUT_OF_BOUNDS(); return &EG(uninitialized_zval); } return property; } static void php_ds_pair_write_property(zval *object, zval *offset, zval *value, void **cache_slot) { zval *property = get_property(Z_DS_PAIR_P(object), offset); if (property) { zval_ptr_dtor(property); ZVAL_COPY(property, value); return; } OFFSET_OUT_OF_BOUNDS(); } static int php_ds_pair_has_property(zval *object, zval *offset, int has_set_exists, void **cache_slot) { zval *value = get_property(Z_DS_PAIR_P(object), offset); if ( ! value) { return false; } // 0 – check whether the property exists and is not NULL; isset // 1 – check whether the property exists and is true; semantics of empty // 2 – check whether the property exists, even if it is NULL; if (has_set_exists == 2) { return true; } return ds_zval_isset(value, has_set_exists); } static void php_ds_pair_unset_property(zval *object, zval *offset, void **cache_slot) { zval *property = get_property(Z_DS_PAIR_P(object), offset); if (property) { zval_ptr_dtor(property); ZVAL_NULL(property); } } static void php_ds_pair_free_object(zend_object *object) { php_ds_pair_t *obj = (php_ds_pair_t*) object; zend_object_std_dtor(&obj->std); ds_pair_free(obj->pair); } static int php_ds_pair_count_elements(zval *object, zend_long *count) { *count = 2; return SUCCESS; } static HashTable *php_ds_pair_get_debug_info(zval *object, int *is_temp) { zval arr; ds_pair_t *pair = Z_DS_PAIR_P(object); *is_temp = 1; array_init_size(&arr, 2); add_assoc_zval_ex(&arr, "key", 3, &pair->key); add_assoc_zval_ex(&arr, "value", 5, &pair->value); Z_TRY_ADDREF_P(&pair->key); Z_TRY_ADDREF_P(&pair->value); return Z_ARRVAL(arr); } static zend_object *php_ds_pair_clone_object(zval *object) { return php_ds_pair_create_clone(Z_DS_PAIR_P(object)); } static HashTable *php_ds_pair_get_gc(zval *obj, zval **gc_data, int *gc_count) { ds_pair_t *pair = Z_DS_PAIR_P(obj); *gc_data = (zval*) pair; *gc_count = (int) 2; return NULL; } void php_ds_register_pair_handlers() { memcpy(&php_pair_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); php_pair_handlers.offset = XtOffsetOf(php_ds_pair_t, std); php_pair_handlers.dtor_obj = zend_objects_destroy_object; php_pair_handlers.get_gc = php_ds_pair_get_gc; php_pair_handlers.free_obj = php_ds_pair_free_object; php_pair_handlers.clone_obj = php_ds_pair_clone_object; php_pair_handlers.cast_object = php_ds_default_cast_object; php_pair_handlers.get_debug_info = php_ds_pair_get_debug_info; php_pair_handlers.count_elements = php_ds_pair_count_elements; php_pair_handlers.get_property_ptr_ptr = php_ds_pair_get_property_ptr_ptr; php_pair_handlers.read_property = php_ds_pair_read_property; php_pair_handlers.write_property = php_ds_pair_write_property; php_pair_handlers.has_property = php_ds_pair_has_property; php_pair_handlers.unset_property = php_ds_pair_unset_property; } ds-1.1.8/src/php/handlers/php_pair_handlers.h0000644000076500000240000000024713065035057021401 0ustar rtheunissenstaff#ifndef DS_PAIR_HANDLERS_H #define DS_PAIR_HANDLERS_H #include "php.h" extern zend_object_handlers php_pair_handlers; void php_ds_register_pair_handlers(); #endif ds-1.1.8/src/php/handlers/php_priority_queue_handlers.c0000644000076500000240000000523013065035057023523 0ustar rtheunissenstaff#include "php_common_handlers.h" #include "php_deque_handlers.h" #include "../objects/php_priority_queue.h" #include "../../ds/ds_priority_queue.h" zend_object_handlers php_priority_queue_handlers; static void php_ds_priority_queue_free_object(zend_object *object) { php_ds_priority_queue_t *queue = (php_ds_priority_queue_t*) object; zend_object_std_dtor(&queue->std); ds_priority_queue_free(queue->queue); if (queue->gc_data != NULL) { efree(queue->gc_data); } } static int php_ds_priority_queue_count_elements(zval *obj, zend_long *count) { *count = DS_PRIORITY_QUEUE_SIZE(Z_DS_PRIORITY_QUEUE_P(obj)); return SUCCESS; } static zend_object *php_ds_priority_queue_clone_obj(zval *obj) { return php_ds_priority_queue_create_clone(Z_DS_PRIORITY_QUEUE_P(obj)); } static HashTable *php_ds_priority_queue_get_debug_info(zval *obj, int *is_temp) { zval array; ds_priority_queue_t *queue = Z_DS_PRIORITY_QUEUE_P(obj); *is_temp = 1; ds_priority_queue_to_array(queue, &array); return Z_ARRVAL(array); } static void ds_priority_queue_copy_gc( php_ds_priority_queue_t *obj, zval **gc_data, int *gc_size ) { zval *value; zval *target = obj->gc_data; DS_PRIORITY_QUEUE_FOREACH_VALUE(obj->queue, value) { ZVAL_COPY_VALUE(target++, value); } DS_PRIORITY_QUEUE_FOREACH_END(); *gc_data = obj->gc_data; *gc_size = obj->gc_size; } static HashTable *php_ds_priority_queue_get_gc(zval *object, zval **gc_data, int *gc_size) { php_ds_priority_queue_t *obj = (php_ds_priority_queue_t *) Z_OBJ_P(object); // We have to reallocate the gc buffer if the size has changed. if (obj->gc_size != obj->queue->size) { obj->gc_size = obj->queue->size; REALLOC_ZVAL_BUFFER(obj->gc_data, obj->gc_size); } // Copy every value from the queue in the gc buffer. ds_priority_queue_copy_gc(obj, gc_data, gc_size); return NULL; } void php_ds_register_priority_queue_handlers() { memcpy(&php_priority_queue_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); php_priority_queue_handlers.offset = XtOffsetOf(php_ds_priority_queue_t, std); php_priority_queue_handlers.get_gc = php_ds_priority_queue_get_gc; php_priority_queue_handlers.free_obj = php_ds_priority_queue_free_object; php_priority_queue_handlers.clone_obj = php_ds_priority_queue_clone_obj; php_priority_queue_handlers.cast_object = php_ds_default_cast_object; php_priority_queue_handlers.get_debug_info = php_ds_priority_queue_get_debug_info; php_priority_queue_handlers.count_elements = php_ds_priority_queue_count_elements; } ds-1.1.8/src/php/handlers/php_priority_queue_handlers.h0000644000076500000240000000031713065035057023531 0ustar rtheunissenstaff#ifndef DS_PRIORITY_QUEUE_HANDLERS_H #define DS_PRIORITY_QUEUE_HANDLERS_H #include "php.h" extern zend_object_handlers php_priority_queue_handlers; void php_ds_register_priority_queue_handlers(); #endif ds-1.1.8/src/php/handlers/php_queue_handlers.c0000644000076500000240000000405313065035057021564 0ustar rtheunissenstaff#include "php_common_handlers.h" #include "php_deque_handlers.h" #include "../objects/php_queue.h" #include "../../ds/ds_queue.h" zend_object_handlers php_queue_handlers; static void php_ds_queue_write_dimension(zval *obj, zval *offset, zval *value) { ds_queue_t *queue = Z_DS_QUEUE_P(obj); if (offset == NULL) { ds_queue_push_one(queue, value); return; } ARRAY_ACCESS_BY_KEY_NOT_SUPPORTED(); } static void php_ds_queue_free_object(zend_object *object) { php_ds_queue_t *queue = (php_ds_queue_t*) object; zend_object_std_dtor(&queue->std); ds_queue_free(queue->queue); } static int php_ds_queue_count_elements(zval *obj, zend_long *count) { *count = QUEUE_SIZE(Z_DS_QUEUE_P(obj)); return SUCCESS; } static zend_object *php_ds_queue_clone_obj(zval *obj) { return php_ds_queue_create_clone(Z_DS_QUEUE_P(obj)); } static HashTable *php_ds_queue_get_debug_info(zval *obj, int *is_temp) { zval array; ds_queue_t *queue = Z_DS_QUEUE_P(obj); *is_temp = 1; ds_queue_to_array(queue, &array); return Z_ARRVAL(array); } static HashTable *php_ds_queue_get_gc(zval *obj, zval **gc_data, int *gc_count) { ds_queue_t *queue = Z_DS_QUEUE_P(obj); *gc_data = queue->deque->buffer; *gc_count = (int) queue->deque->capacity; return NULL; } void php_ds_register_queue_handlers() { memcpy(&php_queue_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); php_queue_handlers.offset = XtOffsetOf(php_ds_queue_t, std); php_queue_handlers.dtor_obj = zend_objects_destroy_object; php_queue_handlers.get_gc = php_ds_queue_get_gc; php_queue_handlers.free_obj = php_ds_queue_free_object; php_queue_handlers.clone_obj = php_ds_queue_clone_obj; php_queue_handlers.cast_object = php_ds_default_cast_object; php_queue_handlers.get_debug_info = php_ds_queue_get_debug_info; php_queue_handlers.count_elements = php_ds_queue_count_elements; php_queue_handlers.write_dimension = php_ds_queue_write_dimension; } ds-1.1.8/src/php/handlers/php_queue_handlers.h0000644000076500000240000000025313065035057021567 0ustar rtheunissenstaff#ifndef DS_QUEUE_HANDLERS_H #define DS_QUEUE_HANDLERS_H #include "php.h" extern zend_object_handlers php_queue_handlers; void php_ds_register_queue_handlers(); #endif ds-1.1.8/src/php/handlers/php_set_handlers.c0000644000076500000240000001274113065035057021236 0ustar rtheunissenstaff#include "php_common_handlers.h" #include "php_set_handlers.h" #include "../../ds/ds_set.h" #include "../objects/php_set.h" #include "../classes/php_set_ce.h" zend_object_handlers php_ds_set_handlers; static zval *php_ds_set_read_dimension(zval *obj, zval *offset, int type, zval *rv) { ds_set_t *set = Z_DS_SET_P(obj); if (offset == NULL) { ds_set_add(set, obj); return NULL; } if (Z_TYPE_P(offset) != IS_LONG) { INTEGER_INDEX_REQUIRED(offset); return NULL; } // Only support read, not write. if (type != BP_VAR_R) { return &EG(uninitialized_zval); } return ds_set_get(set, Z_LVAL_P(offset)); } static void php_ds_set_write_dimension(zval *obj, zval *offset, zval *value) { if (offset == NULL) { ds_set_add(Z_DS_SET_P(obj), value); return; } ARRAY_ACCESS_BY_KEY_NOT_SUPPORTED(); } static int php_ds_set_count_elements(zval *obj, zend_long *count) { *count = DS_SET_SIZE(Z_DS_SET_P(obj)); return SUCCESS; } static void php_ds_set_free_object(zend_object *object) { php_ds_set_t *obj = (php_ds_set_t*) object; zend_object_std_dtor(&obj->std); ds_set_free(obj->set); } static HashTable *php_ds_set_get_debug_info(zval *obj, int *is_temp) { zval arr; ds_set_t *set = Z_DS_SET_P(obj); *is_temp = 1; ds_set_to_array(set, &arr); return Z_ARRVAL(arr); } static zend_object *php_ds_set_clone_obj(zval *obj) { return php_ds_set_create_clone(Z_DS_SET_P(obj)); } // static inline bool is_php_ds_set(zval *op) // { // return Z_TYPE_P(op) == IS_OBJECT && // instanceof_function(Z_OBJCE_P(op), php_ds_set_ce); // } // static int ds_set_do_operation_ex(zend_uchar opcode, zval *result, zval *op1, zval *op2) // { // ds_set_t *set = Z_DS_SET_P(op1); // switch (opcode) { // // &, intersect which creates a new set. // case ZEND_BW_AND: // if (is_php_ds_set(op2)) { // if (op1 == result) { // // &=, intersect which modifies the set. // ds_set_assign_intersect(set, Z_DS_SET_P(op2)); // } else { // ZVAL_DS_SET(result, ds_set_intersect(set, Z_DS_SET_P(op2))); // } // return SUCCESS; // } // break; // // |, union which creates a new set. // case ZEND_BW_OR: // if (is_php_ds_set(op2)) { // ZVAL_DS_SET(result, ds_set_union(set, Z_DS_SET_P(op2))); // return SUCCESS; // } // break; // // |=, union which modifies the set. // case ZEND_ASSIGN_BW_OR: // if (is_php_ds_set(op2)) { // ds_set_assign_union(set, Z_DS_SET_P(op2)); // return SUCCESS; // } // break; // // ^, xor which creates a new set. // case ZEND_BW_XOR: // if (is_php_ds_set(op2)) { // ZVAL_DS_SET(result, ds_set_xor(set, Z_DS_SET_P(op2))); // return SUCCESS; // } // break; // // ^=, xor which modifies the set. // case ZEND_ASSIGN_BW_XOR: // if (is_php_ds_set(op2)) { // ds_set_assign_xor(set, Z_DS_SET_P(op2)); // return SUCCESS; // } // break; // // -, diff which creates a new set. // case ZEND_SUB: // if (is_php_ds_set(op2)) { // ZVAL_DS_SET(result, ds_set_diff(set, Z_DS_SET_P(op2))); // return SUCCESS; // } // break; // // -=, diff which modifies the set. // case ZEND_ASSIGN_SUB: // if (is_php_ds_set(op2)) { // ds_set_assign_diff(set, Z_DS_SET_P(op2)); // return SUCCESS; // } // break; // } // // Operator not supported? // return FAILURE; // } // static int ds_set_do_operation(zend_uchar opcode, zval *result, zval *op1, zval *op2) // { // zval op1_copy; // int retval; // if (result == op1) { // ZVAL_COPY_VALUE(&op1_copy, op1); // op1 = &op1_copy; // } // retval = ds_set_do_operation_ex(opcode, result, op1, op2); // if (retval == SUCCESS && op1 == &op1_copy) { // zval_dtor(op1); // } // return retval; // } static HashTable *php_ds_set_get_gc(zval *obj, zval **gc_data, int *gc_count) { ds_set_t *set = Z_DS_SET_P(obj); if (DS_SET_IS_EMPTY(set)) { *gc_data = NULL; *gc_count = 0; } else { *gc_data = (zval*) set->table->buckets; *gc_count = (int) set->table->next * 2; } return NULL; } void php_ds_register_set_handlers() { memcpy(&php_ds_set_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); php_ds_set_handlers.offset = XtOffsetOf(php_ds_set_t, std); php_ds_set_handlers.get_gc = php_ds_set_get_gc; php_ds_set_handlers.free_obj = php_ds_set_free_object; php_ds_set_handlers.clone_obj = php_ds_set_clone_obj; php_ds_set_handlers.get_debug_info = php_ds_set_get_debug_info; php_ds_set_handlers.count_elements = php_ds_set_count_elements; php_ds_set_handlers.read_dimension = php_ds_set_read_dimension; php_ds_set_handlers.write_dimension = php_ds_set_write_dimension; php_ds_set_handlers.cast_object = php_ds_default_cast_object; // php_ds_set_handlers.do_operation = ds_set_do_operation; } ds-1.1.8/src/php/handlers/php_set_handlers.h0000644000076500000240000000024613065035057021240 0ustar rtheunissenstaff#ifndef DS_SET_HANDLERS_H #define DS_SET_HANDLERS_H #include "php.h" extern zend_object_handlers php_ds_set_handlers; void php_ds_register_set_handlers(); #endif ds-1.1.8/src/php/handlers/php_stack_handlers.c0000644000076500000240000000410613065035057021544 0ustar rtheunissenstaff#include "php_stack_handlers.h" #include "php_common_handlers.h" #include "../../ds/ds_stack.h" #include "../objects/php_stack.h" zend_object_handlers php_ds_stack_handlers; static void php_ds_stack_write_dimension(zval *obj, zval *offset, zval *value) { ds_stack_t *stack = Z_DS_STACK_P(obj); if (offset == NULL) { ds_stack_push(stack, value); return; } ARRAY_ACCESS_BY_KEY_NOT_SUPPORTED(); } static void php_ds_stack_free_object(zend_object *object) { php_ds_stack_t *obj = (php_ds_stack_t*) object; zend_object_std_dtor(&obj->std); ds_stack_free(obj->stack); } static int php_ds_stack_count_elements(zval *obj, zend_long *count) { *count = DS_STACK_SIZE(Z_DS_STACK_P(obj)); return SUCCESS; } static zend_object *php_ds_stack_clone_obj(zval *obj) { return php_ds_stack_create_clone(Z_DS_STACK_P(obj)); } static HashTable *php_ds_stack_get_debug_info(zval *obj, int *is_temp) { zval arr; ds_stack_t *stack = Z_DS_STACK_P(obj); *is_temp = 1; ds_stack_to_array(stack, &arr); return Z_ARRVAL(arr); } static HashTable *php_ds_stack_get_gc(zval *obj, zval **gc_data, int *gc_count) { ds_stack_t *stack = Z_DS_STACK_P(obj); *gc_data = (zval*) stack->vector->buffer; *gc_count = (int) stack->vector->size; return NULL; } void php_register_ds_stack_handlers() { memcpy(&php_ds_stack_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); php_ds_stack_handlers.offset = XtOffsetOf(php_ds_stack_t, std); php_ds_stack_handlers.dtor_obj = zend_objects_destroy_object; php_ds_stack_handlers.get_gc = php_ds_stack_get_gc; php_ds_stack_handlers.free_obj = php_ds_stack_free_object; php_ds_stack_handlers.clone_obj = php_ds_stack_clone_obj; php_ds_stack_handlers.cast_object = php_ds_default_cast_object; php_ds_stack_handlers.get_debug_info = php_ds_stack_get_debug_info; php_ds_stack_handlers.count_elements = php_ds_stack_count_elements; php_ds_stack_handlers.write_dimension = php_ds_stack_write_dimension; } ds-1.1.8/src/php/handlers/php_stack_handlers.h0000644000076500000240000000025613065035057021553 0ustar rtheunissenstaff#ifndef DS_STACK_HANDLERS_H #define DS_STACK_HANDLERS_H #include "php.h" extern zend_object_handlers php_ds_stack_handlers; void php_register_ds_stack_handlers(); #endif ds-1.1.8/src/php/handlers/php_vector_handlers.c0000644000076500000240000000702213065035057021741 0ustar rtheunissenstaff#include "php_common_handlers.h" #include "php_vector_handlers.h" #include "../objects/php_vector.h" #include "../../ds/ds_vector.h" zend_object_handlers php_vector_handlers; static zval *php_ds_vector_read_dimension(zval *obj, zval *offset, int type, zval *return_value) { if (Z_TYPE_P(offset) != IS_LONG) { INTEGER_INDEX_REQUIRED(offset); return NULL; } else { zval *value = ds_vector_get(Z_DS_VECTOR_P(obj), Z_LVAL_P(offset)); // Create a reference to handle nested array access if (value && type != BP_VAR_R) { ZVAL_MAKE_REF(value); } return value; } } static void php_ds_vector_write_dimension(zval *obj, zval *offset, zval *value) { ds_vector_t *vector = Z_DS_VECTOR_P(obj); /* $v[] = ... */ if (offset == NULL) { ds_vector_push(vector, value); } else if (Z_TYPE_P(offset) != IS_LONG) { INTEGER_INDEX_REQUIRED(offset); } else { ds_vector_set(vector, Z_LVAL_P(offset), value); } } static int php_ds_vector_has_dimension(zval *obj, zval *offset, int check_empty) { if (Z_TYPE_P(offset) != IS_LONG) { return 0; } return ds_vector_isset(Z_DS_VECTOR_P(obj), Z_LVAL_P(offset), check_empty); } static void php_ds_vector_unset_dimension(zval *obj, zval *offset) { zend_long index; ds_vector_t *vector = Z_DS_VECTOR_P(obj); if (Z_TYPE_P(offset) == IS_LONG) { index = Z_LVAL_P(offset); } else { if (zend_parse_parameter(ZEND_PARSE_PARAMS_QUIET, 1, offset, "l", &index) == FAILURE) { return; } } if (ds_vector_index_exists(vector, index)) { // to avoid OOB ds_vector_remove(vector, index, NULL); } } static int php_ds_vector_count_elements(zval *obj, zend_long *count) { *count = Z_DS_VECTOR_P(obj)->size; return SUCCESS; } static void php_ds_vector_free_object(zend_object *object) { php_ds_vector_t *obj = (php_ds_vector_t*) object; zend_object_std_dtor(&obj->std); ds_vector_free(obj->vector); } static HashTable *php_ds_vector_get_debug_info(zval *obj, int *is_temp) { zval arr; ds_vector_t *vector = Z_DS_VECTOR_P(obj); *is_temp = 1; ds_vector_to_array(vector, &arr); return Z_ARRVAL(arr); } static zend_object *php_ds_vector_clone_obj(zval *obj) { return php_ds_vector_create_clone(Z_DS_VECTOR_P(obj)); } static HashTable *php_ds_vector_get_gc(zval *obj, zval **gc_data, int *gc_count) { ds_vector_t *vector = Z_DS_VECTOR_P(obj); *gc_data = vector->buffer; *gc_count = (int) vector->size; return NULL; } void php_register_vector_handlers() { memcpy(&php_vector_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); php_vector_handlers.offset = XtOffsetOf(php_ds_vector_t, std); php_vector_handlers.dtor_obj = zend_objects_destroy_object; php_vector_handlers.free_obj = php_ds_vector_free_object; php_vector_handlers.get_gc = php_ds_vector_get_gc; php_vector_handlers.clone_obj = php_ds_vector_clone_obj; php_vector_handlers.cast_object = php_ds_default_cast_object; php_vector_handlers.get_debug_info = php_ds_vector_get_debug_info; php_vector_handlers.count_elements = php_ds_vector_count_elements; php_vector_handlers.read_dimension = php_ds_vector_read_dimension; php_vector_handlers.write_dimension = php_ds_vector_write_dimension; php_vector_handlers.has_dimension = php_ds_vector_has_dimension; php_vector_handlers.unset_dimension = php_ds_vector_unset_dimension; } ds-1.1.8/src/php/handlers/php_vector_handlers.h0000644000076500000240000000026413065035057021747 0ustar rtheunissenstaff#ifndef PHP_DS_VECTOR_HANDLERS_H #define PHP_DS_VECTOR_HANDLERS_H #include "php.h" extern zend_object_handlers php_vector_handlers; void php_register_vector_handlers(); #endif ds-1.1.8/src/php/iterators/php_deque_iterator.c0000644000076500000240000000421313065035057022006 0ustar rtheunissenstaff#include "../../common.h" #include "../../ds/ds_deque.h" #include "../objects/php_deque.h" #include "php_deque_iterator.h" static void php_ds_deque_iterator_dtor(zend_object_iterator *intern) { } static int php_ds_deque_iterator_valid(zend_object_iterator *iter) { php_ds_deque_iterator_t *iterator = (php_ds_deque_iterator_t *) iter; if (iterator->position < iterator->deque->size) { return SUCCESS; } return FAILURE; } static zval *php_ds_deque_iterator_get_current_data(zend_object_iterator *iter) { php_ds_deque_iterator_t *iterator = (php_ds_deque_iterator_t *) iter; return ds_deque_get(iterator->deque, iterator->position); } static void php_ds_deque_iterator_get_current_key(zend_object_iterator *iter, zval *key) { ZVAL_LONG(key, ((php_ds_deque_iterator_t *) iter)->position); } static void php_ds_deque_iterator_move_forward(zend_object_iterator *iter) { ((php_ds_deque_iterator_t *) iter)->position++; } static void php_ds_deque_iterator_rewind(zend_object_iterator *iter) { ((php_ds_deque_iterator_t *) iter)->position = 0; } static zend_object_iterator_funcs iterator_funcs = { php_ds_deque_iterator_dtor, php_ds_deque_iterator_valid, php_ds_deque_iterator_get_current_data, php_ds_deque_iterator_get_current_key, php_ds_deque_iterator_move_forward, php_ds_deque_iterator_rewind }; static zend_object_iterator *create_iterator(ds_deque_t *deque, int by_ref) { php_ds_deque_iterator_t *iterator; if (by_ref) { ITERATION_BY_REF_NOT_SUPPORTED(); return NULL; } iterator = ecalloc(1, sizeof(php_ds_deque_iterator_t)); zend_iterator_init((zend_object_iterator*) iterator); iterator->intern.funcs = &iterator_funcs; iterator->deque = deque; iterator->position = 0; return (zend_object_iterator *) iterator; } zend_object_iterator *php_ds_deque_get_iterator_ex(zend_class_entry *ce, zval *object, int by_ref, ds_deque_t *deque) { return create_iterator(deque, by_ref); } zend_object_iterator *php_ds_deque_get_iterator(zend_class_entry *ce, zval *object, int by_ref) { return create_iterator(Z_DS_DEQUE_P(object), by_ref); } ds-1.1.8/src/php/iterators/php_deque_iterator.h0000644000076500000240000000077213065035057022021 0ustar rtheunissenstaff#ifndef DS_DEQUE_ITERATOR_H #define DS_DEQUE_ITERATOR_H #include "php.h" #include "../../ds/ds_deque.h" typedef struct php_ds_deque_iterator { zend_object_iterator intern; zend_long position; ds_deque_t *deque; } php_ds_deque_iterator_t; zend_object_iterator *php_ds_deque_get_iterator_ex(zend_class_entry *ce, zval *object, int by_ref, ds_deque_t *deque); zend_object_iterator *php_ds_deque_get_iterator(zend_class_entry *ce, zval *object, int by_ref); #endif ds-1.1.8/src/php/iterators/php_htable_iterator.c0000644000076500000240000001342513065035057022147 0ustar rtheunissenstaff#include "../../common.h" #include "../../ds/ds_htable.h" #include "php_htable_iterator.h" static ds_htable_bucket_t *find_starting_bucket(ds_htable_t *table) { ds_htable_bucket_t *bucket = table->buckets; if (table->size != 0) { ds_htable_bucket_t *last = table->buckets + table->capacity; while (bucket != last && DS_HTABLE_BUCKET_DELETED(bucket)) { ++bucket; } } return bucket; } static void php_ds_htable_iterator_dtor(zend_object_iterator *i) { DTOR_AND_UNDEF(&i->data); } static int php_ds_htable_iterator_valid(zend_object_iterator *i) { ds_htable_iterator_t *iterator = (ds_htable_iterator_t *) i; uint32_t size = iterator->table->size; uint32_t position = iterator->position; return position < size ? SUCCESS : FAILURE; } static zval *php_ds_htable_iterator_get_current_value(zend_object_iterator *i) { ds_htable_iterator_t *iterator = (ds_htable_iterator_t *) i; ds_htable_bucket_t *bucket = iterator->bucket; if ( ! DS_HTABLE_BUCKET_DELETED(bucket)) { return &bucket->value; } return NULL; } static zval *php_ds_htable_iterator_get_current_keyval(zend_object_iterator *i) { ds_htable_iterator_t *iterator = (ds_htable_iterator_t *) i; ds_htable_bucket_t *bucket = iterator->bucket; if ( ! DS_HTABLE_BUCKET_DELETED(bucket)) { return &bucket->key; } return NULL; } static void php_ds_htable_iterator_get_current_key(zend_object_iterator *i, zval *key) { ds_htable_iterator_t *iterator = (ds_htable_iterator_t *) i; ds_htable_bucket_t *bucket = iterator->bucket; if ( ! DS_HTABLE_BUCKET_DELETED(bucket)) { ZVAL_COPY(key, &bucket->key); } } static zval *php_ds_htable_iterator_get_current_pair(zend_object_iterator *i) { ds_htable_iterator_t *iterator = (ds_htable_iterator_t *) i; ds_htable_bucket_t *bucket = iterator->bucket; if ( ! DS_HTABLE_BUCKET_DELETED(bucket)) { zval *key = &bucket->key; zval *val = &bucket->value; zval *arr = &iterator->intern.data; Z_TRY_ADDREF_P(key); Z_TRY_ADDREF_P(val); array_init_size(arr, 2); add_next_index_zval(arr, key); add_next_index_zval(arr, val); return arr; } return NULL; } static void php_ds_htable_iterator_get_current_pos(zend_object_iterator *i, zval *key) { ZVAL_LONG(key, ((ds_htable_iterator_t *) i)->position); } static void php_ds_htable_iterator_move_forward(zend_object_iterator *i) { ds_htable_iterator_t *iterator = (ds_htable_iterator_t *) i; if (++iterator->position < iterator->table->size) { do { ++iterator->bucket; } while (DS_HTABLE_BUCKET_DELETED(iterator->bucket)); } } static void php_ds_htable_iterator_rewind(zend_object_iterator *i) { ds_htable_iterator_t *iterator = (ds_htable_iterator_t *) i; iterator->position = 0; iterator->bucket = find_starting_bucket(iterator->table); } static zend_object_iterator_funcs php_ds_htable_get_value_iterator_funcs = { php_ds_htable_iterator_dtor, php_ds_htable_iterator_valid, php_ds_htable_iterator_get_current_value, // value php_ds_htable_iterator_get_current_pos, // key php_ds_htable_iterator_move_forward, php_ds_htable_iterator_rewind }; static zend_object_iterator_funcs php_ds_htable_get_key_iterator_funcs = { php_ds_htable_iterator_dtor, php_ds_htable_iterator_valid, php_ds_htable_iterator_get_current_keyval, // value php_ds_htable_iterator_get_current_pos, // key php_ds_htable_iterator_move_forward, php_ds_htable_iterator_rewind }; static zend_object_iterator_funcs php_ds_htable_get_pair_iterator_funcs = { php_ds_htable_iterator_dtor, php_ds_htable_iterator_valid, php_ds_htable_iterator_get_current_pair, // value php_ds_htable_iterator_get_current_pos, // key php_ds_htable_iterator_move_forward, php_ds_htable_iterator_rewind }; static zend_object_iterator_funcs php_ds_htable_get_assoc_iterator_funcs = { php_ds_htable_iterator_dtor, php_ds_htable_iterator_valid, php_ds_htable_iterator_get_current_value, // value php_ds_htable_iterator_get_current_key, // key php_ds_htable_iterator_move_forward, php_ds_htable_iterator_rewind }; static zend_object_iterator *php_ds_htable_create_htable_iterator(ds_htable_t *table, zend_object_iterator_funcs *funcs, int by_ref) { ds_htable_iterator_t *iterator; if (by_ref) { ITERATION_BY_REF_NOT_SUPPORTED(); return NULL; } iterator = ecalloc(1, sizeof(ds_htable_iterator_t)); zend_iterator_init((zend_object_iterator*) iterator); ZVAL_UNDEF(&iterator->intern.data); iterator->intern.funcs = funcs; iterator->table = table; return (zend_object_iterator *) iterator; } zend_object_iterator *php_ds_htable_get_value_iterator_ex( zend_class_entry *ce, zval *obj, int by_ref, ds_htable_t *table ){ return php_ds_htable_create_htable_iterator( table, &php_ds_htable_get_value_iterator_funcs, by_ref); } zend_object_iterator *php_ds_htable_get_key_iterator_ex( zend_class_entry *ce, zval *obj, int by_ref, ds_htable_t *table ){ return php_ds_htable_create_htable_iterator( table, &php_ds_htable_get_key_iterator_funcs, by_ref); } zend_object_iterator *php_ds_htable_get_pair_iterator_ex( zend_class_entry *ce, zval *obj, int by_ref, ds_htable_t *table ){ return php_ds_htable_create_htable_iterator( table, &php_ds_htable_get_pair_iterator_funcs, by_ref); } zend_object_iterator *php_ds_htable_get_assoc_iterator_ex( zend_class_entry *ce, zval *obj, int by_ref, ds_htable_t *table ){ return php_ds_htable_create_htable_iterator( table, &php_ds_htable_get_assoc_iterator_funcs, by_ref); } ds-1.1.8/src/php/iterators/php_htable_iterator.h0000644000076500000240000000145113065035057022150 0ustar rtheunissenstaff#ifndef DS_HTABLE_ITERATOR_H #define DS_HTABLE_ITERATOR_H #include "php.h" #include "../../ds/ds_htable.h" typedef struct ds_htable_iterator { zend_object_iterator intern; uint32_t position; ds_htable_bucket_t *bucket; ds_htable_t *table; } ds_htable_iterator_t; zend_object_iterator *php_ds_htable_get_value_iterator_ex(zend_class_entry *ce, zval *obj, int by_ref, ds_htable_t *h); zend_object_iterator *php_ds_htable_get_key_iterator_ex (zend_class_entry *ce, zval *obj, int by_ref, ds_htable_t *h); zend_object_iterator *php_ds_htable_get_pair_iterator_ex (zend_class_entry *ce, zval *obj, int by_ref, ds_htable_t *h); zend_object_iterator *php_ds_htable_get_assoc_iterator_ex(zend_class_entry *ce, zval *obj, int by_ref, ds_htable_t *h); #endif ds-1.1.8/src/php/iterators/php_map_iterator.c0000644000076500000240000000062113065035057021457 0ustar rtheunissenstaff#include "../../common.h" #include "../../ds/ds_map.h" #include "../../ds/ds_htable.h" #include "../objects/php_map.h" #include "php_map_iterator.h" #include "php_htable_iterator.h" zend_object_iterator *php_ds_map_get_iterator(zend_class_entry *ce, zval *obj, int by_ref) { ds_htable_t *table = Z_DS_MAP_P(obj)->table; return php_ds_htable_get_assoc_iterator_ex(ce, obj, by_ref, table); } ds-1.1.8/src/php/iterators/php_map_iterator.h0000644000076500000240000000026613065035057021471 0ustar rtheunissenstaff#ifndef DS_MAP_ITERATOR_H #define DS_MAP_ITERATOR_H #include "php.h" /** * */ zend_object_iterator *php_ds_map_get_iterator(zend_class_entry *ce, zval *obj, int by_ref); #endif ds-1.1.8/src/php/iterators/php_priority_queue_iterator.c0000644000076500000240000000456113065035057023776 0ustar rtheunissenstaff#include "../../common.h" #include "../../ds/ds_priority_queue.h" #include "../objects/php_priority_queue.h" #include "php_priority_queue_iterator.h" static void php_ds_priority_queue_iterator_dtor(zend_object_iterator *iter) { } static int php_ds_priority_queue_iterator_valid(zend_object_iterator *iter) { return Z_ISUNDEF(iter->data) ? FAILURE : SUCCESS; } static zval *php_ds_priority_queue_iterator_get_current_data(zend_object_iterator *iter) { return &iter->data; } static void php_ds_priority_queue_iterator_get_current_key(zend_object_iterator *iter, zval *key) { ZVAL_LONG(key, ((php_ds_priority_queue_iterator *) iter)->position); } static void php_ds_priority_queue_iterator_set_current(ds_priority_queue_t *queue, zval *data) { if (DS_PRIORITY_QUEUE_IS_EMPTY(queue)) { ZVAL_UNDEF(data); } else { ds_priority_queue_pop(queue, data); Z_TRY_DELREF_P(data); } } static void php_ds_priority_queue_iterator_move_forward(zend_object_iterator *iter) { php_ds_priority_queue_iterator *iterator = (php_ds_priority_queue_iterator *) iter; php_ds_priority_queue_iterator_set_current(iterator->queue, &iter->data); iterator->position++; } static void php_ds_priority_queue_iterator_rewind(zend_object_iterator *iter) { php_ds_priority_queue_iterator *iterator = (php_ds_priority_queue_iterator *) iter; php_ds_priority_queue_iterator_set_current(iterator->queue, &iter->data); iterator->position = 0; } static zend_object_iterator_funcs iterator_funcs = { php_ds_priority_queue_iterator_dtor, php_ds_priority_queue_iterator_valid, php_ds_priority_queue_iterator_get_current_data, php_ds_priority_queue_iterator_get_current_key, php_ds_priority_queue_iterator_move_forward, php_ds_priority_queue_iterator_rewind }; zend_object_iterator *php_ds_priority_queue_get_iterator(zend_class_entry *ce, zval *object, int by_ref) { php_ds_priority_queue_iterator *iterator; if (by_ref) { ITERATION_BY_REF_NOT_SUPPORTED(); return NULL; } iterator = ecalloc(1, sizeof(php_ds_priority_queue_iterator)); zend_iterator_init((zend_object_iterator*) iterator); ZVAL_UNDEF(&iterator->intern.data); iterator->intern.funcs = &iterator_funcs; iterator->queue = Z_DS_PRIORITY_QUEUE_P(object); iterator->position = 0; return (zend_object_iterator *) iterator; } ds-1.1.8/src/php/iterators/php_priority_queue_iterator.h0000644000076500000240000000067013065035057024000 0ustar rtheunissenstaff#ifndef DS_PRIORITY_QUEUE_ITERATOR_H #define DS_PRIORITY_QUEUE_ITERATOR_H #include "php.h" #include "../../ds/ds_priority_queue.h" typedef struct _php_ds_priority_queue_iterator { zend_object_iterator intern; zend_long position; ds_priority_queue_t *queue; } php_ds_priority_queue_iterator; zend_object_iterator *php_ds_priority_queue_get_iterator(zend_class_entry *ce, zval *object, int by_ref); #endif ds-1.1.8/src/php/iterators/php_queue_iterator.c0000644000076500000240000000404313065035057022030 0ustar rtheunissenstaff#include "../../common.h" #include "../objects/php_queue.h" #include "php_queue_iterator.h" static void php_ds_queue_iterator_dtor(zend_object_iterator *iter) { } static int php_ds_queue_iterator_valid(zend_object_iterator *iter) { return Z_ISUNDEF(iter->data) ? FAILURE : SUCCESS; } static zval *php_ds_queue_iterator_get_current_data(zend_object_iterator *iter) { return &iter->data; } static void php_ds_queue_iterator_get_current_key(zend_object_iterator *iter, zval *key) { ZVAL_LONG(key, ((ds_queue_iterator_t *) iter)->position); } static void php_ds_queue_iterator_set_current(ds_queue_t *queue, zval *data) { if (QUEUE_IS_EMPTY(queue)) { ZVAL_UNDEF(data); } else { ds_queue_pop(queue, data); Z_TRY_DELREF_P(data); } } static void php_ds_queue_iterator_move_forward(zend_object_iterator *iter) { ds_queue_iterator_t *iterator = (ds_queue_iterator_t *) iter; php_ds_queue_iterator_set_current(iterator->queue, &iter->data); iterator->position++; } static void php_ds_queue_iterator_rewind(zend_object_iterator *iter) { ds_queue_iterator_t *iterator = (ds_queue_iterator_t *) iter; php_ds_queue_iterator_set_current(iterator->queue, &iter->data); iterator->position = 0; } static zend_object_iterator_funcs php_ds_queue_iterator_funcs = { php_ds_queue_iterator_dtor, php_ds_queue_iterator_valid, php_ds_queue_iterator_get_current_data, php_ds_queue_iterator_get_current_key, php_ds_queue_iterator_move_forward, php_ds_queue_iterator_rewind }; zend_object_iterator *php_ds_queue_get_iterator(zend_class_entry *ce, zval *object, int by_ref) { ds_queue_iterator_t *iterator; if (by_ref) { ITERATION_BY_REF_NOT_SUPPORTED(); return NULL; } iterator = ecalloc(1, sizeof(ds_queue_iterator_t)); zend_iterator_init((zend_object_iterator*) iterator); iterator->intern.funcs = &php_ds_queue_iterator_funcs; iterator->queue = Z_DS_QUEUE_P(object); iterator->position = 0; return (zend_object_iterator *) iterator; } ds-1.1.8/src/php/iterators/php_queue_iterator.h0000644000076500000240000000060113065035057022031 0ustar rtheunissenstaff#ifndef DS_QUEUE_ITERATOR_H #define DS_QUEUE_ITERATOR_H #include "php.h" #include "../../ds/ds_queue.h" typedef struct _ds_queue_iterator_t { zend_object_iterator intern; zend_long position; ds_queue_t *queue; } ds_queue_iterator_t; zend_object_iterator *php_ds_queue_get_iterator(zend_class_entry *ce, zval *object, int by_ref); #endif ds-1.1.8/src/php/iterators/php_set_iterator.c0000644000076500000240000000062113065035057021475 0ustar rtheunissenstaff#include "../../common.h" #include "../../ds/ds_set.h" #include "../../ds/ds_htable.h" #include "../objects/php_set.h" #include "php_set_iterator.h" #include "php_htable_iterator.h" zend_object_iterator *php_ds_set_get_iterator(zend_class_entry *ce, zval *obj, int by_ref) { ds_htable_t *table = (Z_DS_SET_P(obj))->table; return php_ds_htable_get_key_iterator_ex(ce, obj, by_ref, table); } ds-1.1.8/src/php/iterators/php_set_iterator.h0000644000076500000240000000032613065035057021504 0ustar rtheunissenstaff#ifndef DS_SET_ITERATOR_H #define DS_SET_ITERATOR_H #include "php.h" #include "../../ds/ds_set.h" /** * */ zend_object_iterator *php_ds_set_get_iterator(zend_class_entry *ce, zval *object, int by_ref); #endif ds-1.1.8/src/php/iterators/php_stack_iterator.c0000644000076500000240000000410213065035057022005 0ustar rtheunissenstaff#include "../../common.h" #include "../objects/php_stack.h" #include "php_stack_iterator.h" static void php_ds_stack_iterator_dtor(zend_object_iterator *iter) { } static int php_ds_stack_iterator_valid(zend_object_iterator *iter) { return Z_ISUNDEF(iter->data) ? FAILURE : SUCCESS; } static zval *php_ds_stack_iterator_get_current_data(zend_object_iterator *iter) { return &iter->data; } static void php_ds_stack_iterator_get_current_key(zend_object_iterator *iter, zval *key) { ZVAL_LONG(key, ((php_ds_stack_iterator_t *) iter)->position); } static void php_ds_stack_iterator_set_current(ds_stack_t *stack, zval *data) { if (DS_STACK_IS_EMPTY(stack)) { ZVAL_UNDEF(data); } else { ds_stack_pop(stack, data); Z_TRY_DELREF_P(data); } } static void php_ds_stack_iterator_move_forward(zend_object_iterator *iter) { php_ds_stack_iterator_t *iterator = (php_ds_stack_iterator_t *) iter; php_ds_stack_iterator_set_current(iterator->stack, &iter->data); iterator->position++; } static void php_ds_stack_iterator_rewind(zend_object_iterator *iter) { php_ds_stack_iterator_t *iterator = (php_ds_stack_iterator_t *) iter; php_ds_stack_iterator_set_current(iterator->stack, &iter->data); iterator->position = 0; } static zend_object_iterator_funcs php_ds_stack_iterator_funcs = { php_ds_stack_iterator_dtor, php_ds_stack_iterator_valid, php_ds_stack_iterator_get_current_data, php_ds_stack_iterator_get_current_key, php_ds_stack_iterator_move_forward, php_ds_stack_iterator_rewind }; zend_object_iterator *php_ds_stack_get_iterator(zend_class_entry *ce, zval *object, int by_ref) { php_ds_stack_iterator_t *iterator; if (by_ref) { ITERATION_BY_REF_NOT_SUPPORTED(); return NULL; } iterator = ecalloc(1, sizeof(php_ds_stack_iterator_t)); zend_iterator_init((zend_object_iterator*) iterator); iterator->intern.funcs = &php_ds_stack_iterator_funcs; iterator->stack = Z_DS_STACK_P(object); iterator->position = 0; return (zend_object_iterator *) iterator; } ds-1.1.8/src/php/iterators/php_stack_iterator.h0000644000076500000240000000061113065035057022013 0ustar rtheunissenstaff#ifndef DS_STACK_ITERATOR_H #define DS_STACK_ITERATOR_H #include "php.h" #include "../../ds/ds_stack.h" typedef struct _php_ds_stack_iterator_t { zend_object_iterator intern; zend_long position; ds_stack_t *stack; } php_ds_stack_iterator_t; zend_object_iterator *php_ds_stack_get_iterator(zend_class_entry *ce, zval *object, int by_ref); #endif ds-1.1.8/src/php/iterators/php_vector_iterator.c0000644000076500000240000000466613065035057022221 0ustar rtheunissenstaff#include "../../common.h" #include "../../ds/ds_vector.h" #include "../objects/php_vector.h" #include "php_vector_iterator.h" static void php_ds_vector_iterator_dtor(zend_object_iterator *i) { } static int php_ds_vector_iterator_valid(zend_object_iterator *i) { php_ds_vector_iterator_t *iterator = (php_ds_vector_iterator_t *) i; return iterator->position < iterator->vector->size ? SUCCESS : FAILURE; } static zval *php_ds_vector_iterator_get_current_data(zend_object_iterator *i) { php_ds_vector_iterator_t *iterator = (php_ds_vector_iterator_t *) i; return &iterator->vector->buffer[iterator->position]; } static void php_ds_vector_iterator_get_current_key(zend_object_iterator *i, zval *key) { php_ds_vector_iterator_t *iterator = (php_ds_vector_iterator_t *) i; ZVAL_LONG(key, iterator->position); } static void php_ds_vector_iterator_move_forward(zend_object_iterator *i) { php_ds_vector_iterator_t *iterator = (php_ds_vector_iterator_t *) i; iterator->position++; } static void php_ds_vector_iterator_rewind(zend_object_iterator *i) { php_ds_vector_iterator_t *iterator = (php_ds_vector_iterator_t *) i; iterator->position = 0; } static zend_object_iterator_funcs php_ds_vector_iterator_funcs = { php_ds_vector_iterator_dtor, php_ds_vector_iterator_valid, php_ds_vector_iterator_get_current_data, php_ds_vector_iterator_get_current_key, php_ds_vector_iterator_move_forward, php_ds_vector_iterator_rewind }; static zend_object_iterator *php_ds_vector_create_iterator( ds_vector_t *vector, zend_object_iterator_funcs *funcs, int by_ref ) { php_ds_vector_iterator_t *iterator; if (by_ref) { ITERATION_BY_REF_NOT_SUPPORTED(); return NULL; } iterator = ecalloc(1, sizeof(php_ds_vector_iterator_t)); zend_iterator_init((zend_object_iterator*) iterator); iterator->intern.funcs = funcs; iterator->position = 0; iterator->vector = vector; return (zend_object_iterator *) iterator; } zend_object_iterator *php_ds_vector_get_iterator_ex(zend_class_entry *ce, zval *obj, int by_ref, ds_vector_t *vector) { return php_ds_vector_create_iterator(vector, &php_ds_vector_iterator_funcs, by_ref); } zend_object_iterator *php_ds_vector_get_iterator(zend_class_entry *ce, zval *obj, int by_ref) { ds_vector_t *vector = Z_DS_VECTOR_P(obj); return php_ds_vector_create_iterator(vector, &php_ds_vector_iterator_funcs, by_ref); } ds-1.1.8/src/php/iterators/php_vector_iterator.h0000644000076500000240000000101413065035057022206 0ustar rtheunissenstaff#ifndef DS_VECTOR_ITERATOR_H #define DS_VECTOR_ITERATOR_H #include "php.h" #include "../../ds/ds_vector.h" typedef struct php_ds_vector_iterator { zend_object_iterator intern; zend_long position; ds_vector_t *vector; } php_ds_vector_iterator_t; /** * */ zend_object_iterator *php_ds_vector_get_iterator_ex(zend_class_entry *ce, zval *obj, int by_ref, ds_vector_t *vector); zend_object_iterator *php_ds_vector_get_iterator(zend_class_entry *ce, zval *obj, int by_ref); #endif ds-1.1.8/src/php/objects/php_deque.c0000644000076500000240000000442513065035057017517 0ustar rtheunissenstaff// #include "../iterators/php_deque_iterator.h" #include "../handlers/php_deque_handlers.h" #include "../classes/php_deque_ce.h" #include "php_deque.h" zend_object *php_ds_deque_create_object_ex(ds_deque_t *deque) { php_ds_deque_t *obj = ecalloc(1, sizeof(php_ds_deque_t)); zend_object_std_init(&obj->std, php_ds_deque_ce); obj->std.handlers = &php_deque_handlers; obj->deque = deque; return &obj->std; } zend_object *php_ds_deque_create_object(zend_class_entry *ce) { return php_ds_deque_create_object_ex(ds_deque()); } zend_object *php_ds_deque_create_clone(ds_deque_t *deque) { return php_ds_deque_create_object_ex(ds_deque_clone(deque)); } int php_ds_deque_serialize(zval *object, unsigned char **buffer, size_t *length, zend_serialize_data *data) { ds_deque_t *deque = Z_DS_DEQUE_P(object); php_serialize_data_t serialize_data = (php_serialize_data_t) data; PHP_VAR_SERIALIZE_INIT(serialize_data); if (deque->size == 0) { SERIALIZE_SET_ZSTR(ZSTR_EMPTY_ALLOC()); } else { zval *value; smart_str buf = {0}; DS_DEQUE_FOREACH(deque, value) { php_var_serialize(&buf, value, &serialize_data); } DS_DEQUE_FOREACH_END(); smart_str_0(&buf); SERIALIZE_SET_ZSTR(buf.s); zend_string_release(buf.s); } PHP_VAR_SERIALIZE_DESTROY(serialize_data); return SUCCESS; } int php_ds_deque_unserialize(zval *object, zend_class_entry *ce, const unsigned char *buffer, size_t length, zend_unserialize_data *data) { ds_deque_t *deque = ds_deque(); php_unserialize_data_t unserialize_data = (php_unserialize_data_t) data; const unsigned char *pos = buffer; const unsigned char *end = buffer + length; PHP_VAR_UNSERIALIZE_INIT(unserialize_data); while (*pos != '}') { zval *value = var_tmp_var(&unserialize_data); if ( ! php_var_unserialize(value, &pos, end, &unserialize_data)) { goto error; } ds_deque_push(deque, value); } if (pos != end) { goto error; } ZVAL_DS_DEQUE(object, deque); PHP_VAR_UNSERIALIZE_DESTROY(unserialize_data); return SUCCESS; error: ds_deque_free(deque); PHP_VAR_UNSERIALIZE_DESTROY(unserialize_data); UNSERIALIZE_ERROR(); return FAILURE; } ds-1.1.8/src/php/objects/php_deque.h0000644000076500000240000000231213065035057017515 0ustar rtheunissenstaff#ifndef PHP_DS_DEQUE_H #define PHP_DS_DEQUE_H #include "../../ds/ds_deque.h" #define Z_DS_DEQUE(z) ((php_ds_deque_t*) Z_OBJ(z))->deque #define Z_DS_DEQUE_P(z) Z_DS_DEQUE(*z) #define THIS_DS_DEQUE() Z_DS_DEQUE_P(getThis()) #define ZVAL_DS_DEQUE(z, d) ZVAL_OBJ(z, php_ds_deque_create_object_ex(d)) #define RETURN_DS_DEQUE(d) \ do { \ ds_deque_t *_d = d; \ if (_d) { \ ZVAL_DS_DEQUE(return_value, _d); \ } else { \ ZVAL_NULL(return_value); \ } \ return; \ } while(0) /** * */ typedef struct php_ds_deque { zend_object std; ds_deque_t *deque; } php_ds_deque_t; /** * Creates a new zend_object using an existing deque. */ zend_object *php_ds_deque_create_object_ex(ds_deque_t *deque); /** * Creates a new deque zend_object. */ zend_object *php_ds_deque_create_object(zend_class_entry *ce); /** * Creates an object clone of a deque. */ zend_object *php_ds_deque_create_clone(ds_deque_t *deque); PHP_DS_SERIALIZE_FUNCIONS(php_ds_deque); #endif ds-1.1.8/src/php/objects/php_map.c0000644000076500000240000000361113065035057017165 0ustar rtheunissenstaff#include "../handlers/php_map_handlers.h" #include "../classes/php_map_ce.h" #include "php_map.h" #include "php_pair.h" zend_object *php_ds_map_create_object_ex(ds_map_t *map) { php_ds_map_t *obj = ecalloc(1, sizeof(php_ds_map_t)); zend_object_std_init(&obj->std, php_ds_map_ce); obj->std.handlers = &php_map_handlers; obj->map = map; return &obj->std; } zend_object *php_ds_map_create_object(zend_class_entry *ce) { return php_ds_map_create_object_ex(ds_map()); } zend_object *php_ds_map_create_clone(ds_map_t *map) { return php_ds_map_create_object_ex(ds_map_clone(map)); } HashTable *ds_map_pairs_to_php_hashtable(ds_map_t *map) { HashTable *array; zval *key; zval *value; zval pair; ALLOC_HASHTABLE(array); zend_hash_init(array, DS_MAP_SIZE(map), NULL, ZVAL_PTR_DTOR, 0); DS_HTABLE_FOREACH_KEY_VALUE(map->table, key, value) { ZVAL_DS_PAIR(&pair, ds_pair_ex(key, value)); zend_hash_next_index_insert(array, &pair); } DS_HTABLE_FOREACH_END(); return array; } zval *ds_map_pairs(ds_map_t *map) { zval *buffer = ALLOC_ZVAL_BUFFER(DS_MAP_SIZE(map)); zval *target = buffer; zval *key; zval *value; DS_HTABLE_FOREACH_KEY_VALUE(map->table, key, value) { ZVAL_DS_PAIR(target++, ds_pair_ex(key, value)); } DS_HTABLE_FOREACH_END(); return buffer; } int php_ds_map_serialize(zval *object, unsigned char **buffer, size_t *length, zend_serialize_data *data) { return ds_htable_serialize(Z_DS_MAP_P(object)->table, buffer, length, data); } int php_ds_map_unserialize(zval *object, zend_class_entry *ce, const unsigned char *buffer, size_t length, zend_unserialize_data *data) { ds_map_t *map = ds_map(); if (ds_htable_unserialize(map->table, buffer, length, data) == FAILURE) { ds_map_free(map); return FAILURE; } ZVAL_DS_MAP(object, map); return SUCCESS; } ds-1.1.8/src/php/objects/php_map.h0000644000076500000240000000214013065035057017166 0ustar rtheunissenstaff#ifndef PHP_DS_MAP_H #define PHP_DS_MAP_H #include "../../ds/ds_map.h" #define Z_DS_MAP(z) (((php_ds_map_t*)(Z_OBJ(z)))->map) #define Z_DS_MAP_P(z) Z_DS_MAP(*z) #define THIS_DS_MAP() Z_DS_MAP_P(getThis()) #define ZVAL_DS_MAP(z, map) ZVAL_OBJ(z, php_ds_map_create_object_ex(map)) #define RETURN_DS_MAP(m) \ do { \ ds_map_t *_m = m; \ if (_m) { \ ZVAL_DS_MAP(return_value, _m); \ } else { \ ZVAL_NULL(return_value); \ } \ return; \ } while(0) typedef struct _php_ds_map_t { zend_object std; ds_map_t *map; } php_ds_map_t; zend_object *php_ds_map_create_object_ex(ds_map_t *map); zend_object *php_ds_map_create_object(zend_class_entry *ce); zend_object *php_ds_map_create_clone(ds_map_t *map); zval *ds_map_pairs(ds_map_t *map); HashTable *ds_map_pairs_to_php_hashtable(ds_map_t *map); PHP_DS_SERIALIZE_FUNCIONS(php_ds_map); #endif ds-1.1.8/src/php/objects/php_pair.c0000644000076500000240000000410013065035057017335 0ustar rtheunissenstaff// #include "../iterators/php_pair_iterator.h" #include "../handlers/php_pair_handlers.h" #include "../classes/php_pair_ce.h" #include "php_pair.h" zend_object *php_ds_pair_create_object_ex(ds_pair_t *pair) { php_ds_pair_t *obj = ecalloc(1, sizeof(php_ds_pair_t)); zend_object_std_init(&obj->std, php_ds_pair_ce); obj->std.handlers = &php_pair_handlers; obj->pair = pair; return &obj->std; } zend_object *php_ds_pair_create_object(zend_class_entry *ce) { return php_ds_pair_create_object_ex(ds_pair()); } zend_object *php_ds_pair_create_clone(ds_pair_t *pair) { return php_ds_pair_create_object_ex(ds_pair_clone(pair)); } int php_ds_pair_serialize(zval *object, unsigned char **buffer, size_t *length, zend_serialize_data *data) { smart_str buf = {0}; ds_pair_t *pair = Z_DS_PAIR_P(object); php_serialize_data_t serialize_data = (php_serialize_data_t) data; PHP_VAR_SERIALIZE_INIT(serialize_data); php_var_serialize(&buf, &pair->key, &serialize_data); php_var_serialize(&buf, &pair->value, &serialize_data); smart_str_0(&buf); SERIALIZE_SET_ZSTR(buf.s); zend_string_release(buf.s); PHP_VAR_SERIALIZE_DESTROY(serialize_data); return SUCCESS; } int php_ds_pair_unserialize(zval *object, zend_class_entry *ce, const unsigned char *buffer, size_t length, zend_unserialize_data *data) { zval *key, *value; php_unserialize_data_t unserialize_data = (php_unserialize_data_t) data; const unsigned char *pos = buffer; const unsigned char *max = buffer + length; PHP_VAR_UNSERIALIZE_INIT(unserialize_data); key = var_tmp_var(&unserialize_data); if ( ! php_var_unserialize(key, &pos, max, &unserialize_data)) { goto error; } value = var_tmp_var(&unserialize_data); if ( ! php_var_unserialize(value, &pos, max, &unserialize_data)) { goto error; } ZVAL_DS_PAIR(object, ds_pair_ex(key, value)); PHP_VAR_UNSERIALIZE_DESTROY(unserialize_data); return SUCCESS; error: PHP_VAR_UNSERIALIZE_DESTROY(unserialize_data); UNSERIALIZE_ERROR(); return FAILURE; } ds-1.1.8/src/php/objects/php_pair.h0000644000076500000240000000202113065035057017342 0ustar rtheunissenstaff#ifndef PHP_DS_PAIR_H #define PHP_DS_PAIR_H #include "../../ds/ds_pair.h" #define Z_DS_PAIR(z) (((php_ds_pair_t*)(Z_OBJ(z)))->pair) #define Z_DS_PAIR_P(z) Z_DS_PAIR(*z) #define THIS_DS_PAIR() Z_DS_PAIR_P(getThis()) #define ZVAL_DS_PAIR(z, p) ZVAL_OBJ(z, php_ds_pair_create_object_ex(p)) #define RETURN_DS_PAIR(p) \ do { \ ds_pair_t *_p = p; \ if (_p) { \ ZVAL_DS_PAIR(return_value, _p); \ } else { \ ZVAL_NULL(return_value); \ } \ return; \ } while(0) typedef struct _php_ds_pair_t { zend_object std; ds_pair_t *pair; } php_ds_pair_t; zend_object *php_ds_pair_create_object_ex(ds_pair_t *pair); zend_object *php_ds_pair_create_object(zend_class_entry *ce); zend_object *php_ds_pair_create_clone(ds_pair_t *pair); PHP_DS_SERIALIZE_FUNCIONS(php_ds_pair); #endif ds-1.1.8/src/php/objects/php_priority_queue.c0000644000076500000240000000621513065035057021500 0ustar rtheunissenstaff#include "../iterators/php_priority_queue_iterator.h" #include "../handlers/php_priority_queue_handlers.h" #include "../classes/php_priority_queue_ce.h" #include "php_priority_queue.h" zend_object *php_ds_priority_queue_create_object_ex(ds_priority_queue_t *queue) { php_ds_priority_queue_t *obj = ecalloc(1, sizeof(php_ds_priority_queue_t)); zend_object_std_init(&obj->std, php_ds_priority_queue_ce); obj->std.handlers = &php_priority_queue_handlers; obj->queue = queue; obj->gc_data = NULL; obj->gc_size = 0; return &obj->std; } zend_object *php_ds_priority_queue_create_object(zend_class_entry *ce) { return php_ds_priority_queue_create_object_ex(ds_priority_queue()); } zend_object *php_ds_priority_queue_create_clone(ds_priority_queue_t *queue) { return php_ds_priority_queue_create_object_ex(ds_priority_queue_clone(queue)); } int php_ds_priority_queue_serialize(zval *object, unsigned char **buffer, size_t *length, zend_serialize_data *data) { ds_priority_queue_t *queue = Z_DS_PRIORITY_QUEUE_P(object); php_serialize_data_t serialize_data = (php_serialize_data_t) data; PHP_VAR_SERIALIZE_INIT(serialize_data); if (queue->size == 0) { SERIALIZE_SET_ZSTR(ZSTR_EMPTY_ALLOC()); } else { ds_priority_queue_node_t *nodes = ds_priority_queue_create_sorted_buffer(queue); ds_priority_queue_node_t *pos = nodes; ds_priority_queue_node_t *end = nodes + queue->size; smart_str buf = {0}; for (; pos < end; ++pos) { zval priority; ZVAL_LONG(&priority, pos->priority); php_var_serialize(&buf, &pos->value, &serialize_data); php_var_serialize(&buf, &priority, &serialize_data); } smart_str_0(&buf); SERIALIZE_SET_ZSTR(buf.s); zend_string_release(buf.s); efree(nodes); } PHP_VAR_SERIALIZE_DESTROY(serialize_data); return SUCCESS; } int php_ds_priority_queue_unserialize(zval *object, zend_class_entry *ce, const unsigned char *buffer, size_t length, zend_unserialize_data *data) { ds_priority_queue_t *queue = ds_priority_queue(); php_unserialize_data_t unserialize_data = (php_unserialize_data_t) data; const unsigned char *pos = buffer; const unsigned char *end = buffer + length; PHP_VAR_UNSERIALIZE_INIT(unserialize_data); ZVAL_DS_PRIORITY_QUEUE(object, queue); while (*pos != '}') { zval *value, *priority; value = var_tmp_var(&unserialize_data); if ( ! php_var_unserialize(value, &pos, end, &unserialize_data)) { goto error; } priority = var_tmp_var(&unserialize_data); if ( ! php_var_unserialize(priority, &pos, end, &unserialize_data)) { goto error; } if (Z_TYPE_P(priority) != IS_LONG) { goto error; } ds_priority_queue_push(queue, value, Z_LVAL_P(priority)); } if (pos != end) { goto error; } PHP_VAR_UNSERIALIZE_DESTROY(unserialize_data); return SUCCESS; error: ds_priority_queue_free(queue); PHP_VAR_UNSERIALIZE_DESTROY(unserialize_data); UNSERIALIZE_ERROR(); return FAILURE; } ds-1.1.8/src/php/objects/php_priority_queue.h0000644000076500000240000000264413065035057021507 0ustar rtheunissenstaff#ifndef PHP_DS_PRIORITY_QUEUE_H #define PHP_DS_PRIORITY_QUEUE_H #include "../../ds/ds_priority_queue.h" #define Z_DS_PRIORITY_QUEUE(z) (((php_ds_priority_queue_t*)(Z_OBJ(z)))->queue) #define Z_DS_PRIORITY_QUEUE_P(z) Z_DS_PRIORITY_QUEUE(*z) #define THIS_DS_PRIORITY_QUEUE() Z_DS_PRIORITY_QUEUE_P(getThis()) #define ZVAL_DS_PRIORITY_QUEUE(z, queue) \ ZVAL_OBJ(z, (php_ds_priority_queue_create_object_ex(queue))) #define RETURN_DS_PRIORITY_QUEUE(queue) \ do { \ ds_priority_queue_t *_queue = queue; \ if (_queue) { \ ZVAL_DS_PRIORITY_QUEUE(return_value, _queue); \ } else { \ ZVAL_NULL(return_value); \ } \ return; \ } while(0) typedef struct _php_ds_priority_queue_t { zend_object std; ds_priority_queue_t *queue; zval *gc_data; int gc_size; } php_ds_priority_queue_t; zend_object *php_ds_priority_queue_create_object_ex(ds_priority_queue_t *queue); zend_object *php_ds_priority_queue_create_object(zend_class_entry *ce); zend_object *php_ds_priority_queue_create_clone(ds_priority_queue_t *queue); PHP_DS_SERIALIZE_FUNCIONS(php_ds_priority_queue); #endif ds-1.1.8/src/php/objects/php_queue.c0000644000076500000240000000444413065035057017541 0ustar rtheunissenstaff#include "../iterators/php_queue_iterator.h" #include "../handlers/php_queue_handlers.h" #include "../classes/php_queue_ce.h" #include "php_queue.h" zend_object *php_ds_queue_create_object_ex(ds_queue_t *queue) { php_ds_queue_t *obj = ecalloc(1, sizeof(php_ds_queue_t)); zend_object_std_init(&obj->std, php_ds_queue_ce); obj->std.handlers = &php_queue_handlers; obj->queue = queue; return &obj->std; } zend_object *php_ds_queue_create_object(zend_class_entry *ce) { return php_ds_queue_create_object_ex(ds_queue()); } zend_object *php_ds_queue_create_clone(ds_queue_t *queue) { return php_ds_queue_create_object_ex(ds_queue_clone(queue)); } int php_ds_queue_serialize(zval *object, unsigned char **buffer, size_t *length, zend_serialize_data *data) { ds_queue_t *queue = Z_DS_QUEUE_P(object); php_serialize_data_t serialize_data = (php_serialize_data_t) data; PHP_VAR_SERIALIZE_INIT(serialize_data); if (QUEUE_SIZE(queue) == 0) { SERIALIZE_SET_ZSTR(ZSTR_EMPTY_ALLOC()); } else { zval *value; smart_str buf = {0}; DS_DEQUE_FOREACH(queue->deque, value) { php_var_serialize(&buf, value, &serialize_data); } DS_DEQUE_FOREACH_END(); smart_str_0(&buf); SERIALIZE_SET_ZSTR(buf.s); zend_string_release(buf.s); } PHP_VAR_SERIALIZE_DESTROY(serialize_data); return SUCCESS; } int php_ds_queue_unserialize(zval *object, zend_class_entry *ce, const unsigned char *buffer, size_t length, zend_unserialize_data *data) { ds_queue_t *queue = ds_queue(); php_unserialize_data_t unserialize_data = (php_unserialize_data_t) data; const unsigned char *pos = buffer; const unsigned char *end = buffer + length; PHP_VAR_UNSERIALIZE_INIT(unserialize_data); while (*pos != '}') { zval *value = var_tmp_var(&unserialize_data); if ( ! php_var_unserialize(value, &pos, end, &unserialize_data)) { goto error; } ds_queue_push_one(queue, value); } if (pos != end) { goto error; } ZVAL_DS_QUEUE(object, queue); PHP_VAR_UNSERIALIZE_DESTROY(unserialize_data); return SUCCESS; error: ds_queue_free(queue); PHP_VAR_UNSERIALIZE_DESTROY(unserialize_data); UNSERIALIZE_ERROR(); return FAILURE; } ds-1.1.8/src/php/objects/php_queue.h0000644000076500000240000000207213065035057017541 0ustar rtheunissenstaff#ifndef PHP_DS_QUEUE_H #define PHP_DS_QUEUE_H #include "../../ds/ds_queue.h" #define Z_DS_QUEUE(z) (((php_ds_queue_t*)(Z_OBJ(z)))->queue) #define Z_DS_QUEUE_P(z) Z_DS_QUEUE(*z) #define THIS_DS_QUEUE() Z_DS_QUEUE_P(getThis()) #define ZVAL_DS_QUEUE(z, queue) \ ZVAL_OBJ(z, php_ds_queue_create_object_ex(queue)) #define RETURN_DS_QUEUE(q) \ do { \ ds_queue_t *_q = q; \ if (_q) { \ ZVAL_DS_QUEUE(return_value, _q); \ } else { \ ZVAL_NULL(return_value); \ } \ return; \ } while(0) typedef struct _php_ds_queue_t { zend_object std; ds_queue_t *queue; } php_ds_queue_t; zend_object *php_ds_queue_create_object_ex(ds_queue_t *queue); zend_object *php_ds_queue_create_object(zend_class_entry *ce); zend_object *php_ds_queue_create_clone(ds_queue_t *queue); PHP_DS_SERIALIZE_FUNCIONS(php_ds_queue); #endif ds-1.1.8/src/php/objects/php_set.c0000644000076500000240000000432613065035057017207 0ustar rtheunissenstaff#include "../iterators/php_set_iterator.h" #include "../handlers/php_set_handlers.h" #include "../classes/php_set_ce.h" #include "php_set.h" zend_object *php_ds_set_create_object_ex(ds_set_t *set) { php_ds_set_t *obj = ecalloc(1, sizeof(php_ds_set_t)); zend_object_std_init(&obj->std, php_ds_set_ce); obj->std.handlers = &php_ds_set_handlers; obj->set = set; return &obj->std; } zend_object *php_ds_set_create_object(zend_class_entry *ce) { return php_ds_set_create_object_ex(ds_set()); } zend_object *php_ds_set_create_clone(ds_set_t *set) { return php_ds_set_create_object_ex(ds_set_clone(set)); } int php_ds_set_serialize(zval *object, unsigned char **buffer, size_t *length, zend_serialize_data *data) { ds_set_t *set = Z_DS_SET_P(object); php_serialize_data_t serialize_data = (php_serialize_data_t) data; PHP_VAR_SERIALIZE_INIT(serialize_data); if (set->table->size == 0) { SERIALIZE_SET_ZSTR(ZSTR_EMPTY_ALLOC()); } else { zval *key; smart_str buf = {0}; DS_HTABLE_FOREACH_KEY(set->table, key) { php_var_serialize(&buf, key, &serialize_data); } DS_HTABLE_FOREACH_END(); smart_str_0(&buf); SERIALIZE_SET_ZSTR(buf.s); zend_string_release(buf.s); } PHP_VAR_SERIALIZE_DESTROY(serialize_data); return SUCCESS; } int php_ds_set_unserialize(zval *object, zend_class_entry *ce, const unsigned char *buffer, size_t length, zend_unserialize_data *data) { ds_set_t *set = ds_set(); php_unserialize_data_t unserialize_data = (php_unserialize_data_t) data; const unsigned char *pos = buffer; const unsigned char *end = buffer + length; PHP_VAR_UNSERIALIZE_INIT(unserialize_data); ZVAL_DS_SET(object, set); while (*pos != '}') { zval *value = var_tmp_var(&unserialize_data); if ( ! php_var_unserialize(value, &pos, end, &unserialize_data)) { goto error; } ds_set_add(set, value); } if (pos != end) { goto error; } PHP_VAR_UNSERIALIZE_DESTROY(unserialize_data); return SUCCESS; error: ds_set_free(set); PHP_VAR_UNSERIALIZE_DESTROY(unserialize_data); UNSERIALIZE_ERROR(); return FAILURE; } ds-1.1.8/src/php/objects/php_set.h0000644000076500000240000000200213065035057017201 0ustar rtheunissenstaff#ifndef PHP_DS_SET_H #define PHP_DS_SET_H #include "../../ds/ds_set.h" #define Z_DS_SET(z) (((php_ds_set_t*)(Z_OBJ(z)))->set) #define Z_DS_SET_P(z) Z_DS_SET(*z) #define THIS_DS_SET() Z_DS_SET_P(getThis()) #define ZVAL_DS_SET(z, set) ZVAL_OBJ(z, php_ds_set_create_object_ex(set)) #define RETURN_DS_SET(s) \ do { \ ds_set_t *_s = s; \ if (_s) { \ ZVAL_DS_SET(return_value, _s); \ } else { \ ZVAL_NULL(return_value); \ } \ return; \ } while(0) typedef struct _php_ds_set_t { zend_object std; ds_set_t *set; } php_ds_set_t; zend_object *php_ds_set_create_object_ex(ds_set_t *set); zend_object *php_ds_set_create_object(zend_class_entry *ce); zend_object *php_ds_set_create_clone(ds_set_t *set); PHP_DS_SERIALIZE_FUNCIONS(php_ds_set); #endif ds-1.1.8/src/php/objects/php_stack.c0000644000076500000240000000445013065035057017517 0ustar rtheunissenstaff#include "../iterators/php_stack_iterator.h" #include "../handlers/php_stack_handlers.h" #include "../classes/php_stack_ce.h" #include "php_stack.h" zend_object *php_ds_stack_create_object_ex(ds_stack_t *stack) { php_ds_stack_t *obj = ecalloc(1, sizeof(php_ds_stack_t)); zend_object_std_init(&obj->std, php_ds_stack_ce); obj->std.handlers = &php_ds_stack_handlers; obj->stack = stack; return &obj->std; } zend_object *php_ds_stack_create_object(zend_class_entry *ce) { return php_ds_stack_create_object_ex(ds_stack()); } zend_object *php_ds_stack_create_clone(ds_stack_t *stack) { return php_ds_stack_create_object_ex(ds_stack_clone(stack)); } int php_ds_stack_serialize(zval *object, unsigned char **buffer, size_t *length, zend_serialize_data *data) { ds_stack_t *stack = Z_DS_STACK_P(object); php_serialize_data_t serialize_data = (php_serialize_data_t) data; PHP_VAR_SERIALIZE_INIT(serialize_data); if (DS_STACK_SIZE(stack) == 0) { SERIALIZE_SET_ZSTR(ZSTR_EMPTY_ALLOC()); } else { zval *value; smart_str buf = {0}; DS_VECTOR_FOREACH(stack->vector, value) { php_var_serialize(&buf, value, &serialize_data); } DS_VECTOR_FOREACH_END(); smart_str_0(&buf); SERIALIZE_SET_ZSTR(buf.s); zend_string_release(buf.s); } PHP_VAR_SERIALIZE_DESTROY(serialize_data); return SUCCESS; } int php_ds_stack_unserialize(zval *object, zend_class_entry *ce, const unsigned char *buffer, size_t length, zend_unserialize_data *data) { ds_stack_t *stack = ds_stack(); php_unserialize_data_t unserialize_data = (php_unserialize_data_t) data; const unsigned char *pos = buffer; const unsigned char *end = buffer + length; PHP_VAR_UNSERIALIZE_INIT(unserialize_data); while (*pos != '}') { zval *value = var_tmp_var(&unserialize_data); if ( ! php_var_unserialize(value, &pos, end, &unserialize_data)) { goto error; } ds_stack_push(stack, value); } if (pos != end) { goto error; } ZVAL_DS_STACK(object, stack); PHP_VAR_UNSERIALIZE_DESTROY(unserialize_data); return SUCCESS; error: ds_stack_free(stack); PHP_VAR_UNSERIALIZE_DESTROY(unserialize_data); UNSERIALIZE_ERROR(); return FAILURE; } ds-1.1.8/src/php/objects/php_stack.h0000644000076500000240000000206113065035057017520 0ustar rtheunissenstaff#ifndef PHP_DS_STACK_H #define PHP_DS_STACK_H #include "../../ds/ds_stack.h" #define Z_DS_STACK(z) (((php_ds_stack_t*)(Z_OBJ(z)))->stack) #define Z_DS_STACK_P(z) Z_DS_STACK(*z) #define THIS_DS_STACK() Z_DS_STACK_P(getThis()) #define ZVAL_DS_STACK(z, s) ZVAL_OBJ(z, php_ds_stack_create_object_ex(s)) #define RETURN_DS_STACK(s) \ do { \ ds_stack_t *_s = s; \ if (_s) { \ ZVAL_DS_STACK(return_value, _s); \ } else { \ ZVAL_NULL(return_value); \ } \ return; \ } while(0) typedef struct _php_ds_stack_t { zend_object std; ds_stack_t *stack; } php_ds_stack_t; zend_object *php_ds_stack_create_object_ex(ds_stack_t *stack); zend_object *php_ds_stack_create_object(zend_class_entry *ce); zend_object *php_ds_stack_create_clone(ds_stack_t *stack); PHP_DS_SERIALIZE_FUNCIONS(php_ds_stack); #endif ds-1.1.8/src/php/objects/php_vector.c0000644000076500000240000000450013065035057017710 0ustar rtheunissenstaff// #include "../iterators/php_vector_iterator.h" #include "../handlers/php_vector_handlers.h" #include "../classes/php_vector_ce.h" #include "php_vector.h" zend_object *php_ds_vector_create_object_ex(ds_vector_t *vector) { php_ds_vector_t *obj = ecalloc(1, sizeof(php_ds_vector_t)); zend_object_std_init(&obj->std, php_ds_vector_ce); obj->std.handlers = &php_vector_handlers; obj->vector = vector; return &obj->std; } zend_object *php_ds_vector_create_object(zend_class_entry *ce) { return php_ds_vector_create_object_ex(ds_vector()); } zend_object *php_ds_vector_create_clone(ds_vector_t *vector) { return php_ds_vector_create_object_ex(ds_vector_clone(vector)); } int php_ds_vector_serialize(zval *object, unsigned char **buffer, size_t *length, zend_serialize_data *data) { ds_vector_t *vector = Z_DS_VECTOR_P(object); php_serialize_data_t serialize_data = (php_serialize_data_t) data; PHP_VAR_SERIALIZE_INIT(serialize_data); if (DS_VECTOR_IS_EMPTY(vector)) { SERIALIZE_SET_ZSTR(ZSTR_EMPTY_ALLOC()); } else { zval *value; smart_str buf = {0}; DS_VECTOR_FOREACH(vector, value) { php_var_serialize(&buf, value, &serialize_data); } DS_VECTOR_FOREACH_END(); smart_str_0(&buf); SERIALIZE_SET_ZSTR(buf.s); zend_string_release(buf.s); } PHP_VAR_SERIALIZE_DESTROY(serialize_data); return SUCCESS; } int php_ds_vector_unserialize(zval *obj, zend_class_entry *ce, const unsigned char *buffer, size_t length, zend_unserialize_data *data) { ds_vector_t *vector = ds_vector(); php_unserialize_data_t unserialize_data = (php_unserialize_data_t) data; const unsigned char *pos = buffer; const unsigned char *end = buffer + length; PHP_VAR_UNSERIALIZE_INIT(unserialize_data); while (*pos != '}') { zval *value = var_tmp_var(&unserialize_data); if ( ! php_var_unserialize(value, &pos, end, &unserialize_data)) { goto error; } ds_vector_push(vector, value); } if (pos != end) { goto error; } ZVAL_DS_VECTOR(obj, vector); PHP_VAR_UNSERIALIZE_DESTROY(unserialize_data); return SUCCESS; error: ds_vector_free(vector); PHP_VAR_UNSERIALIZE_DESTROY(unserialize_data); UNSERIALIZE_ERROR(); return FAILURE; } ds-1.1.8/src/php/objects/php_vector.h0000644000076500000240000000210413065035057017713 0ustar rtheunissenstaff#ifndef PHP_DS_VECTOR_H #define PHP_DS_VECTOR_H #include "../../ds/ds_vector.h" #define Z_DS_VECTOR(z) (((php_ds_vector_t*)(Z_OBJ(z)))->vector) #define Z_DS_VECTOR_P(z) Z_DS_VECTOR(*z) #define THIS_DS_VECTOR() Z_DS_VECTOR_P(getThis()) #define ZVAL_DS_VECTOR(z, v) ZVAL_OBJ(z, php_ds_vector_create_object_ex(v)) #define RETURN_DS_VECTOR(v) \ do { \ ds_vector_t *_v = v; \ if (_v) { \ ZVAL_DS_VECTOR(return_value, _v); \ } else { \ ZVAL_NULL(return_value); \ } \ return; \ } while(0) typedef struct php_ds_vector { zend_object std; ds_vector_t *vector; } php_ds_vector_t; zend_object *php_ds_vector_create_object_ex(ds_vector_t *vector); zend_object *php_ds_vector_create_object(zend_class_entry *ce); zend_object *php_ds_vector_create_clone(ds_vector_t *vector); PHP_DS_SERIALIZE_FUNCIONS(php_ds_vector); #endif ds-1.1.8/src/php/arginfo.h0000644000076500000240000002201013065035057015534 0ustar rtheunissenstaff#ifndef DS_ARGINFO_H #define DS_ARGINFO_H #define ARGINFO_NONE(name) \ ZEND_BEGIN_ARG_INFO_EX(arginfo_##name, 0, 0, 0) \ ZEND_END_ARG_INFO() #define ARGINFO_OPTIONAL_ZVAL(name, z) \ ZEND_BEGIN_ARG_INFO_EX(arginfo_##name, 0, 0, 0) \ ZEND_ARG_TYPE_INFO(0, z, 0, 1) \ ZEND_END_ARG_INFO() #define ARGINFO_OPTIONAL_ZVAL_OPTIONAL_ZVAL(name, z1, z2) \ ZEND_BEGIN_ARG_INFO_EX(arginfo_##name, 0, 0, 0) \ ZEND_ARG_TYPE_INFO(0, z1, 0, 1) \ ZEND_ARG_TYPE_INFO(0, z2, 0, 1) \ ZEND_END_ARG_INFO() #define ARGINFO_CALLABLE_OPTIONAL_ZVAL(name, c, z) \ ZEND_BEGIN_ARG_INFO_EX(arginfo_##name, 0, 0, 1) \ ZEND_ARG_TYPE_INFO(0, c, IS_CALLABLE, 0) \ ZEND_ARG_TYPE_INFO(0, z, 0, 1) \ ZEND_END_ARG_INFO() #define ARGINFO_OPTIONAL_STRING(name, s) \ ZEND_BEGIN_ARG_INFO_EX(arginfo_##name, 0, 0, 0) \ ZEND_ARG_TYPE_INFO(0, s, IS_STRING, 0) \ ZEND_END_ARG_INFO() #define ARGINFO_OPTIONAL_CALLABLE(name, c) \ ZEND_BEGIN_ARG_INFO_EX(arginfo_##name, 0, 0, 0) \ ZEND_ARG_TYPE_INFO(0, c, IS_CALLABLE, 1) \ ZEND_END_ARG_INFO() #define ARGINFO_CALLABLE(name, c) \ ZEND_BEGIN_ARG_INFO_EX(arginfo_##name, 0, 0, 1) \ ZEND_ARG_TYPE_INFO(0, c, IS_CALLABLE, 0) \ ZEND_END_ARG_INFO() #define ARGINFO_VARIADIC_ZVAL(name, v) \ ZEND_BEGIN_ARG_INFO_EX(arginfo_##name, 0, 0, 0) \ ZEND_ARG_VARIADIC_INFO(0, v) \ ZEND_END_ARG_INFO() #define ARGINFO_LONG(name, i) \ ZEND_BEGIN_ARG_INFO_EX(arginfo_##name, 0, 0, 1) \ ZEND_ARG_TYPE_INFO(0, i, IS_LONG, 0) \ ZEND_END_ARG_INFO() #define ARGINFO_LONG_ZVAL(name, i, z) \ ZEND_BEGIN_ARG_INFO_EX(arginfo_##name, 0, 0, 2) \ ZEND_ARG_TYPE_INFO(0, i, IS_LONG, 0) \ ZEND_ARG_INFO(0, z) \ ZEND_END_ARG_INFO() #define ARGINFO_ZVAL_LONG(name, z, i) \ ZEND_BEGIN_ARG_INFO_EX(arginfo_##name, 0, 0, 2) \ ZEND_ARG_INFO(0, z) \ ZEND_ARG_TYPE_INFO(0, i, IS_LONG, 0) \ ZEND_END_ARG_INFO() #define ARGINFO_ZVAL(name, z) \ ZEND_BEGIN_ARG_INFO_EX(arginfo_##name, 0, 0, 1) \ ZEND_ARG_INFO(0, z) \ ZEND_END_ARG_INFO() #define ARGINFO_ZVAL_ZVAL(name, z1, z2) \ ZEND_BEGIN_ARG_INFO_EX(arginfo_##name, 0, 0, 2) \ ZEND_ARG_INFO(0, z1) \ ZEND_ARG_INFO(0, z2) \ ZEND_END_ARG_INFO() #define ARGINFO_ZVAL_OPTIONAL_ZVAL(name, z1, z2) \ ZEND_BEGIN_ARG_INFO_EX(arginfo_##name, 0, 0, 1) \ ZEND_ARG_INFO(0, z1) \ ZEND_ARG_TYPE_INFO(0, z2, 0, 1) \ ZEND_END_ARG_INFO() #define ARGINFO_LONG_VARIADIC_ZVAL(name, i, v) \ ZEND_BEGIN_ARG_INFO_EX(arginfo_##name, 0, 0, 1) \ ZEND_ARG_TYPE_INFO(0, i, IS_LONG, 0) \ ZEND_ARG_VARIADIC_INFO(0, v) \ ZEND_END_ARG_INFO() #if PHP_VERSION_ID >= 70200 #define ARGINFO_ZVAL_RETURN_BOOL(name, z) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 1, _IS_BOOL, 0) \ ZEND_ARG_INFO(0, z) \ ZEND_END_ARG_INFO() #else #define ARGINFO_ZVAL_RETURN_BOOL(name, z) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 1, _IS_BOOL, NULL, 0) \ ZEND_ARG_INFO(0, z) \ ZEND_END_ARG_INFO() #endif #if PHP_VERSION_ID >= 70200 #define ARGINFO_CALLABLE_RETURN_DS(name, c, col) \ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_##name, 0, 1, PHP_DS_NS(col), 1) \ ZEND_ARG_TYPE_INFO(0, c, IS_CALLABLE, 0) \ ZEND_END_ARG_INFO() #else #define ARGINFO_CALLABLE_RETURN_DS(name, c, col) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 1, IS_OBJECT, PHP_DS_NS(col), 1) \ ZEND_ARG_TYPE_INFO(0, c, IS_CALLABLE, 0) \ ZEND_END_ARG_INFO() #endif #if PHP_VERSION_ID >= 70200 #define ARGINFO_OPTIONAL_ZVAL_RETURN_DS(name, z, col) \ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_##name, 0, 0, PHP_DS_NS(col), 1) \ ZEND_ARG_TYPE_INFO(0, z, 0, 1) \ ZEND_END_ARG_INFO() #else #define ARGINFO_OPTIONAL_ZVAL_RETURN_DS(name, z, col) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 0, IS_OBJECT, PHP_DS_NS(col), 1) \ ZEND_ARG_TYPE_INFO(0, z, 0, 1) \ ZEND_END_ARG_INFO() #endif #if PHP_VERSION_ID >= 70200 #define ARGINFO_OPTIONAL_STRING_RETURN_STRING(name, s) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 0, IS_STRING, 0) \ ZEND_ARG_TYPE_INFO(0, s, IS_STRING, 0) \ ZEND_END_ARG_INFO() #else #define ARGINFO_OPTIONAL_STRING_RETURN_STRING(name, s) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 0, IS_STRING, NULL, 0) \ ZEND_ARG_TYPE_INFO(0, s, IS_STRING, 0) \ ZEND_END_ARG_INFO() #endif #if PHP_VERSION_ID >= 70200 #define ARGINFO_ZVAL_RETURN_DS(name, z, col) \ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_##name, 0, 1, PHP_DS_NS(col), 1) \ ZEND_ARG_TYPE_INFO(0, z, 0, 0) \ ZEND_END_ARG_INFO() #else #define ARGINFO_ZVAL_RETURN_DS(name, z, col) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 1, IS_OBJECT, PHP_DS_NS(col), 1) \ ZEND_ARG_TYPE_INFO(0, z, 0, 0) \ ZEND_END_ARG_INFO() #endif #if PHP_VERSION_ID >= 70200 #define ARGINFO_OPTIONAL_CALLABLE_RETURN_DS(name, c, col) \ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_##name, 0, 0, PHP_DS_NS(col), 1) \ ZEND_ARG_TYPE_INFO(0, c, IS_CALLABLE, 1) \ ZEND_END_ARG_INFO() #else #define ARGINFO_OPTIONAL_CALLABLE_RETURN_DS(name, c, col) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 0, IS_OBJECT, PHP_DS_NS(col), 1) \ ZEND_ARG_TYPE_INFO(0, c, IS_CALLABLE, 1) \ ZEND_END_ARG_INFO() #endif #if PHP_VERSION_ID >= 70200 #define ARGINFO_LONG_OPTIONAL_LONG_RETURN_DS(name, i1, i2, col) \ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_##name, 0, 1, PHP_DS_NS(col), 1) \ ZEND_ARG_TYPE_INFO(0, i1, IS_LONG, 0) \ ZEND_ARG_TYPE_INFO(0, i2, IS_LONG, 1) \ ZEND_END_ARG_INFO() #else #define ARGINFO_LONG_OPTIONAL_LONG_RETURN_DS(name, i1, i2, col) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 1, IS_OBJECT, PHP_DS_NS(col), 1) \ ZEND_ARG_TYPE_INFO(0, i1, IS_LONG, 0) \ ZEND_ARG_TYPE_INFO(0, i2, IS_LONG, 1) \ ZEND_END_ARG_INFO() #endif #if PHP_VERSION_ID >= 70200 #define ARGINFO_LONG_RETURN_DS(name, i, col) \ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_##name, 0, 1, PHP_DS_NS(col), 1) \ ZEND_ARG_TYPE_INFO(0, i, IS_LONG, 0) \ ZEND_END_ARG_INFO() #else #define ARGINFO_LONG_RETURN_DS(name, i, col) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 1, IS_OBJECT, PHP_DS_NS(col), 1) \ ZEND_ARG_TYPE_INFO(0, i, IS_LONG, 0) \ ZEND_END_ARG_INFO() #endif #if PHP_VERSION_ID >= 70200 #define ARGINFO_NONE_RETURN_LONG(name) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 0, IS_LONG, 0) \ ZEND_END_ARG_INFO() #else #define ARGINFO_NONE_RETURN_LONG(name) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 0, IS_LONG, NULL, 0) \ ZEND_END_ARG_INFO() #endif #if PHP_VERSION_ID >= 70200 #define ARGINFO_NONE_RETURN_STRING(name) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 0, IS_STRING, 0) \ ZEND_END_ARG_INFO() #else #define ARGINFO_NONE_RETURN_STRING(name) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 0, IS_STRING, NULL, 0) \ ZEND_END_ARG_INFO() #endif #if PHP_VERSION_ID >= 70200 #define ARGINFO_NONE_RETURN_DS(name, class_name) \ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_##name, 0, 0, PHP_DS_NS(class_name), 1) \ ZEND_END_ARG_INFO() #else #define ARGINFO_NONE_RETURN_DS(name, class_name) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 0, IS_OBJECT, PHP_DS_NS(class_name), 1) \ ZEND_END_ARG_INFO() #endif #if PHP_VERSION_ID >= 70200 #define ARGINFO_NONE_RETURN_OBJ(name, class_name) \ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_##name, 0, 0, class_name, 1) \ ZEND_END_ARG_INFO() #else #define ARGINFO_NONE_RETURN_OBJ(name, class_name) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 0, IS_OBJECT, class_name, 1) \ ZEND_END_ARG_INFO() #endif #if PHP_VERSION_ID >= 70200 #define ARGINFO_NONE_RETURN_BOOL(name) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 0, _IS_BOOL, 0) \ ZEND_END_ARG_INFO() #else #define ARGINFO_NONE_RETURN_BOOL(name) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 0, _IS_BOOL, NULL, 0) \ ZEND_END_ARG_INFO() #endif #if PHP_VERSION_ID >= 70200 #define ARGINFO_VARIADIC_ZVAL_RETURN_BOOL(name, v) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 0, _IS_BOOL, 0) \ ZEND_ARG_VARIADIC_INFO(0, v) \ ZEND_END_ARG_INFO() #else #define ARGINFO_VARIADIC_ZVAL_RETURN_BOOL(name, v) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 0, _IS_BOOL, NULL, 0) \ ZEND_ARG_VARIADIC_INFO(0, v) \ ZEND_END_ARG_INFO() #endif #if PHP_VERSION_ID >= 70200 #define ARGINFO_NONE_RETURN_ARRAY(name) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 0, IS_ARRAY, 0) \ ZEND_END_ARG_INFO() #else #define ARGINFO_NONE_RETURN_ARRAY(name) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 0, IS_ARRAY, NULL, 0) \ ZEND_END_ARG_INFO() #endif #if PHP_VERSION_ID >= 70200 #define ARGINFO_DS_RETURN_DS(name, obj, cls, col) \ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_##name, 0, 1, PHP_DS_NS(col), 1) \ ZEND_ARG_OBJ_INFO(0, obj, Ds\\cls, 0) \ ZEND_END_ARG_INFO() #else #define ARGINFO_DS_RETURN_DS(name, obj, cls, col) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_##name, 0, 1, IS_OBJECT, PHP_DS_NS(col), 1) \ ZEND_ARG_OBJ_INFO(0, obj, Ds\\cls, 0) \ ZEND_END_ARG_INFO() #endif #endif ds-1.1.8/src/php/parameters.h0000644000076500000240000000422513065035057016262 0ustar rtheunissenstaff#ifndef DS_PARAMETERS_H #define DS_PARAMETERS_H #define SETUP_CALLABLE_VARS() \ zend_fcall_info fci = empty_fcall_info; \ zend_fcall_info_cache fci_cache = empty_fcall_info_cache; #define PARSE_1(spec, a) if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), spec, a) == FAILURE) return #define PARSE_2(spec, a, b) if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), spec, a, b) == FAILURE) return #define PARSE_3(spec, a, b, c) if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), spec, a, b, c) == FAILURE) return #define PARSE_NONE if (zend_parse_parameters_none() == FAILURE) return #define PARSE_OPTIONAL_ZVAL(v) \ zval *v = NULL; \ PARSE_1("|z", &v) #define PARSE_OPTIONAL_ZVAL_OPTIONAL_ZVAL(v1, v2) \ zval *v1 = NULL; \ zval *v2 = NULL; \ PARSE_2("|zz", &v1, &v2) #define PARSE_STRING() \ char *str; \ size_t len; \ PARSE_2("s", &str, &len) #define PARSE_CALLABLE_AND_OPTIONAL_ZVAL(v) \ SETUP_CALLABLE_VARS(); \ zval *v = NULL; \ PARSE_3("f|z", &fci, &fci_cache, &v) #define PARSE_CALLABLE() \ SETUP_CALLABLE_VARS(); \ PARSE_2("f", &fci, &fci_cache) #define PARSE_LONG_AND_LONG(a, b) \ zend_long a = 0; \ zend_long b = 0; \ PARSE_2("ll", &a, &b) #define PARSE_LONG_AND_ZVAL(l, z) \ zend_long l = 0; \ zval *z = NULL; \ PARSE_2("lz", &l, &z) #define PARSE_ZVAL_LONG(z, l) \ zval *z = NULL; \ zend_long l = 0; \ PARSE_2("zl", &z, &l) #define PARSE_VARIADIC_ZVAL() \ zval *argv = NULL; \ zend_long argc = 0; \ PARSE_2("*", &argv, &argc) #define PARSE_LONG_AND_VARIADIC_ZVAL(_l) \ zval *argv = NULL; \ zend_long argc = 0; \ zend_long _l = 0; \ PARSE_3("l*", &_l, &argv, &argc) #define PARSE_LONG(a) \ zend_long a = 0; \ PARSE_1("l", &a) #define PARSE_COMPARE_CALLABLE() \ DSG(user_compare_fci) = empty_fcall_info; \ DSG(user_compare_fci_cache) = empty_fcall_info_cache; \ PARSE_2("f", &DSG(user_compare_fci), &DSG(user_compare_fci_cache)) #define PARSE_ZVAL(z) \ zval *z = NULL; \ PARSE_1("z", &z) #define PARSE_OBJ(o, ce) \ zval *o = NULL; \ PARSE_2("O", &o, ce) #define PARSE_ZVAL_ZVAL(z1, z2) \ zval *z1 = NULL; \ zval *z2 = NULL; \ PARSE_2("zz", &z1, &z2) #define PARSE_ZVAL_OPTIONAL_ZVAL(z1, z2) \ zval *z1 = NULL; \ zval *z2 = NULL; \ PARSE_2("z|z", &z1, &z2) #endif ds-1.1.8/src/common.c0000644000076500000240000001051513065035057014612 0ustar rtheunissenstaff#include "common.h" static int ds_zval_user_compare_func(const void *a, const void *b) { zval params[2]; zval retval; zval *x = (zval*) a; zval *y = (zval*) b; ZVAL_COPY_VALUE(¶ms[0], x); ZVAL_COPY_VALUE(¶ms[1], y); DSG(user_compare_fci).param_count = 2; DSG(user_compare_fci).params = params; DSG(user_compare_fci).retval = &retval; if (zend_call_function( &DSG(user_compare_fci), &DSG(user_compare_fci_cache)) == SUCCESS) { return (int) zval_get_long(&retval); } return 0; } static int ds_zval_compare_func(const void *a, const void *b) { zval retval; zval *x = (zval*) a; zval *y = (zval*) b; if (compare_function(&retval, x, y) == SUCCESS) { return (int) zval_get_long(&retval); } return 0; } void ds_sort_zval_buffer(zval *buffer, zend_long size) { qsort(buffer, size, sizeof(zval), ds_zval_compare_func); } void ds_user_sort_zval_buffer(zval *buffer, zend_long size) { qsort(buffer, size, sizeof(zval), ds_zval_user_compare_func); } int ds_zval_isset(zval *value, int check_empty) { if (value == NULL) { return 0; } if ( ! check_empty) { return Z_TYPE_P(value) != IS_NULL; } return zend_is_true(value); } void ds_normalize_slice_args( zend_long *offset, zend_long *length, zend_long size ) { zend_long idx = *offset; zend_long len = *length; // If the offset is beyond is the end or the length is zero, zero both. if (size == 0 || idx >= size) { idx = 0; len = 0; } else { // If index is negative, start that far from the end. if (idx < 0) { idx = MAX(0, size + idx); } // If length is given and negative, stop that far from the end. if (len < 0) { len = MAX(0, (size + len) - idx); } // If the length extends beyond the end, only go up to the end. if ((idx + len) > size) { len = MAX(0, size - idx); } } *offset = idx; *length = len; } void smart_str_appendz(smart_str *buffer, zval *value) { switch (Z_TYPE_P(value)) { case IS_STRING: smart_str_append(buffer, Z_STR_P(value)); return; case IS_LONG: smart_str_append_long(buffer, Z_LVAL_P(value)); return; } zend_string *str = zval_get_string(value); smart_str_append(buffer, str); zend_string_free(str); } zend_string *ds_join_zval_buffer( zval *buffer, zend_long size, char *glue, size_t len ) { smart_str str = {0}; if (size <= 0) { return ZSTR_EMPTY_ALLOC(); } if (size == 1) { return zval_get_string(buffer); } // Glue is optional, will use empty string by default if NULL if (glue && len) { zval *pos = buffer; zval *end = buffer + size - 1; // Exclude last value // Append each part and the glue right up to the last value. do { smart_str_appendz(&str, pos); smart_str_appendl(&str, glue, len); } while (++pos != end); // Append last value smart_str_appendz(&str, pos); } else { zval *pos = buffer; zval *end = buffer + size; // Append each part including the last, without glue. do { smart_str_appendz(&str, pos); } while (++pos != end); } smart_str_0(&str); return str.s; } bool ds_is_traversable(zval *value) { return Z_TYPE_P(value) == IS_OBJECT && instanceof_function(Z_OBJCE_P(value), zend_ce_traversable); } bool ds_is_array(zval *value) { return Z_TYPE_P(value) == IS_ARRAY; } bool ds_php_array_uses_keys(HashTable *ht) { zend_string *key; zend_long index; zend_long expected = 0; ZEND_HASH_FOREACH_KEY(ht, index, key) { if (key || index != expected++) { return true; } } ZEND_HASH_FOREACH_END(); return false; } void ds_reverse_zval_range(zval *x, zval *y) { for (; x < --y; ++x) SWAP_ZVAL(*x, *y); } void ds_throw_exception(zend_class_entry *ce, const char *format, ...) { va_list ap; zend_string *str; va_start(ap, format); str = vstrpprintf(0, format, ap); va_end(ap); zend_throw_exception(ce, str->val, 0); zend_string_free(str); } ds-1.1.8/src/common.h0000644000076500000240000002071313065035057014620 0ustar rtheunissenstaff#ifndef DS_COMMON_H #define DS_COMMON_H #include "php.h" #include "zend_exceptions.h" #include "ext/standard/php_var.h" #include "ext/spl/spl_exceptions.h" #include "zend_smart_str.h" #include "../php_ds.h" /** * Used for consistent naming when working with callables. */ #define FCI_PARAMS zend_fcall_info fci, zend_fcall_info_cache fci_cache #define FCI_ARGS fci, fci_cache /** * Used for consistent naming when working with variadics. */ #define VA_PARAMS zend_long argc, zval *argv #define VA_ARGS argc, argv /** * Default namespace. */ #define PHP_DS_NS(cls) "Ds\\" #cls /** * */ #define STR_AND_LEN(str) str, sizeof(str) - 1 /** * Combined class, name, and arginfo method entry. */ #define PHP_DS_ME(cls, name) \ PHP_ME(cls, name, arginfo_##cls##_##name, ZEND_ACC_PUBLIC) /** * */ #define DTOR_AND_UNDEF(z) \ do { \ zval *_z = z; \ if (_z && ! Z_ISUNDEF_P(_z)) { \ zval_ptr_dtor(_z); \ ZVAL_UNDEF(_z); \ } \ } while (0) /** * */ #define SET_AS_RETURN_AND_UNDEF(z) \ do { \ zval *_z = z; \ if (return_value) { \ ZVAL_COPY_VALUE(return_value, _z); \ ZVAL_UNDEF(_z); \ } else { \ if ( ! Z_ISUNDEF_P(_z)) { \ zval_ptr_dtor(_z); \ ZVAL_UNDEF(_z); \ } \ } \ } while (0) /** * */ #define SWAP_ZVAL(a, b) \ do { \ zval _t = a; \ a = b; \ b = _t; \ } while (0) /** * */ #define DS_ADD_TO_SUM(value, sum) \ do { \ zval number; \ \ if (Z_TYPE_P(value) == IS_ARRAY || Z_TYPE_P(value) == IS_OBJECT) { \ continue; \ } \ \ ZVAL_COPY(&number, value); \ convert_scalar_to_number(&number); \ fast_add_function(sum, sum, &number); \ } while (0) \ /** * Used to replace a buffer with a new one. */ #define FREE_AND_REPLACE(ptr, repl) \ do { \ void *_repl = repl; \ efree(ptr); \ ptr = _repl; \ } while (0) /** * Allocates a zval buffer of a specified length. */ #define ALLOC_ZVAL_BUFFER(n) ecalloc(n, sizeof(zval)) /** * Reallocates a zval buffer to a specified length. */ #define REALLOC_ZVAL_BUFFER(ptr, n) \ do { \ ptr = erealloc(ptr, (n) * sizeof(zval)); \ } while (0) /** * Copies 'len' values from 'src' into 'dst'. */ #define COPY_ZVAL_BUFFER(dst, src, len) \ do { \ zval *_src = src; \ zval *_dst = dst; \ zval *_end = src + len; \ for (; _src != _end; ++_src, ++_dst) { \ ZVAL_COPY(_dst, _src); \ } \ } while (0) /** * Used to determine if a string zval is equal to a string literal. * Eg. ZVAL_EQUALS_STRING(value, "test") */ #define ZVAL_EQUALS_STRING(z, s) zend_string_equals_literal(Z_STR_P(z), s) /** * Copies a zval into the return_value. */ #define RETURN_ZVAL_COPY(z) \ do { \ zval *_z = z; \ if (_z) { \ ZVAL_COPY(return_value, _z); \ } \ return; \ } while (0) #define SERIALIZE_SET_ZSTR(s) \ *buffer = (unsigned char *) estrndup(ZSTR_VAL((s)), ZSTR_LEN((s))); \ *length = ZSTR_LEN((s)); #define PHP_DS_SERIALIZE_FUNCIONS(name) \ int name##_serialize( \ zval *object, \ unsigned char **buffer, \ size_t *length, \ zend_serialize_data *data \ ); \ int name##_unserialize( \ zval *object, \ zend_class_entry *ce, \ const unsigned char *buffer, \ size_t length, \ zend_unserialize_data *data \ ) /** EXCEPTIONS **************************************************************/ #define ARRAY_ACCESS_BY_KEY_NOT_SUPPORTED() ds_throw_exception( \ spl_ce_OutOfBoundsException, \ "Array access by key is not supported") #define INDEX_OUT_OF_RANGE(index, max) ds_throw_exception( \ spl_ce_OutOfRangeException, \ max == 0 \ ? "Index out of range: %d" \ : "Index out of range: %d, expected 0 <= x <= %d", \ index, \ max - 1) #define OFFSET_OUT_OF_BOUNDS() ds_throw_exception( \ spl_ce_OutOfBoundsException, \ "Offset out of bounds") #define ARRAY_ACCESS_PUSH_NOT_SUPPORTED() ds_throw_exception( \ spl_ce_OutOfBoundsException, \ "Array access push syntax is not supported") #define KEY_NOT_FOUND() ds_throw_exception( \ spl_ce_OutOfBoundsException, \ "Key not found") #define OBJ_HASH_MUST_BE_SCALAR(z) ds_throw_exception( \ spl_ce_UnexpectedValueException, \ "Object hash must be scalar, %s given", zend_get_type_by_const(Z_TYPE_P(z))) #define VALUE_MUST_BE_INTEGER(z) ds_throw_exception( \ spl_ce_UnexpectedValueException, \ "Value must be of type integer, %d given", zend_get_type_by_const(Z_TYPE_P(z))) #define NOT_ALLOWED_WHEN_EMPTY() ds_throw_exception( \ spl_ce_UnderflowException, \ "Unexpected empty state") #define ARRAY_OR_TRAVERSABLE_REQUIRED() ds_throw_exception( \ spl_ce_InvalidArgumentException, \ "Value must be an array or traversable object") #define INTEGER_INDEX_REQUIRED(z) ds_throw_exception( \ zend_ce_type_error, \ "Index must be of type integer, %s given", zend_get_type_by_const(Z_TYPE_P(z))) #define ITERATION_BY_REF_NOT_SUPPORTED() ds_throw_exception( \ zend_ce_error, \ "Iterating by reference is not supported") #define ACCESS_BY_REF_NOT_ALLOWED() ds_throw_exception( \ zend_ce_error, \ "Access by reference is not allowed") #define UNSERIALIZE_ERROR() ds_throw_exception( \ zend_ce_error, \ "Failed to unserialize data") #define RECONSTRUCTION_NOT_ALLOWED() ds_throw_exception( \ zend_ce_error, \ "Immutable objects may not be reconstructed") #define MUTABILITY_NOT_ALLOWED() ds_throw_exception( \ zend_ce_error, \ "Immutable objects may not be changed") /** * */ void ds_throw_exception(zend_class_entry *ce, const char *format, ...); /*****************************************************************************/ /** * Similar to 'implode', joins a zval buffer using an optional 'glue'. * Use NULL and 0 for 'str' and 'len' to indicate an optional glue. */ zend_string *ds_join_zval_buffer( zval *buffer, zend_long size, char *str, size_t len ); /** * Normalizes input parameters for slicing so that the implementation can focus * on the actual slicing. Takes care of negative values, length > size etc. */ void ds_normalize_slice_args( zend_long *offset, zend_long *length, zend_long size ); /** * Sorts a zval buffer in place using the default internal compare_func. */ void ds_sort_zval_buffer(zval *buffer, zend_long size); /** * Sorts a zval buffer in place using a user-provided, global compare function. */ void ds_user_sort_zval_buffer(zval *buffer, zend_long size); /** * Reverses zvals between two ranges, usually a range within a buffer. */ void ds_reverse_zval_range(zval *x, zval *y); /** * Determines if a zval is set, ie. 'isset' and 'empty'. */ int ds_zval_isset(zval *value, int check_empty); /** * Determines if a zval is an array. */ bool ds_is_array(zval *value); /** * Determines if an array uses keys, similar to how json_encode does it. */ bool ds_php_array_uses_keys(HashTable *ht); /** * Determines if a zval is an object and implements Traversable. */ bool ds_is_traversable(zval *value); /** * */ void smart_str_appendz(smart_str *buffer, zval *value); #endif ds-1.1.8/LICENSE0000644000076500000240000000207213065035057013373 0ustar rtheunissenstaffThe MIT License (MIT) Copyright (c) 2016 Rudi Theunissen Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ds-1.1.8/config.m40000644000076500000240000000670313065035057014102 0ustar rtheunissenstaffPHP_ARG_ENABLE(ds, whether to enable ds support, [ --enable-ds Enable ds support]) if test "$PHP_DS" != "no"; then PHP_NEW_EXTENSION(ds, \ \ src/common.c \ \ dnl Internal src/ds/ds_vector.c \ src/ds/ds_deque.c \ src/ds/ds_htable.c \ src/ds/ds_set.c \ src/ds/ds_map.c \ src/ds/ds_stack.c \ src/ds/ds_pair.c \ src/ds/ds_priority_queue.c \ src/ds/ds_queue.c \ \ src/php/objects/php_vector.c \ src/php/objects/php_deque.c \ src/php/objects/php_map.c \ src/php/objects/php_pair.c \ src/php/objects/php_priority_queue.c \ src/php/objects/php_queue.c \ src/php/objects/php_set.c \ src/php/objects/php_stack.c \ \ dnl Iterators src/php/iterators/php_vector_iterator.c \ src/php/iterators/php_deque_iterator.c \ src/php/iterators/php_set_iterator.c \ src/php/iterators/php_map_iterator.c \ src/php/iterators/php_stack_iterator.c \ src/php/iterators/php_htable_iterator.c \ src/php/iterators/php_priority_queue_iterator.c \ src/php/iterators/php_queue_iterator.c \ \ dnl Handlers src/php/handlers/php_common_handlers.c \ src/php/handlers/php_vector_handlers.c \ src/php/handlers/php_deque_handlers.c \ src/php/handlers/php_set_handlers.c \ src/php/handlers/php_map_handlers.c \ src/php/handlers/php_stack_handlers.c \ src/php/handlers/php_pair_handlers.c \ src/php/handlers/php_priority_queue_handlers.c \ src/php/handlers/php_queue_handlers.c \ \ dnl Interfaces src/php/classes/php_hashable_ce.c \ src/php/classes/php_collection_ce.c \ src/php/classes/php_sequence_ce.c \ \ dnl Classes src/php/classes/php_vector_ce.c \ src/php/classes/php_deque_ce.c \ src/php/classes/php_set_ce.c \ src/php/classes/php_map_ce.c \ src/php/classes/php_stack_ce.c \ src/php/classes/php_pair_ce.c \ src/php/classes/php_priority_queue_ce.c \ src/php/classes/php_queue_ce.c \ \ php_ds.c \ \ , $ext_shared, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) PHP_ADD_BUILD_DIR($ext_builddir/src, 1) PHP_ADD_BUILD_DIR($ext_builddir/src/ds, 1) PHP_ADD_BUILD_DIR($ext_builddir/src/php, 1) PHP_ADD_BUILD_DIR($ext_builddir/src/php/objects, 1) PHP_ADD_BUILD_DIR($ext_builddir/src/php/classes, 1) PHP_ADD_BUILD_DIR($ext_builddir/src/php/iterators, 1) PHP_ADD_BUILD_DIR($ext_builddir/src/php/handlers, 1) PHP_ADD_EXTENSION_DEP(ds, spl) PHP_ADD_EXTENSION_DEP(ds, json) fi ds-1.1.8/config.w320000644000076500000240000000400513065035057014166 0ustar rtheunissenstaffvar DS_EXT_NAME="ds"; var DS_EXT_DIR="ext/ds/src"; var DS_EXT_API="php_ds.c"; var DS_EXT_FLAGS="/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 /I" + configure_module_dirname; function ds_src(dir, files) { return ADD_SOURCES( DS_EXT_DIR + dir, files.join(" "), DS_EXT_NAME ); } //////////////////////////////////// ARG_ENABLE("ds", "enable ds support", "no"); if (PHP_DS != "no") { EXTENSION(DS_EXT_NAME, DS_EXT_API, PHP_DS_SHARED, DS_EXT_FLAGS); ds_src("/", [ "common.c" ]); ds_src("/ds", [ "ds_deque.c", "ds_vector.c", "ds_htable.c", "ds_set.c", "ds_map.c", "ds_stack.c", "ds_pair.c", "ds_priority_queue.c", "ds_queue.c", ]); ds_src("/php/objects", [ "php_deque.c", "php_vector.c", "php_map.c", "php_pair.c", "php_priority_queue.c", "php_set.c", "php_stack.c", "php_queue.c", ]); ds_src("/php/iterators", [ "php_vector_iterator.c", "php_deque_iterator.c", "php_set_iterator.c", "php_map_iterator.c", "php_stack_iterator.c", "php_htable_iterator.c", "php_priority_queue_iterator.c", "php_queue_iterator.c", ]); ds_src("/php/handlers", [ "php_common_handlers.c", "php_vector_handlers.c", "php_deque_handlers.c", "php_set_handlers.c", "php_map_handlers.c", "php_stack_handlers.c", "php_pair_handlers.c", "php_priority_queue_handlers.c", "php_queue_handlers.c", ]); ds_src("/php/classes", [ "php_hashable_ce.c", "php_collection_ce.c", "php_sequence_ce.c", "php_vector_ce.c", "php_deque_ce.c", "php_set_ce.c", "php_map_ce.c", "php_stack_ce.c", "php_pair_ce.c", "php_priority_queue_ce.c", "php_queue_ce.c", ]); ADD_EXTENSION_DEP('ds', 'spl'); ADD_EXTENSION_DEP('ds', 'json'); } ds-1.1.8/php_ds.c0000644000076500000240000000414013065035057014005 0ustar rtheunissenstaff#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "main/php.h" #include "ext/standard/info.h" #include "ext/standard/php_var.h" #include "php_ds.h" #include "src/php/classes/php_hashable_ce.h" #include "src/php/classes/php_collection_ce.h" #include "src/php/classes/php_sequence_ce.h" #include "src/php/classes/php_vector_ce.h" #include "src/php/classes/php_deque_ce.h" #include "src/php/classes/php_set_ce.h" #include "src/php/classes/php_map_ce.h" #include "src/php/classes/php_stack_ce.h" #include "src/php/classes/php_pair_ce.h" #include "src/php/classes/php_priority_queue_ce.h" #include "src/php/classes/php_queue_ce.h" ZEND_DECLARE_MODULE_GLOBALS(ds); static inline void php_ds_init_globals(zend_ds_globals *dsg) { memset(dsg, 0, sizeof(zend_ds_globals)); } PHP_MINIT_FUNCTION(ds) { ZEND_INIT_MODULE_GLOBALS(ds, php_ds_init_globals, NULL); // Interfaces php_ds_register_hashable(); php_ds_register_collection(); php_ds_register_sequence(); // Classes php_ds_register_vector(); php_ds_register_deque(); php_ds_register_stack(); php_ds_register_queue(); php_ds_register_map(); php_ds_register_set(); php_ds_register_priority_queue(); php_ds_register_pair(); return SUCCESS; } PHP_RINIT_FUNCTION(ds) { #if defined(COMPILE_DL_DS) && defined(ZTS) ZEND_TSRMLS_CACHE_UPDATE(); #endif return SUCCESS; } PHP_RSHUTDOWN_FUNCTION(ds) { return SUCCESS; } PHP_MINFO_FUNCTION(ds) { php_info_print_table_start(); php_info_print_table_row(2, "ds support", "enabled"); php_info_print_table_row(2, "ds version", PHP_DS_VERSION); php_info_print_table_end(); } static const zend_module_dep ds_deps[] = { ZEND_MOD_REQUIRED("json") ZEND_MOD_REQUIRED("spl") ZEND_MOD_END }; zend_module_entry ds_module_entry = { STANDARD_MODULE_HEADER_EX, NULL, ds_deps, "ds", NULL, PHP_MINIT(ds), NULL, PHP_RINIT(ds), PHP_RSHUTDOWN(ds), PHP_MINFO(ds), PHP_DS_VERSION, STANDARD_MODULE_PROPERTIES }; #ifdef COMPILE_DL_DS #ifdef ZTS ZEND_TSRMLS_CACHE_DEFINE(); #endif ZEND_GET_MODULE(ds) #endif ds-1.1.8/php_ds.h0000644000076500000240000000217613065035057014021 0ustar rtheunissenstaff#ifndef PHP_DS_H #define PHP_DS_H #include #include "php.h" #include "main/php.h" #include "zend_exceptions.h" #include "zend_interfaces.h" #include "zend_operators.h" #include "ext/standard/info.h" #include "ext/standard/php_var.h" #include "ext/spl/spl_iterators.h" #include "ext/spl/spl_exceptions.h" #include "zend_smart_str.h" #include "ext/json/php_json.h" extern zend_module_entry ds_module_entry; #define phpext_ds_ptr &ds_module_entry /* Replace with version number for your extension */ #define PHP_DS_VERSION "1.1.8" #ifdef PHP_WIN32 # define PHP_API __declspec(dllexport) #elif defined(__GNUC__) && __GNUC__ >= 4 # define PHP_API __attribute__ ((visibility("default"))) #else # define PHP_API #endif #ifdef ZTS #include "TSRM.h" #endif ZEND_BEGIN_MODULE_GLOBALS(ds) zend_fcall_info user_compare_fci; zend_fcall_info_cache user_compare_fci_cache; ZEND_END_MODULE_GLOBALS(ds) #ifdef ZTS #define DSG(v) TSRMG(ds_globals_id, zend_ds_globals *, v) #else #define DSG(v) (ds_globals.v) #endif ZEND_EXTERN_MODULE_GLOBALS(ds); #if defined(ZTS) && defined(COMPILE_DL_DS) ZEND_TSRMLS_CACHE_EXTERN(); #endif #endif