Add a generic PlArrayIterator.
authorFlorent Bruneau <florent.bruneau@polytechnique.org>
Tue, 19 Aug 2008 20:42:39 +0000 (22:42 +0200)
committerFlorent Bruneau <florent.bruneau@polytechnique.org>
Tue, 19 Aug 2008 20:44:00 +0000 (22:44 +0200)
Signed-off-by: Florent Bruneau <florent.bruneau@polytechnique.org>
classes/plarrayiterator.php [new file with mode: 0644]

diff --git a/classes/plarrayiterator.php b/classes/plarrayiterator.php
new file mode 100644 (file)
index 0000000..d249b8a
--- /dev/null
@@ -0,0 +1,125 @@
+<?php
+/***************************************************************************
+ *  Copyright (C) 2003-2008 Polytechnique.org                              *
+ *  http://opensource.polytechnique.org/                                   *
+ *                                                                         *
+ *  This program is free software; you can redistribute it and/or modify   *
+ *  it under the terms of the GNU General Public License as published by   *
+ *  the Free Software Foundation; either version 2 of the License, or      *
+ *  (at your option) any later version.                                    *
+ *                                                                         *
+ *  This program is distributed in the hope that it will be useful,        *
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ *  GNU General Public License for more details.                           *
+ *                                                                         *
+ *  You should have received a copy of the GNU General Public License      *
+ *  along with this program; if not, write to the Free Software            *
+ *  Foundation, Inc.,                                                      *
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
+ ***************************************************************************/
+
+class PlArrayIterator implements PlIterator
+{
+    private $array;
+    private $depth;
+
+    private $_its = array();
+
+    private $_total;
+    private $_first;
+    private $_last;
+    private $_pos;
+
+    public function __construct(array &$array, $depth = 1)
+    {
+        $this->array  =& $array;
+        $this->depth  = $depth;
+        $this->_total = $this->count($array, $depth - 1);
+        $this->_pos   = 0;
+        $this->_first = false;
+        $this->_last  = false;
+
+        for ($i = 0 ; $i < $depth ; ++$i) {
+            if ($i == 0) {
+                $this->_its[] = $array;
+            } else {
+                $this->_its[] = current($this->_its[$i - 1]);
+            }
+            reset($this->_its[$i]);
+        }
+    }
+
+    private function count(array &$array, $depth)
+    {
+        if ($depth == 0) {
+            return count($array);
+        } else {
+            $sum = 0;
+            foreach ($array as &$item) {
+                $sum += $this->count($item, $depth - 1);
+            }
+            return $sum;
+        }
+    }
+
+    private function nextArray($depth)
+    {
+        if ($depth == 0) {
+            return;
+        }
+        $this->_its[$depth] = next($this->_its[$depth - 1]);
+        if ($this->_its[$depth] === false) {
+            $this->nextArray($depth - 1);
+            if ($this->_its[$depth - 1] === false) {
+                return;
+            }
+            $this->_its[$depth] = current($this->_its[$depth - 1]);
+        }
+        reset($this->_its[$depth]);
+    }
+
+    public function next()
+    {
+        ++$this->_pos;
+        $this->_first = ($this->_total > 0 && $this->_pos == 1);
+        $this->_last  = ($this->_pos == $this->_total);
+        if ($this->_pos > $this->_total) {
+            return null;
+        }
+
+        $val = current($this->_its[$this->depth - 1]);
+        if ($val === false) {
+            $this->nextArray($this->depth - 1);
+            $val = current($this->_its[$this->depth - 1]);
+            if ($val === false) {
+                return null;
+            }
+        }
+        $keys = array();
+        for ($i = 0 ; $i < $this->depth ; ++$i) {
+            $keys[] = key($this->_its[$i]);
+        }
+        next($this->_its[$this->depth - 1]);
+        return array('keys'  => $keys,
+                     'value' => $val);
+    }
+
+    public function total()
+    {
+        return $this->_total;
+    }
+
+    public function first()
+    {
+        return $this->_first;
+    }
+
+    public function last()
+    {
+        return $this->_last;
+    }
+}
+
+// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
+?>