f0539e10fc0f0130a222cae198b9ca370f48f295
[core.git] / inc / classes / main / stacker / file / class_BaseFileStack.php
1 <?php
2 /**
3  * A general file-based stack class
4  *
5  * @author              Roland Haeder <webmaster@ship-simu.org>
6  * @version             0.0.0
7  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2013 Core Developer Team
8  * @license             GNU GPL 3.0 or any newer version
9  * @link                http://www.ship-simu.org
10  *
11  * This program is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23  */
24 class BaseFileStack extends BaseStacker {
25         /**
26          * Magic for this stack
27          */
28         const STACK_MAGIC = 'STACKv0.1';
29
30         /**
31          * Separator magic->count
32          */
33         const SEPARATOR_MAGIC_COUNT = 0x00;
34
35         /**
36          * Separator position->entries
37          */
38         const SEPARATOR_SEEK_POS_ENTRIES = 0xff;
39
40         /**
41          * Separator hash->name
42          */
43         const SEPARATOR_HASH_NAME = 0x05;
44
45         /**
46          * Protected constructor
47          *
48          * @param       $className      Name of the class
49          * @return      void
50          */
51         protected function __construct ($className) {
52                 // Call parent constructor
53                 parent::__construct($className);
54         }
55
56         /**
57          * Checks whether the file header is initialized
58          *
59          * @return      $isInitialized  Whether the file header is initialized
60          */
61         private function isFileHeaderInitialized () {
62                 // Default is not initialized
63                 $isInitialized = FALSE;
64
65                 // Is the file initialized?
66                 if ($this->isFileInitialized()) {
67                         // Some bytes has been written, so rewind to start of it.
68                         $this->getIteratorInstance()->rewind();
69
70                         // Read file header
71                         $this->readFileHeader();
72                 } // END - if
73
74                 // Return result
75                 return $isInitialized;
76         }
77
78         /**
79          * Checks whether the file-based stack has been initialized
80          *
81          * @return      $isInitialized          Whether the file's size is zero
82          */
83         private function isFileInitialized () {
84                 // Default is not initialized
85                 $isInitialized = FALSE;
86
87                 // Get it from iterator which holds the pointer instance. If FALSE is returned
88                 $fileSize = $this->getIteratorInstance()->size();
89
90                 /*
91                  * The returned file size should not be FALSE or NULL as this means
92                  * that the pointer class does not work correctly.
93                  */
94                 assert(is_int($fileSize));
95
96                 // Is more than 0 returned?
97                 if ($fileSize > 0) {
98                         // So is the header written?
99                         $isInitialized = $this->getIteratorInstance()->isHeaderInitialized();
100                 } // END - if
101
102                 // Return result
103                 return $isInitialized;
104         }
105
106         /**
107          * Initializes this file-based stack.
108          *
109          * @param       $fileName       File name of this stack
110          * @return      void
111          */
112         protected function initFileStack ($fileName) {
113                 // Get a file i/o pointer instance
114                 $pointerInstance = ObjectFactory::createObjectByConfiguredName('file_raw_input_output_class', array($fileName));
115
116                 // Get iterator instance
117                 $iteratorInstance = ObjectFactory::createObjectByConfiguredName('file_io_iterator_class', array($pointerInstance));
118
119                 // Is the instance implementing the right interface?
120                 assert($iteratorInstance instanceof SeekableWritableFileIterator);
121
122                 // Set iterator here
123                 $this->setIteratorInstance($iteratorInstance);
124
125                 // Is the file's header initialized?
126                 if ($this->isFileHeaderInitialized()) {
127                         // Then load it
128                         $this->loadFileHeader();
129                 } else {
130                         // No, then create it (which may pre-allocate the stack)
131                         $this->createFileHeader();
132                 }
133         }
134
135         /**
136          * Initializes given stacker
137          *
138          * @param       $stackerName    Name of the stack
139          * @param       $forceReInit    Force re-initialization
140          * @return      void
141          * @throws      AlreadyInitializedStackerException      If the stack is already initialized
142          */
143         public function initStack ($stackerName, $forceReInit = FALSE) {
144                 // Is the stack already initialized?
145                 if (($forceReInit === FALSE) && ($this->isStackInitialized($stackerName))) {
146                         // Then throw the exception
147                         throw new AlreadyInitializedStackerException(array($this, $stackerName, $forceReInit), self::EXCEPTION_STACKER_ALREADY_INITIALIZED);
148                 } // END - if
149
150                 // Initialize the given stack
151                 $this->partialStub('stackerName=' . $stackerName . ',forceReInit=' . intval($forceReInit));
152         }
153
154         /**
155          * Checks whether the given stack is initialized (set in array $stackers)
156          *
157          * @param       $stackerName    Name of the stack
158          * @return      $isInitialized  Whether the stack is initialized
159          */
160         public function isStackInitialized ($stackerName) {
161                 // Is is there?
162                 $this->partialStub('stackerName=' . $stackerName);
163                 $isInitialized = TRUE;
164
165                 // Return result
166                 return $isInitialized;
167         }
168
169         /**
170          * Getter for size of given stack (array count)
171          *
172          * @param       $stackerName    Name of the stack
173          * @return      $count                  Size of stack (array count)
174          * @throws      NoStackerException      If given stack is missing
175          */
176         public function getStackCount ($stackerName) {
177                 // Is the stack not yet initialized?
178                 if (!$this->isStackInitialized($stackerName)) {
179                         // Throw an exception
180                         throw new NoStackerException(array($this, $stackerName), self::EXCEPTION_NO_STACKER_FOUND);
181                 } // END - if
182
183                 // Now, count the array of entries
184                 $this->partialStub('stackerName=' . $stackerName);
185                 $count = 0;
186
187                 // Return result
188                 return $count;
189         }
190
191         /**
192          * Adds a value to given stack
193          *
194          * @param       $stackerName    Name of the stack
195          * @param       $value                  Value to add to this stacker
196          * @return      void
197          * @throws      FullStackerException    Thrown if the stack is full
198          */
199         protected function addValue ($stackerName, $value) {
200                 // Is the stack not yet initialized or full?
201                 if (!$this->isStackInitialized($stackerName)) {
202                         // Then do it here
203                         $this->initStack($stackerName);
204                 } elseif ($this->isStackFull($stackerName)) {
205                         // Stacker is full
206                         throw new FullStackerException(array($this, $stackerName, $value), self::EXCEPTION_STACKER_IS_FULL);
207                 }
208
209                 // Now add the value to the stack
210                 $this->partialStub('stackerName=' . $stackerName . ',value[]=' . gettype($value));
211         }
212
213         /**
214          * Get last value from named stacker
215          *
216          * @param       $stackerName    Name of the stack
217          * @return      $value                  Value of last added value
218          * @throws      NoStackerException      If the named stacker was not found
219          * @throws      EmptyStackerException   If the named stacker is empty
220          */
221         protected function getLastValue ($stackerName) {
222                 // Is the stack not yet initialized or full?
223                 if (!$this->isStackInitialized($stackerName)) {
224                         // Throw an exception
225                         throw new NoStackerException(array($this, $stackerName), self::EXCEPTION_NO_STACKER_FOUND);
226                 } elseif ($this->isStackEmpty($stackerName)) {
227                         // Throw an exception
228                         throw new EmptyStackerException(array($this, $stackerName), self::EXCEPTION_STACKER_IS_EMPTY);
229                 }
230
231                 // Now get the last value
232                 $this->partialStub('stackerName=' . $stackerName);
233                 $value = NULL;
234
235                 // Return it
236                 return $value;
237         }
238
239         /**
240          * Get first value from named stacker
241          *
242          * @param       $stackerName    Name of the stack
243          * @return      $value                  Value of last added value
244          * @throws      NoStackerException      If the named stacker was not found
245          * @throws      EmptyStackerException   If the named stacker is empty
246          */
247         protected function getFirstValue ($stackerName) {
248                 // Is the stack not yet initialized or full?
249                 if (!$this->isStackInitialized($stackerName)) {
250                         // Throw an exception
251                         throw new NoStackerException(array($this, $stackerName), self::EXCEPTION_NO_STACKER_FOUND);
252                 } elseif ($this->isStackEmpty($stackerName)) {
253                         // Throw an exception
254                         throw new EmptyStackerException(array($this, $stackerName), self::EXCEPTION_STACKER_IS_EMPTY);
255                 }
256
257                 // Now get the first value
258                 $this->partialStub('stackerName=' . $stackerName);
259                 $value = NULL;
260
261                 // Return it
262                 return $value;
263         }
264
265         /**
266          * "Pops" last entry from stack
267          *
268          * @param       $stackerName    Name of the stack
269          * @return      $value                  Value "poped" from array
270          * @throws      NoStackerException      If the named stacker was not found
271          * @throws      EmptyStackerException   If the named stacker is empty
272          */
273         protected function popLast ($stackerName) {
274                 // Is the stack not yet initialized or full?
275                 if (!$this->isStackInitialized($stackerName)) {
276                         // Throw an exception
277                         throw new NoStackerException(array($this, $stackerName), self::EXCEPTION_NO_STACKER_FOUND);
278                 } elseif ($this->isStackEmpty($stackerName)) {
279                         // Throw an exception
280                         throw new EmptyStackerException(array($this, $stackerName), self::EXCEPTION_STACKER_IS_EMPTY);
281                 }
282
283                 // Now, remove the last entry, we don't care about the return value here, see elseif() block above
284                 $this->partialStub('stackerName=' . $stackerName);
285                 return NULL;
286         }
287
288         /**
289          * "Pops" first entry from stack
290          *
291          * @param       $stackerName    Name of the stack
292          * @return      $value                  Value "shifted" from array
293          * @throws      NoStackerException      If the named stacker was not found
294          * @throws      EmptyStackerException   If the named stacker is empty
295          */
296         protected function popFirst ($stackerName) {
297                 // Is the stack not yet initialized or full?
298                 if (!$this->isStackInitialized($stackerName)) {
299                         // Throw an exception
300                         throw new NoStackerException(array($this, $stackerName), self::EXCEPTION_NO_STACKER_FOUND);
301                 } elseif ($this->isStackEmpty($stackerName)) {
302                         // Throw an exception
303                         throw new EmptyStackerException(array($this, $stackerName), self::EXCEPTION_STACKER_IS_EMPTY);
304                 }
305
306                 // Now, remove the last entry, we don't care about the return value here, see elseif() block above
307                 $this->partialStub('stackerName=' . $stackerName);
308                 return NULL;
309         }
310 }
311
312 // [EOF]
313 ?>