I have seen UInt
s being natively supported in other languages. PHP allows you to install a third party extension, but I can't do that ATM, so I've decided to create my own class.
In which ways could/should I improve my code. Both in terms of overall code quality aswel as performance?
final class UintArray implements \Countable,\ArrayAccess,\IteratorAggregate
{
private $arr=array(); //all the saved data will be here
private $maxlen=0; //maximum length of the array
private $cnt=0; //current count
//numbers of bytes to store
const UInt8=1;
const UInt16=2;
const UInt24=3;
const UInt32=4;
//used to be sure the value doesn't go above the maximum value
private $bits=0xFFFFFFFF;
public function __construct($maxlen,$b=4)
{
//stores the maximum length, check if it higher than 0
$this->maxlen=$maxlen>>0>0?$maxlen>>0:1;
switch($b)
{
case 1:$this->bits=0xFF;break;
case 2:$this->bits=0xFFFF;break;
case 3:$this->bits=0xFFFFFF;break;
case 4:default:$this->bits=0xFFFFFFFF;
}
//fill the array ahead, so it's space will be all reserved
//in theory, this will be faster than creating elements each time
$this->arr=array_fill(0,$this->maxlen,0);
}
//countable
public function count(){return $this->cnt;}
//arrayaccess
public function offsetSet($offset,$value)
{
//verifies if the offset is valid, and if still have space
if($this->cnt>=$this->maxlen||($offset>>0>=$this->maxlen)||$offset<0)
{
return false;
}
//allows for $arr[]=<value>;
if(is_null($offset))
{
$this->arr[++$this->cnt]=$value&$this->bits;
}
//stores $arr[<offset>]=<value>;
else
{
$this->arr[$offset>>0]=$value&$this->bits;
}
}
//used with isset($arr[<offset>]);
public function offsetExists($offset){return isset($this->arr[$offset>>0]);}
//used with unset($arr[<offset>]);
public function offsetUnset($offset){$this->arr[$offset>>0]=0;}
//used with $arr[<offset>];
public function offsetGet($offset)
{
return isset($this->arr[$offset>>0])
?$this->arr[$offset>>0]
:null;
}
//iteratoraggregate
//used on the foreach loop
public function getIterator(){return new ArrayIterator($this->toArray());}
//magic methods
public function __toString()
{
if(error_reporting()&E_NOTICE)
{
@trigger_error('Array to string conversion',E_USER_NOTICE);
}
return 'Array';
}
public function __invoke(){return $a=&$this->arr;}
public function __set_state(){return $a=&$this->arr;}
public function __set($key,$value){return $this->offsetSet($key,$value);}
public function __get($key){return $this->offsetGet($key);}
public function __sleep(){return $this->arr;}
//other functionality methods
public function push()
{
//we retrieve all the arguments
$args=func_get_args();
foreach($args as &$value)
{
//if we still have space
if($this->cnt<$this->maxlen)
{
//add to the array, increasing the count
$this->arr[$this->cnt++]=$value&$this->bits;
}
//if not, return the size (replicates array_push behaviour)
else return $this->cnt;
}
//returns the size (replicates array_push behaviour)
return $this->cnt;
}
public function pop()
{
//if the array is empty
if(!$this->cnt)
{
return null;
}
else
{
//decreases the count and stores the last value
$r=$this->arr[--$this->cnt];
//stores 0 on the last value
$this->arr[$this->cnt]=0;
//returns the last element
return $r;
}
}
public function maxlen(){return $this->maxlen;}
public function maxint(){return $this->bits;}
public function toArray(){return array_slice($this->arr,0,$this->cnt);}
}
Example of usage:
$arr=new UIntArray(32); //same as $arr=new UIntArray(32,UIntArray::UInt32);
echo $arr->push(1,3,5,6,3,23,3,1,2);
echo $arr[0];
echo $arr->pop();
foreach($arr as $v)echo PHP_EOL,$v;
/*
outputs:
912
1
3
5
6
3
23
3
1
*/