If the EOF is reached (means no block found or really reached the last block),
[core.git] / inc / classes / main / iterator / io / class_FileIoIterator.php
index 171c6777f66f00b314b70c529af2753ca9c3b9fb..20d351f5e694d09b43376e8d1badc8b6f7368dfa 100644 (file)
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 class FileIoIterator extends BaseIterator implements SeekableWritableFileIterator {
+       /**
+        * Back-buffer
+        */
+       private $backBuffer = '';
+
+       /**
+        * Currently loaded block (will be returned by current())
+        */
+       private $currentBlock = '';
+
        /**
         * Protected constructor
         *
@@ -36,32 +46,78 @@ class FileIoIterator extends BaseIterator implements SeekableWritableFileIterato
         * Creates an instance of this class
         *
         * @param       $pointerInstance        An instance of a InputOutputPointer class
+        * @param       $blockInstance          An instance of a CalculatableBlock class
         * @return      $iteratorInstance       An instance of a Iterator class
         */
-       public final static function createFileIoIterator (InputOutputPointer $pointerInstance) {
+       public final static function createFileIoIterator (InputOutputPointer $pointerInstance, CalculatableBlock $blockInstance) {
                // Get new instance
                $iteratorInstance = new FileIoIterator();
 
                // Set the instance here
                $iteratorInstance->setPointerInstance($pointerInstance);
 
+               // Set the block instance here
+               $iteratorInstance->setBlockInstance($blockInstance);
+
                // Return the prepared instance
                return $iteratorInstance;
        }
 
+       /**
+        * Initializes the back-buffer by setting it to an empty string.
+        *
+        * @return      void
+        */
+       private function initBackBuffer () {
+               // Simply call the setter
+               $this->setBackBuffer('');
+       }
+
+       /**
+        * Setter for backBuffer field
+        *
+        * @param       $backBuffer             Characters to "store" in back-buffer
+        * @return      void
+        */
+       private function setBackBuffer ($backBuffer) {
+               // Cast to string (so no arrays or objects)
+               $backBuffer = (string) $backBuffer;
+
+               // ... and set it
+               $this->backBuffer = $backBuffer;
+       }
+
+       /**
+        * Getter for backBuffer field
+        *
+        * @return      $backBuffer             Characters "stored" in back-buffer
+        */
+       private function getBackBuffer () {
+               return $this->backBuffer;
+       }
+
+       /**
+        * Setter for currentBlock field
+        *
+        * @param       $currentBlock           Characters to set a currently loaded block
+        * @return      void
+        */
+       private function setCurrentBlock ($currentBlock) {
+               // Cast to string (so no arrays or objects)
+               $currentBlock = (string) $currentBlock;
+
+               // ... and set it
+               $this->currentBlock = $currentBlock;
+       }
+
        /**
         * Gets currently read data
         *
         * @return      $current        Currently read data
         */
        public function current () {
-               // Default is null
-               $current = null;
-
-               $this->partialStub('Please implement this method.');
-
                // Return it
-               return $current;
+               return $this->currentBlock;
        }
 
        /**
@@ -80,7 +136,53 @@ class FileIoIterator extends BaseIterator implements SeekableWritableFileIterato
         * @return      void
         */
        public function next () {
-               $this->partialStub('Please implement this method.');
+               // Is there nothing to read?
+               if (!$this->valid()) {
+                       // Nothing to read
+                       return;
+               } // END - if
+
+               // First calculate minimum block length
+               $length = $this->getBlockInstance()->caluclateMinimumBlockLength();
+
+               // Short be more than zero!
+               assert($length > 0);
+
+               // Wait until a entry/block separator has been found
+               $data = $this->getBackBuffer();
+               while ((!$this->getPointerInstance()->isEndOfFileReached()) && (!$this->getBlockInstance()->isBlockSeparatorFound($data))) {
+                       // Then read the block
+                       $data .= $this->read($length);
+                       //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('data()=' . strlen($data));
+               } // END - if
+
+               // EOF reached?
+               if ($this->getPointerInstance()->isEndOfFileReached()) {
+                       // Set whole data as current block
+                       //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('Calling setCurrentBlock(' . strlen($data) . ') ...');
+                       $this->setCurrentBlock($data);
+
+                       // Then abort here silently
+                       //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('EOF reached.');
+                       return;
+               } // END - if
+
+               /*
+                * Init back-buffer which is the data that has been found beyond the
+                * separator.
+                */
+               $this->initBackBuffer();
+
+               // Separate data
+               $dataArray = explode(self::getBlockSeparator(), $data);
+
+               // This array must contain two elements
+               //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('dataArray=' . print_r($dataArray, TRUE));
+               assert(count($dataArray) == 2);
+
+               // Left part is the actual block, right one the back-buffer data
+               $this->setCurrentBlock($dataArray[0]);
+               $this->setBackBuffer($dataArray[1]);
        }
 
        /**
@@ -97,11 +199,38 @@ class FileIoIterator extends BaseIterator implements SeekableWritableFileIterato
         * Checks wether the current entry is valid (not at the end of the file).
         * This method will return TRUE if an emptied (nulled) entry has been found.
         *
-        * @return      void
+        * @return      $isValid        Whether the next entry is valid
         */
        public function valid () {
-               // Call pointer instance
-               return $this->getPointerInstance()->valid();
+               // First calculate minimum block length
+               $length = $this->getBlockInstance()->caluclateMinimumBlockLength();
+
+               // Short be more than zero!
+               assert($length > 0);
+
+               // Get current seek position
+               $seekPosition = $this->key();
+
+               // Then try to read it
+               $data = $this->read($length);
+
+               // If some bytes could be read, all is fine
+               $isValid = ((is_string($data)) && (strlen($data) > 0));
+
+               // Get header size
+               $headerSize = $this->getBlockInstance()->getHeaderSize();
+
+               // Is the seek position at or beyond the header?
+               if ($seekPosition >= $headerSize) {
+                       // Seek back to old position
+                       $this->seek($seekPosition);
+               } else {
+                       // Seek directly behind the header
+                       $this->seek($headerSize);
+               }
+
+               // Return result
+               return $isValid;
        }
 
        /**