/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2005 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 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_0.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. |
+----------------------------------------------------------------------+
| Author: Alexander Veremyev <cawa@csa.ru> |
+----------------------------------------------------------------------+
*/
/* $Id: header,v 1.15 2004/01/08 16:46:52 sniper Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_bitset.h"
#if COMPILE_DL_BITSET
/* {{{ content from zend_arg_defs.c:
* since it is a .c file, it won't be installed for use by PECL extensions, so we include it here. */
ZEND_BEGIN_ARG_INFO(first_arg_force_ref, 0)
ZEND_ARG_PASS_INFO(1)
ZEND_END_ARG_INFO();
/* }}} */
#endif
/* True global resources - no need for thread safety here */
static int le_bitset;
static short big_endian_byte_oder;
/* indicates that bytes order is big endian (highest byte comes first)
should be used for optimized shift operations
should be initialized on module load .
that's better to have this information on a compile time, but I don't know a way to do this
(commeted by Alexander Veremyev cawa@csa.ru)
*/
/* {{{ bitset_functions[]
*/
function_entry bitset_functions[] = {
PHP_FE(bitset_empty, NULL)
PHP_FE(bitset_incl, first_arg_force_ref)
PHP_FE(bitset_excl, first_arg_force_ref)
PHP_FE(bitset_in, NULL)
PHP_FE(bitset_fill, NULL)
PHP_FE(bitset_intersection, NULL)
PHP_FE(bitset_union, NULL)
PHP_FE(bitset_invert, NULL)
PHP_FE(bitset_subset, NULL)
PHP_FE(bitset_equal, NULL)
PHP_FE(bitset_to_string, NULL)
PHP_FE(bitset_from_string, NULL)
PHP_FE(bitset_to_hash, NULL)
PHP_FE(bitset_from_hash, NULL)
PHP_FE(bitset_to_array, NULL)
PHP_FE(bitset_from_array, NULL)
PHP_FE(bitset_is_empty, NULL)
{NULL, NULL, NULL} /* Must be the last line in bitset_functions[] */
};
/* }}} */
/* {{{ bitset_module_entry
*/
zend_module_entry bitset_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
"bitset",
bitset_functions,
PHP_MINIT(bitset),
PHP_MSHUTDOWN(bitset),
NULL,
NULL,
PHP_MINFO(bitset),
#if ZEND_MODULE_API_NO >= 20010901
"1.0", /* Extension version number */
#endif
STANDARD_MODULE_PROPERTIES
};
/* }}} */
#ifdef COMPILE_DL_BITSET
ZEND_GET_MODULE(bitset)
#endif
/* {{{ PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(bitset)
{
unsigned long long_value;
long_value = 1;
big_endian_byte_oder = (((unsigned char *)&long_value)[ 0 ] == 0);
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MSHUTDOWN_FUNCTION
*/
PHP_MSHUTDOWN_FUNCTION(bitset)
{
/* uncomment this line if you have INI entries
UNREGISTER_INI_ENTRIES();
*/
return SUCCESS;
}
/* }}} */
/* {{{ 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_end();
/* Remove comments if you have entries in php.ini
DISPLAY_INI_ENTRIES();
*/
}
/* }}} */
/* {{{ proto string bitset_empty(integer bitcount)
Return an empty bitset represented in a binary string. Optional parameter bitcount preallocates memory for bitset */
PHP_FUNCTION(bitset_empty)
{
long len, bits = 0;
unsigned char *bitset_data;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &bits) == FAILURE) {
return;
}
if( bits < 0 ) {
zend_error(E_WARNING, "First argument is not non-negative integer.");
return;
}
if( bits == 0 ) {
RETURN_EMPTY_STRING();
} else {
len = (bits+CHAR_BIT-1)/CHAR_BIT;
bitset_data = emalloc( len+1 );
memset( bitset_data, 0, len+1 );
RETURN_STRINGL(bitset_data, len, 0);
}
}
/* }}} */
/* {{{ proto void bitset_incl(string bitset, integer bit)
Includes bit into bitset */
PHP_FUNCTION(bitset_incl)
{
zval *param;
long bit;
unsigned char *bitset_data;
long old_len, new_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl", ¶m, &bit) == FAILURE) {
return;
}
if( bit < 0 ) {
zend_error(E_WARNING, "Second argument is not non-negative integer.");
return;
}
if( Z_TYPE_P(param) == IS_STRING ) {
bitset_data = Z_STRVAL_P( param );
if( bit >= (Z_STRLEN_P( param ))*CHAR_BIT ) {
old_len = Z_STRLEN_P( param );
new_len = (old_len*2*CHAR_BIT > bit) ? old_len*2 : bit/CHAR_BIT + 1;
if( old_len ) {
Z_STRVAL_P( param ) = bitset_data = erealloc(bitset_data, new_len+1);
Z_STRLEN_P( param ) = new_len;
memset( bitset_data + old_len, 0, new_len - old_len + 1 );
} else {
zval_dtor(param);
bitset_data = emalloc( new_len+1 ) ;
memset( bitset_data, 0, new_len+1 );
ZVAL_STRINGL(param, bitset_data, new_len, 0);
}
}
bitset_data[ bit/CHAR_BIT ] |= 1 << (bit % CHAR_BIT);
} else {
zend_error(E_WARNING, "The first argument is not a bitset");
}
}
/* }}} */
/* {{{ proto void bitset_excl(string bitset, integer bit)
Excludes bit into bitset */
PHP_FUNCTION(bitset_excl)
{
zval *param;
long bit;
unsigned char *bitset_data;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl", ¶m, &bit) == FAILURE) {
return;
}
if( bit < 0 ) {
zend_error(E_WARNING, "Second argument is not non-negative integer.");
return;
}
if( Z_TYPE_P(param) == IS_STRING ) {
bitset_data = Z_STRVAL_P( param );
if( bit < Z_STRLEN_P( param )*CHAR_BIT )
bitset_data[ bit/CHAR_BIT ] &= ~(1 << (bit % CHAR_BIT));
} else {
zend_error(E_WARNING, "The first argument is not a bitset");
}
}
/* }}} */
/* {{{ proto bool bitset_in(string bitset, integer bit)
Checks if bit in bitset */
PHP_FUNCTION(bitset_in)
{
long len, bit;
unsigned char *bitset_data;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &bitset_data, &len, &bit) == FAILURE) {
return;
}
if( bit < 0 ) {
RETURN_FALSE; /* All bits with a negative index should be treated as 0 */
}
if( len == 0 ) {
RETURN_FALSE;
} else if( bit >= len*CHAR_BIT ) {
RETURN_FALSE;
} else if( bitset_data[ bit/CHAR_BIT ] & (1 << (bit % CHAR_BIT) ) ) {
RETURN_TRUE;
} else {
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto string bitset_fill(integer bitcount)
Return a bitset represented in a binary string. Bitcount sets first bitcount bits */
PHP_FUNCTION(bitset_fill)
{
long len, bits;
unsigned char *bitset_data;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &bits) == FAILURE) {
return;
}
if( bits < 0 ) {
zend_error(E_WARNING, "First argument is not non-negative integer.");
RETURN_EMPTY_STRING();
} else if( bits == 0 ) {
RETURN_EMPTY_STRING();
} else {
len = (bits+CHAR_BIT-1)/CHAR_BIT;
bitset_data = emalloc( len+1 );
memset( bitset_data, ~0, len );
bitset_data[ len ] = '\0';
if( bits % CHAR_BIT )
bitset_data[ len-1 ] >>= (CHAR_BIT - (bits % CHAR_BIT));
RETURN_STRINGL(bitset_data, len, 0);
}
}
/* }}} */
/* {{{ proto string bitset_intersection(string bitset1, string bitset2)
Return an intersection of two bitsets */
PHP_FUNCTION(bitset_intersection)
{
long len1, len2, len;
unsigned char *bitset_data1, *bitset_data2, *bitset_datares;
long count;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"ss", &bitset_data1, &len1, &bitset_data2, &len2) == FAILURE) {
return;
}
if( (len1 == 0)||(len2 == 0) ) {
RETURN_EMPTY_STRING();
} else {
len = (len1 < len2) ? len1 : len2;
bitset_datares = emalloc( len+1 );
bitset_datares[ len ] = '\0';
for( count = 0; count < len/(short)sizeof(unsigned long); count++ )
((unsigned long *)bitset_datares)[ count ] =
((unsigned long *)bitset_data1)[ count ] & ((unsigned long *)bitset_data2)[ count ];
for( count = len - len % sizeof(unsigned long); count < len; count++ )
bitset_datares[ count ] = bitset_data1[ count ] & bitset_data2[ count ];
RETURN_STRINGL(bitset_datares, len, 0);
}
}
/* }}} */
/* {{{ proto string bitset_union(string bitset1, string bitset2)
Return an union of two bitsets */
PHP_FUNCTION(bitset_union)
{
long len1, len2, len, union_len;
unsigned char *bitset_data1, *bitset_data2, *bitset_datares;
long count;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"ss", &bitset_data1, &len1, &bitset_data2, &len2) == FAILURE) {
return;
}
if( (len1 == 0)&&(len2 == 0) ) {
RETURN_EMPTY_STRING();
} else {
if( len1 == len2 ) {
union_len = len = len1;
bitset_datares = emalloc( len+1 );
} else if( len1 > len2 ) {
len = len1;
union_len = len2;
bitset_datares = emalloc( len+1 );
memcpy( bitset_datares + union_len, bitset_data1 + union_len, len1-len2);
} else {
len = len2;
union_len = len1;
bitset_datares = emalloc( len+1 );
memcpy( bitset_datares + union_len, bitset_data2 + union_len, len2-len1);
}
bitset_datares[ len ] = '\0';
for( count = 0; count < union_len/(short)sizeof(unsigned long); count++ )
((unsigned long *)bitset_datares)[ count ] =
((unsigned long *)bitset_data1)[ count ] | ((unsigned long *)bitset_data2)[ count ];
for( count = union_len - union_len % sizeof(unsigned long); count < union_len; count++ )
bitset_datares[ count ] = bitset_data1[ count ] | bitset_data2[ count ];
RETURN_STRINGL(bitset_datares, len, 0);
}
}
/* }}} */
/* {{{ proto void bitset_invert(string bitset, integer size)
Invert bitset */
PHP_FUNCTION(bitset_invert)
{
long size;
unsigned char *bitset_data, *bitset_out;
long invert_count, src_len, new_len, count;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &bitset_data, &src_len, &size) == FAILURE) {
return;
}
if( size < 0 ) {
zend_error(E_WARNING, "First argument is not non-negative integer.");
RETURN_EMPTY_STRING();
} else if( size == 0 ) {
RETURN_EMPTY_STRING();
} else {
new_len = (size + CHAR_BIT-1)/CHAR_BIT;
bitset_out = emalloc( new_len+1 );
bitset_out[ new_len ] = '\0';
if( new_len > src_len ) {
memset(bitset_out + src_len, ~0, new_len - src_len);
invert_count = src_len;
} else {
invert_count = new_len;
}
for( count = 0; count < invert_count/(short)sizeof(unsigned long); count++ )
((unsigned long *)bitset_out)[ count ] = ~((unsigned long *)bitset_data)[ count ];
for( count = invert_count - invert_count % sizeof(unsigned long); count < invert_count; count++ )
bitset_out[ count ] = ~bitset_data[ count ];
if( size % CHAR_BIT ) { /* We should clear last bits */
bitset_out[ new_len-1 ] &= ( 0xFF >> ( CHAR_BIT - size % CHAR_BIT ) );
}
RETURN_STRINGL(bitset_out, new_len, 0);
}
}
/* }}} */
/* {{{ proto bool bitset_subset(string bitset1, string bitset2)
Return TRUE if bitset2 is a subset of bitset1 */
PHP_FUNCTION(bitset_subset)
{
long len1, len2;
unsigned char *bitset_data1, *bitset_data2, *rest;
long count, compare_len, zero_count;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"ss", &bitset_data1, &len1, &bitset_data2, &len2) == FAILURE) {
return;
}
if(len1 >= len2) { /* We should ot care about the rest of bitset1 */
rest = NULL;
zero_count = 0;
compare_len = len2;
} else if(len1 < len2) { /* We should check, that the rest of bitset2 is empty */
/* first step up to the "long" boundary should be done here */
for( count=len1; (count % sizeof(unsigned long))&&( count < len2 ); count++ )
if( bitset_data2[ count ] )
RETURN_FALSE;
rest = bitset_data2 + count;
zero_count = len2 - count;
compare_len = len1;
}
for( count = 0; count < compare_len/(short)sizeof(unsigned long); count++ )
if( ((unsigned long *)bitset_data2)[ count ] !=
(((unsigned long *)bitset_data2)[ count ] &
((unsigned long *)bitset_data1)[ count ] ) )
RETURN_FALSE;
for( count = compare_len - compare_len % sizeof(unsigned long); count < compare_len; count++ )
if( bitset_data2[ count ] != (bitset_data2[ count ] & bitset_data1[ count ]) )
RETURN_FALSE;
for( count = 0; count < zero_count/(short)sizeof(unsigned long); count++ )
if( ((unsigned long *)rest)[ count ] )
RETURN_FALSE;
for( count = zero_count - zero_count % sizeof(unsigned long); count < zero_count; count++ )
if( rest[ count ] )
RETURN_FALSE;
RETURN_TRUE;
}
/* }}} */
/* {{{ proto bool bitset_equal(string bitset1, string bitset2)
Return TRUE if bitset1 and bitset2 are equal. Please note that "01001110" and "0100111000000000" are equal */
PHP_FUNCTION(bitset_equal)
{
long len1, len2;
unsigned char *bitset_data1, *bitset_data2, *rest;
long count, compare_len, zero_count;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"ss", &bitset_data1, &len1, &bitset_data2, &len2) == FAILURE) {
return;
}
if(len1 == len2) { /* We should ot care about the rest of bitset1 */
rest = NULL;
zero_count = 0;
compare_len = len2;
} else if(len1 < len2) { /* We should check, that the rest of bitset2 is empty */
/* first step up to the "long" boundary should be done here */
for( count=len1; (count % sizeof(unsigned long))&&( count < len2 ); count++ )
if( bitset_data2[ count ] )
RETURN_FALSE;
rest = bitset_data2 + count;
zero_count = len2 - count;
compare_len = len1;
} else { /* len1 > len2 */
/* We should check, that the rest of bitset1 is empty */
/* first step up to the "long" boundary should be done here */
for( count=len2; (count % sizeof(unsigned long))&&( count < len1 ); count++ )
if( bitset_data1[ count ] )
RETURN_FALSE;
rest = bitset_data1 + count;
zero_count = len1 - count;
compare_len = len2;
}
if( memcmp( bitset_data1, bitset_data2, compare_len ) != 0 )
RETURN_FALSE;
for( count = 0; count < zero_count/(short)sizeof(unsigned long); count++ )
if( ((unsigned long *)rest)[ count ] )
RETURN_FALSE;
for( count = zero_count - zero_count % sizeof(unsigned long); count < zero_count; count++ )
if( rest[ count ] )
RETURN_FALSE;
RETURN_TRUE;
}
/* }}} */
/* {{{ proto string bitset_to_string(string bitset)
Return a human readable string representation of a bitset */
PHP_FUNCTION(bitset_to_string)
{
long len = 0;
unsigned char *bitset_data, *output_str;
long count;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &bitset_data, &len) == FAILURE) {
return;
}
if( len == 0 ) {
RETURN_EMPTY_STRING();
} else {
len *= CHAR_BIT;
output_str = emalloc( len+1 );
output_str[ len ] = '\0';
for(count = 0; count < len; count++ )
output_str[ count ] = ( (bitset_data[ count/CHAR_BIT ] >> (count % CHAR_BIT)) & 1 ) ? '1' : '0';
RETURN_STRINGL(output_str, len, 0);
}
}
/* }}} */
/* {{{ proto string bitset_from_string(string source_str)
Return a bitset, calculated from a string */
PHP_FUNCTION(bitset_from_string)
{
long str_len, len;
unsigned char *str_data, *bitset_data;
long data_index, str_index;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str_data, &str_len) == FAILURE) {
return;
}
if( str_len == 0 ) {
RETURN_EMPTY_STRING();
} else {
len = (str_len+CHAR_BIT-1)/CHAR_BIT;
bitset_data = emalloc( len+1 );
memset( bitset_data, 0, len+1 );
for( data_index = str_index = 0; str_index < str_len; str_index++ )
if( str_data[ str_index ] == '1' ) {
bitset_data[ data_index/CHAR_BIT ] |= (1 << (data_index % CHAR_BIT) );
data_index++;
} else if( str_data[ str_index ] == '0' ) {
data_index++;
}
RETURN_STRINGL(bitset_data, len, 0);
}
}
/* }}} */
/* {{{ proto array bitset_to_hash(string bitset)
Return bitset mapped to an array */
PHP_FUNCTION(bitset_to_hash)
{
long len, count, count1;
unsigned char *bitset_data;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &bitset_data, &len) == FAILURE) {
return;
}
/* Initialize return array */
array_init(return_value);
for( count=0; count < len; count++ )
for( count1=0; count1 < CHAR_BIT; count1++ ) {
if( bitset_data[ count ] & (1 << count1) )
add_index_long(return_value, count*CHAR_BIT + count1, 1 );
}
}
/* }}} */
/* {{{ proto string bitset_from_hash(array bit_array)
Maps an array of bits to a bitset */
PHP_FUNCTION(bitset_from_hash)
{
long len, arr_len;
unsigned char *bitset_data;
zval *bit_arr;
zval **arr_val;
char *arr_key_str;
uint arr_key_strlen;
long arr_key_num;
long max_key = -1;
int key_type;
HashPosition pos;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &bit_arr) == FAILURE) {
return;
}
arr_len = zend_hash_num_elements(Z_ARRVAL_P(bit_arr));
if( arr_len == 0 ) {
RETURN_EMPTY_STRING();
}
/* We should walk through an array to get maximum key value */
for( zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(bit_arr), &pos);
(key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(bit_arr), &arr_key_str, &arr_key_strlen, &arr_key_num, 0, &pos)) != HASH_KEY_NON_EXISTANT;
zend_hash_move_forward_ex(Z_ARRVAL_P(bit_arr), &pos)
) {
if( key_type == HASH_KEY_IS_STRING )
arr_key_num = strtol(arr_key_str, NULL, 10); /* Important: it uses base 10 conversion like convert_to_long() function */
if( max_key < arr_key_num )
max_key = arr_key_num;
}
if( max_key < 0 ) {
RETURN_EMPTY_STRING();
}
len = ( max_key+1 + CHAR_BIT-1 )/CHAR_BIT;
bitset_data = emalloc( len+1 );
memset( bitset_data, 0, len+1 );
for( zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(bit_arr), &pos);
zend_hash_get_current_data_ex(Z_ARRVAL_P(bit_arr), (void **) &arr_val, &pos) == SUCCESS;
zend_hash_move_forward_ex(Z_ARRVAL_P(bit_arr), &pos)
) {
if( zend_is_true(*arr_val) ) {
if( zend_hash_get_current_key_ex(Z_ARRVAL_P(bit_arr), &arr_key_str, &arr_key_strlen, &arr_key_num, 0, &pos) == HASH_KEY_IS_STRING )
arr_key_num = strtol(arr_key_str, NULL, 10); /* Important: it uses base 10 conversion like convert_to_long() function */
if( arr_key_num >= 0)
bitset_data[ arr_key_num/CHAR_BIT] |= 1 << (arr_key_num % CHAR_BIT);
}
}
RETURN_STRINGL(bitset_data, len, 0);
}
/* }}} */
/* {{{ proto array bitset_to_array(string bitset)
Return bitset represented as an array of bits */
PHP_FUNCTION(bitset_to_array)
{
long len, count, count1;
unsigned char *bitset_data;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &bitset_data, &len) == FAILURE) {
return;
}
/* Initialize return array */
array_init(return_value);
for( count=0; count < len; count++ )
for( count1=0; count1 < CHAR_BIT; count1++ ) {
if( bitset_data[ count ] & (1 << count1) )
add_next_index_long(return_value, count*CHAR_BIT + count1 );
}
}
/* }}} */
static int arrval_compare(const void *a, const void *b TSRMLS_DC)
{
Bucket *f, *s;
zval *fval, *sval;
int result;
unsigned char fneed_destroy = 0, sneed_destroy = 0;
f = *((Bucket **) a);
s = *((Bucket **) b);
fval = *((zval **) f->pData);
sval = *((zval **) s->pData);
if (Z_TYPE_P(fval) != IS_LONG) {
fneed_destroy = 1;
zval_copy_ctor(fval);
convert_to_long(fval);
}
if (Z_TYPE_P(sval) != IS_LONG) {
sneed_destroy = 1;
zval_copy_ctor(sval);
convert_to_long(sval);
}
result = Z_LVAL_P(fval) - Z_LVAL_P(sval);
if (fneed_destroy)
zval_dtor(sval);
if (sneed_destroy)
zval_dtor(sval);
return result;
}
/* {{{ proto string bitset_from_array(array bit_array)
Converts an array of bits to a bitset */
PHP_FUNCTION(bitset_from_array)
{
long len, arr_len;
unsigned char *bitset_data;
zval *bit_arr;
zval **arr_val;
unsigned char need_destroy;
HashPosition pos;
long max_val = -1;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &bit_arr) == FAILURE) {
return;
}
arr_len = zend_hash_num_elements(Z_ARRVAL_P(bit_arr));
if( arr_len == 0 ) {
RETURN_EMPTY_STRING();
}
zend_hash_minmax(Z_ARRVAL_P(bit_arr), arrval_compare, 1, (void **) &arr_val TSRMLS_CC);
need_destroy = 0;
if (Z_TYPE_PP(arr_val)!=IS_LONG) {
zval_copy_ctor(*arr_val);
convert_to_long(*arr_val);
need_destroy = 1;
}
max_val = Z_LVAL_PP(arr_val);
if( need_destroy )
zval_dtor(*arr_val);
if( max_val < 0 ) {
RETURN_EMPTY_STRING();
}
len = ( max_val+1 + CHAR_BIT-1 )/CHAR_BIT;
bitset_data = emalloc( len+1 );
memset( bitset_data, 0, len+1 );
for( zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(bit_arr), &pos);
zend_hash_get_current_data_ex(Z_ARRVAL_P(bit_arr), (void **) &arr_val, &pos) == SUCCESS;
zend_hash_move_forward_ex(Z_ARRVAL_P(bit_arr), &pos)
) {
need_destroy = 0;
if (Z_TYPE_PP(arr_val)!=IS_LONG) {
zval_copy_ctor(*arr_val);
convert_to_long(*arr_val);
need_destroy = 1;
}
if( Z_LVAL_PP(arr_val) >= 0 )
bitset_data[ Z_LVAL_PP(arr_val)/CHAR_BIT] |= 1 << (Z_LVAL_PP(arr_val) % CHAR_BIT);
if( need_destroy )
zval_dtor(*arr_val);
}
RETURN_STRINGL(bitset_data, len, 0);
}
/* }}} */
/* {{{ proto bool bitset_is_empty(string bitset)
Return TRUE if bitset is empty */
PHP_FUNCTION(bitset_is_empty)
{
long len;
unsigned char *bitset_data;
long count;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &bitset_data, &len) == FAILURE) {
return;
}
for( count = 0; count < len/(short)sizeof(unsigned long); count++ )
if( ((unsigned long *)bitset_data)[ count ] )
RETURN_FALSE;
for( count = len - len % sizeof(unsigned long); count < len; count++ )
if( bitset_data[ count ] )
RETURN_FALSE;
RETURN_TRUE;
}
/* }}} */
/*
* 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
*/
syntax highlighted by Code2HTML, v. 0.9.1