<?php
 
 
/**
 
 * JAVA Autoboxing (part of Lotos Framework)
 
 *
 
 * Copyright (c) 2005-2010 Artur Graniszewski ([email protected]) 
 
 * All rights reserved.
 
 * 
 
 * @category   Library
 
 * @package    Lotos
 
 * @subpackage DataTypes
 
 * @copyright  Copyright (c) 2005-2010 Artur Graniszewski ([email protected])
 
 * @license    GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007
 
 * @version    $Id$
 
 */
 
 
 
 
// load required library
 
include("./variablesManager.php");
 
 
class PrimitiveTypeWrapper extends AutoBoxedObject
 
{
 
    protected $value = null;
 
    
 
    protected $allowedCasting = array();
 
    
 
    public function __toString() {
 
        // NOTE: this must be a string, PHP forbids returning different type of variables in __toString() methods.
 
        return "{$this->value}";
 
    }
 
    
 
    /**
 
     * Converts this variable to Integer object.
 
     * 
 
     * @return Integer
 
     */
 
    public function & toInt() {
 
        $x = & integer((int)$this->value);
 
        return $x;
 
    }
 
    
 
    /**
 
     * Converts this variable to Float object.
 
     * 
 
     * @return Float
 
     */    
 
    public function & toFloat() {
 
        $x = & float((int)$this->value);
 
        return $x;
 
    }
 
    
 
    /**
 
     * Converts this variable to String object.
 
     * 
 
     * @return String
 
     */ 
 
    public function & toString() {
 
        $x = & string((string)$this->value);
 
        return $x;
 
    }
 
    
 
    /**
 
     * Destructor used to datatype enforcing and final cleanups.
 
     * 
 
     * This time we are overwritting default Lotos VariablesManager behaviour and use
 
     * strong data type enforcing
 
     * 
 
     * @return void
 
     */
 
    public function __destruct() {
 
        if($this->ref === null) {
 
            return;
 
        }
 
        if(is_object(VariablesManager::$memory[$this->ref]) && get_class(VariablesManager::$memory[$this->ref]) === get_class($this) && in_array('setPointer', get_class_methods(VariablesManager::$memory[$this->ref]))) {
 
            VariablesManager::$memory[$this->ref]->setPointer($this->ref);
 
 
        } else if(is_scalar(VariablesManager::$memory[$this->ref])){
 
            $val = VariablesManager::$memory[$this->ref];
 
            $class = get_class($this);
 
            
 
            VariablesManager::$memory[$this->ref] = new $class($val);
 
            VariablesManager::$memory[$this->ref]->setPointer($this->ref);
 
        } else if(is_object(VariablesManager::$memory[$this->ref])) {
 
            foreach($this->allowedCasting as $dataType) {
 
                if(is_a(VariablesManager::$memory[$this->ref], $dataType)) {
 
                    return;
 
                }
 
            }
 
 
            throw new Exception('Cannot cast '.get_class(VariablesManager::$memory[$this->ref]).' data type to '.get_class($this).'!');
 
        }
 
    }                
 
}
 
 
/**
 
 * Example class.
 
 * 
 
 * Note: in order to use AutoBoxing, your class need to extend "AutoBoxedObject" class.
 
 */
 
class String extends PrimitiveTypeWrapper
 
{
 
    
 
    protected $allowedCasting = array('Integer', 'Double', 'Float', 'Bool', 'Number');
 
    
 
    public function __construct($value) {
 
        
 
        // TYPE ENFORCING
 
        if($value && !is_scalar ($value)) {
 
            throw new Exception('The new value is not a scalar!!!');
 
        }
 
        
 
        $this->value = (string)$value;
 
    }
 
    
 
    public function getHex() {
 
        $x = strtoupper(dechex($this->value));
 
        $y = ceil(strlen($x) / 2);
 
        return str_pad($x, $y * 2, '0', STR_PAD_LEFT);
 
    }
 
}
 
 
/**
 
 * Example class.
 
 * 
 
 * Note: in order to use AutoBoxing, your class need to extend "AutoBoxedObject" class.
 
 */
 
class Bool extends PrimitiveTypeWrapper
 
{
 
    public function __construct($value) {
 
        
 
        // TYPE ENFORCING
 
        if($value && !is_bool ($value)) {
 
            throw new Exception('The new value is not a boolean type!!!');
 
        }
 
        
 
        $this->value = (bool)$value;
 
    }
 
    
 
    /**
 
     * Converts this variable to String object.
 
     * 
 
     * @return String
 
     */ 
 
    public function & toString() {
 
        $x = & string($this->value === true ? 'true' : ($this->value === false ? 'false' : 'null'));
 
        return $x;
 
    }    
 
}
 
 
/**
 
 * Example class.
 
 * 
 
 * Note: in order to use AutoBoxing, your class need to extend "AutoBoxedObject" class.
 
 */
 
class Integer extends PrimitiveTypeWrapper
 
{
 
  
 
    public function __construct($value) {
 
        
 
        // TYPE ENFORCING
 
        if($value && !is_int ($value) && !is_float($value)) {
 
            throw new Exception('The new value cannot be cast to integer!!!');
 
        }
 
        
 
        $this->value = (int)$value;
 
    }
 
    
 
    public function toHex($useX = false) {
 
        $x = strtoupper(dechex($this->value));
 
        $y = ceil(strlen($x) / 2);
 
        return ($useX ? '0x': '').str_pad($x, $y * 2, '0', STR_PAD_LEFT);
 
    }
 
}
 
 
/**
 
 * Example class.
 
 * 
 
 * Note: in order to use AutoBoxing, your class need to extend "AutoBoxedObject" class.
 
 */
 
class Number extends PrimitiveTypeWrapper
 
{
 
    protected $allowedCasting = array('Integer', 'Double', 'Float');
 
    
 
    public function __construct($value) {
 
        
 
        // TYPE ENFORCING
 
        if($value && !is_int ($value) && !is_float($value) && !is_double($value)) {
 
            throw new Exception('The new value cannot be cast to integer!!!');
 
        }
 
        
 
        $this->value = (double)$value;
 
    }
 
    
 
    public function toHex($useX = false) {
 
        $x = strtoupper(dechex($this->value));
 
        $y = ceil(strlen($x) / 2);
 
        return ($useX ? '0x': '').str_pad($x, $y * 2, '0', STR_PAD_LEFT);
 
    }
 
}
 
 
/**
 
 * Example class.
 
 * 
 
 * Note: in order to use AutoBoxing, your class need to extend "AutoBoxedObject" class.
 
 */
 
class Float extends PrimitiveTypeWrapper
 
{
 
    protected $allowedCasting = array('Double');
 
    
 
    public function __construct($value) {
 
        
 
        // TYPE ENFORCING
 
        if($value && !is_int ($value) && !is_float($value)) {
 
            throw new Exception('The new value cannot be cast to float!!!');
 
        }
 
        
 
        $this->value = (float)$value;
 
    }
 
}
 
 
/**
 
 * Example class.
 
 * 
 
 * Note: in order to use AutoBoxing, your class need to extend "AutoBoxedObject" class.
 
 */
 
class Double extends Float
 
{
 
    
 
}
 
 
/**
 
 * Initializes a newly created Float object.
 
 * @return Float created String object
 
 */
 
function & float($value = null) {
 
    $type = ucfirst(strtolower(__FUNCTION__));
 
    $x = & VariablesManager::getNewPointer(new $type($value));
 
    return $x;
 
}
 
 
/**
 
 * Initializes a newly created Float object.
 
 * @return Float created String object
 
 */
 
function & double($value = null) {
 
    $type = ucfirst(strtolower(__FUNCTION__));
 
    $x = & VariablesManager::getNewPointer(new $type($value));
 
    return $x;
 
}
 
 
/**
 
 * Initializes a newly created Integer object.
 
 * @return Integer created String object
 
 */
 
function & integer($value = null) {
 
    $type = ucfirst(strtolower(__FUNCTION__));
 
    $x = & VariablesManager::getNewPointer(new $type($value));
 
    return $x;
 
}
 
 
/**
 
 * Initializes a newly created String object.
 
 * @return String created String object
 
 */
 
function & string($value = null) {
 
    $type = ucfirst(strtolower(__FUNCTION__));
 
    $x = & VariablesManager::getNewPointer(new $type($value));
 
    return $x;
 
}
 
 
/**
 
 * Initializes a newly created Bool object.
 
 * @return Bool created String object
 
 */
 
function & bool($value = null) {
 
    $type = ucfirst(strtolower(__FUNCTION__));
 
    $x = & VariablesManager::getNewPointer(new $type($value));
 
    return $x;
 
}
 
 
/**
 
 * Initializes a newly created Bool object.
 
 * @return Bool created String object
 
 */
 
function & number($value = null) {
 
    $type = ucfirst(strtolower(__FUNCTION__));
 
    $x = & VariablesManager::getNewPointer(new $type($value));
 
    return $x;
 
}
 
 
// ---------------------------------------------------------------------------
 
// simple autoboxing checks
 
$x = & integer(12);
 
$x = "$x" + 1;
 
echo $x.' => '.$x->toHex(true)."<br />";
 
 
$x = & float(12.12);
 
$x = "$x" * 2;
 
echo $x.' => '.$x->toInt()."<br />";
 
 
 
// ---------------------------------------------------------------------------
 
// with strong data type enforcing set integer value of 12 to the boolean variable
 
$x = & bool();
 
$x = true;
 
 
try {
 
    $x = 12;
 
} catch (Exception $e) {
 
    echo "Exception catched: ".$e->getMessage().' (code: '.$e->getCode().')<br />';
 
}
 
 
// ---------------------------------------------------------------------------
 
// with strong data type enforcing we cannot cast String ($y) to Number($x):
 
$x = & number();
 
$x = 12.33;
 
$y = & string("ok");
 
 
try {
 
    $x = $y;
 
} catch(Exception $e) {
 
    echo "Exception catched: ".$e->getMessage().' (code: '.$e->getCode().')<br />';
 
}
 
 
// ---------------------------------------------------------------------------
 
// but we can cast Number to Double, Float, etc.
 
$x = & number();
 
$x = 12.33;
 
$y = & double(3.33);
 
 
$x = $y;
 
echo $x.' => '.$x->toString()."<br />";
 
 
 |