mirror of
https://github.com/slawkens/myaac.git
synced 2025-10-14 01:34:55 +02:00
First public release of MyAAC
This commit is contained in:
361
system/libs/pot/OTS_FileLoader.php
Normal file
361
system/libs/pot/OTS_FileLoader.php
Normal file
@@ -0,0 +1,361 @@
|
||||
<?php
|
||||
|
||||
/**#@+
|
||||
* @version 0.0.6
|
||||
* @since 0.0.6
|
||||
*/
|
||||
|
||||
/**
|
||||
* Code in this file bases on oryginal OTServ binary format loading C++ code (fileloader.h, fileloader.cpp).
|
||||
*
|
||||
* @package POT
|
||||
* @version 0.1.3
|
||||
* @author Wrzasq <wrzasq@gmail.com>
|
||||
* @copyright 2007 - 2008 (C) by Wrzasq
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt GNU Lesser General Public License, Version 3
|
||||
*/
|
||||
|
||||
/**
|
||||
* Universal OTServ binary formats reader.
|
||||
*
|
||||
* <p>
|
||||
* This class is general class that handle node-based binary OTServ files. It provides no file format-related logic, only loading nodes from files. To open given file format you need to use proper class like {@link OTS_OTBMFile OTS_OTBMFile} or {@link OTS_ItemsList OTS_ItemsList} classes.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* This class is mostly usefull when you create own extensions for POT code.
|
||||
* </p>
|
||||
*
|
||||
* @package POT
|
||||
* @version 0.1.3
|
||||
* @property-write IOTS_FileCache $cacheDriver Cache driver.
|
||||
*/
|
||||
class OTS_FileLoader
|
||||
{
|
||||
/**
|
||||
* Start of node.
|
||||
*/
|
||||
const NODE_START = 0xFE;
|
||||
/**
|
||||
* End of node.
|
||||
*/
|
||||
const NODE_END = 0xFF;
|
||||
/**
|
||||
* Escape another special byte.
|
||||
*/
|
||||
const ESCAPE_CHAR = 0xFD;
|
||||
|
||||
/**
|
||||
* File handle.
|
||||
*
|
||||
* @var resource
|
||||
*/
|
||||
private $file;
|
||||
|
||||
/**
|
||||
* Root node.
|
||||
*
|
||||
* @var OTS_FileNode
|
||||
*/
|
||||
protected $root;
|
||||
|
||||
/**
|
||||
* Cache handler.
|
||||
*
|
||||
* @var IOTS_FileCache
|
||||
*/
|
||||
protected $cache;
|
||||
|
||||
/**
|
||||
* Magic PHP5 method.
|
||||
*
|
||||
* <p>
|
||||
* Allows object serialisation.
|
||||
* </p>
|
||||
*
|
||||
* @version 0.0.6
|
||||
* @since 0.0.6
|
||||
* @return array List of properties that should be saved.
|
||||
*/
|
||||
public function __sleep()
|
||||
{
|
||||
return array('root', 'cache');
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates clone of object.
|
||||
*
|
||||
* <p>
|
||||
* Copy of object needs to have different ID.
|
||||
* </p>
|
||||
*
|
||||
* @version 0.0.6
|
||||
* @since 0.0.6
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
// clones node tree
|
||||
$this->root = clone $this->root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic PHP5 method.
|
||||
*
|
||||
* <p>
|
||||
* Allows object importing from {@link http://www.php.net/manual/en/function.var-export.php var_export()}.
|
||||
* </p>
|
||||
*
|
||||
* @version 0.0.6
|
||||
* @since 0.0.6
|
||||
* @param array $properties List of object properties.
|
||||
*/
|
||||
public static function __set_state($properties)
|
||||
{
|
||||
$object = new self();
|
||||
|
||||
// loads properties
|
||||
foreach($properties as $name => $value)
|
||||
{
|
||||
$object->$name = $value;
|
||||
}
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets cache handler.
|
||||
*
|
||||
* <p>
|
||||
* You have to set cache driver before loading/saving any file in order to apply it to that file.
|
||||
* </p>
|
||||
*
|
||||
* @param IOTS_FileCache $cache Cache handler (leave this parameter if you want to unset caching).
|
||||
*/
|
||||
public function setCacheDriver(IOTS_FileCache $cache = null)
|
||||
{
|
||||
$this->cache = $cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens file.
|
||||
*
|
||||
* @version 0.1.3
|
||||
* @param string $file Filepath.
|
||||
* @throws E_OTS_FileLoaderError When error occurs during file operation.
|
||||
*/
|
||||
public function loadFile($file)
|
||||
{
|
||||
// attemts to read from cache
|
||||
if( isset($this->cache) )
|
||||
{
|
||||
$this->root = $this->cache->readCache( md5_file($file) );
|
||||
|
||||
// checks if cache was loaded
|
||||
if( isset($this->root) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// opens for read in binary mode
|
||||
$this->file = fopen($file, 'rb');
|
||||
|
||||
if($this->file)
|
||||
{
|
||||
// reads file version
|
||||
$version = unpack('V', fread($this->file, 4) );
|
||||
|
||||
if($version[1] > 0)
|
||||
{
|
||||
throw new E_OTS_FileLoaderError(E_OTS_FileLoaderError::ERROR_INVALID_FILE_VERSION);
|
||||
}
|
||||
|
||||
$this->safeSeek(4);
|
||||
|
||||
if( $this->readByte() != self::NODE_START)
|
||||
{
|
||||
throw new E_OTS_FileLoaderError(E_OTS_FileLoaderError::ERROR_INVALID_FORMAT);
|
||||
}
|
||||
|
||||
// reads root node
|
||||
$this->root = new OTS_FileNode();
|
||||
$this->parseNode($this->root);
|
||||
|
||||
fclose($this->file);
|
||||
|
||||
// writes new cache
|
||||
if( isset($this->cache) )
|
||||
{
|
||||
$this->cache->writeCache( md5_file($file), $this->root);
|
||||
}
|
||||
}
|
||||
// failed to open the file
|
||||
else
|
||||
{
|
||||
throw new E_OTS_FileLoaderError(E_OTS_FileLoaderError::ERROR_CAN_NOT_OPEN);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loades node from file.
|
||||
*
|
||||
* @param OTS_FileNode $node Node into which file fragment should be parsed.
|
||||
* @throws E_OTS_FileLoaderError When error occurs during file operation.
|
||||
*/
|
||||
private function parseNode(OTS_FileNode $node)
|
||||
{
|
||||
$current = $node;
|
||||
|
||||
// reads node type
|
||||
$current->setType( $this->readByte() );
|
||||
|
||||
$buffer = '';
|
||||
$propertiesSet = false;
|
||||
|
||||
while(true)
|
||||
{
|
||||
// reads single byte from file
|
||||
$byte = $this->readByte();
|
||||
|
||||
switch($byte)
|
||||
{
|
||||
// start of new node
|
||||
case self::NODE_START:
|
||||
// reads child node
|
||||
$child = new OTS_FileNode();
|
||||
$current->setBuffer($buffer);
|
||||
$propertiesSet = true;
|
||||
$current->setChild($child);
|
||||
$this->parseNode($child);
|
||||
break;
|
||||
|
||||
// end of current node
|
||||
case self::NODE_END:
|
||||
if(!$propertiesSet)
|
||||
{
|
||||
$current->setBuffer($buffer);
|
||||
}
|
||||
|
||||
// end of file
|
||||
if($node === $this->root)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch( $this->readByte() )
|
||||
{
|
||||
// starts next node
|
||||
case self::NODE_START:
|
||||
$next = new OTS_FileNode();
|
||||
$current->setNext($next);
|
||||
$current = $next;
|
||||
$current->setType( $this->readByte() );
|
||||
$propertiesSet = false;
|
||||
$buffer = '';
|
||||
break;
|
||||
|
||||
// up 1 level and move 1 position back
|
||||
case self::NODE_END:
|
||||
$this->safeSeek( $this->safeTell() - 1);
|
||||
return;
|
||||
|
||||
// invliad file format
|
||||
default:
|
||||
throw new E_OTS_FileLoaderError(E_OTS_FileLoaderError::ERROR_INVALID_FORMAT);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// ignores next character
|
||||
case self::ESCAPE_CHAR:
|
||||
$buffer .= chr( $this->readByte() );
|
||||
break;
|
||||
|
||||
// normal character
|
||||
default:
|
||||
$buffer .= chr($byte);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads single byte from file.
|
||||
*
|
||||
* @return int Read value.
|
||||
* @throws E_OTS_FileLoaderError When error occurs during file operation.
|
||||
*/
|
||||
private function readByte()
|
||||
{
|
||||
$value = fgetc($this->file);
|
||||
|
||||
// checks eof
|
||||
if($value === false)
|
||||
{
|
||||
throw new E_OTS_FileLoaderError(E_OTS_FileLoaderError::ERROR_EOF);
|
||||
}
|
||||
|
||||
return ord($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Seeks file pointer into given position.
|
||||
*
|
||||
* @param int $pos Seek position.
|
||||
* @throws E_OTS_FileLoaderError When error occurs during file operation.
|
||||
*/
|
||||
private function safeSeek($pos)
|
||||
{
|
||||
if( fseek($this->file, $pos, SEEK_SET) == -1)
|
||||
{
|
||||
// error occured
|
||||
throw new E_OTS_FileLoaderError(E_OTS_FileLoaderError::ERROR_SEEK_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current position in file.
|
||||
*
|
||||
* @return int Position in file.
|
||||
* @throws E_OTS_FileLoaderError When error occurs during file operation.
|
||||
*/
|
||||
private function safeTell()
|
||||
{
|
||||
// reads file position
|
||||
$pos = ftell($this->file);
|
||||
|
||||
// checks if operation succeeded
|
||||
if($pos === false)
|
||||
{
|
||||
throw new E_OTS_FileLoaderError(E_OTS_FileLoaderError::ERROR_TELL_ERROR);
|
||||
}
|
||||
|
||||
return $pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic PHP5 method.
|
||||
*
|
||||
* @version 0.1.0
|
||||
* @since 0.1.0
|
||||
* @param string $name Property name.
|
||||
* @param mixed $value Property value.
|
||||
* @throws OutOfBoundsException For non-supported properties.
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
switch($name)
|
||||
{
|
||||
case 'cacheDriver':
|
||||
$this->setCacheDriver($value);
|
||||
break;
|
||||
|
||||
// not-supported
|
||||
default:
|
||||
throw new OutOfBoundsException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**#@-*/
|
||||
|
||||
?>
|
Reference in New Issue
Block a user