Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
25 / 25
CRAP
100.00% covered (success)
100.00%
105 / 105
DynamicArray
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
25 / 25
46
100.00% covered (success)
100.00%
105 / 105
 __construct($size = 0) // [\SplFixedArray]
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
5 / 5
 __clone()
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 count() // -> int [\Countable]
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 current() // -> mixed [\Iterator]
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 fromArray($array, $save_indexes = true) // -> DynamicArray [\SplFixedArray]
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 getAllocatedSize() // -> int
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 getSize() // -> int [\SplFixedArray]
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 isEmpty() // -> bool
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 key() // -> int [\Iterator]
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 next() // [\Iterator]
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
5 / 5
 offsetExists($index) // -> bool [\ArrayAccess]
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
1 / 1
 offsetGet($index) // -> mixed [\ArrayAccess]
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
7 / 7
 offsetSet($index, $newval) // [\ArrayAccess]
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
10 / 10
 offsetUnset($index) // [\ArrayAccess]
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
6 / 6
 pop() // -> mixed
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
10 / 10
 push($value)
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
3 / 3
 rewind() // [\Iterator]
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 setSize($size) // -> int [\SplFixedArray]
100.00% covered (success)
100.00%
1 / 1
6
100.00% covered (success)
100.00%
19 / 19
 toArray() // -> array [\SplFixedArray]
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 valid() // -> bool [\Iterator]
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
2 / 2
 __wakeup() // [\SplFixedArray]
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 grow()
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
8 / 8
 offsetValid($index) // -> bool
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
1 / 1
 resize($size, $count = null)
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
8 / 8
 shrink()
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
6 / 6
<?php namespace SEIDS\Arrays\Dynamic;
//==============================================================================
// PHP SEIDS: Supplementary, Easily Interchangeable Data Structures
// 
// Copyright 2015, Daniel A.C. Martin
// Distributed under the MIT License.
// (See LICENSE file for details.)
//==============================================================================
use \SEIDS\Arrays\CantPopFromEmptyException;
use \SEIDS\Arrays\InvalidArgumentException;
use \SEIDS\Arrays\InvalidIndexException;
class DynamicArray implements \ArrayAccess, \Countable, \Iterator
{
    ////////////////////////////////////////////////////////////////////////////
    // Members
    ////////////////////////////////////////////////////////////////////////////
    
    protected $data  = null; // &\SplFixedArray
    protected $count = 0;    // int
    
    ////////////////////////////////////////////////////////////////////////////
    // Public methods
    ////////////////////////////////////////////////////////////////////////////
    
    public function __construct($size = 0) // [\SplFixedArray]
    {
        $this->data  = ($size instanceof \SplFixedArray) ? $size
                                                         : new \SplFixedArray($size);
        $this->count = ($size instanceof \SplFixedArray) ? $this->data->getSize()
                                                         : $size;
    }
    
    public function __clone()
    {
        $this->data = clone $this->data;
    }
    
    public function count() // -> int [\Countable]
    {
        return $this->count;
    }
    
    public function current() // -> mixed [\Iterator]
    {
        return $this->data->current();
    }
    
    public static function fromArray($array, $save_indexes = true) // -> DynamicArray [\SplFixedArray]
    {
        return new DynamicArray(\SplFixedArray::fromArray($array, $save_indexes));
    }
    
    public function getAllocatedSize() // -> int
    {
        return $this->data->getSize();
    }
    
    public function getSize() // -> int [\SplFixedArray]
    {
        return $this->count();
    }
    
    public function isEmpty() // -> bool
    {
        return 0 === $this->count;
    }
    
    public function key() // -> int [\Iterator]
    {
        return $this->data->key();
    }
    
    public function next() // [\Iterator]
    {
        if($this->valid())
        {
            $this->data->next();
        }
    }
    
    public function offsetExists($index) // -> bool [\ArrayAccess]
    {
        return (!$this->offsetValid($index)) ? false : $this->data->offsetExists($index);
    }
    
    public function offsetGet($index) // -> mixed [\ArrayAccess]
    {
        $r = null;
        
        if($this->offsetValid($index))
        {
            $r = $this->data->offsetGet($index);
        }
        else
        {
            throw new InvalidIndexException('Index invalid or out of range');
        }
        
        return $r;
    }
    
    public function offsetSet($index, $newval) // [\ArrayAccess]
    {
        if(null === $index)
        {
            $this->push($newval);
        }
        else if($this->offsetValid($index))
        {
            $this->data->offsetSet($index, $newval);
        }
        else
        {
            throw new InvalidIndexException('Index invalid or out of range');
        }
    }
    
    public function offsetUnset($index) // [\ArrayAccess]
    {
        if($this->offsetValid($index))
        {
            $this->data->offsetUnset($index);
        }
        else
        {
            throw new InvalidIndexException('Index invalid or out of range');
        }
    }
    
    public function pop() // -> mixed
    {
        $r = null;
        
        if($this->isEmpty())
        {
            throw new CantPopFromEmptyException('Can\'t pop from an empty datastructure');
        }
        else
        {
            $n = $this->count - 1;
            $r = $this->offsetGet($n);
        
            $this->offsetUnset($n);
            
            --$this->count;
            $this->shrink();
        }
        
        return $r;
    }
    
    public function push($value)
    {
        $this->grow();
        
        $this->offsetSet($this->count++, $value);
    }
    
    public function rewind() // [\Iterator]
    {
        $this->data->rewind();
    }
    
    public function setSize($size) // -> int [\SplFixedArray]
    {
        if(true === $size)
        {
            $size = 1;
        }
        else if(false === $size)
        {
            $size = 0;
        }
        else if(null === $size)
        {
            $size = 0;
        }
        
        if(!is_numeric($size))
            trigger_error('SplFixedArray::setSize() expects parameter 1 to be long, ' . gettype($size) . ' given', E_USER_WARNING); // No braces to workaround code coverage bug.
        else if($size < 0)
        {
            throw new InvalidArgumentException('array size cannot be less than zero');
        }
        else
        {
            $this->resize($size, $size);
        }
        
        return 1;
    }
    
    public function toArray() // -> array [\SplFixedArray]
    {
        return array_slice($this->data->toArray(), 0, $this->count);
    }
    
    public function valid() // -> bool [\Iterator]
    {
        return ($this->data->key() < $this->count) ? $this->data->valid()
                                                   : false;
    }
    
    public function __wakeup() // [\SplFixedArray]
    {
        $this->data->__wakeup();
    }
    
    ////////////////////////////////////////////////////////////////////////////
    // Protected methods
    ////////////////////////////////////////////////////////////////////////////
    
    protected function grow()
    {
        $size = $this->data->getSize();
        
        if($size === $this->count)
        {
            $size = (0 < $size) ? 2 * $size
                                : 1;
            
            $this->resize($size);
        }
    }
    
    protected function offsetValid($index) // -> bool
    {
        return (0 <= $index) && ($index < $this->count);
    }
    
    protected function resize($size, $count = null)
    {
        $count = (null === $count) ? $this->count : $count;
        
        $this->data->SetSize($size);
        
        $n = $count;
        
        while($n < $size)
        {
            $this->data->offsetUnset($n++);
        }
        
        $this->count = $count;
    }
    
    protected function shrink()
    {
        $new_size = $this->data->getSize() / 2;
        
        if($this->count < ($new_size / 2) )
        {
            $this->resize($new_size);
        }
    }
}