Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?PHP
- /**
- * ILLI
- *
- * @category ILLI_System
- * @package ILLI
- * @subpackage System
- * @link http://illi.be
- * @license http://l.illi.be
- * @copyright ILLI Conference
- */
- NAMESPACE ILLI\System;
- /**
- * ILLI System Abstract Prototype Array
- *
- * Basic Array: index : offset : value
- * support for LIFO, LILO, FIFO, FILO
- *
- * @category ILLI_System
- * @package ILLI
- * @subpackage System
- * @namespace ILLI\System
- * @link http://illi.be
- * @license http://l.illi.be
- * @copyright ILLI Conference
- * @since 2.0.0-1
- * @version 2.0.0-1
- * @abstract
- * @todo flags/it-modes
- */
- ABSTRACT CLASS ProtoArray EXTENDS Proto IMPLEMENTS iCountable, iArrayAccess, iSerializable, iIterator
- {
- /**
- * iterator modes
- * [LIFO 0] [LILO 4] [FIFO 2] [FILO 6] [default: LIFO]
- * @var int
- */
- const IT_MODE_FI = 0x00000002;
- /**
- * @see IT_MODE_FI
- * @var int
- */
- const IT_MODE_LO = 0x00000004;
- /**
- * typedef values: if set, strict type for values
- * [mixed: 0] [safe: 32] [default: 0]
- * @var int
- */
- const VALUE_TYPE_SAFE = 0x00000020;
- /**
- * typedef: zerobased or assoc array
- * [array: 0] [assoc: 256] [default: 0]
- * @var int
- */
- const ARRAY_MODE_ASSOC = 0x00000100;
- /**
- * array_merge: order of priority
- * [new before existing: 0] [existing before new: 1024] [default: 0]
- * @var int
- */
- const PERM_ARRAY_AS_SUPER = 0x00000400;
- /**
- * serializable private properties
- * @var array
- * @static
- */
- private static $__serializable =
- [
- '__array',
- '__offsets',
- '__indexes',
- '__bitFlag'
- ];
- /**
- * bitflag
- * @var ProtoFlag
- * @see IT_MODE_FI
- * @see IT_MODE_LO
- * @see VALUE_TYPE_SAFE
- * @see ARRAY_MODE_ASSOC
- * @see PERM_ARRAY_AS_SUPER
- */
- private $__FLAG = NULL;
- /**
- * data array
- * @var array
- */
- private $__array = [];
- /**
- * offset cache: array keys from $__array
- * @var array
- */
- private $__offsets = [];
- /**
- * index cache: flipped $__offsets
- * @var array
- */
- private $__indexes = [];
- /**
- * iterator index
- * @var int32
- */
- private $__itIndex = 0;
- /**
- * last insert offset
- */
- private $__lastInsertOffset = NULL;
- /**
- * last changed offset
- */
- private $__lastChangedOffset = NULL;
- /**
- * @param array|ProtoArray $array initial value
- */
- public function __construct($array = [], ProtoFlag $flag = NULL)
- {
- if(NULL === $array)
- $array = [];
- if($array instanceOf ProtoArray
- || $array instanceOf ProtoArraySegment)
- $array = $array->toArray();
- if(FALSE === is_array($array))
- throw new ArgumentException(E::ARGUMENT_EXPECTED_ARRAY);
- $this->__FLAG = (NULL !== $flag)
- ? $flag
- : new ProtoFlag;
- self::$__tSerializableProperties = self::$__serializable;
- $this->__array = $array;
- $this->updateEvent();
- }
- // iSerializable
- /**
- * @see tSerializable
- */
- USE tSerializable;
- // Countable
- public function count()
- {
- return sizeOf($this->__array);
- }
- // Iterator
- public function rewind()
- {
- $this->__itIndex = (TRUE === $this->__FLAG->valueGet(self::IT_MODE_LO))
- ? $this->lastIndex()
- : $this->firstIndex();
- return $this;
- }
- public function current()
- {
- return $this->indexGet($this->__itIndex);
- }
- public function key()
- {
- return $this->indexToOffset($this->__itIndex);
- }
- public function next()
- {
- if(TRUE === $this->__FLAG->valueGet(self::IT_MODE_LO))
- return $this->prev();
- return ++$this->__itIndex;
- }
- public function prev()
- {
- return --$this->__itIndex;
- }
- public function valid()
- {
- return $this->indexExists($this->__itIndex);
- }
- public function currentIeratorIndex()
- {
- return $this->__itIndex;
- }
- public function setIteratorIndex($itIndex)
- {
- if(NULL === $itIndex)
- throw new ArgumentNullException;
- if(FALSE === is_integer($itIndex))
- throw new ArgumentException(E::ARGUMENT_EXPECTED_INTEGER);
- if(FALSE === $this->indexExists($itIndex))
- throw new ArgumentOutOfRangeException(E::ARGUMENT_OUT_OF_ARRAY_INDEX,
- ['key' => $itIndex]);
- $this->__itIndex = $itIndex;
- return $this;
- }
- // ArrayAccess
- public function offsetSet($offset, $value)
- {
- if(NULL === $offset)
- $offset = $this->nextAvailOffset();
- if(FALSE === is_scalar($offset))
- throw new ArgumentException(E::ARGUMENT_EXPECTED_SCALAR);
- if($offset === "")
- throw new ArgumentException(E::ARGUMENT_EXPECTED_STRING_EMPTY);
- if(FALSE === $this->offsetExists($offset))
- {
- $this->__array = $this->insert($offset, $value);
- $this->__lastInsertOffset = $offset;
- return $this->updateEvent();
- }
- $this->__array[$offset] = $value;
- $this->__lastChangedOffset = $offset;
- return $this->updateEvent();
- }
- /**
- * array merge
- *
- * merge by priority
- * PERM_ARRAY_AS_SUPER: existing offsets will be ignored
- *
- * merge will not cleanup existing offsets!
- *
- * merge appends/prepends by IT_MODE_FI of $this->__array and IT_MODE_LO of $array
- *
- * no modifiers set: LIFO
- *
- * <code>
- * <?PHP
- * $mArray = ["m.foo", "m.bar", "m.fox"];
- * $aArray = ["a.foo", "a.bar" => "a.bar", 7 => "a.fox"];
- *
- * var_dump($mArray);
- * var_dump($aArray);
- *
- *
- * $m = new tArray($mArray);
- * $a = new tArray($aArray);
- *
- * // default replace like array_merge
- * $m->merge($a);
- * // => a.foo m.bar m.fox a.bar a.fox
- * var_dump($m->toArray());
- *
- * // it-mode FI in $m: values of $a at first; note the order of $a!
- * // => a.fox a.bar a.foo m.bar m.fox
- * var_dump((new tArray($mArray, new System\ProtoFlag(tArray::IT_MODE_FI)))->merge($a)->toArray());
- *
- * // $m with it-mode FI: to hold the positions of $a set it-mode to LO
- * $aLO = new tArray($aArray, new System\ProtoFlag(tArray::IT_MODE_LO));
- * // => a.bar a.fox a.foo m.bar m.fox
- * var_dump((new tArray($mArray, new System\ProtoFlag(tArray::IT_MODE_FI)))->merge($aLO)->toArray());
- * ?>
- * </code>
- */
- public function merge($array)
- {
- if(FALSE === ($array instanceOf ProtoArray)
- && FALSE === ($array instanceOf ProtoArraySegment)
- && FALSE === is_array($array))
- throw new ArgumentException(E::ARGUMENT_EXPECTED_ARRAY);
- if(FALSE === (bool) $array)
- return $this;
- foreach($array as $k => $v)
- {
- if(TRUE === $this->__FLAG->valueGet(self::PERM_ARRAY_AS_SUPER)
- && $this->offsetExists($k))
- continue;
- $this[$k] = $v;
- }
- return $this;
- }
- /**
- * cleanup numeric offsets
- */
- public function cleanup()
- {
- $this->__array = array_merge($this->__array, []);
- $this->updateEvent();
- return $this;
- }
- public function offsetExists($offset)
- {
- if(NULL === $offset)
- throw new ArgumentNullException;
- if(FALSE === is_scalar($offset))
- throw new ArgumentException(E::ARGUMENT_EXPECTED_SCALAR);
- if($offset === "")
- throw new ArgumentException(E::ARGUMENT_EXPECTED_STRING_EMPTY);
- return array_key_exists($offset, $this->__array);
- }
- public function offsetUnset($offset)
- {
- if(NULL === $offset)
- throw new ArgumentNullException;
- if(FALSE === is_scalar($offset))
- throw new ArgumentException(E::ARGUMENT_EXPECTED_SCALAR);
- if($offset === "")
- throw new ArgumentException(E::ARGUMENT_EXPECTED_STRING_EMPTY);
- if(FALSE === $this->offsetExists($offset))
- return $this;
- unset($this->__array[$offset]);
- return $this->updateEvent();
- }
- public function offsetGet($offset)
- {
- if(NULL === $offset)
- throw new ArgumentNullException;
- if(FALSE === is_scalar($offset))
- throw new ArgumentException(E::ARGUMENT_EXPECTED_SCALAR);
- if($offset === "")
- throw new ArgumentException(E::ARGUMENT_EXPECTED_STRING_EMPTY);
- return (TRUE === $this->offsetExists($offset))
- ? $this->__array[$offset]
- : null;
- }
- // IndexAccess
- /**
- * index-based alias for offsetExists
- */
- public function indexExists($index)
- {
- if(NULL === $index)
- throw new ArgumentNullException;
- if(FALSE === is_integer($index))
- throw new ArgumentException(E::ARGUMENT_EXPECTED_INTEGER);
- return array_key_exists($index, $this->__offsets);
- }
- /**
- * index-based alias for offsetSet
- */
- public function indexSet($index, $value)
- {
- if(NULL === $index)
- throw new ArgumentNullException;
- if(FALSE === is_integer($index))
- throw new ArgumentException(E::ARGUMENT_EXPECTED_INTEGER);
- if(FALSE === $this->indexExists($index))
- throw new ArgumentOutOfRangeException(E::ARGUMENT_OUT_OF_ARRAY_INDEX,
- ['key' => $index]);
- return $this->offsetSet($this->indexToOffset($index), $value);
- }
- /**
- * index-based alias for offsetUnset
- */
- public function indexUnset($index)
- {
- if(NULL === $index)
- throw new ArgumentNullException;
- if(FALSE === is_integer($index))
- throw new ArgumentException(E::ARGUMENT_EXPECTED_INTEGER);
- if(FALSE === $this->indexExists($index))
- throw new ArgumentOutOfRangeException(E::ARGUMENT_OUT_OF_ARRAY_INDEX,
- ['key' => $index]);
- return $this->offsetUnset($this->indexToOffset($index));
- }
- /**
- * index-based alias for offsetGet
- */
- public function indexGet($index)
- {
- if(NULL === $index)
- throw new ArgumentNullException;
- if(FALSE === is_integer($index))
- throw new ArgumentException(E::ARGUMENT_EXPECTED_INTEGER);
- if(FALSE === $this->indexExists($index))
- throw new ArgumentOutOfRangeException(E::ARGUMENT_OUT_OF_ARRAY_INDEX,
- ['key' => $index]);
- return $this->offsetGet($this->indexToOffset($index));
- }
- // Conversation
- /**
- * get the next avail numeric offset
- */
- public function nextAvailOffset()
- {
- return max($this->__offsets) + 1;
- }
- /**
- * get the index by offset
- */
- public function offsetToIndex($offset)
- {
- if(NULL === $offset)
- throw new ArgumentNullException;
- if(FALSE === is_scalar($offset))
- throw new ArgumentException(E::ARGUMENT_EXPECTED_SCALAR);
- if($offset === "")
- throw new ArgumentException(E::ARGUMENT_EXPECTED_STRING_EMPTY);
- if(FALSE === $this->offsetExists($offset))
- throw new ArgumentOutOfRangeException(E::ARGUMENT_OUT_OF_ARRAY_INDEX,
- ['key' => $offset]);
- return $this->__indexes[$offset];
- }
- /**
- * get the offset by index
- */
- public function indexToOffset($index)
- {
- if(NULL === $index)
- throw new ArgumentNullException;
- if(FALSE === is_integer($index))
- throw new ArgumentException(E::ARGUMENT_EXPECTED_INTEGER);
- if(FALSE === $this->indexExists($index))
- throw new ArgumentOutOfRangeException(E::ARGUMENT_OUT_OF_ARRAY_INDEX,
- ['key' => $index]);
- return $this->__offsets[$index];
- }
- /**
- * bottom value
- */
- public function firstValue()
- {
- return $this->__array[$this->firstOffset()];
- }
- /**
- * top value
- */
- public function lastValue()
- {
- return $this->__array[$this->lastOffset()];
- }
- /**
- * last insert value
- */
- public function lastInsertValue()
- {
- return $this->__array[$this->lastInsertOffset()];
- }
- /**
- * last changed value
- */
- public function lastChangedValue()
- {
- return $this->__array[$this->lastChangedOffset()];
- }
- /**
- * bottom offset
- */
- public function firstOffset()
- {
- return $this->__offsets[$this->firstIndex()];
- }
- /**
- * top offset
- */
- public function lastOffset()
- {
- return $this->__offsets[$this->lastIndex()];
- }
- /**
- * last insert offset
- */
- public function lastInsertOffset()
- {
- return $this->__lastInsertOffset;
- }
- /**
- * last changed offset
- */
- public function lastChangedOffset()
- {
- return $this->__lastChangedOffset;
- }
- /**
- * bottom index
- */
- public function firstIndex()
- {
- return 0;
- }
- /**
- * top index
- */
- public function lastIndex()
- {
- return $this->count() - 1;
- }
- /**
- * last insert index
- */
- public function lastInsertIndex()
- {
- return $this->offsetToIndex($this->lastInsertOffset());
- }
- /**
- * last changed index
- */
- public function lastChangedIndex()
- {
- return $this->offsetToIndex($this->lastChangedOffset());
- }
- /**
- * returns the value by offset or by top-offset
- */
- public function peekValueByOffset($offset)
- {
- if(NULL === $offset)
- throw new ArgumentNullException;
- if(FALSE === is_scalar($offset))
- throw new ArgumentException(E::ARGUMENT_EXPECTED_SCALAR);
- if($offset === "")
- throw new ArgumentException(E::ARGUMENT_EXPECTED_STRING_EMPTY);
- return (FALSE === $this->offsetExists($offset))
- ? $this->lastValue()
- : $this->offsetGet($offset);
- }
- /**
- * returns the value by index or by top-index
- */
- public function peekValueByIndex($index)
- {
- if(NULL === $index)
- throw new ArgumentNullException;
- if(FALSE === is_integer($index))
- throw new ArgumentException(E::ARGUMENT_EXPECTED_INTEGER);
- return (FALSE === $this->indexExists($index))
- ? $this->lastValue()
- : $this->indexGet($index);
- }
- /**
- * returns the index by offset or by top-offset
- */
- public function peekIndexByOffset($offset)
- {
- if(NULL === $offset)
- throw new ArgumentNullException;
- if(FALSE === is_scalar($offset))
- throw new ArgumentException(E::ARGUMENT_EXPECTED_SCALAR);
- if($offset === "")
- throw new ArgumentException(E::ARGUMENT_EXPECTED_STRING_EMPTY);
- return (FALSE === $this->offsetExists($offset))
- ? $this->lastIndex()
- : $this->offsetToIndex($offset);
- }
- /**
- * returns the offset by index or by top-index
- */
- public function peekOffsetByIndex($index)
- {
- if(NULL === $index)
- throw new ArgumentNullException;
- if(FALSE === is_integer($index))
- throw new ArgumentException(E::ARGUMENT_EXPECTED_INTEGER);
- return (FALSE === $this->indexExists($index))
- ? $this->lastOffset()
- : $this->indexToOffset($index);
- }
- // generic array functions
- public function push($value)
- {
- }
- public function toArray()
- {
- return $this->__array;
- }
- /**
- * synchronize $__array with $__indexes and $__offsets
- *
- * its essential to update the both arrays whenever you edit $__array
- *
- * @see $__array
- * @see $__indexes
- * @see $__offsets
- */
- protected function updateEvent()
- {
- $this->__offsets = array_keys($this->__array);
- $this->__indexes = array_flip($this->__offsets);
- if(NULL !== $this->__lastInsertOffset
- && FALSE === $this->offsetExists($this->__lastInsertOffset))
- $this->__lastInsertOffset = NULL;
- if(NULL !== $this->__lastChangedOffset
- && FALSE === $this->offsetExists($this->__lastChangedOffset))
- $this->__lastChangedOffset = NULL;
- return $this;
- }
- /**
- * append or prepend offset by IT_MODE_FI
- */
- private function insert($offset, $value)
- {
- if(TRUE === $this->__FLAG->valueGet(self::IT_MODE_FI))
- {
- $array1 = [$offset => $value];
- $array2 = $this->__array;
- }
- else
- {
- $array1 = $this->__array;
- $array2 = [$offset => $value];
- }
- $result = [];
- if(TRUE === (bool) $array1)
- foreach($array1 as $k => $v)
- $result[$k] = $v;
- if(TRUE === (bool) $array2)
- foreach($array2 as $k => $v)
- $result[$k] = $v;
- return $result;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement