PageRenderTime 49ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/src/type/varbase.php

https://github.com/php-tox/tox
PHP | 228 lines | 96 code | 17 blank | 115 comment | 15 complexity | 4d1596ccaf3e9b4359124de90a26a7b6 MD5 | raw file
Possible License(s): GPL-3.0
  1. <?php
  2. /**
  3. * Defines the runtime variables manager.
  4. *
  5. * This file is part of Tox.
  6. *
  7. * Tox is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * Tox is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with Tox. If not, see <http://www.gnu.org/licenses/>.
  19. *
  20. * @copyright Š 2012-2013 PHP-Tox.org
  21. * @license GNU General Public License, version 3
  22. */
  23. namespace Tox\Type;
  24. use Tox\Core;
  25. /**
  26. * Represents as the runtime variables manager.
  27. *
  28. * **WARNING: THIS CLASS IS DESIGNED TO MAINTAIN BOXABLE OBJECTS. DO NOT DO
  29. * ANYTHING TO CHANGE IT UNLESS YOU ARE VERY SURE ABOUT YOUR PURPOSES AND ITS
  30. * MECHANISM.**
  31. *
  32. * @package tox.type
  33. * @author Artur Graniszewski <aargoth@boo.pl>
  34. * @author Snakevil Zen <zsnakevil@gmail.com>
  35. * @since 0.2.0
  36. */
  37. class Varbase extends Core\Assembly implements IVarbase
  38. {
  39. /**
  40. * Stores the only instance.
  41. *
  42. * @var self
  43. */
  44. protected static $instance;
  45. /**
  46. * Stores the maintained variables.
  47. *
  48. * @var IBoxable[]
  49. */
  50. protected $vars;
  51. /**
  52. * Stores the boxable types of variables.
  53. *
  54. * @var string[]
  55. */
  56. protected $types;
  57. /**
  58. * Stores the seed to generate reference IDs.
  59. *
  60. * @var string
  61. */
  62. protected $seed;
  63. /**
  64. * Stores the stacking reference ID to feed out.
  65. *
  66. * @var string
  67. */
  68. protected $feed;
  69. /**
  70. * CONSTRUCT FUNCTION
  71. */
  72. protected function __construct()
  73. {
  74. $this->vars =
  75. $this->types = array();
  76. $this->seed = microtime();
  77. $this->feed = '';
  78. }
  79. /**
  80. * {@inheritdoc}
  81. *
  82. * @param IBoxable $var Boxable object to be maintained.
  83. * @return IBoxable
  84. */
  85. public static function & tee(IBoxable $var)
  86. {
  87. if (!self::$instance instanceof self) {
  88. self::$instance = new static;
  89. }
  90. $s_ref = $var->setRef(self::$instance);
  91. self::$instance->vars[$s_ref] = $var;
  92. self::$instance->types[$s_ref] = get_class($var);
  93. return self::$instance->vars[$s_ref];
  94. }
  95. /**
  96. * {@inheritdoc}
  97. *
  98. * NOTICE: This method would not work well until the boxed objects have
  99. * already been `unset()`.
  100. *
  101. * $o_var = & String::box('foo');
  102. * unset($o_var);
  103. * Varbase::gc();
  104. *
  105. * @return void
  106. */
  107. public static function gc()
  108. {
  109. if (!self::$instance instanceof self) {
  110. return;
  111. }
  112. $a_list = array();
  113. reset(self::$instance->vars);
  114. while (list($s_ref, ) = each(self::$instance->vars)) {
  115. ob_start();
  116. debug_zval_dump(self::$instance->vars[$s_ref]);
  117. $s_dump = ob_get_clean();
  118. if (preg_match('@\) refcount\((\d+)\)\{\n@', $s_dump, $a_matches)) {
  119. $i_refs = (int) $a_matches[1];
  120. } else {
  121. $i_refs = 2;
  122. }
  123. if (2 == $i_refs) {
  124. $a_list[] = $s_ref;
  125. }
  126. }
  127. for ($ii=0, $jj = count($a_list); $ii < $jj; $ii++) {
  128. unset(self::$instance->vars[$a_list[$ii]]);
  129. }
  130. }
  131. /**
  132. * {@inheritdoc}
  133. *
  134. * @return string
  135. */
  136. public function feedRef()
  137. {
  138. if (strlen($this->feed)) {
  139. $s_ref = $this->feed;
  140. $this->feed = '';
  141. } else {
  142. do {
  143. $s_ref = sha1(microtime() . $this->seed);
  144. } while ($this->offsetExists($s_ref));
  145. }
  146. return $s_ref;
  147. }
  148. /**
  149. * Be invoked on checking the existance of a variable.
  150. *
  151. * @param string $ref Reference ID of that variable.
  152. * @return bool
  153. */
  154. public function offsetExists($ref)
  155. {
  156. return array_key_exists((string) $ref, $this->vars);
  157. }
  158. /**
  159. * Be invoked on retrieving a variable.
  160. *
  161. * @param string $ref Reference ID of that variable.
  162. * @return IBoxable|null
  163. */
  164. public function offsetGet($ref)
  165. {
  166. if (!$this->offsetExists($ref)) {
  167. return null;
  168. }
  169. return $this->vars[(string) $ref];
  170. }
  171. /**
  172. * Be invoked on reboxing a variable.
  173. *
  174. * @param string $ref Reference ID of that variable.
  175. * @param IBoxable $var New boxed variable.
  176. * @return void
  177. */
  178. public function offsetSet($ref, $var)
  179. {
  180. $ref = (string) $ref;
  181. if (!$this->offsetExists($ref) ||
  182. !$var instanceof IBoxable ||
  183. get_class($var) != $this->types[$ref] ||
  184. $var->getValue() != $this->offsetGet($ref)
  185. ) {
  186. throw new VarbaseUnderAttackException;
  187. }
  188. $this->feed = $ref;
  189. $var->setRef($this);
  190. $this->vars[$ref] = $var;
  191. }
  192. /**
  193. * Be invoked on garbage collecting a variable.
  194. *
  195. * @param string $ref Reference ID of that variable.
  196. * @return void
  197. */
  198. public function offsetUnset($ref)
  199. {
  200. }
  201. /**
  202. * Retrieves the amount of maintained variables.
  203. *
  204. * @return int
  205. */
  206. public function count()
  207. {
  208. return count($this->vars);
  209. }
  210. }
  211. // vi:ft=php fenc=utf-8 ff=unix ts=4 sts=4 et sw=4 fen fdm=indent fdl=1 tw=120