Add stuff for reading header of a file-based stack.
authorRoland Haeder <roland@mxchange.org>
Sun, 18 May 2014 08:53:04 +0000 (10:53 +0200)
committerRoland Haeder <roland@mxchange.org>
Sun, 18 May 2014 08:53:04 +0000 (10:53 +0200)
Signed-off-by: Roland Häder <roland@mxchange.org>
contrib/file_stack/format.txt
inc/classes/interfaces/io/pointer/class_InputPointer.php
inc/classes/interfaces/iterator/class_SeekableWritableFileIterator.php
inc/classes/main/file_directories/io/class_FrameworkFileInputOutputPointer.php
inc/classes/main/iterator/io/class_FileIoIterator.php
inc/classes/main/stacker/file/class_BaseFileStack.php

index cb8c07ee480035adbe08365984e84ef663e7b331..336428dbbcf26fc5e1b1daccf362c249fd2921b6 100644 (file)
@@ -9,7 +9,7 @@ Purpose: | "magic"   | separator | count    | separator | position | separator |
 ---------+-----------+-----------+----------+-----------+------0---+-----------+
 Bytes:   | 9         | 1         | 20 (hex) | 1         | 20 (hex) | 1         |
 ---------+-----------+-----------+----------+-----------+----------+-----------+
-Example: | STACKv1.0 | 01        | 00...ff  | 02        | 00...ff  | 03        |
+Example: | STACKv1.0 | 01        | 00...ff  | 01        | 00...ff  | 02        |
 
 Continued:
 
@@ -17,7 +17,7 @@ Purpose: | hash 0 | separator | name 0 | entry 0    | hash n | separator | name
 ---------+--------+-----------+--------+------------+--------+-----------+--------+------------+-----+
 Bytes:   |  64    | 1         | 10     | 1-n (pack) |  64    | 1         | 10     | 1-n (pack) | 1   |
 ---------+--------+-----------+--------+------------+--------+-----------+--------+------------+-----+
-Example: | abc    |    04     | foo    |    ...     | abc    |    04     | bar    |     ...    | EOF |
+Example: | abc    |    03     | foo    |    ...     | abc    |    03     | bar    |     ...    | EOF |
 
 Explanations:
 -------------
index 1d67cd24599fb3ba1b66e2bad501fdf510adb6eb..0c15cc7b07b7f0620e0c7003bd01bbf77c255263 100644 (file)
@@ -31,6 +31,14 @@ interface InputPointer extends StreamableInput {
         * @throws      InvalidResourceException        If there is being set
         */
        function readFromFile ();
+
+       /**
+        * Reads given amount of bytes from file.
+        *
+        * @param       $bytes  Amount of bytes to read
+        * @return      $data   Data read from file
+        */
+       function read ($bytes);
 }
 
 // [EOF]
index 1dde2c27235b52e32bc25e46cbefa1959e56d10d..abd1e583fbcf998cff8cea1441e780c73bf8ef19 100644 (file)
@@ -46,6 +46,14 @@ interface SeekableWritableFileIterator extends SeekableIterator {
         * @return      void
         */
        function writeAtPosition ($seedPosition, $data);
+
+       /**
+        * Reads given amount of bytes from file.
+        *
+        * @param       $bytes  Amount of bytes to read
+        * @return      $data   Data read from file
+        */
+       function read ($bytes);
 }
 
 // [EOF]
index 198c5b09df6c463f8bcdd9a4ee8f84b1d24f7bad..073c2c7fe0f91059c99001e783742329f0f52ad0 100644 (file)
@@ -75,7 +75,7 @@ class FrameworkFileInputOutputPointer extends BaseFileIo implements InputOutputP
        }
 
        /**
-        * Read data a file pointer
+        * Read 1024 bytes data from a file pointer
         *
         * @return      mixed   The result of fread()
         * @throws      NullPointerException    If the file pointer instance
@@ -92,7 +92,7 @@ class FrameworkFileInputOutputPointer extends BaseFileIo implements InputOutputP
                }
 
                // Read data from the file pointer and return it
-               return fread($this->getPointer(), 1024);
+               return $this->read(1024);
        }
 
        /**
@@ -139,6 +139,23 @@ class FrameworkFileInputOutputPointer extends BaseFileIo implements InputOutputP
                // Move the file pointer
                return fseek($this->getPointer(), $seekPosition, $whence);
        }
+
+       /**
+        * Reads given amount of bytes from file.
+        *
+        * @param       $bytes  Amount of bytes to read
+        * @return      $data   Data read from file
+        */
+       public function read ($bytes) {
+               // Try to read given characters
+               $data = fread($this->getPointer(), $bytes);
+
+               // Was this successfull?
+               assert(is_string($data));
+
+               // Then return it
+               return $data;
+       }
 }
 
 // [EOF]
index af4c1b47f8b8174a176a7faa7626a72a7de1665f..e6aee1d9190ce602dca07bc4ae1851a3e89ca347 100644 (file)
@@ -93,6 +93,17 @@ class FileIoIterator extends BaseIterator implements SeekableWritableFileIterato
                return $this->getPointerInstance()->rewind();
        }
 
+       /**
+        * 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
+        */
+       public function valid () {
+               // Call pointer instance
+               return $this->getPointerInstance()->valid();
+       }
+
        /**
         * Seeks to given position
         *
@@ -133,13 +144,14 @@ 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.
+        * Reads given amount of bytes from file.
         *
-        * @return      void
+        * @param       $bytes  Amount of bytes to read
+        * @return      $data   Data read from file
         */
-       public function valid () {
-               $this->partialStub('Please implement this method.');
+       public function read ($bytes) {
+               // Call pointer instance
+               return $this->getPointerInstance()->read($bytes);
        }
 }
 
index dd8570c45185aeb0f202bb0452221f093ae3c27a..0485b12c20e84eca7e73b8e00dd14ca7fd753468 100644 (file)
@@ -28,39 +28,34 @@ class BaseFileStack extends BaseStacker {
        const STACK_MAGIC = 'STACKv0.1';
 
        /**
-        * Separator magic->count
+        * Separator for header data
         */
-       const SEPARATOR_MAGIC_COUNT = 0x01;
+       const SEPARATOR_HEADER_DATA = 0x01;
 
        /**
-        * Separator count->position
+        * Separator header->entries
         */
-       const SEPARATOR_COUNT_SEEK_POS = 0x02;
-
-       /**
-        * Separator position->entries
-        */
-       const SEPARATOR_SEEK_POS_ENTRIES = 0x03;
+       const SEPARATOR_HEADER_ENTRIES = 0x02;
 
        /**
         * Separator hash->name
         */
-       const SEPARATOR_HASH_NAME = 0x04;
+       const SEPARATOR_HASH_NAME = 0x03;
 
        /**
         * Length of name
         */
-       const COUNT_NAME = 10;
+       const LENGTH_NAME = 10;
 
        /**
         * Length of count
         */
-       const COUNT_LENGTH = 20;
+       const LENGTH_COUNT = 20;
 
        /**
         * Length of position
         */
-       const COUNT_POSITION = 20;
+       const LENGTH_POSITION = 20;
 
        /**
         * Counter for total entries
@@ -72,6 +67,16 @@ class BaseFileStack extends BaseStacker {
         */
        private $seekPosition = 0;
 
+       /**
+        * Size of header
+        */
+       private $headerSize = 0;
+
+       /**
+        * File header
+        */
+       private $header = array();
+
        /**
         * Protected constructor
         *
@@ -81,6 +86,16 @@ class BaseFileStack extends BaseStacker {
        protected function __construct ($className) {
                // Call parent constructor
                parent::__construct($className);
+
+               // Calculate header size
+               $this->headerSize =
+                       strlen(self::MAGIC) +
+                       strlen(self::SEPARATOR_HEADER_DATA) +
+                       self::LENGTH_COUNT +
+                       strlen(self::SEPARATOR_HEADER_DATA) +
+                       self::LENGTH_POSITION +
+                       strlen(self::SEPARATOR_HEADER_ENTRIES)
+               );
        }
 
        /**
@@ -142,6 +157,55 @@ class BaseFileStack extends BaseStacker {
                /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] EXIT!', __METHOD__, __LINE__));
        }
 
+       /**
+        * Reads the file header
+        *
+        * @return      void
+        */
+       private function readFileHeader () {
+               /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] CALLED!', __METHOD__, __LINE__));
+
+               // First rewind to beginning as the header sits at the beginning ...
+               $this->getIteratorInstance()->rewind();
+
+               // Then read it (see constructor for calculation)
+               $data = $this->getIteratorInstance()->read($this->headerLength);
+
+               // Last character must be the separator
+               assert(substr($data, -1, 1) == self::SEPARATOR_HEADER_ENTRIES);
+
+               // Okay, then remove it
+               $data = substr($data, 0, -1);
+
+               // And update seek position
+               $this->updateSeekPosition();
+
+               /*
+                * Now split it:
+                *
+                * 0 => Magic
+                * 1 => Total entries
+                * 2 => Current seek position
+                */
+               $this->header = explode(self::SEPARATOR_HEADER_DATA, $data);
+
+               // Check if the array has only 3 elements
+               assert(count($this->header) == 3);
+
+               // Check magic
+               assert($this->header[0] == self::MAGIC);
+
+               // Check length of count and seek position
+               assert(strlen($this->header[1]) == self::LENGTH_COUNT);
+               assert(strlen($this->header[2]) == self::LENGTH_POSITION);
+
+               // Decode count and seek position
+               $this->header[1] = hex2bin($this->header[1]);
+               $this->header[2] = hex2bin($this->header[2]);
+
+               /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] EXIT!', __METHOD__, __LINE__));
+       }
+
        /**
         * Checks whether the file header is initialized
         *
@@ -166,6 +230,8 @@ class BaseFileStack extends BaseStacker {
 
                        // Read file header
                        $this->readFileHeader();
+
+                       // Check if its format is valid.
                } // END - if
 
                // Return result
@@ -229,19 +295,19 @@ class BaseFileStack extends BaseStacker {
                        self::STACK_MAGIC,
 
                        // Separator magic<->count
-                       chr(self::SEPARATOR_MAGIC_COUNT),
+                       chr(self::SEPARATOR_HEADER_DATA),
 
                        // Total entries (will be zero) and pad it to 20 chars
-                       str_pad($this->dec2hex($this->getCounter()), self::COUNT_LENGTH, '0', STR_PAD_LEFT),
+                       str_pad($this->dec2hex($this->getCounter()), self::LENGTH_COUNT, '0', STR_PAD_LEFT),
 
                        // Separator count<->seek position
-                       chr(self::SEPARATOR_COUNT_SEEK_POS),
+                       chr(self::SEPARATOR_HEADER_DATA),
 
                        // Position (will be zero)
-                       str_pad($this->dec2hex($this->getSeekPosition(), 2), self::COUNT_POSITION, '0', STR_PAD_LEFT),
+                       str_pad($this->dec2hex($this->getSeekPosition(), 2), self::LENGTH_POSITION, '0', STR_PAD_LEFT),
 
                        // Separator position<->entries
-                       chr(self::SEPARATOR_SEEK_POS_ENTRIES)
+                       chr(self::SEPARATOR_HEADER_ENTRIES)
                );
 
                // Write it to disk (header is always at seek position 0)
@@ -293,7 +359,7 @@ class BaseFileStack extends BaseStacker {
                 * Calculate minimum length for one entry:
                 * minimum length = hash length + separator + name + minimum entry size = ?? + 1 + 10 + 1 = ??
                 */
-               $minLengthEntry = self::getHashLength() + strlen(self::SEPARATOR_HASH_NAME) + self::COUNT_NAME + 1;
+               $minLengthEntry = self::getHashLength() + strlen(self::SEPARATOR_HASH_NAME) + self::LENGTH_NAME + 1;
                /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] minLengthEntry=%s', __METHOD__, __LINE__, $minLengthEntry));
 
                // Calulcate seek position