Add Zend_Io package proposal

git-svn-id: http://php-reader.googlecode.com/svn/branches/zend@151 51a70ab9-7547-0410-9469-37e369ee0574
This commit is contained in:
svollbehr
2009-04-26 18:24:18 +00:00
parent c072a6b826
commit 3e11eab961
8 changed files with 1607 additions and 1 deletions

624
src/Zend/Io/Writer.php Normal file
View File

@@ -0,0 +1,624 @@
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend_Io
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
* The Zend_Io_Writer class represents a character stream providing means to
* write primitive types (string, integers, ...) to it.
*
* @category Zend
* @package Zend_Io
* @author Sven Vollbehr <sven@vollbehr.eu>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
class Zend_Io_Writer
{
const MACHINE_ENDIAN_ORDER = 0;
const LITTLE_ENDIAN_ORDER = 1;
const BIG_ENDIAN_ORDER = 2;
/**
* The endianess of the current machine.
*
* @var integer
*/
private static $_endianess = 0;
/**
* The resource identifier of the stream.
*
* @var resource
*/
protected $_fd = null;
/**
* Size of the underlying stream.
*
* @var integer
*/
protected $_size = 0;
/**
* Constructs the Zend_Io_Writer class with given open file descriptor.
*
* @param resource $fd The file descriptor.
* @throws Zend_Io_Exception if file descriptor is not valid
*/
public function __construct($fd)
{
if (!is_resource($fd) ||
!in_array(get_resource_type($fd), array('stream'))) {
require_once('Zend/Io/Exception.php');
throw new Zend_Io_Exception('Invalid resource type (only resources of type stream are supported)');
}
$this->_fd = $fd;
$offset = $this->getOffset();
fseek($this->_fd, 0, SEEK_END);
$this->_size = ftell($this->_fd);
fseek($this->_fd, $offset);
}
/**
* Default destructor.
*/
public function __destruct() {}
/**
* Returns the current point of operation.
*
* @return integer
* @throws Zend_Io_Exception if the stream is closed
*/
public function getOffset()
{
if ($this->_fd === null) {
require_once('Zend/Io/Exception.php');
throw new Zend_Io_Exception('Cannot operate on a closed stream');
}
return ftell($this->_fd);
}
/**
* Sets the point of operation, ie the cursor offset value. The offset may
* also be set to a negative value when it is interpreted as an offset from
* the end of the stream instead of the beginning.
*
* @param integer $offset The new point of operation.
* @return void
* @throws Zend_Io_Exception if the stream is closed
*/
public function setOffset($offset)
{
if ($this->_fd === null) {
require_once('Zend/Io/Exception.php');
throw new Zend_Io_Exception('Cannot operate on a closed stream');
}
fseek($this->_fd, $offset < 0 ? $this->getSize() + $offset : $offset);
}
/**
* Returns the stream size in bytes.
*
* @return integer
* @throws Zend_Io_Exception if the stream is closed
*/
public function getSize()
{
if ($this->_fd === null) {
require_once('Zend/Io/Exception.php');
throw new Zend_Io_Exception('Cannot operate on a closed stream');
}
return $this->_size;
}
/**
* Sets the stream size in bytes, and truncates if required.
*
* @param integer $size The new size
* @return void
* @throws Zend_Io_Exception if the stream is closed
*/
public function setSize($size)
{
if ($this->_fd === null) {
require_once('Zend/Io/Exception.php');
throw new Zend_Io_Exception('Cannot operate on a closed stream');
}
ftruncate($this->_fd, $size);
}
/**
* Returns the underlying stream file descriptor.
*
* @return resource
*/
public function getFileDescriptor()
{
return $this->_fd;
}
/**
* Writes <var>value</var> up to <var>length</var> bytes to the stream.
*
* @param string $value The value to write to the stream.
* @param integer $length The number of bytes to write. Defaults to the
* length of the given value.
* @return Zend_Io_Writer
* @throws Zend_Io_Exception if the stream is closed
*/
public function write($value, $length = null)
{
if ($this->_fd === null) {
require_once('Zend/Io/Exception.php');
throw new Zend_Io_Exception('Cannot operate on a closed stream');
}
fwrite($this->_fd, $value, $length === null ? strlen($value) : $length);
return $this;
}
/**
* Writes an 8-bit integer as binary data to the stream.
*
* @param integer $value The input value.
* @return Zend_Io_Writer
* @throws Zend_Io_Exception if the stream is closed
*/
public final function writeInt8($value)
{
return $this->write(pack('c*', $value));
}
/**
* Writes an unsigned 8-bit integer as binary data to the stream.
*
* @param integer $value The input value.
* @return Zend_Io_Writer
* @throws Zend_Io_Exception if the stream is closed
*/
public final function writeUInt8()
{
return $this->write(pack('C*', $value));
}
/**
* Returns signed 16-bit integer as machine endian ordered binary data.
*
* @param integer $value The input value.
* @return string
*/
private function _toInt16($value)
{
return pack('s*', $value);
}
/**
* Writes a signed 16-bit integer as little-endian ordered binary data to
* the stream.
*
* @param integer $value The input value.
* @return Zend_Io_Writer
* @throws Zend_Io_Exception if the stream is closed
*/
public final function writeInt16LE($value)
{
if ($this->_isBigEndian()) {
return $this->write(strrev($this->_toInt16($value)));
} else {
return $this->write($this->_toInt16($value));
}
}
/**
* Returns signed 16-bit integer as big-endian ordered binary data to the
* stream.
*
* @param integer $value The input value.
* @return Zend_Io_Writer
* @throws Zend_Io_Exception if the stream is closed
*/
public final function writeInt16BE($value)
{
if ($this->_isLittleEndian()) {
return $this->write(strrev($this->_toInt16($value)));
} else {
return $this->write($this->_toInt16($value));
}
}
/**
* Writes unsigned 16-bit integer as little-endian ordered binary data
* to the stream.
*
* @param integer $value The input value.
* @return Zend_Io_Writer
* @throws Zend_Io_Exception if the stream is closed
*/
public final function writeUInt16LE($value)
{
return $this->write(pack('v*', $value));
}
/**
* Writes unsigned 16-bit integer as big-endian ordered binary data to the
* stream.
*
* @param integer $value The input value.
* @return Zend_Io_Writer
* @throws Zend_Io_Exception if the stream is closed
*/
public final function writeUInt16BE($value)
{
return $this->write(pack('n*', $value));
}
/**
* Returns signed 32-bit integer as machine-endian ordered binary data.
*
* @param integer $value The input value.
* @return string
*/
private final function _toInt32($value)
{
return pack('l*', $value);
}
/**
* Writes signed 32-bit integer as little-endian ordered binary data to the
* stream.
*
* @param integer $value The input value.
* @return Zend_Io_Writer
* @throws Zend_Io_Exception if the stream is closed
*/
public final function writeInt32LE($value)
{
if ($this->_isBigEndian()) {
return $this->write(strrev($this->_toInt32($value)));
} else {
return $this->write($this->_toInt32($value));
}
}
/**
* Writes signed 32-bit integer as big-endian ordered binary data to the
* stream.
*
* @param integer $value The input value.
* @return Zend_Io_Writer
* @throws Zend_Io_Exception if the stream is closed
*/
public final function writeInt32BE($value)
{
if ($this->_isLittleEndian()) {
return $this->write(strrev($this->_toInt32($value)));
} else {
return $this->write($this->_toInt32($value));
}
}
/**
* Writes unsigned 32-bit integer as little-endian ordered binary data to
* the stream.
*
* @param integer $value The input value.
* @return Zend_Io_Writer
* @throws Zend_Io_Exception if the stream is closed
*/
public final function writeUInt32LE($value)
{
return $this->write(pack('V*', $value));
}
/**
* Writes unsigned 32-bit integer as big-endian ordered binary data to the
* stream.
*
* @param integer $value The input value.
* @return Zend_Io_Writer
* @throws Zend_Io_Exception if the stream is closed
*/
public final function writeUInt32BE($value)
{
return $this->write(pack('N*', $value));
}
/**
* Writes 64-bit float as little-endian ordered binary data string to the
* stream.
*
* @param integer $value The input value.
* @return Zend_Io_Writer
* @throws Zend_Io_Exception if the stream is closed
*/
public final function writeInt64LE($value)
{
return $this->write(pack('V*', $value & 0xffffffff, $value / (0xffffffff+1)));
}
/**
* Writes 64-bit float as big-endian ordered binary data string to the
* stream.
*
* @param integer $value The input value.
* @return Zend_Io_Writer
* @throws Zend_Io_Exception if the stream is closed
*/
public final function writeInt64BE($value)
{
return $this->write(pack('N*', $value / (0xffffffff+1), $value & 0xffffffff));
}
/**
* Returns a floating point number as machine endian ordered binary data.
*
* @param float $value The input value.
* @return string
*/
private function _toFloat($value)
{
return pack('f*', $value);
}
/**
* Writes a floating point number as little-endian ordered binary data to
* the stream.
*
* @param float $value The input value.
* @return Zend_Io_Writer
* @throws Zend_Io_Exception if the stream is closed
*/
public final function writeFloatLE($value)
{
if ($this->_isBigEndian()) {
return $this->write(strrev($this->_toFloat($value)));
} else {
return $this->write($this->_toFloat($value));
}
}
/**
* Writes a floating point number as big-endian ordered binary data to the
* stream.
*
* @param float $value The input value.
* @return Zend_Io_Writer
* @throws Zend_Io_Exception if the stream is closed
*/
public final function writeFloatBE($value)
{
if ($this->_isLittleEndian()) {
return $this->write(strrev($this->_toFloat($value)));
} else {
return $this->write($this->_toFloat($value));
}
}
/**
* Writes string as binary data padded to given length with zeros. If
* <var>length</var> is smaller than the length of the string, it is
* considered as the length of the padding.
*
* @param string $value The input value.
* @param integer $length The length to which to pad the value.
* @param string $padding The padding character.
* @return Zend_Io_Writer
* @throws Zend_Io_Exception if the stream is closed
*/
public final function writeString8($value, $length = null, $padding = "\0")
{
if ($length === null) {
$length = strlen($value);
}
if ($length < ($tmp = strlen($value))) {
$length = $tmp + $length;
}
return $this->write(str_pad($value, $length, $padding));
}
/**
* Writes the multibyte string as binary data with given byte order mark
* (BOM) and padded to given length with zeros. Length is given in unicode
* characters so each character adds two zeros to the string. If length is
* smaller than the length of the string, it is considered as the length of
* the padding.
*
* If byte order mark is <var>null</var> no mark is inserted to the binary
* data.
*
* @param string $value The input value.
* @param integer $order The byte order of the binary data string.
* @param integer $length The length to which to pad the value.
* @param string $padding The padding character.
* @return string
* @throws Zend_Io_Exception if the stream is closed
*/
public final function writeString16
($value, $order = null, $length = null, $padding = "\0")
{
if ($length === null) {
$length = (int)(strlen($value) / 2);
}
if ($length < ($tmp = strlen($value) / 2)) {
$length = $tmp + $length;
}
if ($order == self::BIG_ENDIAN_ORDER &&
!(ord($value[0]) == 0xfe && ord($value[1]) == 0xff)) {
$value = 0xfeff . $value;
$length++;
}
if ($order == self::LITTLE_ENDIAN_ORDER &&
!(ord($value[0]) == 0xff && ord($value[1]) == 0xfe)) {
$value = 0xfffe . $value;
$length++;
}
return $this->write(str_pad($value, $length * 2, $padding));
}
/**
* Writes hexadecimal string having high nibble first as binary data to the
* stream.
*
* @param string $value The input value.
* @return Zend_Io_Writer
* @throws Zend_Io_Exception if <var>length</var> attribute is negative or
* if the stream is closed
*/
public final function writeHHex($length)
{
return $this->write(pack('H*', $value));
}
/**
* Writes hexadecimal string having low nibble first as binary data to the
* stream.
*
* @param string $value The input value.
* @return Zend_Io_Writer
* @throws Zend_Io_Exception if <var>length</var> attribute is negative or
* if the stream is closed
*/
public final function writeLHex($length)
{
return $this->write(pack('h*', $value));
}
/**
* Writes big-endian ordered hexadecimal GUID string as little-endian
* ordered binary data string to the stream.
*
* @param string $value The input value.
* @return Zend_Io_Writer
* @throws Zend_Io_Exception if the stream is closed
*/
public final function writeGuid()
{
$string = '';
$C = preg_split('/-/', $value);
return $this->write
(pack
('V1v2N2', hexdec($C[0]), hexdec($C[1]), hexdec($C[2]),
hexdec($C[3] . substr($C[4], 0, 4)), hexdec(substr($C[4], 4))));
}
/**
* Forces write of all buffered output to the underlying resource.
*
* @return void
* @throws Zend_Io_Exception if the stream is closed
*/
public function flush()
{
if ($this->_fd === null) {
require_once('Zend/Io/Exception.php');
throw new Zend_Io_Exception('Cannot operate on a closed stream');
}
fflush($this->_fd);
}
/**
* Closes the stream. Once a stream has been closed, further calls to write
* methods will throw an exception. Closing a previously-closed stream,
* however, has no effect.
*
* @return void
* @throws Zend_Io_Exception if the stream is closed
*/
public function close()
{
if ($this->_fd !== null) {
@fclose($this->_fd);
$this->_fd = null;
}
}
/**
* Returns the current machine endian order.
*
* @return integer
*/
private function _getEndianess()
{
if (self::$_endianess === 0) {
self::$_endianess = $this->_toInt32("\x01\x00\x00\x00") == 1 ?
self::LITTLE_ENDIAN_ORDER : self::BIG_ENDIAN_ORDER;
}
return self::$_endianess;
}
/**
* Returns whether the current machine endian order is little endian.
*
* @return boolean
*/
private function _isLittleEndian()
{
return $this->_getEndianess() == self::LITTLE_ENDIAN_ORDER;
}
/**
* Returns whether the current machine endian order is big endian.
*
* @return boolean
*/
private function _isBigEndian()
{
return $this->_getEndianess() == self::BIG_ENDIAN_ORDER;
}
/**
* Magic function so that $obj->value will work.
*
* @param string $name The field name.
* @return mixed
*/
public function __get($name)
{
if (method_exists($this, 'get' . ucfirst(strtolower($name)))) {
return call_user_func
(array($this, 'get' . ucfirst(strtolower($name))));
} else {
require_once('Zend/Io/Exception.php');
throw new Zend_Io_Exception('Unknown field: ' . $name);
}
}
/**
* Magic function so that assignments with $obj->value will work.
*
* @param string $name The field name.
* @param string $value The field value.
* @return mixed
*/
public function __set($name, $value)
{
if (method_exists($this, 'set' . ucfirst(strtolower($name)))) {
call_user_func
(array($this, 'set' . ucfirst(strtolower($name))), $value);
} else {
require_once('Zend/Io/Exception.php');
throw new Zend_Io_Exception('Unknown field: ' . $name);
}
}
}