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
*/
private $seekPosition = 0;
+ /**
+ * Size of header
+ */
+ private $headerSize = 0;
+
+ /**
+ * File header
+ */
+ private $header = array();
+
/**
* Protected constructor
*
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)
+ );
}
/**
/* 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
*
// Read file header
$this->readFileHeader();
+
+ // Check if its format is valid.
} // END - if
// Return result
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)
* 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