Annotation of embedaddon/php/ext/spl/tests/bug65328.phpt, revision 1.1
1.1 ! misho 1: --TEST--
! 2: Bug #65328 (Segfault when getting SplStack object Value)
! 3: --FILE--
! 4: <?php
! 5: /**
! 6: * @author AlexanderC
! 7: */
! 8:
! 9: class Tree
! 10: {
! 11: /**
! 12: * @var Node
! 13: */
! 14: protected $head;
! 15:
! 16: /**
! 17: * @param Node $head
! 18: */
! 19: public function __construct(Node $head = null)
! 20: {
! 21: $this->head = $head ? : new Node('HEAD');
! 22: }
! 23:
! 24: /**
! 25: * @return Node
! 26: */
! 27: public function getHead()
! 28: {
! 29: return $this->head;
! 30: }
! 31:
! 32: /**
! 33: * @param mixed $uid
! 34: * @return Node|bool
! 35: */
! 36: public function find($uid)
! 37: {
! 38: $iterator = $this->getIterator();
! 39:
! 40: /** @var Node $node */
! 41: foreach($iterator as $node) {
! 42: if($node->getUid() === $uid) {
! 43: return $node;
! 44: }
! 45: }
! 46:
! 47: return false;
! 48: }
! 49:
! 50: /**
! 51: * @param mixed $uid
! 52: * @return \SplStack
! 53: */
! 54: public function & findAll($uid)
! 55: {
! 56: $result = new \SplStack();
! 57:
! 58: /** @var Node $node */
! 59: foreach($this->getIterator() as $node) {
! 60: if($node->getUid() == $uid) {
! 61: $result->push($node);
! 62: }
! 63: }
! 64:
! 65: return $result;
! 66: }
! 67:
! 68: /**
! 69: * @return \RecursiveIteratorIterator
! 70: */
! 71: public function getIterator()
! 72: {
! 73: return new \RecursiveIteratorIterator(
! 74: $this->head->getChildren(),
! 75: \RecursiveIteratorIterator::SELF_FIRST
! 76: );
! 77: }
! 78: }
! 79:
! 80: class Node extends \RecursiveArrayIterator implements \Countable
! 81: {
! 82: /**
! 83: * @var array
! 84: */
! 85: protected $children = [];
! 86:
! 87: /**
! 88: * @var Node
! 89: */
! 90: protected $parent;
! 91:
! 92: /**
! 93: * @var mixed
! 94: */
! 95: protected $data;
! 96:
! 97: /**
! 98: * @var mixed
! 99: */
! 100: protected $uid;
! 101:
! 102: /**
! 103: * @var int
! 104: */
! 105: protected $index = 0;
! 106:
! 107: /**
! 108: * @var bool
! 109: */
! 110: protected $assureUnique;
! 111:
! 112: /**
! 113: * @param mixed $data
! 114: * @param mixed $uid
! 115: * @param Node $parent
! 116: * @param bool $assureUnique
! 117: */
! 118: public function __construct($data, $uid = null, Node $parent = null, $assureUnique = false)
! 119: {
! 120: if(null !== $parent) {
! 121: $this->parent = $parent;
! 122: }
! 123:
! 124: $this->data = $data;
! 125: $this->uid = $uid ? : uniqid(sha1(serialize($data)), true);
! 126: $this->assureUnique = $assureUnique;
! 127: }
! 128:
! 129: /**
! 130: * @param mixed $uid
! 131: */
! 132: public function setUid($uid)
! 133: {
! 134: $this->uid = $uid;
! 135: }
! 136:
! 137: /**
! 138: * @return mixed
! 139: */
! 140: public function getUid()
! 141: {
! 142: return $this->uid;
! 143: }
! 144:
! 145: /**
! 146: * @param Node $child
! 147: */
! 148: public function addChild(Node $child)
! 149: {
! 150: $child->setParent($this);
! 151: $this->children[] = $child;
! 152: }
! 153:
! 154: /**
! 155: * @param array $children
! 156: */
! 157: public function setChildren(array $children)
! 158: {
! 159: $this->children = $children;
! 160: }
! 161:
! 162: /**
! 163: * @return array
! 164: */
! 165: public function getChildrenArray()
! 166: {
! 167: return $this->children;
! 168: }
! 169:
! 170: /**
! 171: * @param mixed $data
! 172: */
! 173: public function setData($data)
! 174: {
! 175: $this->data = $data;
! 176: }
! 177:
! 178: /**
! 179: * @return mixed
! 180: */
! 181: public function getData()
! 182: {
! 183: return $this->data;
! 184: }
! 185:
! 186: /**
! 187: * @param Node $parent
! 188: * @throws \RuntimeException
! 189: */
! 190: public function setParent(Node $parent)
! 191: {
! 192: if(true === $this->assureUnique && !self::checkUnique($parent, $this->uid)) {
! 193: throw new \RuntimeException("Node uid is not unique in assigned node tree");
! 194: }
! 195:
! 196: $this->parent = $parent;
! 197: }
! 198:
! 199: /**
! 200: * @param Node $node
! 201: * @param mixed $uid
! 202: * @return bool
! 203: */
! 204: protected static function checkUnique(Node $node, $uid)
! 205: {
! 206: $headNode = $node;
! 207: do {
! 208: $headNode = $node;
! 209: } while($node = $node->getParent());
! 210:
! 211: $tree = new Tree($headNode);
! 212:
! 213: return !$tree->find($uid);
! 214: }
! 215:
! 216: /**
! 217: * @return \IJsonRPC\Helpers\Tree\Node
! 218: */
! 219: public function getParent()
! 220: {
! 221: return $this->parent;
! 222: }
! 223:
! 224: /**
! 225: * @return Node
! 226: */
! 227: public function current()
! 228: {
! 229: return $this->children[$this->index];
! 230: }
! 231:
! 232: /**
! 233: * @return scalar
! 234: */
! 235: public function key()
! 236: {
! 237: return $this->index;
! 238: }
! 239:
! 240: /**
! 241: * @return void
! 242: */
! 243: public function next()
! 244: {
! 245: ++$this->index;
! 246: }
! 247:
! 248: /**
! 249: * @return void
! 250: */
! 251: public function rewind()
! 252: {
! 253: $this->index = 0;
! 254: }
! 255:
! 256: /**
! 257: * @return bool
! 258: */
! 259: public function valid()
! 260: {
! 261: return array_key_exists($this->index, $this->children);
! 262: }
! 263:
! 264: /**
! 265: * @return int
! 266: */
! 267: public function count()
! 268: {
! 269: return count($this->children);
! 270: }
! 271:
! 272: /**
! 273: * @return bool
! 274: */
! 275: public function hasChildren()
! 276: {
! 277: return !empty($this->children);
! 278: }
! 279:
! 280: /**
! 281: * @return \RecursiveArrayIterator
! 282: */
! 283: public function getChildren()
! 284: {
! 285: return new \RecursiveArrayIterator($this->children);
! 286: }
! 287: }
! 288:
! 289: $tree = new Tree();
! 290: $node1 = new Node('value1', 1);
! 291: $tree->getHead()->addChild($node1);
! 292: $node2 = new Node('value2', 2);
! 293: $node1->addChild($node2);
! 294:
! 295: print_r($tree->findAll(2)->offsetGet(0));
! 296: --EXPECTF--
! 297: Node Object
! 298: (
! 299: [children:protected] => Array
! 300: (
! 301: )
! 302:
! 303: [parent:protected] => Node Object
! 304: (
! 305: [children:protected] => Array
! 306: (
! 307: [0] => Node Object
! 308: *RECURSION*
! 309: )
! 310:
! 311: [parent:protected] => Node Object
! 312: (
! 313: [children:protected] => Array
! 314: (
! 315: [0] => Node Object
! 316: *RECURSION*
! 317: )
! 318:
! 319: [parent:protected] =>
! 320: [data:protected] => HEAD
! 321: [uid:protected] => %s
! 322: [index:protected] => 0
! 323: [assureUnique:protected] =>
! 324: [storage:ArrayIterator:private] => Array
! 325: (
! 326: )
! 327:
! 328: )
! 329:
! 330: [data:protected] => value1
! 331: [uid:protected] => 1
! 332: [index:protected] => 1
! 333: [assureUnique:protected] =>
! 334: [storage:ArrayIterator:private] => Array
! 335: (
! 336: )
! 337:
! 338: )
! 339:
! 340: [data:protected] => value2
! 341: [uid:protected] => 2
! 342: [index:protected] => 0
! 343: [assureUnique:protected] =>
! 344: [storage:ArrayIterator:private] => Array
! 345: (
! 346: )
! 347:
! 348: )
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>