3v4l.org

run code in 150+ php & hhvm versions
Bugs & Features
<?php /** * JAVA Autoboxing (part of Lotos Framework) * * Copyright (c) 2005-2010 Artur Graniszewski (aargoth@boo.pl) * All rights reserved. * * @category Library * @package Lotos * @subpackage DataTypes * @copyright Copyright (c) 2005-2010 Artur Graniszewski (aargoth@boo.pl) * @license GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 * @version $Id$ */ final class VariablesManager { /** * Security checks * * @var bool */ private static $initFinished = false; /** * Minimal string size to cache. * * @var integer */ private static $minStringSize; /** * Number of the most current pointer. * * @var int */ private static $counter; public static $memory = array(); /** * Internal pool * array($privateInternId => * array( * [0] - Variable value * [1] - Number of different instances sharing this variable * [2] - Variable length * [3] - Public Intern id * ) * ) */ private static $internPool = array(); /** * Array of internal pools' names. * * @var string[] */ private static $internPoolId = array(); /** * Number of the most current internal pool id. * * @var int */ private static $internPoolCounter = 1; /** * Initializes new variable of the given type and returns C-like pointer to it. * * It allows us to do variable type enforcing and silent object casting * * @param String Data type * @return mixed Pointer to variable * @todo change to array pool? */ public static function & getNewPointer($dataType) { do { ++self::$counter; $name = 'vm_var_'.self::$counter; } while (isset(VariablesManager::$memory[$name])); VariablesManager::$memory[$name] = $dataType; if(is_object($dataType) && in_array('setPointer', get_class_methods($dataType))) { $dataType->setPointer($name); } return VariablesManager::$memory[$name]; } /** * Returns intern reference of the existing string or creates and returns new one if it doesn't exist. * * @param string Simple type string * @param string Internal pool id reserved for given string * @param integer String length if calculated in a cache or null otherwise * @return string String reference or null if string was invalid */ public static function & getIntern(& $string, & $internId, & $length = null) { if(!$length) { $length = strlen($string); } // cache only big strings if($string === '' || !isset($string[self::$minStringSize]) || strlen($string) < self::$minStringSize) { $internId = 0; return $string; } $intern = & self::$internPool[$string]; if(isset($intern)) { // variable exists in cache: // increase the 'variable in use' counter by one ++$intern[1]; // set flags, etc $length = $intern[2]; $internId = $intern[3]; return $intern[0]; } else { $internId = self::$internPoolCounter++; self::$internPool[$string] = array(0 => & $string, 1 => 1, 2 => & $length, 3 => $internId); self::$internPoolId[$internId] = & $string; return $string; } } /** * Unsets internal pool entity or decreases it's counter by one if variable is still in use by other instances. * * @param String intern */ public static function unsetIntern($internId) { // is PHP shutting down? if it is, then avoid unnecesary cleaning, PHP will do it automatically if($internId === 0) { return; } $id = $internId; $intern = & self::$internPool[self::$internPoolId[$internId]]; if(isset($intern)) { --$intern[1]; if($intern[1] === 0) { unset(self::$internPool[self::$internPoolId[$internId]]); unset(self::$internPoolId[$internId]); } } } /** * Initialises LOTOS Variables Manager. * @access public * @static * @param integer Minimal variable size needed to put it in cache * @return void */ public static function init(& $minStringSize = 2) { self::$minStringSize = & $minStringSize; if(self::$initFinished) { return null; } self::$initFinished = true; return new self(); } /** * LOTOS VM constructor. * * @return void */ private function __construct() { } /** * LOTOS VM destructor (not used). * * @return void */ public function __destruct() { } /** * Returns LOTOS VM statistics. * * @return mixed[] Array containing VM statistics. */ public function getPoolUsage() { $len = 0; $shared = 0; $real = 0; $count = 0; foreach(self::$internPool as $var) { $len = strlen($var[0]); $real += $len; $shared += $len * $var[1]; $count += $var[1]; } $segments = count(self::$internPool); $ret = array('count' => $count, 'segments' => $segments, 'ratio' => ($segments > 0 ? ($count / $segments) * 100 : 0), 'memory' => array('real' => $real, 'shared' => $shared, 'ratio' => $real > 0 ? ($shared/$real) * 100 : 0)); return $ret; } } /** * AutoBoxedObject * * Every class needs to inherit this class in order to use PHP autoboxing. * @author Artur Graniszewski */ abstract class AutoBoxedObject { /** * C-like variable pointer. * * @var mixed */ protected $ref; /** * Internal ID used by caching mechanism (but not used frequently). * * @var int */ protected $internId; /** * Public constructor * * @return AutoBoxedObject */ public function __construct() { } /** * Destructor used to datatype enforcing and final cleanups. * * @return void */ public function __destruct() { if($this->ref === null) { return; } if(VariablesManager::$memory[$this->ref] instanceof self) { 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); } } /** * Sets C-like pointer for this object. * * @param mixed $name */ public function setPointer($name) { $this->ref = $name; } /** * Returns internal ID of this object. * * @return mixed */ public function getIntern() { return $this->internId; } /** * Returns string representation of this object. * * @return string */ public function toString() { return $this->__toString(); } } 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; } // Lotos VM auto init (taken from the Lotos frameworks' autostart and executed manually below) VariablesManager::init(); // --------------------------------------------------------------------------- // 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 />";
Output for 5.3.4 - 5.6.28
13 => 0x0D<br />24.24 => 24<br />Exception catched: The new value is not a boolean type!!! (code: 0)<br />Exception catched: Cannot cast String data type to Number! (code: 0)<br />3.33 => 3.33<br />
Output for 5.3.0 - 5.3.3
Strict Standards: Declaration of PrimitiveTypeWrapper::toString() should be compatible with that of AutoBoxedObject::toString() in /in/mqtub on line 356 13 => 0x0D<br />24.24 => 24<br />Exception catched: The new value is not a boolean type!!! (code: 0)<br />Exception catched: Cannot cast String data type to Number! (code: 0)<br />3.33 => 3.33<br />
Output for 5.2.0 - 5.2.17
Strict Standards: Declaration of PrimitiveTypeWrapper::toString() should be compatible with that of AutoBoxedObject::toString() in /in/mqtub on line 356 13 => 0x0D<br />24.24 => 24<br />Exception catched: The new value is not a boolean type!!! (code: 0)<br /> Strict Standards: is_a(): Deprecated. Please use the instanceof operator in /in/mqtub on line 348 Strict Standards: is_a(): Deprecated. Please use the instanceof operator in /in/mqtub on line 348 Strict Standards: is_a(): Deprecated. Please use the instanceof operator in /in/mqtub on line 348 Exception catched: Cannot cast String data type to Number! (code: 0)<br /> Strict Standards: is_a(): Deprecated. Please use the instanceof operator in /in/mqtub on line 348 Strict Standards: is_a(): Deprecated. Please use the instanceof operator in /in/mqtub on line 348 3.33 => 3.33<br />
Output for 5.0.2 - 5.1.6
Strict Standards: Declaration of PrimitiveTypeWrapper::toString() should be compatible with that of AutoBoxedObject::toString() in /in/mqtub on line 356 Object id #2 => 0x01<br />Object id #3 => Object id #1<br />Exception catched: The new value is not a boolean type!!! (code: 0)<br /> Strict Standards: is_a(): Deprecated. Please use the instanceof operator in /in/mqtub on line 348 Strict Standards: is_a(): Deprecated. Please use the instanceof operator in /in/mqtub on line 348 Strict Standards: is_a(): Deprecated. Please use the instanceof operator in /in/mqtub on line 348 Exception catched: Cannot cast String data type to Number! (code: 0)<br /> Strict Standards: is_a(): Deprecated. Please use the instanceof operator in /in/mqtub on line 348 Strict Standards: is_a(): Deprecated. Please use the instanceof operator in /in/mqtub on line 348 Object id #6 => Object id #4<br />
Output for 5.0.0 - 5.0.1
Strict Standards: Declaration of PrimitiveTypeWrapper::toString() should be compatible with that of AutoBoxedObject::toString() in /in/mqtub on line 356 Object id #2 => 0x01<br />Object id #3 => Object id #1<br /> Strict Standards: is_a(): Deprecated. Please use the instanceof operator in /in/mqtub on line 348 Strict Standards: is_a(): Deprecated. Please use the instanceof operator in /in/mqtub on line 348 Strict Standards: is_a(): Deprecated. Please use the instanceof operator in /in/mqtub on line 348 Strict Standards: is_a(): Deprecated. Please use the instanceof operator in /in/mqtub on line 348 Strict Standards: is_a(): Deprecated. Please use the instanceof operator in /in/mqtub on line 348 Object id #6 => Object id #4<br />
Output for 4.4.2 - 4.4.9
Parse error: syntax error, unexpected T_CLASS in /in/mqtub on line 16
Process exited with code 255.
Output for 4.3.0 - 4.3.1, 4.3.5 - 4.4.1
Parse error: parse error, unexpected T_CLASS in /in/mqtub on line 16
Process exited with code 255.
Output for 4.3.2 - 4.3.4
Parse error: parse error in /in/mqtub on line 16
Process exited with code 255.