]> git.mxchange.org Git - friendica.git/blob - src/Util/ReversedFileReader.php
Fix code formatting
[friendica.git] / src / Util / ReversedFileReader.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2021, Friendica
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as
9  * published by the Free Software Foundation, either version 3 of the
10  * License, or (at your option) any later version.
11  *
12  * This program 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 Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  *
20  */
21
22 namespace Friendica\Util;
23
24 /**
25  * An iterator which returns lines from file in reversed order
26  *
27  * original code https://stackoverflow.com/a/10494801
28  */
29 class ReversedFileReader implements \Iterator
30 {
31         const BUFFER_SIZE = 4096;
32         const SEPARATOR   = "\n";
33
34         /** @var int */
35         private $filesize;
36
37         /** @var int */
38         private $pos;
39
40         /** @var array */
41         private $buffer;
42
43         /** @var int */
44         private $key;
45
46         /** @var string */
47         private $value;
48
49         public function __construct($filename)
50         {
51                 $this->_fh = fopen($filename, 'r');
52                 if (!$this->_fh) {
53                         // this should use a custom exception.
54                         throw \Exception("Unable to open $filename");
55                 }
56                 $this->filesize = filesize($filename);
57                 $this->pos      = -1;
58                 $this->buffer   = null;
59                 $this->key      = -1;
60                 $this->value    = null;
61         }
62
63         public function _read($size)
64         {
65                 $this->pos -= $size;
66                 fseek($this->_fh, $this->pos);
67                 return fread($this->_fh, $size);
68         }
69
70         public function _readline()
71         {
72                 $buffer = & $this->buffer;
73                 while (true) {
74                         if ($this->pos == 0) {
75                                 return array_pop($buffer);
76                         }
77                         if (count($buffer) > 1) {
78                                 return array_pop($buffer);
79                         }
80                         $buffer = explode(self::SEPARATOR, $this->_read(self::BUFFER_SIZE) . $buffer[0]);
81                 }
82         }
83
84         public function next()
85         {
86                 ++$this->key;
87                 $this->value = $this->_readline();
88         }
89
90         public function rewind()
91         {
92                 if ($this->filesize > 0) {
93                         $this->pos    = $this->filesize;
94                         $this->value  = null;
95                         $this->key    = -1;
96                         $this->buffer = explode(self::SEPARATOR, $this->_read($this->filesize % self::BUFFER_SIZE ?: self::BUFFER_SIZE));
97                         $this->next();
98                 }
99         }
100
101         public function key()
102         {
103                 return $this->key;
104         }
105
106         public function current()
107         {
108                 return $this->value;
109         }
110
111         public function valid()
112         {
113                 return ! is_null($this->value);
114         }
115 }