fruffl icon

PHP Datatype Class

fruffl | 09/18/13 12:40:35 PM UTC | 0 ⭐ | 279 👁️ | Never ⏰ | []
PHP |

4.3 KB

|

None

|

0 👍

/

0 👎

<?PHP
    NAMESPACE ILLI\Core\Type;
    USE ILLI\Core\Spl\Fsm;
    USE ILLI\Core\Std\Clsid;
    USE ILLI\Core\Type\__flag_T;
    USE ILLI\Core\Type\T\GC;
    USE ILLI\Core\Type\T\Data;
    USE ILLI\Core\Type\ILimitable;
    USE ILLI\Core\Type\IListable;
    USE ILLI\Core\Std\Exception;
    USE ILLI\Core\Util\UUID;
    
    ABSTRACT CLASS T
    {
        private static $__gc    = [];
        
        protected $__super  = NULL;
        protected $__context    = NULL;
        protected $__clsid  = NULL;
        protected $__prop   = 0b00;
        protected $__Definition = NULL;
        
        private $__Data = NULL;
        
        function __construct(array $__type, $__context = UUID::NIL, $__super = UUID::NIL)
        {
            $this->__context    = UUID::normalize($__context);
            $this->__super      = UUID::normalize($__super);
            
            $G          = &self::$__gc[$this->__super][get_called_class()][$this->__context];
            $this->__Definition = &$G[0x00];
            $this->__clsid      = &$G[0x01];
            
            #+ create data matrix:
            $this->__Data instanceOf Data ?: $this->__Data = new Data;
            
            #+ load or create type declaration for this class
            if(NULL === ($T = &$G[0x00]))
                $T = new GC((array) $__type);
            
            #+ set property flag by type declaration
            switch(TRUE):
                case 0x00 === $T->getSize():        $this->__prop |= __flag_T::T_VOID;          break;
                case 0x01 === $T->getSize():        $this->__prop |= __flag_T::T_SHALLOW;           break;
                case 0x02 === $T->getSize():        $this->__prop |= __flag_T::T_PAIR;          break;
                case 0x02  <  $T->getSize():        $this->__prop |= __flag_T::T_ROW;           break;
            endswitch;
            
            foreach(class_implements($this) as $interface)
                switch($interface):
                    case IListable::class:      $this->__prop |= __flag_T::T_LISTABLE;          break;
                    case ILimitable::class:     $this->__prop |= __flag_T::T_LIMITABLE;         break;
                endswitch;
            
            #+ set matrix dimension
            switch(TRUE):
                case $this instanceOf IListable:    $this->__Data->setSize($T->getSize());          break;
                case 0x00 === $T->getSize():        $this->__Data->setDimension(0x00, 0x00);        break;
                case 0x00  <  $T->getSize():        $this->__Data->setDimension($T->getSize(), 0x01);   break;
            endswitch;
                
            
            #+ clsid
            NULL !== ($C = &$G[0x01]) ?:
                $C = (new Clsid(__CLASS__, get_called_class(), [
                    'definition'    => $T->invoke('invoke', ['clsid']), // Fsc->Fsc->Define::clsid()
                    'prop'      => $this->__prop
                ], $this->__context, $this->__super))->uuid();
        }
        
        /**
         * add or remove lines in data FSM
         *
         * @param int   $__length   Lines : y range
         * @throws Exception when interface T_LISTABLE is not implemented
         * @throws Exception when interface T_LIMITABLE is implemented
         */
        function setLength($__length)
        {
            if(__flag_T::T_LISTABLE !== ($this->__prop & __flag_T::T_LISTABLE)
            || __flag_T::T_LIMITABLE === ($this->__prop & __flag_T::T_LIMITABLE))
                throw new Exception('Unable to add or remove lines (y offset): {:class} does not implement interface {:IListable} or implements {:ILimitable}.',
                    ['class' => get_called_class(), 'ILimitable' => ILimitable::class, 'IListable' => IListable::class]);
            
            $this->__Data->setLength($__length);
            
            return $this;
        }
        
        function inRange($__field = 0x00, $__line = 0x00)
        {
            return $__field >= 0x00
                && $__line  >= 0x00
                && $__field <= $this->__Data->getSize() - 1
                && $__line  <= $this->__Data->getLength() - 1;
        }
        
        /**
         * store value at specific offset in data FSM
         * 
         * n = 0 ... defined fields - 1
         * i = 0 ... infinite
         * f = 0 ... finite
         *
         *      T           T<IListable>            T<IListable:ILimited>
         *
         *     & T_PAIR [0,0] [1,0]     [0,i] [1,i]         [0,f] [1,f]
         *      & T_ROW [n,0]           [n,i]               [n,f]
         *  & T_SHALLOW [0,0]           [0,i]               [0,f]
         *
         * @param mixed     $__value    expected type is defined in Field Declaration
         * @param int       $__field    Field : offset x, default 0
         * @param int       $__line     Line  : offset y, default 0
         *
         * @internal this method should be protected
         * @testing default address for $__prop
         * @todo 
         */
        function set($__value, $__field = 0x00, $__line = 0x00)
        {
            if(FALSE === $this->inRange($__field, $__line))
                throw new Exception('Unable to set data: address {:class}<x:{:field},y:{:line}> not found.',
                    ['field' => $__field, 'line' => $__line, 'class' => get_called_class()]);
            
            $this->__Data->offsetGet($__field)->offsetSet($__line, $__value);
        }

Comments