Advertisement
fruffl

Class Array/ArraySegment

Mar 6th, 2012
94
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 14.41 KB | None | 0 0
  1. <?PHP
  2.     /**
  3.      * ILLI
  4.      *
  5.      * @category   ILLI_System
  6.      * @package    ILLI
  7.      * @subpackage System
  8.      * @link       http://illi.be
  9.      * @license    http://l.illi.be
  10.      * @copyright  ILLI Conference
  11.      */
  12.     NAMESPACE ILLI\System;
  13.  
  14.     /**
  15.      * ILLI System Abstract Prototype Array
  16.      *
  17.      * Basic Array: index : offset : value
  18.      *
  19.      * @category    ILLI_System
  20.      * @package ILLI
  21.      * @subpackage  System
  22.      * @namespace   ILLI\System
  23.      * @link    http://illi.be
  24.      * @license http://l.illi.be
  25.      * @copyright   ILLI Conference
  26.      * @since   2.0.0-1
  27.      * @version 2.0.0-1
  28.      * @abstract
  29.      * @todo    flags/it-modes
  30.      */
  31.     ABSTRACT CLASS ProtoArray EXTENDS Proto IMPLEMENTS iCountable, iArrayAccess, iSerializable, iIterator
  32.     {
  33.         /**
  34.          * iterator modes
  35.          * [fifo: 0] [lifo: 0x00000002] [filo: 0x00000004] [lilo: 0x00000006] [default: 0]
  36.          * @var int
  37.          */
  38.         const IT_MODE_FI        = 0x00000000;
  39.        
  40.         /**
  41.          * @see IT_MODE_FI
  42.          * @var int
  43.          */
  44.         const IT_MODE_FO        = 0x00000000;
  45.        
  46.         /**
  47.          * @see IT_MODE_FI
  48.          * @var int
  49.          */
  50.         const IT_MODE_LI        = 0x00000002;
  51.        
  52.         /**
  53.          * @see IT_MODE_FI
  54.          * @var int
  55.          */
  56.         const IT_MODE_LO        = 0x00000004;
  57.        
  58.         /**
  59.          * typedef values: if set, strict type for values
  60.          * [mixed: 0] [safe: 0x00000032] [default: 0]
  61.          * @var int
  62.          */
  63.         const VALUE_TYPE_UNSAFE     = 0x00000000;
  64.        
  65.         /**
  66.          * @see VALUE_TYPE_UNSAFE
  67.          * @var int
  68.          */
  69.         const VALUE_TYPE_SAFE       = 0x00000032;
  70.        
  71.         /**
  72.          * typedef: zerobased or assoc array
  73.          * [array: 0] [assoc: 0x00000256] [default: 0]
  74.          * @var int
  75.          */
  76.         const ARRAY_MODE_ARRAY      = 0x00000000;
  77.        
  78.         /**
  79.          * @see ARRAY_MODE_ASSOC
  80.          * @var int
  81.          */
  82.         const ARRAY_MODE_ASSOC      = 0x00000256;
  83.        
  84.         /**
  85.          * array_merge: order of priority
  86.          * [new before existing: 0] [existing before new: 0x00001024] [default: 0]
  87.          * @var int
  88.          */
  89.         const PERM_VALUE_AS_SUPER   = 0x00000000;
  90.        
  91.         /**
  92.          * @see PERM_VALUE_AS_SUPER
  93.          * @var int
  94.          */
  95.         const PERM_ARRAY_AS_SUPER   = 0x00001024;
  96.        
  97.         /**
  98.          * serializable private properties
  99.          * @var array
  100.          * @static
  101.          */
  102.         private static $__serializable  =
  103.                         [
  104.                             '__array',
  105.                             '__offsets',
  106.                             '__indexes',
  107.                             '__bitFlag'
  108.                         ];
  109.        
  110.         /**
  111.          * bitflag
  112.          * @var int
  113.          * @see IT_MODE_FI
  114.          * @see IT_MODE_FO
  115.          * @see VALUE_TYPE_UNSAFE
  116.          * @see ARRAY_MODE_ARRAY
  117.          * @see PERM_VALUE_AS_SUPER
  118.          */
  119.         private $__bitFlag      = 0x00000000;
  120.        
  121.         /**
  122.          * data array
  123.          * @var array
  124.          */
  125.         private $__array        = [];
  126.        
  127.         /**
  128.          * offset cache: array keys from $__array
  129.          * @var array
  130.          */
  131.         private $__offsets      = [];
  132.        
  133.         /**
  134.          * index cache: flipped $__offsets
  135.          * @var array
  136.          */
  137.         private $__indexes      = [];
  138.        
  139.         /**
  140.          * iterator index
  141.          * @var int32
  142.          */
  143.         private $__itIndex      = 0;
  144.        
  145.         /**
  146.          * @param array|ProtoArray $array initial value
  147.          */
  148.         public function __construct($array = [])
  149.         {
  150.             if(NULL === $array)
  151.                 $array = [];
  152.            
  153.             if($array instanceOf ProtoArray
  154.             || $array instanceOf ProtoArraySegment)
  155.                 $array = $array->toArray();
  156.            
  157.             if(FALSE === is_array($array))
  158.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_ARRAY);
  159.            
  160.             self::$__tSerializableProperties = self::$__serializable;
  161.            
  162.             $this->__array = $array;
  163.             $this->updateEvent();
  164.         }
  165.        
  166.         // iSerializable
  167.        
  168.         /**
  169.          * @see tSerializable
  170.          */
  171.         USE tSerializable;
  172.        
  173.         /**
  174.          * synchronize $__array with $__indexes and $__offsets
  175.          *
  176.          * its essential to update the both arrays whenever you edit $__array
  177.          *
  178.          * @see $__array
  179.          * @see $__indexes
  180.          * @see $__offsets
  181.          */
  182.         protected function updateEvent()
  183.         {
  184.             $this->__offsets = array_keys($this->__array);
  185.             $this->__indexes = array_flip($this->__offsets);
  186.             return $this;
  187.         }
  188.        
  189.         // Countable
  190.        
  191.         public function count()
  192.         {
  193.             return sizeOf($this->__array);
  194.         }
  195.        
  196.         // Iterator
  197.        
  198.         public function rewind()
  199.         {
  200.             $this->__itIndex = $this->firstIndex();
  201.             return $this->__itIndex;
  202.         }
  203.        
  204.         public function current()
  205.         {
  206.             return $this->indexGet($this->__itIndex);
  207.         }
  208.        
  209.         public function key()
  210.         {
  211.             return $this->indexToOffset($this->__itIndex);
  212.         }
  213.        
  214.         public function next()
  215.         {
  216.             return ++$this->__itIndex;
  217.         }
  218.        
  219.         public function prev()
  220.         {
  221.             return --$this->__itIndex;
  222.         }
  223.        
  224.         public function valid()
  225.         {
  226.             return $this->indexExists($this->__itIndex);
  227.         }
  228.        
  229.         public function currentIndex()
  230.         {
  231.             return $this->__itIndex;
  232.         }
  233.        
  234.         public function updateIndex($itIndex)
  235.         {
  236.             if(NULL === $itIndex)
  237.                 throw new ArgumentNullException;
  238.                
  239.             if(FALSE === is_integer($itIndex))
  240.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_INTEGER);
  241.            
  242.             if(FALSE === $this->indexExists($itIndex))
  243.                 throw new ArgumentOutOfRangeException(E::ARGUMENT_OUT_OF_ARRAY_INDEX,
  244.                     ['key' => $itIndex]);
  245.            
  246.             $this->__itIndex = $itIndex;
  247.             return $this;
  248.         }
  249.        
  250.         // ArrayAccess
  251.        
  252.         public function offsetSet($offset, $value)
  253.         {
  254.             if(NULL === $offset)
  255.                 throw new ArgumentNullException;
  256.                
  257.             if(FALSE === is_scalar($offset))
  258.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_SCALAR);
  259.                
  260.             if($offset === "")
  261.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_STRING_EMPTY);
  262.                    
  263.             $this->__array[$offset] = $value;
  264.             return $this->updateEvent();
  265.         }
  266.        
  267.         public function offsetExists($offset)
  268.         {
  269.             if(NULL === $offset)
  270.                 throw new ArgumentNullException;
  271.                
  272.             if(FALSE === is_scalar($offset))
  273.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_SCALAR);
  274.                
  275.             if($offset === "")
  276.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_STRING_EMPTY);
  277.                
  278.             return array_key_exists($offset, $this->__array);
  279.         }
  280.        
  281.         public function offsetUnset($offset)
  282.         {
  283.             if(NULL === $offset)
  284.                 throw new ArgumentNullException;
  285.                
  286.             if(FALSE === is_scalar($offset))
  287.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_SCALAR);
  288.                
  289.             if($offset === "")
  290.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_STRING_EMPTY);
  291.                
  292.             if(FALSE === $this->offsetExists($offset))
  293.                 return $this;
  294.            
  295.             unset($this->__array[$offset]);
  296.             return $this->updateEvent();
  297.         }
  298.        
  299.         public function offsetGet($offset)
  300.         {
  301.             if(NULL === $offset)
  302.                 throw new ArgumentNullException;
  303.                
  304.             if(FALSE === is_scalar($offset))
  305.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_SCALAR);
  306.                
  307.             if($offset === "")
  308.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_STRING_EMPTY);
  309.                
  310.             return (TRUE === $this->offsetExists($offset))
  311.                 ? $this->__array[$offset]
  312.                 : null;
  313.         }
  314.        
  315.         // IndexAccess
  316.            
  317.         /**
  318.          * index-based alias for offsetExists
  319.          */
  320.         public function indexExists($index)
  321.         {
  322.             if(NULL === $index)
  323.                 throw new ArgumentNullException;
  324.                
  325.             if(FALSE === is_integer($index))
  326.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_INTEGER);
  327.                
  328.             return array_key_exists($index, $this->__offsets);
  329.         }
  330.            
  331.         /**
  332.          * index-based alias for offsetSet
  333.          */
  334.         public function indexSet($index, $value)
  335.         {
  336.             if(NULL === $index)
  337.                 throw new ArgumentNullException;
  338.                
  339.             if(FALSE === is_integer($index))
  340.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_INTEGER);
  341.            
  342.             if(FALSE === $this->indexExists($index))
  343.                 throw new ArgumentOutOfRangeException(E::ARGUMENT_OUT_OF_ARRAY_INDEX,
  344.                     ['key' => $index]);
  345.            
  346.             return $this->offsetSet($this->indexToOffset($index), $value);
  347.         }
  348.            
  349.         /**
  350.          * index-based alias for offsetUnset
  351.          */
  352.         public function indexUnset($index)
  353.         {
  354.             if(NULL === $index)
  355.                 throw new ArgumentNullException;
  356.                
  357.             if(FALSE === is_integer($index))
  358.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_INTEGER);
  359.            
  360.             if(FALSE === $this->indexExists($index))
  361.                 throw new ArgumentOutOfRangeException(E::ARGUMENT_OUT_OF_ARRAY_INDEX,
  362.                     ['key' => $index]);
  363.            
  364.             return $this->offsetUnset($this->indexToOffset($index));
  365.         }
  366.            
  367.         /**
  368.          * index-based alias for offsetGet
  369.          */
  370.         public function indexGet($index)
  371.         {
  372.             if(NULL === $index)
  373.                 throw new ArgumentNullException;
  374.                
  375.             if(FALSE === is_integer($index))
  376.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_INTEGER);
  377.            
  378.             if(FALSE === $this->indexExists($index))
  379.                 throw new ArgumentOutOfRangeException(E::ARGUMENT_OUT_OF_ARRAY_INDEX,
  380.                     ['key' => $index]);
  381.            
  382.             return $this->offsetGet($this->indexToOffset($index));
  383.         }
  384.        
  385.         // Conversation
  386.            
  387.         /**
  388.          * get the index by offset
  389.          */
  390.         public function offsetToIndex($offset)
  391.         {
  392.             if(NULL === $offset)
  393.                 throw new ArgumentNullException;
  394.                
  395.             if(FALSE === is_scalar($offset))
  396.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_SCALAR);
  397.                
  398.             if($offset === "")
  399.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_STRING_EMPTY);
  400.            
  401.             if(FALSE === $this->offsetExists($offset))
  402.                 throw new ArgumentOutOfRangeException(E::ARGUMENT_OUT_OF_ARRAY_INDEX,
  403.                     ['key' => $offset]);
  404.                
  405.             return $this->__indexes[$offset];
  406.         }
  407.        
  408.         /**
  409.          * get the offset by index
  410.          */
  411.         public function indexToOffset($index)
  412.         {
  413.             if(NULL === $index)
  414.                 throw new ArgumentNullException;
  415.                
  416.             if(FALSE === is_integer($index))
  417.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_INTEGER);
  418.            
  419.             if(FALSE === $this->indexExists($index))
  420.                 throw new ArgumentOutOfRangeException(E::ARGUMENT_OUT_OF_ARRAY_INDEX,
  421.                     ['key' => $index]);
  422.            
  423.             return $this->__offsets[$index];
  424.         }
  425.        
  426.         /**
  427.          * bottom value
  428.          */
  429.         public function firstValue()
  430.         {
  431.             return $this->__array[$this->firstOffset()];
  432.         }
  433.        
  434.         /**
  435.          * top value
  436.          */
  437.         public function lastValue()
  438.         {
  439.             return $this->__array[$this->lastOffset()];
  440.         }
  441.        
  442.         /**
  443.          * bottom offset
  444.          */
  445.         public function firstOffset()
  446.         {
  447.             return $this->__offsets[$this->firstIndex()];
  448.         }
  449.        
  450.         /**
  451.          * top offset
  452.          */
  453.         public function lastOffset()
  454.         {
  455.             return $this->__offsets[$this->lastIndex()];
  456.         }
  457.        
  458.         /**
  459.          * bottom index
  460.          */
  461.         public function firstIndex()
  462.         {
  463.             return 0;
  464.         }
  465.        
  466.         /**
  467.          * top index
  468.          */
  469.         public function lastIndex()
  470.         {
  471.             return $this->count() - 1;
  472.         }
  473.        
  474.         /**
  475.          * returns the value by offset or by top-offset
  476.          */
  477.         public function peekValueByOffset($offset)
  478.         {
  479.             if(NULL === $offset)
  480.                 throw new ArgumentNullException;
  481.                
  482.             if(FALSE === is_scalar($offset))
  483.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_SCALAR);
  484.                
  485.             if($offset === "")
  486.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_STRING_EMPTY);
  487.            
  488.             return (FALSE === $this->offsetExists($offset))
  489.                 ? $this->lastValue()
  490.                 : $this->offsetGet($offset);
  491.         }
  492.        
  493.         /**
  494.          * returns the value by index or by top-index
  495.          */
  496.         public function peekValueByIndex($index)
  497.         {
  498.             if(NULL === $index)
  499.                 throw new ArgumentNullException;
  500.                
  501.             if(FALSE === is_integer($index))
  502.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_INTEGER);
  503.            
  504.             return (FALSE === $this->indexExists($index))
  505.                 ? $this->lastValue()
  506.                 : $this->indexGet($index);
  507.         }
  508.        
  509.         /**
  510.          * returns the index by offset or by top-offset
  511.          */
  512.         public function peekIndexByOffset($offset)
  513.         {
  514.             if(NULL === $offset)
  515.                 throw new ArgumentNullException;
  516.                
  517.             if(FALSE === is_scalar($offset))
  518.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_SCALAR);
  519.                
  520.             if($offset === "")
  521.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_STRING_EMPTY);
  522.            
  523.             return (FALSE === $this->offsetExists($offset))
  524.                 ? $this->lastIndex()
  525.                 : $this->offsetToIndex($offset);
  526.         }
  527.        
  528.         /**
  529.          * returns the offset by index or by top-index
  530.          */
  531.         public function peekOffsetByIndex($index)
  532.         {
  533.             if(NULL === $index)
  534.                 throw new ArgumentNullException;
  535.                
  536.             if(FALSE === is_integer($index))
  537.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_INTEGER);
  538.            
  539.             return (FALSE === $this->indexExists($index))
  540.                 ? $this->lastOffset()
  541.                 : $this->indexToOffset($index);
  542.         }
  543.        
  544.         // generic array functions
  545.        
  546.         public function push($value)
  547.         {
  548.         }
  549.        
  550.         public function toArray()
  551.         {
  552.             return $this->__array;
  553.         }
  554.     }
  555.  
  556.     /**
  557.      * ILLI System Abstract Prototype Array Segment
  558.      *
  559.      * Basic Array: reference to ProtoArray
  560.      *
  561.      * @category   ILLI_System
  562.      * @package    ILLI
  563.      * @subpackage System
  564.      * @namespace  ILLI\System
  565.      * @link       http://illi.be
  566.      * @license    http://l.illi.be
  567.      * @copyright  ILLI Conference
  568.      * @since      2.0.0-1
  569.      * @version    2.0.0-1
  570.      * @abstract
  571.      */
  572.     CLASS ProtoArraySegment EXTENDS Proto IMPLEMENTS iCountable, iIterator
  573.     {
  574.         private $__reference    = NULL;
  575.         private $__start    = 0;
  576.         private $__length   = 0;
  577.         private $__last     = 0;
  578.        
  579.         public function __construct(ProtoArray &$proto, $start = NULL, $length = NULL)
  580.         {
  581.             $this->__reference =& $proto;
  582.            
  583.             if(NULL !== $start
  584.             && FALSE === is_integer($start))
  585.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_INTEGER);
  586.            
  587.             if(NULL !== $length
  588.             && FALSE === is_integer($length))
  589.                 throw new ArgumentException(E::ARGUMENT_EXPECTED_INTEGER);
  590.            
  591.             $this->__start = (NULL === $start)
  592.                 ? 0
  593.                 : $start;
  594.                
  595.             $this->__length = (NULL === $length)
  596.                 ? $this->count()
  597.                 : $length;
  598.            
  599.             $this->__last = $this->__start + $this->__length - 1;
  600.         }
  601.        
  602.         // Iterator Wrapper for $__reference
  603.        
  604.         /**
  605.          * @see ProtoArray::count()
  606.          */    
  607.         public function count()
  608.         {
  609.             return $this->__length;
  610.         }
  611.        
  612.         /**
  613.          * @see ProtoArray::rewind()
  614.          */
  615.         public function rewind()
  616.         {
  617.             return $this->__reference->updateIndex($this->__start);
  618.         }
  619.        
  620.         /**
  621.          * @see ProtoArray::current()
  622.          */
  623.         public function current()
  624.         {
  625.             return $this->__reference->current();
  626.         }
  627.        
  628.         /**
  629.          * @see ProtoArray::key()
  630.          */
  631.         public function key()
  632.         {
  633.             return $this->__reference->key();
  634.         }
  635.        
  636.         /**
  637.          * @see ProtoArray::next()
  638.          */
  639.         public function next()
  640.         {
  641.             return $this->__reference->next();
  642.         }
  643.        
  644.         /**
  645.          * @see ProtoArray::prev()
  646.          */
  647.         public function prev()
  648.         {
  649.             return $this->__reference->prev();
  650.         }
  651.        
  652.         /**
  653.          * @see ProtoArray::valid()
  654.          */
  655.         public function valid()
  656.         {
  657.             return $this->__reference->valid() && $this->__reference->currentIndex() <= $this->__last;
  658.         }
  659.        
  660.         /**
  661.          * @return ProtoArray refernced Object
  662.          */
  663.         public function getReference()
  664.         {
  665.             return $this->__reference;
  666.         }
  667.        
  668.         /**
  669.          * @return array copy of segment
  670.          */
  671.         public function toArray()
  672.         {
  673.             $array  = [];
  674.             foreach($this as $key => $value)
  675.                 $array[$key] = $value;
  676.                
  677.             return $array;
  678.         }
  679.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement