From fc83e6b1ac6fe3a5e09a3e4f8bad20fa2240cae4 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Roland=20H=C3=A4der?= Date: Mon, 7 Dec 2020 15:16:48 +0100 Subject: [PATCH] Rewrites: - more thrown exceptions - more debug logging (currently messing up phpunit output) - more type-hints for primitive variables added - writeAtPosition() must be used instead of writeData() as the later one increments the counter - debug log files could contain non-text data, so let's treat them as as text anyway ... MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Roland Häder --- contrib/missing-methods.sh | 2 +- .../result/class_CachedDatabaseResult.php | 2 +- .../binary/class_BaseBinaryFile.php | 236 ++++++++++++------ .../class_BaseAbstractFile.php | 6 + .../file_directories/class_BaseFileIo.php | 22 +- .../class_FrameworkFileInputOutputPointer.php | 13 +- .../main/classes/index/class_BaseIndex.php | 39 ++- .../index/file_stack/class_FileStackIndex.php | 28 +++ .../iterator/file/class_FileIterator.php | 47 +++- .../output/console/class_ConsoleOutput.php | 2 +- .../console/class_DebugConsoleOutput.php | 12 +- .../debug/error/class_DebugErrorLogOutput.php | 8 +- .../output/debug/web/class_DebugWebOutput.php | 8 +- .../classes/output/web/class_WebOutput.php | 2 +- .../stacker/file/class_BaseFileStack.php | 63 ++++- .../stacker/file/fifo/class_FiFoFileStack.php | 5 +- .../main/interfaces/block/class_Block.php | 10 + .../main/interfaces/debug/class_Debugger.php | 2 +- .../io/output/class_OutputStreamer.php | 2 +- .../class_SeekableWritableFileIterator.php | 9 + 20 files changed, 377 insertions(+), 141 deletions(-) diff --git a/contrib/missing-methods.sh b/contrib/missing-methods.sh index 6c7ac041..91dc1241 100755 --- a/contrib/missing-methods.sh +++ b/contrib/missing-methods.sh @@ -13,4 +13,4 @@ then exit 255 fi -grep __call "${DEBUG_FILE}" | cut -d "[" -f 4 | cut -d "]" -f 1 +grep -a __call "${DEBUG_FILE}" | cut -d "[" -f 4 | cut -d "]" -f 1 diff --git a/framework/main/classes/database/result/class_CachedDatabaseResult.php b/framework/main/classes/database/result/class_CachedDatabaseResult.php index 664270e6..74766038 100644 --- a/framework/main/classes/database/result/class_CachedDatabaseResult.php +++ b/framework/main/classes/database/result/class_CachedDatabaseResult.php @@ -174,7 +174,7 @@ class CachedDatabaseResult extends BaseDatabaseResult implements SearchableResul * @param $index Index to seek for * @return void */ - public function seek ($index) { + public function seek (int $index) { // Rewind to beginning $this->rewind(); diff --git a/framework/main/classes/file_directories/binary/class_BaseBinaryFile.php b/framework/main/classes/file_directories/binary/class_BaseBinaryFile.php index 04e6da4e..187ac493 100644 --- a/framework/main/classes/file_directories/binary/class_BaseBinaryFile.php +++ b/framework/main/classes/file_directories/binary/class_BaseBinaryFile.php @@ -13,6 +13,7 @@ use Org\Mxchange\CoreFramework\Filesystem\File\BaseAbstractFile; use \BadMethodCallException; use \InvalidArgumentException; use \SplFileInfo; +use \UnexpectedValueException; /** * A general binary file class @@ -179,28 +180,20 @@ abstract class BaseBinaryFile extends BaseAbstractFile { * @return $isGapsOnly Whether the abstracted file only contains gaps */ private function isFileOnlyGaps () { - // First/last gap found? - /* Only for debugging - if (isset($this->gaps[0])) { - // Output first and last gap - self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] this->gaps[0]=%s,this->gaps[%s]=%s', print_r($this->gaps[0], true), (count($this->gaps) - 1), print_r($this->gaps[count($this->gaps) - 1], true))); - } - */ - - // Now count every gap + // Count every gap + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: CALLED!'); $gapsSize = 0; foreach ($this->gaps as $gap) { // Calculate size of found gap: end-start including both $gapsSize += ($gap[self::GAPS_INDEX_END] - $gap[self::GAPS_INDEX_START]); } - // Debug output - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] gapsSize=%s,this->headerSize=%s', $gapsSize, $this->getHeaderSize())); - // Total gap size + header size must be same as file size + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: gapsSize=%s,this->headerSize=%s', $gapsSize, $this->getHeaderSize())); $isGapsOnly = (($this->getHeaderSize() + $gapsSize) == $this->getFileSize()); // Return status + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: isGapsOnly=%d - EXIT!', intval($isGapsOnly))); return $isGapsOnly; } @@ -213,13 +206,17 @@ abstract class BaseBinaryFile extends BaseAbstractFile { * @return void */ public function initCountersGapsArray () { - // Init counter and seek position + // Init counter and seek position to header size + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: CALLED!'); $this->setCounter(0); - $this->setSeekPosition(0); + $this->setSeekPosition($this->getHeaderSize()); // Init arrays $this->gaps = []; $this->damagedEntries = []; + + // Trace message + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: CALLED!'); } /** @@ -270,7 +267,7 @@ abstract class BaseBinaryFile extends BaseAbstractFile { * @return $seekPosition Current seek position (stored here in object) */ public final function getSeekPosition () { - // Get it + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: Getting this->seekPosition=%d - CALLED!', $this->seekPosition)); return $this->seekPosition; } @@ -281,7 +278,7 @@ abstract class BaseBinaryFile extends BaseAbstractFile { * @return void */ protected final function setSeekPosition (int $seekPosition) { - // And set it + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: Setting seekPosition=%d - CALLED!', $seekPosition)); $this->seekPosition = $seekPosition; } @@ -291,40 +288,43 @@ abstract class BaseBinaryFile extends BaseAbstractFile { * @return void */ public function updateSeekPosition () { - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] CALLED!')); - // Get key (= seek position) + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: CALLED!'); $seekPosition = $this->key(); - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] Setting seekPosition=%s', $seekPosition)); // And set it here + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: seekPosition=%d', $seekPosition)); $this->setSeekPosition($seekPosition); - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] EXIT!')); + // Trace message + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: EXIT!'); } /** * Seeks to beginning of file, updates seek position in this object and * flushes the header. * + * @param $flushHeader Wether the file's header should be flushed (default: false) * @return void */ - protected function rewindUpdateSeekPosition () { - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] CALLED!')); - - // flushFileHeader must be callable - assert(is_callable(array($this, 'flushFileHeader'))); - + protected function rewindUpdateSeekPosition (bool $flushHeader = false) { // Seek to beginning of file + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: flushHeader=%d - CALLED!', intval($flushHeader))); $this->rewind(); // And update seek position ... + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: Calling this->updateSeekPosition() ...'); $this->updateSeekPosition(); - // ... to write it back into the file - $this->flushFileHeader(); + // Flush headers? + if ($flushHeader) { + // ... to write it back into the file + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: Calling this->flushFileHeader() ...'); + $this->flushFileHeader(); + } - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] EXIT!')); + // Trace message + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: EXIT!'); } /** @@ -333,12 +333,12 @@ abstract class BaseBinaryFile extends BaseAbstractFile { * @return void */ protected function seekToOldPosition () { - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] CALLED!')); - // Seek to currently ("old") saved position + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: CALLED!'); $this->seek($this->getSeekPosition()); - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] EXIT!')); + // Trace message + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: EXIT!'); } /** @@ -346,12 +346,21 @@ abstract class BaseBinaryFile extends BaseAbstractFile { * * @param $str String to look in * @return $isFound Whether the block separator has been found + * @throws InvalidArgumentException If a parameter is not valid */ - public static function isBlockSeparatorFound ($str) { + public static function isBlockSeparatorFound (string $str) { + // Validate parameter + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: str=%s - CALLED!', $str)); + if (empty($str)) { + // Throw IAE + throw new InvalidArgumentException('Parameter "str" is empty'); + } + // Determine it $isFound = (strpos($str, chr(self::SEPARATOR_ENTRIES)) !== false); // Return result + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: isFound=%d - EXIT!', intval($isFound))); return $isFound; } @@ -362,7 +371,11 @@ abstract class BaseBinaryFile extends BaseAbstractFile { */ private function initBackBuffer () { // Simply call the setter + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: CALLED!'); $this->setBackBuffer(''); + + // Trace message + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: EXIT!'); } /** @@ -388,7 +401,7 @@ abstract class BaseBinaryFile extends BaseAbstractFile { /** * Setter for currentBlock field * - * @param $currentBlock Characters to set a currently loaded block + * @param $currentBlock Characters to set a currently loaded block * @return void */ private function setCurrentBlock (string $currentBlock) { @@ -446,20 +459,26 @@ abstract class BaseBinaryFile extends BaseAbstractFile { } // Write data at given position - $this->getPointerInstance()->writeAtPosition($seekPosition, $data); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: Calling this->writeAtPosition(%d,%s) ...', $seekPosition, $data)); + $this->writeAtPosition($seekPosition, $data); // Increment counter + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: Calling this->incrementCounter() ...'); $this->incrementCounter(); // Update seek position + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: Calling this->updateSeekPosition() ...'); $this->updateSeekPosition(); // Flush the header? + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: flushHeader=%d', intval($flushHeader))); if ($flushHeader === true) { // Flush header + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: Calling this->flushFileHeader() ...'); $this->flushFileHeader(); // Seek to old position + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: Calling this->seekToOldPosition() ...'); $this->seekToOldPosition(); } @@ -467,6 +486,34 @@ abstract class BaseBinaryFile extends BaseAbstractFile { /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: EXIT!'); } + /** + * Writes at given position by seeking to it. + * + * @param $seekPosition Seek position in file + * @param $dataStream Data to be written + * @return mixed Number of writes bytes or false on error + * @throws InvalidArgumentException If a parameter is not valid + */ + public function writeAtPosition (int $seekPosition, string $dataStream) { + // Validate parameter + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: seekPosition=%d,dataStream(%d)=%s - CALLED!', $seekPosition, strlen($dataStream), $dataStream)); + if ($seekPosition < 0) { + // Invalid seek position + throw new InvalidArgumentException(sprintf('seekPosition=%d is not valid.', $seekPosition)); + } elseif (empty($dataStream)) { + // Empty dataStream + throw new InvalidArgumentException('Parameter "dataStream" is empty'); + } + + // Call pointer's method + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: Calling this->pointerInstance->writeAtPosition(%d, %s) ...', $seekPosition, $dataStream)); + $status = $this->getPointerInstance()->writeAtPosition($seekPosition, $dataStream); + + // Return status + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: status[%s]=%d - EXIT!', gettype($status), $status)); + return $status; + } + /** * Marks the currently loaded block as empty (with length of the block) * @@ -476,7 +523,7 @@ abstract class BaseBinaryFile extends BaseAbstractFile { */ protected function markCurrentBlockAsEmpty (int $length) { // Validate parameter - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: length=%d - CALLED!', $length)); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: length=%d - CALLED!', $length)); if ($length < 1) { // Length cannot below one throw new InvalidArgumentException(sprintf('length=%d is not valid', $length)); @@ -492,7 +539,7 @@ abstract class BaseBinaryFile extends BaseAbstractFile { )); // Trace message - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: EXIT!'); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: EXIT!'); } /** @@ -508,20 +555,18 @@ abstract class BaseBinaryFile extends BaseAbstractFile { // Is the file initialized? if ($this->isFileInitialized()) { // Some bytes has been written, so rewind to start of it. - $rewindStatus = $this->rewind(); - - // Is the rewind() call successfull? - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: rewindStatus=%d', $rewindStatus)); - if ($rewindStatus != 1) { - // Something bad happened - self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: Could not rewind().'); - } + $this->rewind(); // Read file header + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: Calling this->readFileHeader() ...'); $this->readFileHeader(); + // Get header count + $headerCount = count($this->getHeader()); + // The above method does already check the header - $isInitialized = true; + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: headerCount=%d', $headerCount)); + $isInitialized = ($headerCount > 0); } // Return result @@ -536,21 +581,21 @@ abstract class BaseBinaryFile extends BaseAbstractFile { */ public function isFileInitialized () { // Get it from iterator which holds the pointer instance. If false is returned - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: CALLED!'); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: CALLED!'); $fileSize = $this->size(); - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: fileSize=%s', $fileSize)); /* * The returned file size should not be false or NULL as this means * that the pointer class does not work correctly. */ + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: fileSize[%s]=%d', gettype($fileSize), $fileSize)); assert(is_int($fileSize)); // Is more than 0 returned? $isInitialized = ($fileSize > 0); // Return result - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: isInitialized=%d - EXIT!', intval($isInitialized))); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: isInitialized=%d - EXIT!', intval($isInitialized))); return $isInitialized; } @@ -558,20 +603,27 @@ abstract class BaseBinaryFile extends BaseAbstractFile { * Creates the assigned file * * @return void + * @throws BadMethodCallException If this file's header is already initialized */ public function createFileHeader () { // The file's header should not be initialized here - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: CALLED!'); - assert(!$this->isFileHeaderInitialized()); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: CALLED!'); + if ($this->isFileHeaderInitialized()) { + // Bad method call + //* DEBUG-DIE: */ die(sprintf('[%s:%d]: this=%s', __METHOD__, __LINE__, print_r($this, TRUE))); + throw new BadMethodCallException('File header is already initialized but method called'); + } // Simple flush file header which will create it. + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: Calling this->flushFileHeader() ...'); $this->flushFileHeader(); // Rewind seek position (to beginning of file) and update/flush file header + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: Calling this->rewindUpdateSeekPosition() ...'); $this->rewindUpdateSeekPosition(); // Trace message - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: EXIT!'); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: EXIT!'); } /** @@ -597,18 +649,18 @@ abstract class BaseBinaryFile extends BaseAbstractFile { self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: Pre-allocating file ...'); // Calculate minimum length for one entry - $minLengthEntry = $this->getBlockInstance()->calculateMinimumBlockLength(); + $minimumBlockLength = $this->getBlockInstance()->calculateMinimumBlockLength(); // Calulcate seek position - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: minLengthEntry=%s', $minLengthEntry)); - $seekPosition = $minLengthEntry * FrameworkBootstrap::getConfigurationInstance()->getConfigEntry($type . '_pre_allocate_count'); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: minimumBlockLength=%s', $minimumBlockLength)); + $seekPosition = $minimumBlockLength * FrameworkBootstrap::getConfigurationInstance()->getConfigEntry($type . '_pre_allocate_count'); // Now simply write a NUL there. This will pre-allocate the file. - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: seekPosition=%d', $seekPosition)); - $this->writeData($seekPosition, chr(0)); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: Calling this->writeAtPosition(%d,NUL) ...', $seekPosition)); + $this->writeAtPosition($seekPosition, chr(0)); - // Rewind seek position (to beginning of file) and update/flush file header - $this->rewindUpdateSeekPosition(); + // Rewind seek position + $this->rewind(); // Trace message /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: EXIT!'); @@ -631,7 +683,7 @@ abstract class BaseBinaryFile extends BaseAbstractFile { * @param $whence Added to offset (default: only use offset to seek to) * @return $status Status of file seek: 0 = success, -1 = failed */ - public function seek (int $offset, $whence = SEEK_SET) { + public function seek (int $offset, int $whence = SEEK_SET) { // Call pointer instance return $this->getPointerInstance()->seek($offset, $whence); } @@ -667,7 +719,7 @@ abstract class BaseBinaryFile extends BaseAbstractFile { */ public function analyzeFile () { // Make sure the file is initialized - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: CALLED!'); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: CALLED!'); if (!$this->isFileInitialized()) { // Bad method call throw new BadMethodCallException('Method called but file is not initialized.'); @@ -725,7 +777,7 @@ abstract class BaseBinaryFile extends BaseAbstractFile { $this->doRunDefragmentation(); } } - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: EXIT!'); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: EXIT!'); } /** @@ -736,16 +788,16 @@ abstract class BaseBinaryFile extends BaseAbstractFile { */ public function next () { // Is there nothing to read? - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: CALLED!'); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: CALLED!'); if (!$this->valid()) { // Nothing to read return; } // First calculate minimum block length - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: key()=%d', $this->key())); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: key()=%d', $this->key())); $length = $this->getBlockInstance()->calculateMinimumBlockLength(); - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: length=%s', $length)); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: length=%d', $length)); // Read possibly back-buffered bytes from previous call of next(). $data = $this->getBackBuffer(); @@ -755,20 +807,21 @@ abstract class BaseBinaryFile extends BaseAbstractFile { * "block" may not fit, so this loop will continue until the EOB or EOF * has been reached whatever comes first. */ - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: data()=%d', strlen($data))); - while ((!$this->isEndOfFileReached()) && (!self::isBlockSeparatorFound($data))) { + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: data()=%d', strlen($data))); + while ((!$this->isEndOfFileReached()) && (empty($data) || !self::isBlockSeparatorFound($data))) { // Then read the next possible block + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: Calling this->read(%d) ...', $length)); $block = $this->read($length); // Is it all empty? - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: block()=%d,length=%s', strlen($block), $length)); - if (strlen(trim($block)) == 0) { + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: block()=%d,length=%s', strlen($block), $length)); + if (strlen(trim($block, chr(0))) == 0) { // Mark this block as empty - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: Calling markCurrentBlockAsEmpty(%d) ...', strlen($block))); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: Calling markCurrentBlockAsEmpty(%d) ...', strlen($block))); $this->markCurrentBlockAsEmpty(strlen($block)); // Skip to next block - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: CONTINUE!'); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: CONTINUE!'); continue; } @@ -776,17 +829,17 @@ abstract class BaseBinaryFile extends BaseAbstractFile { $data .= $block; // A debug message - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: data()=%d', strlen($data))); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: data()=%d', strlen($data))); } // EOF reached? if ($this->isEndOfFileReached()) { // Set whole data as current read block - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: Calling setCurrentBlock(%d) ...', strlen($data))); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: Calling setCurrentBlock(%d) ...', strlen($data))); $this->setCurrentBlock($data); // Then abort here silently - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: EOF reached - EXIT!'); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: EOF reached - EXIT!'); return; } @@ -800,7 +853,8 @@ abstract class BaseBinaryFile extends BaseAbstractFile { $dataArray = explode(chr(self::SEPARATOR_ENTRIES), $data); // This array must contain two elements - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: dataArray=' . print_r($dataArray, true)); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: dataArray()=%d', count($dataArray))); + //* PRINTR-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: dataArray=%s', print_r($dataArray, true))); if (count($dataArray) != 2) { // Bad count throw new UnexpectedValueException(sprintf('dataArray()=%d is not expected, want 2', count($dataArray))); @@ -811,7 +865,7 @@ abstract class BaseBinaryFile extends BaseAbstractFile { $this->setBackBuffer($dataArray[1]); // Trace message - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: EXIT!'); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: EXIT!'); } /** @@ -819,6 +873,7 @@ abstract class BaseBinaryFile extends BaseAbstractFile { * This method will return true if an emptied (nulled) entry has been found. * * @return $isValid Whether the next entry is valid + * @throws UnexpectedValueException If some value is not expected */ public function valid () { // First calculate minimum block length @@ -826,30 +881,38 @@ abstract class BaseBinaryFile extends BaseAbstractFile { $length = $this->getBlockInstance()->calculateMinimumBlockLength(); // Short be more than zero! - assert($length > 0); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: length=%d', $length)); + if ($length < 1) { + // Throw UVE + throw new UnexpectedValueException(sprintf('length=%d is not expected', $length)); + } // Get current seek position $seekPosition = $this->key(); // Then try to read it + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: seekPosition=%d', $seekPosition)); $data = $this->read($length); // If some bytes could be read, all is fine + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: data[%s]()=%d', gettype($data), strlen($data))); $isValid = ((is_string($data)) && (strlen($data) > 0)); // Get header size + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: isValid=%d', intval($isValid))); $headerSize = $this->getHeaderSize(); // Is the seek position at or beyond the header? if ($seekPosition >= $headerSize) { // Seek back to old position - $this->seek($seekPosition); + $isValid = ($isValid && $this->seek($seekPosition) === 0); } else { // Seek directly behind the header - $this->seek($headerSize); + $isValid = ($isValid && $this->seek($headerSize) === 0); } // Return result + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: isValid=%d - EXIT!', intval($isValid))); return $isValid; } @@ -860,7 +923,12 @@ abstract class BaseBinaryFile extends BaseAbstractFile { */ public function key () { // Call pointer instance - return $this->getPointerInstance()->determineSeekPosition(); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: CALLED!'); + $key = $this->getPointerInstance()->determineSeekPosition(); + + // Return key + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-BINARY-FILE: key[%s]=%d - EXIT!', gettype($key), $key)); + return $key; } /** @@ -870,7 +938,11 @@ abstract class BaseBinaryFile extends BaseAbstractFile { */ public function readFileHeader () { // Call block instance + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: CALLED!'); $this->getBlockInstance()->readFileHeader(); + + // Trace message + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: EXIT!'); } /** @@ -880,7 +952,11 @@ abstract class BaseBinaryFile extends BaseAbstractFile { */ public function flushFileHeader () { // Call block instance + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: CALLED!'); $this->getBlockInstance()->flushFileHeader(); + + // Trace message + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-BINARY-FILE: EXIT!'); } /** diff --git a/framework/main/classes/file_directories/class_BaseAbstractFile.php b/framework/main/classes/file_directories/class_BaseAbstractFile.php index f72d7753..07524bca 100644 --- a/framework/main/classes/file_directories/class_BaseAbstractFile.php +++ b/framework/main/classes/file_directories/class_BaseAbstractFile.php @@ -117,6 +117,7 @@ abstract class BaseAbstractFile extends BaseFrameworkSystem implements FilePoint */ public final function getCounter () { // Get it + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-ABSTRACT-FILE: Getting this->totalEntries=%d ... - CALLED!', $this->totalEntries)); return $this->totalEntries; } @@ -128,6 +129,7 @@ abstract class BaseAbstractFile extends BaseFrameworkSystem implements FilePoint */ protected final function setCounter (int $counter) { // Set it + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-ABSTRACT-FILE: Setting this->totalEntries=%d ... - CALLED!', $counter)); $this->totalEntries = $counter; } @@ -138,7 +140,11 @@ abstract class BaseAbstractFile extends BaseFrameworkSystem implements FilePoint */ protected final function incrementCounter () { // Get it + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-ABSTRACT-FILE: CALLED!'); $this->totalEntries++; + + // Trace message + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-ABSTRACT-FILE: EXIT!'); } /** diff --git a/framework/main/classes/file_directories/class_BaseFileIo.php b/framework/main/classes/file_directories/class_BaseFileIo.php index 4a024c8d..71d6d3ba 100644 --- a/framework/main/classes/file_directories/class_BaseFileIo.php +++ b/framework/main/classes/file_directories/class_BaseFileIo.php @@ -9,6 +9,7 @@ use Org\Mxchange\CoreFramework\Generic\NullPointerException; use Org\Mxchange\CoreFramework\Object\BaseFrameworkSystem; // Import SPL stuff +use \InvalidArgumentException; use \SplFileObject; /** @@ -76,7 +77,7 @@ abstract class BaseFileIo extends BaseFrameworkSystem implements FilePointer, Cl */ public function closeFile () { // Debug message - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d]: fileName=%s - CALLED!', __METHOD__, __LINE__, $this->getFileObject()->getPathname())); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-IO: fileName=%s - CALLED!', $this->getFileObject()->getPathname())); if (is_null($this->getFileObject())) { // Pointer not initialized @@ -87,13 +88,13 @@ abstract class BaseFileIo extends BaseFrameworkSystem implements FilePointer, Cl } // Debug message - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d]: Closing file %s ...', __METHOD__, __LINE__, $this->getFileObject()->getPathname())); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-IO: Closing file %s ...', $this->getFileObject()->getPathname())); // Close the file pointer by NULL-ing it $this->resetFileObject(); // Debug message - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d]: EXIT!', __METHOD__, __LINE__)); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-IO: EXIT!')); } /** @@ -151,11 +152,18 @@ abstract class BaseFileIo extends BaseFrameworkSystem implements FilePointer, Cl * @return $status Status of file seek: 0 = success, -1 = failed */ public function seek (int $offset, int $whence = SEEK_SET) { + // Validate parameter + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-IO: offset=%d,whence=%d - CALLED!', $offset, $whence)); + if ($offset < 0) { + // Throw IAE + throw new InvalidArgumentException(sprintf('offset=%d is not valid', $offset)); + } + // Seek to position $status = $this->getFileObject()->fseek($offset, $whence); // Return status - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] status=%d', __METHOD__, __LINE__, $status)); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-IO: status=%d - EXIT!', $status)); return $status; } @@ -167,21 +175,21 @@ abstract class BaseFileIo extends BaseFrameworkSystem implements FilePointer, Cl */ public function size () { // Get current seek position - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] CALLED!', __METHOD__, __LINE__)); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-IO: CALLED!'); $seekPosition = $this->determineSeekPosition(); // Seek to end $seekStatus = $this->seek(0, SEEK_END); // Get position again (which is the end of the file) - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] seekStatus=%d', __METHOD__, __LINE__, $seekStatus)); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-IO: seekStatus=%d', $seekStatus)); $size = $this->determineSeekPosition(); // Reset seek position to old $this->seek($seekPosition); // Return size - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] size=%s - EXIT!', __METHOD__, __LINE__, $size)); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-IO: size=%s - EXIT!', $size)); return $size; } diff --git a/framework/main/classes/file_directories/io/class_FrameworkFileInputOutputPointer.php b/framework/main/classes/file_directories/io/class_FrameworkFileInputOutputPointer.php index 4e79954f..2805546f 100644 --- a/framework/main/classes/file_directories/io/class_FrameworkFileInputOutputPointer.php +++ b/framework/main/classes/file_directories/io/class_FrameworkFileInputOutputPointer.php @@ -149,7 +149,7 @@ class FrameworkFileInputOutputPointer extends BaseFileIo implements InputOutputP } // First seek to it, if file size is larger than zero - if ($this->getFileSize() > 0 && !$this->seek($seekPosition)) { + if (($this->getFileSize() > 0 || $seekPosition > 0) && $this->seek($seekPosition) === -1) { // Could not seek throw new InvalidArgumentException(sprintf('Could not seek to seekPosition=%d', $seekPosition)); } @@ -165,12 +165,15 @@ class FrameworkFileInputOutputPointer extends BaseFileIo implements InputOutputP /** * Rewinds to the beginning of the file * - * @return $status Status of this operation + * @return void */ public function rewind () { // Rewind the pointer /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('FILE-INPUT-OUTPUT-POINTER: CALLED!'); - return $this->getFileObject()->rewind(); + $this->getFileObject()->rewind(); + + // Trace message + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('FILE-INPUT-OUTPUT-POINTER: EXIT!'); } /** @@ -217,7 +220,7 @@ class FrameworkFileInputOutputPointer extends BaseFileIo implements InputOutputP */ public function read (int $bytes = 0) { // Validatre parameter - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-INPUT-OUTPUT-POINTER: bytes=%d - CALLED!', $bytes)); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-INPUT-OUTPUT-POINTER: bytes=%d - CALLED!', $bytes)); if ($bytes < 0) { // Bytes cannot be lesser than zero throw new InvalidArgumentException(sprintf('bytes=%d is not valid', $bytes)); @@ -233,7 +236,7 @@ class FrameworkFileInputOutputPointer extends BaseFileIo implements InputOutputP } // Then return it - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-INPUT-OUTPUT-POINTER: data[%s]=%s - EXIT!', gettype($data), $data)); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-INPUT-OUTPUT-POINTER: data[%s]=%s - EXIT!', gettype($data), $data)); return $data; } diff --git a/framework/main/classes/index/class_BaseIndex.php b/framework/main/classes/index/class_BaseIndex.php index 21a79b7d..cd9648b9 100644 --- a/framework/main/classes/index/class_BaseIndex.php +++ b/framework/main/classes/index/class_BaseIndex.php @@ -80,6 +80,10 @@ abstract class BaseIndex extends BaseFrameworkSystem { $data, $this->getIteratorInstance()->getHeaderSize() )); + } elseif (empty(trim($data, chr(0)))) { + // Empty file header + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-INDEX: File header is empty - EXIT!'); + return; } elseif (substr($data, -1, 1) != chr(BaseBinaryFile::SEPARATOR_HEADER_ENTRIES)) { // Bad last character throw new UnexpectedValueException(sprintf('data=%s does not end with "%s"', @@ -92,6 +96,7 @@ abstract class BaseIndex extends BaseFrameworkSystem { $data = substr($data, 0, -1); // And update seek position + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-INDEX: Calling this->iteratorInstance->updateSeekPosition() ...'); $this->getIteratorInstance()->updateSeekPosition(); /* @@ -149,7 +154,8 @@ abstract class BaseIndex extends BaseFrameworkSystem { ); // Write it to disk (header is always at seek position 0) - $this->getIteratorInstance()->writeData(0, $header, false); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-INDEX: Calling this->iteratorInstance->writeAtPosition(0, header=%s) ...', $header)); + $this->getIteratorInstance()->writeAtPosition(0, $header); // Trace message /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-INDEX: EXIT!'); @@ -174,30 +180,49 @@ abstract class BaseIndex extends BaseFrameworkSystem { $this->setIteratorInstance($iteratorInstance); // Calculate header size - $this->getIteratorInstance()->setHeaderSize( + $headerSize = ( strlen(Indexable::INDEX_MAGIC) + strlen(chr(BaseBinaryFile::SEPARATOR_HEADER_DATA)) + BaseBinaryFile::LENGTH_COUNT + strlen(chr(BaseBinaryFile::SEPARATOR_HEADER_ENTRIES)) ); + // Set it + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-INDEX: Setting headerSize=%d ...', $headerSize)); + $this->getIteratorInstance()->setHeaderSize($headerSize); + // Init counters and gaps array + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-INDEX: Calling this->iteratorInstance->initCountersGapsArray() ...'); $this->getIteratorInstance()->initCountersGapsArray(); + // Default is not created + $created = false; + // Is the file's header initialized? if (!$this->getIteratorInstance()->isFileHeaderInitialized()) { - // No, then create it (which may pre-allocate the index) + // First pre-allocate a bit + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-INDEX: Calling this->iteratorInstance->preAllocateFile(index) ...'); + $this->getIteratorInstance()->preAllocateFile('index'); + + // Then write file header + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-INDEX: Calling this->iteratorInstance->createFileHeader() ...'); $this->getIteratorInstance()->createFileHeader(); - // And pre-allocate a bit - $this->getIteratorInstance()->preAllocateFile('index'); + // Mark as freshly created + $created = true; } // Load the file header + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-INDEX: Calling this->readFileHeader() ...'); $this->readFileHeader(); - // Count all entries in file - $this->getIteratorInstance()->analyzeFile(); + // Freshly created? + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-INDEX: created=%d', intval($created))); + if (!$created) { + // Count all entries in file + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-INDEX: Calling this->iteratorInstance->analyzeFile() ...'); + $this->getIteratorInstance()->analyzeFile(); + } // Trace message /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-INDEX: EXIT!'); diff --git a/framework/main/classes/index/file_stack/class_FileStackIndex.php b/framework/main/classes/index/file_stack/class_FileStackIndex.php index efb563cc..0d169246 100644 --- a/framework/main/classes/index/file_stack/class_FileStackIndex.php +++ b/framework/main/classes/index/file_stack/class_FileStackIndex.php @@ -124,4 +124,32 @@ class FileStackIndex extends BaseIndex implements IndexableStack, Registerable { } } + /** + * Writes at given position by seeking to it. + * + * @param $seekPosition Seek position in file + * @param $dataStream Data to be written + * @return mixed Number of writes bytes or false on error + * @throws InvalidArgumentException If a parameter is not valid + */ + public function writeAtPosition (int $seekPosition, string $dataStream) { + // Validate parameter + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-STACK-INDEX: seekPosition=%d,dataStream(%d)=%s - CALLED!', $seekPosition, strlen($dataStream), $dataStream)); + if ($seekPosition < 0) { + // Invalid seek position + throw new InvalidArgumentException(sprintf('seekPosition=%d is not valid.', $seekPosition)); + } elseif (empty($dataStream)) { + // Empty dataStream + throw new InvalidArgumentException('Parameter "dataStream" is empty'); + } + + // Call iterated object's method + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-STACK-INDEX: Calling this->iteratorInstance->writeAtPosition(%d, %s) ...', $seekPosition, $dataStream)); + $status = $this->getIteratorInstance()->writeAtPosition($seekPosition, $dataStream); + + // Return status + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-STACK-INDEX: status[%s]=%d - EXIT!', gettype($status), $status)); + return $status; + } + } diff --git a/framework/main/classes/iterator/file/class_FileIterator.php b/framework/main/classes/iterator/file/class_FileIterator.php index a246927c..24fb2780 100644 --- a/framework/main/classes/iterator/file/class_FileIterator.php +++ b/framework/main/classes/iterator/file/class_FileIterator.php @@ -153,11 +153,10 @@ class FileIterator extends BaseIterator implements SeekableWritableFileIterator public function rewind () { // Call block instance /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('FILE-ITERATOR: CALLED!'); - $status = $this->getBlockInstance()->rewind(); + $this->getBlockInstance()->rewind(); - // Return status - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-ITERATOR: status=%d - EXIT!', intval($status))); - return $status; + // Trace message + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('FILE-ITERATOR: EXIT!'); } /** @@ -180,19 +179,20 @@ class FileIterator extends BaseIterator implements SeekableWritableFileIterator * Seeks to given position * * @param $seekPosition Seek position in file + * @param $whence Added to offset (default: only use offset to seek to) * @return $status Status of this operation * @throws InvalidArgumentException If a parameter is not valid */ - public function seek (int $seekPosition) { + public function seek (int $seekPosition, int $whence = SEEK_SET) { // Validate parameter - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-ITERATOR: seekPosition=%d - CALLED!', $seekPosition)); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-ITERATOR: seekPosition=%d,whence=%d - CALLED!', $seekPosition, $whence)); if ($seekPosition < 0) { // Throw IAE throw new InvalidArgumentException(sprintf('seekPosition=%d is not valid', $seekPosition)); } // Call block instance - $status = $this->getBlockInstance()->seek($seekPosition); + $status = $this->getBlockInstance()->seek($seekPosition, $whence); // Return status /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-ITERATOR: status=%d - EXIT!', intval($status))); @@ -445,12 +445,41 @@ class FileIterator extends BaseIterator implements SeekableWritableFileIterator } // Call block instance + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-ITERATOR: Calling this->blockInstance->writeData(%d,data()=%d,%d) ...', $seekPosition, strlen($data), intval($flushHeader))); $this->getBlockInstance()->writeData($seekPosition, $data, $flushHeader); // Trace message /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('FILE-ITERATOR: EXIT!'); } + /** + * Writes at given position by seeking to it. + * + * @param $seekPosition Seek position in file + * @param $dataStream Data to be written + * @return mixed Number of writes bytes or false on error + * @throws InvalidArgumentException If a parameter is not valid + */ + public function writeAtPosition (int $seekPosition, string $dataStream) { + // Validate parameter + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-ITERATOR: seekPosition=%d,dataStream(%d)=%s - CALLED!', $seekPosition, strlen($dataStream), $dataStream)); + if ($seekPosition < 0) { + // Invalid seek position + throw new InvalidArgumentException(sprintf('seekPosition=%d is not valid.', $seekPosition)); + } elseif (empty($dataStream)) { + // Empty dataStream + throw new InvalidArgumentException('Parameter "dataStream" is empty'); + } + + // Call iterated object's method + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-ITERATOR: Calling this->blockInstance->writeAtPosition(%d, %s) ...', $seekPosition, $dataStream)); + $status = $this->getBlockInstance()->writeAtPosition($seekPosition, $dataStream); + + // Return status + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-ITERATOR: status[%s]=%d - EXIT!', gettype($status), $status)); + return $status; + } + /** * Getter for seek position * @@ -462,7 +491,7 @@ class FileIterator extends BaseIterator implements SeekableWritableFileIterator $seekPosition = $this->getBlockInstance()->getSeekPosition(); // Return position - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-ITERATOR: seekPosition=%d - EXIT!', $seekPosition)); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-ITERATOR: seekPosition[%s]=%d - EXIT!', gettype($seekPosition), $seekPosition)); return $seekPosition; } @@ -533,7 +562,7 @@ class FileIterator extends BaseIterator implements SeekableWritableFileIterator $seekPosition = $this->getBlockInstance()->searchNextGap($length); // Return position - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-ITERATOR: seekPosition=%d - EXIT!', $seekPosition)); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FILE-ITERATOR: seekPosition[%s]=%d - EXIT!', gettype($seekPosition), $seekPosition)); return $seekPosition; } diff --git a/framework/main/classes/output/console/class_ConsoleOutput.php b/framework/main/classes/output/console/class_ConsoleOutput.php index 3ffff09f..1b11c51a 100644 --- a/framework/main/classes/output/console/class_ConsoleOutput.php +++ b/framework/main/classes/output/console/class_ConsoleOutput.php @@ -95,7 +95,7 @@ class ConsoleOutput extends BaseOutput implements OutputStreamer { * @param $stripTags Whether HTML tags shall be stripped out * @return void */ - public final function output ($outStream = false, $stripTags = false) { + public final function output (string $outStream = '', bool $stripTags = false) { print trim($outStream) . PHP_EOL; } diff --git a/framework/main/classes/output/debug/console/class_DebugConsoleOutput.php b/framework/main/classes/output/debug/console/class_DebugConsoleOutput.php index 7875e001..8f7d19f6 100644 --- a/framework/main/classes/output/debug/console/class_DebugConsoleOutput.php +++ b/framework/main/classes/output/debug/console/class_DebugConsoleOutput.php @@ -63,18 +63,18 @@ class DebugConsoleOutput extends BaseDebugOutput implements Debugger, OutputStre * @param $stripTags Whether HTML tags shall be stripped out * @return void */ - public final function outputStream ($output, $stripTags = false) { + public final function outputStream (string $output, bool $stripTags = false) { // Strip HTML tags out? if ($stripTags === true) { // Prepare the output without HTML tags $output = trim(html_entity_decode(strip_tags(stripslashes($output)))); - } // END - if + } // Are debug times enabled? if (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('debug_' . FrameworkBootstrap::getRequestTypeFromSystem() . '_output_timings') == 'Y') { // Output it first $output = $this->getPrintableExecutionTime() . $output; - } // END - if + } // And print it out... printf('%s%s', str_replace('->', '->', $output), PHP_EOL); @@ -87,11 +87,11 @@ class DebugConsoleOutput extends BaseDebugOutput implements Debugger, OutputStre * @param $stripTags Whether HTML tags shall be stripped out * @return void */ - public final function output ($outStream = false, $stripTags = false) { + public final function output (string $outStream = '', bool $stripTags = false) { // Empty output will be silently ignored - if ($outStream !== false) { + if (!empty($outStream)) { $this->outputStream($outStream, $stripTags); - } // END - if + } } /** diff --git a/framework/main/classes/output/debug/error/class_DebugErrorLogOutput.php b/framework/main/classes/output/debug/error/class_DebugErrorLogOutput.php index cdbcf57c..7903b910 100644 --- a/framework/main/classes/output/debug/error/class_DebugErrorLogOutput.php +++ b/framework/main/classes/output/debug/error/class_DebugErrorLogOutput.php @@ -61,7 +61,7 @@ class DebugErrorLogOutput extends BaseDebugOutput implements Debugger, OutputStr * @param $stripTags Whether HTML tags shall be stripped out * @return void */ - public final function outputStream ($output, $stripTags = false) { + public final function outputStream (string $output, bool $stripTags = false) { // Split multiple lines into and array to put them out line-by-line $errorLines = explode(chr(10), $output); @@ -85,11 +85,11 @@ class DebugErrorLogOutput extends BaseDebugOutput implements Debugger, OutputStr * @param $stripTags Whether HTML tags shall be stripped out * @return void */ - public final function output ($outStream = false, $stripTags = false) { + public final function output (string $outStream = '', bool $stripTags = false) { // Empty output will be silently ignored - if ($outStream !== false) { + if (!empty($outStream)) { $this->outputStream($outStream); - } // END - if + } } /** diff --git a/framework/main/classes/output/debug/web/class_DebugWebOutput.php b/framework/main/classes/output/debug/web/class_DebugWebOutput.php index 2f87522c..e2656b1d 100644 --- a/framework/main/classes/output/debug/web/class_DebugWebOutput.php +++ b/framework/main/classes/output/debug/web/class_DebugWebOutput.php @@ -61,7 +61,7 @@ class DebugWebOutput extends BaseDebugOutput implements Debugger, OutputStreamer * @param $stripTags Whether HTML tags shall be stripped out * @return void */ - public final function outputStream ($output, $stripTags = false) { + public final function outputStream (string $output, bool $stripTags = false) { // Strip out any
$output = str_replace('
', '', $output); printf('' . PHP_EOL, stripslashes($output)); @@ -74,11 +74,11 @@ class DebugWebOutput extends BaseDebugOutput implements Debugger, OutputStreamer * @param $stripTags Whether HTML tags shall be stripped out * @return void */ - public final function output ($outStream = false, $stripTags = false) { + public final function output (string $outStream = '', bool $stripTags = false) { // Empty output will be silently ignored - if ($outStream !== false) { + if (!empty($outStream)) { $this->outputStream($outStream, $stripTags); - } // END - if + } } /** diff --git a/framework/main/classes/output/web/class_WebOutput.php b/framework/main/classes/output/web/class_WebOutput.php index 44e24e01..6abfc10f 100644 --- a/framework/main/classes/output/web/class_WebOutput.php +++ b/framework/main/classes/output/web/class_WebOutput.php @@ -82,7 +82,7 @@ class WebOutput extends BaseOutput implements OutputStreamer, Registerable { * @param $stripTags Whether HTML tags shall be stripped out * @return void */ - public final function output ($outStream = false, $stripTags = false) { + public final function output (string $outStream = '', bool $stripTags = false) { print(stripslashes($outStream)); } diff --git a/framework/main/classes/stacker/file/class_BaseFileStack.php b/framework/main/classes/stacker/file/class_BaseFileStack.php index 54205230..859eebd8 100644 --- a/framework/main/classes/stacker/file/class_BaseFileStack.php +++ b/framework/main/classes/stacker/file/class_BaseFileStack.php @@ -81,9 +81,9 @@ abstract class BaseFileStack extends BaseStacker implements StackableFile { // Then read it (see constructor for calculation) $data = $this->getIteratorInstance()->read($this->getIteratorInstance()->getHeaderSize()); - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: Read %d bytes (%d wanted).', strlen($data), $this->getIteratorInstance()->getHeaderSize())); // Have all requested bytes been read? + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: Read %d bytes (%d wanted).', strlen($data), $this->getIteratorInstance()->getHeaderSize())); if (strlen($data) != $this->getIteratorInstance()->getHeaderSize()) { // Bad data length throw new UnexpectedValueException(sprintf('data(%d)=%s does not match iteratorInstance->headerSize=%d', @@ -91,6 +91,10 @@ abstract class BaseFileStack extends BaseStacker implements StackableFile { $data, $this->getIteratorInstance()->getHeaderSize() )); + } elseif (empty(trim($data, chr(0)))) { + // Empty header, file is freshly pre-allocated + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-STACK: Empty file header detected - EXIT!'); + return; } // Last character must be the separator @@ -107,6 +111,7 @@ abstract class BaseFileStack extends BaseStacker implements StackableFile { $data = substr($data, 0, -1); // And update seek position + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-STACK: Calling this->iteratorInstance->updateSeekPosition() ...'); $this->getIteratorInstance()->updateSeekPosition(); /* @@ -156,7 +161,7 @@ abstract class BaseFileStack extends BaseStacker implements StackableFile { $this->getIteratorInstance()->setHeader($header); // Trace message - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: EXIT!', __METHOD__, __LINE__)); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-STACK: EXIT!'); } /** @@ -174,13 +179,13 @@ abstract class BaseFileStack extends BaseStacker implements StackableFile { // Separator magic<->count chr(BaseBinaryFile::SEPARATOR_HEADER_DATA), - // Total entries (will be zero) and pad it to 20 chars + // Padded total entries str_pad(StringUtils::dec2hex($this->getIteratorInstance()->getCounter()), BaseBinaryFile::LENGTH_COUNT, '0', STR_PAD_LEFT), // Separator count<->seek position chr(BaseBinaryFile::SEPARATOR_HEADER_DATA), - // Position (will be zero) + // Padded seek position str_pad(StringUtils::dec2hex($this->getIteratorInstance()->getSeekPosition(), 2), BaseBinaryFile::LENGTH_POSITION, '0', STR_PAD_LEFT), // Separator position<->entries @@ -188,7 +193,8 @@ abstract class BaseFileStack extends BaseStacker implements StackableFile { ); // Write it to disk (header is always at seek position 0) - $this->getIteratorInstance()->writeData(0, $header, false); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: Calling this->iteratorInstance->writeAtPosition(0, header=%s) ...', $header)); + $this->getIteratorInstance()->writeAtPosition(0, $header); // Trace message /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-STACK: EXIT!'); @@ -221,7 +227,7 @@ abstract class BaseFileStack extends BaseStacker implements StackableFile { $this->setIteratorInstance($iteratorInstance); // Calculate header size - $this->getIteratorInstance()->setHeaderSize( + $headerSize = ( strlen(StackableFile::STACK_MAGIC) + strlen(chr(BaseBinaryFile::SEPARATOR_HEADER_DATA)) + BaseBinaryFile::LENGTH_COUNT + @@ -230,28 +236,48 @@ abstract class BaseFileStack extends BaseStacker implements StackableFile { strlen(chr(BaseBinaryFile::SEPARATOR_HEADER_ENTRIES)) ); + // Setting it + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: Setting headerSize=%d ...', $headerSize)); + $this->getIteratorInstance()->setHeaderSize($headerSize); + // Init counters and gaps array + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-STACK: Calling this->iteratorInstance->initCountersGapsArray() ...'); $this->getIteratorInstance()->initCountersGapsArray(); + // Default is not created/already exists + $created = false; + // Is the file's header initialized? if (!$this->getIteratorInstance()->isFileHeaderInitialized()) { - // No, then create it (which may pre-allocate the stack) + // First pre-allocate a bit + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-STACK: Calling this->iteratorInstance->preAllocateFile(file_stack) ...'); + $this->getIteratorInstance()->preAllocateFile('file_stack'); + + // Then create file header + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-STACK: this->iteratorInstance->createFileHeader() ...'); $this->getIteratorInstance()->createFileHeader(); - // And pre-allocate a bit - $this->getIteratorInstance()->preAllocateFile('file_stack'); + // Set flag + $created = true; } // Load the file header + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-STACK: Calling this->readFileHeader() ...'); $this->readFileHeader(); - // Count all entries in file - $this->getIteratorInstance()->analyzeFile(); + // Not created/already exists? + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: created=%d', intval($created))); + if (!$created) { + // Count all entries in file + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-FILE-STACK: Calling this->iteratorInstance->analyzeFile() ...'); + $this->getIteratorInstance()->analyzeFile(); + } /* * Get stack index instance. This can be used for faster * "defragmentation" and startup. */ + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: fileInfoInstance[%s]=%s,type=%s', get_class($fileInfoInstance), $fileInfoInstance, $type)); $indexInstance = FileStackIndexFactory::createFileStackIndexInstance($fileInfoInstance, $type); // And set it here @@ -618,10 +644,25 @@ abstract class BaseFileStack extends BaseStacker implements StackableFile { * @throws UnsupportedOperationException This method is not (and maybe never will be) supported */ public function writeData (int $seekPosition, string $data, bool $flushHeader = true) { + // Not supported /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: seekPosition=%s,data[]=%s,flushHeader=%d', $seekPosition, gettype($data), intval($flushHeader))); throw new UnsupportedOperationException(array($this, __FUNCTION__, $this->getIteratorInstance()->getPointerInstance()), self::EXCEPTION_UNSPPORTED_OPERATION); } + /** + * Writes at given position by seeking to it. + * + * @param $seekPosition Seek position in file + * @param $dataStream Data to be written + * @return mixed Number of writes bytes or false on error + * @throws UnsupportedOperationException This method is not (and maybe never will be) supported + */ + public function writeAtPosition (int $seekPosition, string $dataStream) { + // Not supported + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-FILE-STACK: seekPosition=%d,dataStream(%d)=%s - CALLED!', $seekPosition, strlen($dataStream), $dataStream)); + throw new UnsupportedOperationException(array($this, __FUNCTION__, $this->getIteratorInstance()->getPointerInstance()), self::EXCEPTION_UNSPPORTED_OPERATION); + } + /** * Writes given value to the file and returns a hash and gap position for it * diff --git a/framework/main/classes/stacker/file/fifo/class_FiFoFileStack.php b/framework/main/classes/stacker/file/fifo/class_FiFoFileStack.php index f2fce745..42eab523 100644 --- a/framework/main/classes/stacker/file/fifo/class_FiFoFileStack.php +++ b/framework/main/classes/stacker/file/fifo/class_FiFoFileStack.php @@ -160,12 +160,13 @@ class FiFoFileStack extends BaseFileStack implements StackableFile, Calculatable * Seeks to given position * * @param $seekPosition Seek position in file + * @param $whence Added to offset (default: only use offset to seek to) * @return $status Status of this operation * @throws InvalidArgumentException If a parameter is invalid */ - public function seek (int $seekPosition) { + public function seek (int $seekPosition, int $whence = SEEK_SET) { // Validate parameter - /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FIFO-FILE-STACK: seekPosition=%d - CALLED!', $seekPosition)); + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('FIFO-FILE-STACK: seekPosition=%d,whence=%d - CALLED!', $seekPosition, $whence)); if ($seekPosition < 0) { // Invalid seek position throw new InvalidArgumentException(sprintf('seekPosition=%d is not valid', $seekPosition)); diff --git a/framework/main/interfaces/block/class_Block.php b/framework/main/interfaces/block/class_Block.php index 9f593ecc..5c25324b 100644 --- a/framework/main/interfaces/block/class_Block.php +++ b/framework/main/interfaces/block/class_Block.php @@ -139,6 +139,16 @@ interface Block extends FrameworkInterface { */ function writeData (int $seekPosition, string $data, bool $flushHeader = true); + /** + * Writes at given position by seeking to it. + * + * @param $seekPosition Seek position in file + * @param $dataStream Data to be written + * @return mixed Number of writes bytes or false on error + * @throws InvalidArgumentException If a parameter is not valid + */ + function writeAtPosition (int $seekPosition, string $dataStream); + /** * Searches for next suitable gap the given length of data can fit in * including padding bytes. diff --git a/framework/main/interfaces/debug/class_Debugger.php b/framework/main/interfaces/debug/class_Debugger.php index 437a462c..7f2ac43f 100644 --- a/framework/main/interfaces/debug/class_Debugger.php +++ b/framework/main/interfaces/debug/class_Debugger.php @@ -35,6 +35,6 @@ interface Debugger extends FrameworkInterface { * @param $stripTags Whether HTML tags shall be stripped out * @return void */ - function outputStream ($output, $stripTags = false); + function outputStream (string $output, bool $stripTags = false); } diff --git a/framework/main/interfaces/io/output/class_OutputStreamer.php b/framework/main/interfaces/io/output/class_OutputStreamer.php index b7b7ae72..1448c698 100644 --- a/framework/main/interfaces/io/output/class_OutputStreamer.php +++ b/framework/main/interfaces/io/output/class_OutputStreamer.php @@ -35,6 +35,6 @@ interface OutputStreamer extends StreamableOutput { * @param $stripTags Whether HTML tags shall be stripped out * @return void */ - function output ($outStream = false, $stripTags = false); + function output (string $outStream = '', bool $stripTags = false); } diff --git a/framework/main/interfaces/iterator/file/class_SeekableWritableFileIterator.php b/framework/main/interfaces/iterator/file/class_SeekableWritableFileIterator.php index 4a497bf3..728a3457 100644 --- a/framework/main/interfaces/iterator/file/class_SeekableWritableFileIterator.php +++ b/framework/main/interfaces/iterator/file/class_SeekableWritableFileIterator.php @@ -154,6 +154,15 @@ interface SeekableWritableFileIterator extends SeekableIterator { */ function writeData (int $seekPosition, string $data, bool $flushHeader = true); + /** + * Writes at given position by seeking to it. + * + * @param $seekPosition Seek position in file + * @param $data Data to be written + * @return mixed Number of writes bytes or false on error + */ + function writeAtPosition (int $seedPosition, string $data); + /** * Getter for seek position * -- 2.39.5