/* +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Will Fitch | | Alexander Veremyev | | Remi Collet | +----------------------------------------------------------------------+ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_ini.h" #include "zend_exceptions.h" #include "ext/spl/spl_exceptions.h" #include "ext/standard/info.h" #include "php_bitset.h" #include #if PHP_VERSION_ID >= 80000 #include "bitset_arginfo.h" #else #include "bitset_legacy_arginfo.h" #define RETURN_THROWS() return #endif #define BITSET_DEPRECATED_MESSAGE "The bitset_* functions are deprecated and will be removed in 3.0. Please update to the BitSet class API" zend_class_entry *bitset_class_entry = NULL; static zend_object_handlers bitset_object_handlers; static php_bitset_object *bitset_get_intern_object(zval *object); static php_bitset_object *php_bitset_object_new(zend_class_entry *ce); static long bitset_get_highest_value_from_array(zval *arr); static void bitset_initialize_object(php_bitset_object *intern, long bits); /* {{{ zend_module_dep zend_module_entry ZEND_GET_MODULE */ zend_module_entry bitset_module_entry = { STANDARD_MODULE_HEADER_EX, NULL, NULL, "bitset", NULL, PHP_MINIT(bitset), PHP_MSHUTDOWN(bitset), NULL, NULL, PHP_MINFO(bitset), PHP_BITSET_VERSION, STANDARD_MODULE_PROPERTIES }; #ifdef COMPILE_DL_BITSET ZEND_GET_MODULE(bitset) #endif /* }}} */ /* {{{ proto void BitSet::__construct(int value) Class constructor */ PHP_METHOD(BitSet, __construct) { php_bitset_object *intern = NULL; zend_long bits = 0; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &bits) == FAILURE) { RETURN_THROWS(); } intern = bitset_get_intern_object(getThis()); /* Default the bit count to 64 bits */ if (bits == 0) { bits = BITSET_DEFAULT_BITS; } else if (bits < 0) { /* Bits can't be negative */ zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "The total bits to allocate must be 0 or greater"); RETURN_THROWS(); } bitset_initialize_object(intern, bits); if (bits % CHAR_BIT) { intern->bitset_val[intern->bitset_len - 1] >>= (CHAR_BIT - (bits % CHAR_BIT)); } } /* }}} */ /* {{{ proto void BitSet::andOp(BitSet set) Performs a logical AND of target bit set with provided object */ PHP_METHOD(BitSet, andOp) { php_bitset_object *intern, *param; zval *param_id; long bitset_len1, bitset_len2, i, to_bits; if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", ¶m_id, bitset_class_entry) == FAILURE) { RETURN_THROWS(); } intern = bitset_get_intern_object(getThis()); param = bitset_get_intern_object(param_id); bitset_len1 = intern->bitset_len; bitset_len2 = param->bitset_len; to_bits = bitset_len1 > bitset_len2 ? bitset_len2 : bitset_len1; for (i = 0; i < to_bits; i++) { intern->bitset_val[i] &= param->bitset_val[i]; } } /* }}} */ /* {{{ proto void BitSet::andNotOp(BitSet set) Clears all bits in this object whose bit is set in the provided object */ PHP_METHOD(BitSet, andNotOp) { php_bitset_object *intern, *param; zval *param_id; long bitset_len1, bitset_len2, i, to_bits; if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", ¶m_id, bitset_class_entry) == FAILURE) { RETURN_THROWS(); } intern = bitset_get_intern_object(getThis()); param = bitset_get_intern_object(param_id); bitset_len1 = intern->bitset_len * CHAR_BIT; bitset_len2 = param->bitset_len * CHAR_BIT; to_bits = bitset_len1 > bitset_len2 ? bitset_len2 : bitset_len1; for (i = 0; i < to_bits; i++) { /* If the incoming bit is set, clear on this object */ if (param->bitset_val[i / CHAR_BIT] & (1 << (i % CHAR_BIT))) { intern->bitset_val[i / CHAR_BIT] &= ~(1 << (i % CHAR_BIT)); } } } /* }}} */ /* {{{ proto int BitSet::cardinality(void) Returns the number of true bits */ PHP_METHOD(BitSet, cardinality) { php_bitset_object *intern; long i, total_bits, true_bits = 0; if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); } intern = bitset_get_intern_object(getThis()); total_bits = intern->bitset_len * CHAR_BIT; for (i = 0; i < total_bits; i++) { if (intern->bitset_val[i / CHAR_BIT] & (1 << (i % CHAR_BIT))) { true_bits++; } } RETURN_LONG(true_bits); } /* }}} */ /* {{{ proto void BitSet::clear([int indexOrFromIndex[, int toIndex]]) Sets all bits to false */ PHP_METHOD(BitSet, clear) { php_bitset_object *intern; long index_from = -1, index_to = 0, usable_index = 0; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &index_from, &index_to) == FAILURE) { RETURN_THROWS(); } intern = bitset_get_intern_object(getThis()); /* Clear all bits and reset */ if (index_from == -1 && index_to == 0) { memset(intern->bitset_val, 0, intern->bitset_len); intern->bitset_val[intern->bitset_len] = '\0'; } else { /* Verify the start index is not greater than total bits */ if (index_from >= intern->bitset_len * CHAR_BIT) { zend_throw_exception_ex(spl_ce_OutOfRangeException, 0, "The requested start index is greater than the total number of bits"); RETURN_THROWS(); } if (index_to == 0) { usable_index = index_from; } else { usable_index = index_to > intern->bitset_len * CHAR_BIT ? intern->bitset_len * CHAR_BIT : index_to; } for (; index_from <= usable_index; index_from++) { intern->bitset_val[index_from / CHAR_BIT] &= ~(1 << (index_from % CHAR_BIT)); } } } /* }}} */ /* {{{ proto bool BitSet::get(int index) Returns the bool value of the bit at the specified index */ PHP_METHOD(BitSet, get) { php_bitset_object *intern; zend_long bit; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &bit) == FAILURE) { RETURN_THROWS(); } intern = bitset_get_intern_object(getThis()); /* The bit requested is larger than all bits in this set */ if (bit >= intern->bitset_len * CHAR_BIT) { zend_throw_exception_ex(spl_ce_OutOfRangeException, 0, "The specified index parameter exceeds the total number of bits available"); RETURN_THROWS(); } if (intern->bitset_val[bit / CHAR_BIT] & (1 << (bit % CHAR_BIT))) { RETURN_TRUE; } else { RETURN_FALSE; } } /* }}} */ /* {{{ proto string BitSet::getRawValue(void) */ PHP_METHOD(BitSet, getRawValue) { php_bitset_object *intern; intern = bitset_get_intern_object(getThis()); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); } if (intern->bitset_val) { RETURN_STRINGL((char *) intern->bitset_val, intern->bitset_len); } else { RETURN_EMPTY_STRING(); } } /* }}} */ /* {{{ proto string BitSet::fromRawValue(void) */ PHP_METHOD(BitSet, fromRawValue) { php_bitset_object *newobj; zend_class_entry *ce = bitset_class_entry; zend_string *str; if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) { RETURN_THROWS(); } newobj = php_bitset_object_new(ce); if (str->len == 0) { bitset_initialize_object(newobj, BITSET_DEFAULT_BITS); return; } bitset_initialize_object(newobj, (str->len * CHAR_BIT)); memcpy(newobj->bitset_val, str->val, str->len); ZVAL_OBJ(return_value, &newobj->zo); } /* }}} */ /* {{{ proto bool BitSet::intersects(BitSet set) Determines if the provided value has any bits set to true that are also true in this object */ PHP_METHOD(BitSet, intersects) { php_bitset_object *a, *b; zval *param_id; long bitset_len1, bitset_len2, i, to_bits; if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", ¶m_id, bitset_class_entry) == FAILURE) { RETURN_THROWS(); } a = bitset_get_intern_object(getThis()); b = bitset_get_intern_object(param_id); bitset_len1 = a->bitset_len; bitset_len2 = b->bitset_len; to_bits = bitset_len1 > bitset_len2 ? bitset_len2 : bitset_len1; for (i = 0; i < to_bits; i++) { /* If the bits is set in both */ if (a->bitset_val[i] & b->bitset_val[i]) { RETURN_TRUE; } } RETURN_FALSE; } /* }}} */ /* {{{ proto bool BitSet::isEmpty(void) Determines if this value contains no bits */ PHP_METHOD(BitSet, isEmpty) { php_bitset_object *intern; long total_bits, i; if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); } intern = bitset_get_intern_object(getThis()); total_bits = intern->bitset_len; /* Loop through all bits and determine if there is a true bit. */ for (i = 0; i < total_bits; i++) { if (intern->bitset_val[i]) { RETURN_FALSE; } } RETURN_TRUE; } /* }}} */ /* {{{ proto int BitSet::length(void) Returns the highest set bit plus one */ PHP_METHOD(BitSet, length) { php_bitset_object *intern; long highest_bit = -1, i; if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); } intern = bitset_get_intern_object(getThis()); i = intern->bitset_len * CHAR_BIT; while (i > 0) { i--; if (intern->bitset_val[i / CHAR_BIT] & (1 << (i % CHAR_BIT))) { highest_bit = i; break; } } RETURN_LONG(highest_bit + 1); } /* }}} */ /* {{{ proto int BitSet::nextClearBit(int index) Returns the index of the next bit after the provided index that is set to false */ PHP_METHOD(BitSet, nextClearBit) { php_bitset_object *intern; zend_long start_bit = 0; long bit_diff = 0, next_bit = 0; short found = 0; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &start_bit) == FAILURE) { RETURN_THROWS(); } intern = bitset_get_intern_object(getThis()); bit_diff = intern->bitset_len * CHAR_BIT; if (start_bit >= bit_diff - 1) { zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "There are no bits larger than the index provided"); RETURN_THROWS(); } start_bit++; while (start_bit <= bit_diff) { if (!(intern->bitset_val[start_bit / CHAR_BIT] & (1 << (start_bit % CHAR_BIT)))) { next_bit = start_bit; found = 1; break; } start_bit++; } if (found) { RETURN_LONG(next_bit); } else { RETURN_FALSE; } } /* }}} */ /* {{{ proto int BitSet::nextSetBit(int index) Returns the index of the next bit after the provided index that is set to true */ PHP_METHOD(BitSet, nextSetBit) { php_bitset_object *intern; zend_long start_bit = 0; long bit_diff = 0, next_bit = 0; short found = 0; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &start_bit) == FAILURE) { RETURN_THROWS(); } intern = bitset_get_intern_object(getThis()); bit_diff = intern->bitset_len * CHAR_BIT; if (start_bit >= bit_diff - 1) { zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "There are no bits larger than the index provided"); RETURN_THROWS(); } start_bit++; while (start_bit <= bit_diff) { if (intern->bitset_val[start_bit / CHAR_BIT] & (1 << (start_bit % CHAR_BIT))) { next_bit = start_bit; found = 1; break; } start_bit++; } if (found) { RETURN_LONG(next_bit); } else { RETURN_FALSE; } } /* }}} */ /* {{{ proto void BitSet::orOp(BitSet set) Performs a logical OR of this object with the provided argument object */ PHP_METHOD(BitSet, orOp) { php_bitset_object *intern, *param; zval *param_id; long bitset_len1, bitset_len2, i, to_bits; if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", ¶m_id, bitset_class_entry) == FAILURE) { RETURN_THROWS(); } intern = bitset_get_intern_object(getThis()); param = bitset_get_intern_object(param_id); bitset_len1 = intern->bitset_len; bitset_len2 = param->bitset_len; to_bits = bitset_len1 > bitset_len2 ? bitset_len2 : bitset_len1; for (i = 0; i < to_bits; i++) { intern->bitset_val[i] |= param->bitset_val[i]; } } /* }}} */ /* {{{ proto int BitSet::previousClearBit(int index) Returns the index of the previous bit before the provided index that is set to false */ PHP_METHOD(BitSet, previousClearBit) { php_bitset_object *intern; long start_bit = 0, bit_diff = 0; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &start_bit) == FAILURE) { RETURN_THROWS(); } if (start_bit < 1) { zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "There are no bits smaller than the index provided"); RETURN_THROWS(); } intern = bitset_get_intern_object(getThis()); bit_diff = intern->bitset_len * CHAR_BIT; if (start_bit > bit_diff) { zend_throw_exception_ex(spl_ce_OutOfRangeException, 0, "The specified index parameter exceeds the total number of bits available"); RETURN_THROWS(); } start_bit--; while (start_bit >= 0) { if (!(intern->bitset_val[start_bit / CHAR_BIT] & (1 << (start_bit % CHAR_BIT)))) { break; } start_bit--; } if (start_bit < 0) { RETURN_FALSE; } else { RETURN_LONG(start_bit); } } /* }}} */ /* {{{ proto int BitSet::previousSetBit(int index) Returns the index of the previous bit before the provided index that is set to true */ PHP_METHOD(BitSet, previousSetBit) { php_bitset_object *intern; zend_long start_bit = 0; long bit_diff = 0; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &start_bit) == FAILURE) { RETURN_THROWS(); } if (start_bit < 1) { zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "There are no bits smaller than the index provided"); RETURN_THROWS(); } intern = bitset_get_intern_object(getThis()); bit_diff = intern->bitset_len * CHAR_BIT; if (start_bit > bit_diff) { zend_throw_exception_ex(spl_ce_OutOfRangeException, 0, "The specified index parameter exceeds the total number of bits available"); RETURN_THROWS(); } start_bit--; while (start_bit >= 0) { if (intern->bitset_val[start_bit / CHAR_BIT] & (1 << (start_bit % CHAR_BIT))) { break; } start_bit--; } if (start_bit < 0) { RETURN_FALSE; } else { RETURN_LONG(start_bit); } } /* }}} */ /* {{{ proto void BitSet::set([int indexOrFromIndex[, toIndex]]) Sets the bits from the specified index or range to true */ PHP_METHOD(BitSet, set) { php_bitset_object *intern; zend_long index_from = -1, index_to = 0; long usable_index = 0; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &index_from, &index_to) == FAILURE) { RETURN_THROWS(); } intern = bitset_get_intern_object(getThis()); /* Set all bits */ if (index_from == -1 && index_to == 0) { for (; usable_index < intern->bitset_len * CHAR_BIT; usable_index++) { intern->bitset_val[usable_index / CHAR_BIT] |= (1 << (usable_index % CHAR_BIT)); } intern->bitset_val[intern->bitset_len] = '\0'; } else { /* Verify the start index is not greater than total bits */ if (index_from > (intern->bitset_len * CHAR_BIT - 1)) { zend_throw_exception_ex(spl_ce_OutOfRangeException, 0, "The requested start index is greater than the total number of bits"); RETURN_THROWS(); } if (index_to == 0) { usable_index = index_from; } else { usable_index = index_to > intern->bitset_len * CHAR_BIT ? intern->bitset_len * CHAR_BIT : index_to; } for (; index_from <= usable_index; index_from++) { intern->bitset_val[index_from / CHAR_BIT] |= (1 << (index_from % CHAR_BIT)); } } } /* }}} */ /* {{{ proto int BitSet::size(void) Returns the number of bits of space in use */ PHP_METHOD(BitSet, size) { php_bitset_object *intern; intern = bitset_get_intern_object(getThis()); if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); } RETURN_LONG(intern->bitset_len * CHAR_BIT); } /* }}} */ /* {{{ proto BitSet BitSet::fromString(string) * Returns a new instance of BitSet based on the provided string */ PHP_METHOD(BitSet, fromString) { php_bitset_object *newobj; zend_class_entry *ce = bitset_class_entry; zend_string *str = NULL; int i; if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) { RETURN_THROWS(); } newobj = php_bitset_object_new(ce); if (str->len > 0) { bitset_initialize_object(newobj, str->len); } else { bitset_initialize_object(newobj, BITSET_DEFAULT_BITS); } for (i = 0; i < str->len; i++) { /* If the char is explicitly '1', set it as 1. Otherwise, it's 0 */ if (str->val[i] == '1') { newobj->bitset_val[i / CHAR_BIT] |= (1 << (i % CHAR_BIT)); } } ZVAL_OBJ(return_value, &newobj->zo); } /* }}} */ /* {{{ proto BitSet BitSet::fromArray(array inputArray) * Returns a new Bitset instance based on the input array. All positive integers * within the array values are considered positions of set bits */ PHP_METHOD(BitSet, fromArray) { php_bitset_object *newobj; zval *bit_array; zval *entry; zend_class_entry *ce = bitset_class_entry; long array_len, highest_value, entry_actual; if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &bit_array) == FAILURE) { RETURN_THROWS(); } array_len = zend_hash_num_elements(Z_ARRVAL_P(bit_array)); newobj = php_bitset_object_new(ce); if (array_len == 0) { bitset_initialize_object(newobj, BITSET_DEFAULT_BITS); return; } highest_value = bitset_get_highest_value_from_array(bit_array); bitset_initialize_object(newobj, highest_value+1); ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(bit_array), entry) { zend_long entry_long = zval_get_long(entry); if (entry_long >= 0) { entry_actual = entry_long / CHAR_BIT; newobj->bitset_val[entry_actual] |= (1 << (entry_long % CHAR_BIT)); } } ZEND_HASH_FOREACH_END(); ZVAL_OBJ(return_value, &newobj->zo); } /* }}} */ /* {{{ proto array BitSet::toArray(void) Returns the on bits as an array */ PHP_METHOD(BitSet, toArray) { php_bitset_object *intern; long i, total_bits; if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); } intern = bitset_get_intern_object(getThis()); array_init(return_value); total_bits = intern->bitset_len * CHAR_BIT; for (i = 0; i < total_bits; i++) { if (intern->bitset_val[i / CHAR_BIT] & (1 << (i % CHAR_BIT))) { add_next_index_long(return_value, i); } } } /* }}} */ /* {{{ proto BitSet BitSet::fromInteger(integer value) * Returns a new Bitset instance based on the input value */ PHP_METHOD(BitSet, fromInteger) { php_bitset_object *newobj; zend_class_entry *ce = bitset_class_entry; zend_long value; int i; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &value) == FAILURE) { RETURN_THROWS(); } newobj = php_bitset_object_new(ce); bitset_initialize_object(newobj, sizeof(value) * CHAR_BIT); for (i = 0; i < sizeof(value) ; i++) { newobj->bitset_val[i] = value & ((1 << CHAR_BIT) -1); value >>= CHAR_BIT; } ZVAL_OBJ(return_value, &newobj->zo); } /* }}} */ /* {{{ proto integer BitSet::toInteger(void) Returns the on bits as an integer */ PHP_METHOD(BitSet, toInteger) { php_bitset_object *intern; int i; zend_long value = 0; if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); } intern = bitset_get_intern_object(getThis()); if (intern->bitset_len > sizeof(value)) { zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "The total bits doesn't fit in an integer"); RETURN_THROWS(); } for (i = 0; i < intern->bitset_len; i++) { value |= intern->bitset_val[i] << (i * CHAR_BIT); } RETURN_LONG(value); } /* }}} */ /* {{{ proto void BitSet::xorOp(BitSet set) Performs an XOR operation against the current object bit set with the specified argument */ PHP_METHOD(BitSet, xorOp) { php_bitset_object *intern, *param; zval *param_id; long bitset_len1, bitset_len2, i, to_bits; if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", ¶m_id, bitset_class_entry) == FAILURE) { RETURN_THROWS(); } intern = bitset_get_intern_object(getThis()); param = bitset_get_intern_object(param_id); bitset_len1 = intern->bitset_len; bitset_len2 = param->bitset_len; to_bits = bitset_len1 > bitset_len2 ? bitset_len2 : bitset_len1; for (i = 0; i < to_bits; i++) { intern->bitset_val[i] ^= param->bitset_val[i]; } } /* }}} */ /* {{{ proto string BitSet::__toString(void) Returns a human-readable string representation of the bit set */ PHP_METHOD(BitSet, __toString) { php_bitset_object *intern = NULL; zend_string *retval; char *internval = NULL; long len, i; if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); } intern = bitset_get_intern_object(getThis()); if (intern->bitset_len == 0) { RETURN_EMPTY_STRING(); } else { len = intern->bitset_len * CHAR_BIT; retval = zend_string_alloc(len, 0); internval = ZSTR_VAL(retval); internval[len] = '\0'; for (i = 0; i < len; i++) { internval[i] = ((intern->bitset_val[i / CHAR_BIT] >> (i % CHAR_BIT)) & 1) ? '1' : '0'; } RETURN_STR(retval); } } /* }}} */ /* {{{ php_bitset_object *bitset_get_intern_object */ static php_bitset_object *bitset_get_intern_object(zval *object) { zend_object *obj = Z_OBJ_P(object); return php_bitset_fetch_object(obj); } /* }}} */ /* {{{ long bitset_get_highest_value_from_array */ static long bitset_get_highest_value_from_array(zval *arr) { zval *entry; long highest_value = 0; ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(arr), entry) { zend_long entry_long = zval_get_long(entry); if (entry_long > highest_value) { highest_value = entry_long; } } ZEND_HASH_FOREACH_END(); return highest_value; } /* }}} */ /* {{{ php_bitset_object php_bitset_object_new */ static php_bitset_object *php_bitset_object_new(zend_class_entry *ce) { php_bitset_object *intern; intern = ecalloc(1, sizeof(php_bitset_object) + zend_object_properties_size(ce)); intern->bitset_val = 0; zend_object_std_init(&intern->zo, ce); object_properties_init(&intern->zo, ce); intern->zo.handlers = &bitset_object_handlers; return intern; } /* }}} */ /* {{{ void bitset_initialize_object */ static void bitset_initialize_object(php_bitset_object *intern, long bits) { intern->bitset_len = (bits + CHAR_BIT - 1) / CHAR_BIT; intern->bitset_val = (unsigned char *) emalloc(intern->bitset_len + 1); memset(intern->bitset_val, 0, intern->bitset_len); intern->bitset_val[intern->bitset_len] = '\0'; } /* }}} */ /* {{{ bitset_destroy_object */ static void bitset_destroy_object(zend_object *obj) { zend_objects_destroy_object(obj); } /* }}} */ /* {{{ void bitset_free_object */ static void bitset_free_object(zend_object *obj) { php_bitset_object *bitset_obj; bitset_obj = php_bitset_fetch_object(obj); if (bitset_obj->bitset_val) { efree(bitset_obj->bitset_val); } zend_object_std_dtor(obj); } /* }}} */ /* {{{ zend_object bitset_create_object */ static zend_object *bitset_create_object(zend_class_entry *ce) { php_bitset_object *intern; intern = ecalloc(1, sizeof(php_bitset_object) + zend_object_properties_size(ce)); intern->bitset_val = 0; zend_object_std_init(&intern->zo, ce); object_properties_init(&intern->zo, ce); intern->zo.handlers = &bitset_object_handlers; return &intern->zo; } /* }}} */ /* {{{ PHP_MINFO_FUNCTION */ PHP_MINFO_FUNCTION(bitset) { php_info_print_table_start(); php_info_print_table_header(2, "BitSet Support", "enabled"); php_info_print_table_row(2, "BitSet Version", PHP_BITSET_VERSION); php_info_print_table_row(2, "64-bit Integer Support", sizeof(unsigned long long) == 8 ? "yes" : "no"); php_info_print_table_end(); DISPLAY_INI_ENTRIES(); } /* }}} */ /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(bitset) { bitset_class_entry = register_class_BitSet(); bitset_class_entry->create_object = bitset_create_object; memcpy(&bitset_object_handlers, zend_get_std_object_handlers(), sizeof(bitset_object_handlers)); bitset_object_handlers.free_obj = bitset_free_object; bitset_object_handlers.dtor_obj = bitset_destroy_object; bitset_object_handlers.offset = XtOffsetOf(php_bitset_object, zo); return SUCCESS; } /* }}} */ /* {{{ PHP_MSHUTDOWN_FUNCTION */ PHP_MSHUTDOWN_FUNCTION(bitset) { bitset_class_entry = NULL; return SUCCESS; } /* }}} */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */