*/
const LENGTH_TYPE = 20;
+ //***** Array elements for 'gaps' array *****
+
+ /**
+ * Start of gap
+ */
+ const GAPS_INDEX_START = 'start';
+
/**
- * Length of output from hash()
+ * End of gap
*/
- private static $hashLength = NULL;
+ const GAPS_INDEX_END = 'end';
/**
* Counter for total entries
*
* @return void
*/
- protected function initCountersGapsArray () {
+ public function initCountersGapsArray () {
// Init counter and seek position
$this->setCounter(0);
$this->setSeekPosition(0);
* @param $headerSize Size of file header
* @return void
*/
- protected final function setHeaderSize ($headerSize) {
+ public final function setHeaderSize ($headerSize) {
// Set it
$this->headerSize = $headerSize;
}
*
* @return $totalEntries Size of file header
*/
- protected final function getHeade () {
+ public final function getHeader () {
// Get it
return $this->header;
}
* @param $header Array for a file header
* @return void
*/
- protected final function setHeader (array $header) {
+ public final function setHeader (array $header) {
// Set it
$this->header = $header;
}
*
* @return void
*/
- protected function updateSeekPosition () {
+ public function updateSeekPosition () {
//* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] CALLED!', __METHOD__, __LINE__));
// Get key (= seek position)
- $seekPosition = $this->getIteratorInstance()->key();
+ $seekPosition = $this->key();
//* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] Setting seekPosition=%s', __METHOD__, __LINE__, $seekPosition));
// And set it here
*
* @return void
*/
- protected function rewineUpdateSeekPosition () {
+ protected function rewindUpdateSeekPosition () {
//* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] CALLED!', __METHOD__, __LINE__));
// flushFileHeader must be callable
assert(is_callable(array($this, 'flushFileHeader')));
// Seek to beginning of file
- $this->getIteratorInstance()->rewind();
+ $this->rewind();
// And update seek position ...
$this->updateSeekPosition();
//* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] CALLED!', __METHOD__, __LINE__));
// Seek to currently ("old") saved position
- $this->getIteratorInstance()->seek($this->getSeekPosition());
+ $this->seek($this->getSeekPosition());
//* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] EXIT!!', __METHOD__, __LINE__));
}
//* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] EXIT!', __METHOD__, __LINE__));
}
+ /**
+ * Marks the currently loaded block as empty (with length of the block)
+ *
+ * @param $length Length of the block
+ * @return void
+ */
+ protected function markCurrentBlockAsEmpty ($length) {
+ // Get current seek position
+ $currentPosition = $this->key();
+
+ // Now add it as gap entry
+ array_push($this->gaps, array(
+ self::GAPS_INDEX_START => ($currentPosition - $length),
+ self::GAPS_INDEX_END => $currentPosition,
+ ));
+ }
+
/**
* Checks whether the file header is initialized
*
$this->flushFileHeader();
// Rewind seek position (to beginning of file) and update/flush file header
- $this->rewineUpdateSeekPosition();
+ $this->rewindUpdateSeekPosition();
//* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] EXIT!!', __METHOD__, __LINE__));
}
$this->writeData($seekPosition, chr(0));
// Rewind seek position (to beginning of file) and update/flush file header
- $this->rewineUpdateSeekPosition();
+ $this->rewindUpdateSeekPosition();
//* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d:] EXIT!', __METHOD__, __LINE__));
}
* Advances to next "block" of bytes
*
* @return void
- * @todo This method will load large but empty files in a whole
*/
public function next () {
// Is there nothing to read?
// Short be more than zero!
assert($length > 0);
- // Wait until a entry/block separator has been found
+ // Read possibly back-buffered bytes from previous call of next().
$data = $this->getBackBuffer();
+
+ /*
+ * Read until a entry/block separator has been found. The next read
+ * "block" may not fit, so this loop will continue until the EOB or EOF
+ * has been reached whatever comes first.
+ */
while ((!$this->isEndOfFileReached()) && (!self::isBlockSeparatorFound($data))) {
- // Then read the block
- $data .= $this->read($length);
- //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('data()=' . strlen($data));
+ // Then read the next possible block
+ $block = $this->read($length);
+
+ // Is it all empty?
+ if (strlen(trim($block)) == 0) {
+ // Mark this block as empty
+ $this->markCurrentBlockAsEmpty($length);
+
+ // Skip to next block
+ continue;
+ } // END - if
+
+ // At this block then
+ $data .= $block;
+
+ // A debug message
+ //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput(sprintf('[%s:%d] data()=%s', __FUNCTION__, __LINE__, strlen($data)));
} // END - if
// EOF reached?
if ($this->isEndOfFileReached()) {
- // Set whole data as current block
+ // Set whole data as current read block
//* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('Calling setCurrentBlock(' . strlen($data) . ') ...');
$this->setCurrentBlock($data);