mirror of
https://github.com/Icinga/icingaweb2.git
synced 2025-09-24 02:17:40 +02:00
parent
2a4fdd12d7
commit
2f46929ac7
176
library/Icinga/Util/Buffer.php
Normal file
176
library/Icinga/Util/Buffer.php
Normal file
@ -0,0 +1,176 @@
|
||||
<?php
|
||||
/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */
|
||||
|
||||
namespace Icinga\Util;
|
||||
|
||||
use Icinga\Exception\IcingaException;
|
||||
|
||||
/**
|
||||
* Stores data in memory or a temporary file not to get out of memory
|
||||
*/
|
||||
class Buffer
|
||||
{
|
||||
/**
|
||||
* The actual buffer
|
||||
*
|
||||
* @var resource
|
||||
*/
|
||||
protected $handle;
|
||||
|
||||
/**
|
||||
* The amount of bytes currently stored in the buffer
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $size = 0;
|
||||
|
||||
/**
|
||||
* Whether the current position of {@link handle} is the end of file
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $atEOF = true;
|
||||
|
||||
/**
|
||||
* Buffer constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->handle = fopen('php://temp', 'w+b');
|
||||
}
|
||||
|
||||
/**
|
||||
* Append the given data to the buffer
|
||||
*
|
||||
* @param string $data
|
||||
*/
|
||||
public function append($data)
|
||||
{
|
||||
$strlen = strlen($data);
|
||||
if ($strlen) {
|
||||
$this->seekToEnd();
|
||||
$this->fwrite($this->handle, $data);
|
||||
$this->size += $strlen;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get size
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getSize()
|
||||
{
|
||||
return $this->size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data stored in the buffer
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws IcingaException In case of an error
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$result = '';
|
||||
|
||||
if ($this->size) {
|
||||
$this->seekToBegin();
|
||||
for (;;) {
|
||||
$buf = fread($this->handle, $this->size);
|
||||
if ($buf === '') {
|
||||
break;
|
||||
}
|
||||
$result .= $buf;
|
||||
}
|
||||
|
||||
if (strlen($result) !== $this->size) {
|
||||
throw new IcingaException('Couldn\'t read all data from the buffer');
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass the data stored in the buffer to the user agent (as with {@link fpassthru()})
|
||||
*/
|
||||
public function fpassthru()
|
||||
{
|
||||
if ($this->size) {
|
||||
$this->seekToBegin();
|
||||
// fpassthru() returns the amount of bytes passed so we could perform
|
||||
// the same error check as in __toString(), but throwing exceptions here
|
||||
// makes no sense as we're already writing the response body
|
||||
fpassthru($this->handle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fseek({@link handle}) to the begin of the buffer if not already done
|
||||
*/
|
||||
protected function seekToBegin()
|
||||
{
|
||||
if ($this->atEOF) {
|
||||
if ($this->size) {
|
||||
$this->fseek($this->handle, 0);
|
||||
}
|
||||
$this->atEOF = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fseek({@link handle}) to the end of the buffer if not already done
|
||||
*/
|
||||
protected function seekToEnd()
|
||||
{
|
||||
if (! $this->atEOF) {
|
||||
if ($this->size) {
|
||||
$this->fseek($this->handle, 0, SEEK_END);
|
||||
}
|
||||
$this->atEOF = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards all passed parameters to {@link fseek()}
|
||||
*
|
||||
* @throws IcingaException In case of an error
|
||||
*/
|
||||
protected function fseek()
|
||||
{
|
||||
if (call_user_func_array('fseek', func_get_args()) === -1) {
|
||||
$this->reportFunctionCallError('fseek', func_get_args());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards all passed parameters to {@link fwrite()}
|
||||
*
|
||||
* @throws IcingaException In case of an error
|
||||
*/
|
||||
protected function fwrite()
|
||||
{
|
||||
if (call_user_func_array('fwrite', func_get_args()) === 0) {
|
||||
$this->reportFunctionCallError('fwrite', func_get_args());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an exception telling that the given function call didn't succeed
|
||||
*
|
||||
* @param string $functionName
|
||||
* @param array $passedArgs
|
||||
*
|
||||
* @throws IcingaException unconditional
|
||||
*/
|
||||
protected function reportFunctionCallError($functionName, array $passedArgs)
|
||||
{
|
||||
$args = array();
|
||||
foreach ($passedArgs as $arg) {
|
||||
$args[] = print_r($arg, true);
|
||||
}
|
||||
throw new IcingaException('Couldn\'t ' . $functionName . '(' . implode(', ', $args) . ')');
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user