<?php
# CFile
# coded by Alessandro Rosa
# e-mail : zandor_zz@yahoo.it
# site : http://alessandrorosa.altervista.org
# Copyright (C) 2011 Alessandro Rosa
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
# Compiled with PHP 5
define( CFILE_BINARY_WRITEMODE, 1, true ) ;
define( CFILE_TEXT_WRITEMODE, 2, true ) ;
define( CFILE_MOVE_FROM_START, SEEK_SET, true ) ;
define( CFILE_MOVE_FROM_END, SEEK_END, true ) ;
define( CFILE_MOVE_FROM_CURRENT, SEEK_CUR, true ) ;
define( CFILE_MOVE_BEGIN, 0, true ) ;
define( CFILE_LITTLE_ENDIAN, 1, true );
define( CFILE_BIG_ENDIAN, 2, true );
define( CFILE_READ_MODE, "r", true ) ;
define( CFILE_WRITE_MODE, "c", true ) ;
define( CFILE_READWRITE_NO_CREATE_MODE, "c+", true ) ;
define( CFILE_READWRITE_CREATE_MODE, "w+", true ) ;
define( CFILE_BINARY_INT_MODE, 1, true ) ;
define( CFILE_BINARY_FLOAT_MODE, 2, true ) ;
define( CFILE_BINARY_DOUBLE_MODE, 3, true ) ;
define( CFILE_TEXT_MODE, 4, true ) ;
define( CFILE_INT_LITTLE_ENDIAN_PACK_MODE_READ, "h", true ) ;
define( CFILE_INT_LITTLE_ENDIAN_PACK_MODE_WRITE, "i", true ) ;
define( CFILE_INT_BIG_ENDIAN_PACK_MODE_READ, "H", true ) ;
define( CFILE_INT_BIG_ENDIAN_PACK_MODE_WRITE, "I", true ) ;
define( CFILE_INT_PACK_MODE, "i", true ) ;
define( CFILE_DOUBLE_PACK_MODE, "d", true ) ;
define( CFILE_FLOAT_PACK_MODE, "f", true ) ;
define( CFILE_TEXT_PACK_MODE, "a", true ) ;
define( CFILE_FLOAT_ROUND_DIGITS, 4, true );
define( CFILE_DOUBLE_ROUND_DIGITS, 7, true );
// giving an example of a integer variable to compute its memory size
$INT_VAL = (integer)32 ; $H = pack( CFILE_INT_PACK_MODE."*", $INT_VAL );
define( CFILE_SIZE_OF_INT, strlen($H), true ) ;
// giving an example of a float variable to compute its memory size
$FLOAT_VAL = (float)32 ; $H = pack( CFILE_FLOAT_PACK_MODE."*", $FLOAT_VAL );
define( CFILE_SIZE_OF_FLOAT, strlen($H), true ) ;
// giving an example of a double variable to compute its memory size
$DOUBLE_VAL = (double)32 ; $H = pack( CFILE_DOUBLE_PACK_MODE."*", $DOUBLE_VAL );
define( CFILE_SIZE_OF_DOUBLE, strlen($H), true ) ;
class cfile
{
var $FILE_HANDLE = false ;
var $FILE_PATH = "" ;
var $FILE_SIZE = 0 ;
var $bERROR = false ;
var $error_no = 0 ;
var $error_msg = "" ;
var $byte_order = 0 ;
function cfile( $FP, $BYTE_ORDER = CFILE_BIG_ENDIAN )
{
$FP = trim( $FP );
$this->FILE_PATH = $FP ;
if ( strlen( $FP ) == 0 )
{
$this->bERROR = true ;
$this->error_no = 1.1 ;
}
else
{
$this->byte_order = $BYTE_ORDER ;
$REG_EXP = '/^([A-Za-z]:)|[a-z0-9_.\/\\\]*$/i' ;
$bRET = preg_match( $REG_EXP, $FP ) ;
if ( !$bRET )
{
$this->bERROR = true ;
$this->error_no = 1.3 ;
}
}
}
function open( $OPEN_MODE = CFILE_READ_MODE )
{
$this->FILE_SIZE = ( file_exists( $this->FILE_PATH ) ) ? filesize( $this->FILE_PATH ) : 0 ;
$this->FILE_SIZE = intval( $this->FILE_SIZE ); if ( is_nan( $this->FILE_SIZE ) ) $this->FILE_SIZE = 0 ;
$this->FILE_HANDLE = ( $this->bERROR ) ? false : @fopen( $this->FILE_PATH, $OPEN_MODE );
if ( !( $this->FILE_HANDLE ) )
{
$this->bERROR = true ;
$this->error_no = 1.4 ;
}
return ( $this->FILE_HANDLE !== false ) ? true : false ;
}
function move_to_beginning() { return $this->move( 0, 0 ); }
function move_to_end() { return $this->move( 0, $this->FILE_SIZE - 1 ); }
function move_backward( $nbytes = 0 )
{
$bRET = true ;
if ( $this->FILE_HANDLE !== false )
{
$nbytes = abs( $nbytes ); $nbytes = -$nbytes ;
$SEEK = @fseek( $this->FILE_HANDLE, $nbytes, SEEK_CUR );
$SEEK = intval( $SEEK ); if ( is_nan( $SEEK ) ) $SEEK = 0 ;
$bRET = ( $SEEK == 0 ) ? true : false ;
if ( $bRET )
{
$this->bERROR = true ;
$this->error_no = 5.2 ;
}
}
else $bRET = false ;
return $bRET ;
}
function move_forward( $nbytes = 0 )
{
$bRET = true ;
if ( $this->FILE_HANDLE !== false )
{
$nbytes = abs( $nbytes );
$SEEK = @fseek( $this->FILE_HANDLE, $nbytes, SEEK_CUR );
$SEEK = intval( $SEEK ); if ( is_nan( $SEEK ) ) $SEEK = 0 ;
$bRET = ( $SEEK == 0 ) ? true : false ;
if ( $bRET )
{
$this->bERROR = true ;
$this->error_no = 5.2 ;
}
}
else $bRET = false ;
return $bRET ;
}
function move( $start, $nbytes = 0 ) // minus and plus for backward and forward direction respectively
{
$FS = $this->FILE_SIZE ;
$nbytes = intval( $nbytes ); if ( is_nan( $nbytes ) ) $nbytes = 0 ;
$newpos = $start + $nbytes ;
if ( $newpos > $FS || $newpos < 0 )
{
$this->bERROR = true ;
$this->error_no = 5.3 ;
return false ;
}
else
{
if ( $this->FILE_HANDLE !== false )
{
// move to start point first
if ( $start >= 0 ) @fseek( $this->FILE_HANDLE, $start, SEEK_SET );
$SEEK = @fseek( $this->FILE_HANDLE, $nbytes, SEEK_CUR );
$SEEK = intval( $SEEK ); if ( is_nan( $SEEK ) ) $SEEK = 0 ;
$bRET = ( $SEEK == 0 ) ? true : false ;
if ( $bRET )
{
$this->bERROR = true ;
$this->error_no = 5.2 ;
}
return $bRET ;
}
else
{
$this->bERROR = true ;
$this->error_no = 5.1 ;
return false ;
}
}
}
public function read_array( &$item, $BYTE_ORDER = CFILE_BIG_ENDIAN, $bREVERSE_BYTE_ORDER = true )
{
if ( is_array( $item ) )
{
$bRET = true ;
$nitems = count( $item );
$readmode = 0 ;
foreach( $item AS $key => $chunk )
{
if ( is_array( $chunk ) )
{
$cast = key( $chunk );
$cast_array = ( strpos( $cast, "@", 0 ) !== false ) ? explode( "@", $cast ) : array( $cast, 0 ) ;
$cast_type = strtolower( $cast_array[0] ) ;
$cast_bytes = intval( $cast_array[1] ) ;
$writemode = 0 ;
switch( $cast_type )
{
case "string" :
$readmode = CFILE_TEXT_MODE ;
if ( is_nan( $cast_bytes ) || $cast_bytes == 0 ) $cast_bytes = 0 ;
break ;
case "float" :
$readmode = CFILE_BINARY_FLOAT_MODE ;
if ( is_nan( $cast_bytes ) || $cast_bytes == 0 ) $cast_bytes = CFILE_SIZE_OF_FLOAT ;
break ;
case "double" :
$readmode = CFILE_BINARY_DOUBLE_MODE ;
if ( is_nan( $cast_bytes ) || $cast_bytes == 0 ) $cast_bytes = CFILE_SIZE_OF_DOUBLE ;
break ;
case "int" :
case "integer" :
$readmode = CFILE_BINARY_INT_MODE ;
if ( is_nan( $cast_bytes ) || $cast_bytes == 0 ) $cast_bytes = CFILE_SIZE_OF_INT ;
break ;
default :
$readmode = CFILE_BINARY_INT_MODE ;
if ( is_nan( $cast_bytes ) || $cast_bytes == 0 ) $cast_bytes = CFILE_SIZE_OF_INT ;
break ;
}
if ( $cast_bytes == 0 )
{
$this->bERROR = true ;
$this->error_no = 2.5 ;
return false ;
}
else
{
$val = $this->read( $cast_bytes, $readmode, $BYTE_ORDER, $bREVERSE_BYTE_ORDER ) ;
if ( $val !== false ) $item["$key"] = array( $cast => $val ) ;
}
}
}
return true ;
}
else
{
$this->bERROR = true ;
$this->error_no = 2.4 ;
return false ;
}
}
function read( $nbytes, $mode = CFILE_TEXT_MODE, $BYTE_ORDER = CFILE_BIG_ENDIAN, $bREVERSE_BYTE_ORDER = true )
{
$original_bytes = $nbytes ;
$mode = intval( $mode ); if ( is_nan( $mode ) ) $mode = CFILE_BINARY_INT_MODE ;
$nbytes = intval( $nbytes ); if ( is_nan( $nbytes ) ) $nbytes = 0 ;
$FS = $this->FILE_SIZE ;
$start = @ftell( $this->FILE_HANDLE );
$newpos = $start + $nbytes ;
if ( $mode == CFILE_TEXT_MODE ) $bREVERSE_BYTE_ORDER = false ;
if ( $newpos > $FS || $newpos < 0 )
{
$this->bERROR = true ;
$this->error_no = 2.3 ;
return false ;
}
else
{
if ( $this->FILE_HANDLE !== false && $nbytes > 0 )
{
$F = "" ;
$READ = @fread( $this->FILE_HANDLE, $nbytes ) ;
if ( $READ === false )
{
$this->bERROR = true ;
$this->error_no = 2.2 ;
return false ;
}
else
{
$INPUT_LEN = 0 ;
if ( $mode != CFILE_TEXT_MODE )
{
if ( $mode == CFILE_BINARY_INT_MODE ) { $F = CFILE_INT_PACK_MODE ; $F = "h*" ; $INPUT_LEN = CFILE_SIZE_OF_INT ; }
else if ( $mode == CFILE_BINARY_FLOAT_MODE ) { $F = CFILE_FLOAT_PACK_MODE ; $F = "$F*" ; $INPUT_LEN = CFILE_SIZE_OF_FLOAT ; }
else if ( $mode == CFILE_BINARY_DOUBLE_MODE ) { $F = CFILE_DOUBLE_PACK_MODE ; $F = "$F*" ; $INPUT_LEN = CFILE_SIZE_OF_DOUBLE ; }
}
else if ( $mode == CFILE_TEXT_MODE ) { $F = CFILE_TEXT_PACK_MODE ; $F = "$F*" ; $INPUT_LEN = strlen( $READ ) ; }
$RET = unpack( "$F", $READ ) ;
if ( $mode == CFILE_TEXT_MODE ) $bRET = $RET[1] ;
else
{
if ( $mode == CFILE_BINARY_INT_MODE )
{
if ( $bREVERSE_BYTE_ORDER ) $RET[1] = cfile::reverse_byte_order( $RET[1] ) ;
$RET[1] = ltrim( $RET[1], 0 );
$bRET = hexdec( $RET[1] ) ;
}
else $bRET = $RET[1] ;
}
return $bRET ;
}
}
else
{
$this->bERROR = true ;
$this->error_no = 2.1 ;
return false ;
}
}
}
private function write_binary( $FH, $chunk, $nbytes, $writemode )
{
if ( is_array( $chunk ) )
{
$bRET = true ;
foreach( $chunk AS $key => $val )
{
$b = strlen( $val ) ;
$bRET &= $this->write_binary( $FH, $val, $b ) ;
}
return $bRET ;
}
else
{
$IN = null ; $F = "" ;
if ( is_numeric( $chunk ) )
{
if ( $writemode == CFILE_BINARY_INT_MODE )
{
switch( $this->byte_order )
{
case CFILE_LITTLE_ENDIAN :
$F = CFILE_INT_LITTLE_ENDIAN_PACK_MODE_WRITE ;
break ;
case CFILE_BIG_ENDIAN :
$F = CFILE_INT_BIG_ENDIAN_PACK_MODE_WRITE ;
break ;
default :
$this->byte_order = CFILE_BIG_ENDIAN ;
$F = CFILE_INT_BIG_ENDIAN_PACK_MODE_WRITE ;
break ;
}
}
else if ( $writemode == CFILE_BINARY_FLOAT_MODE )
{
$chunk = round( $chunk, CFILE_FLOAT_ROUND_DIGITS );
$F = CFILE_FLOAT_PACK_MODE ;
}
else if ( $writemode == CFILE_BINARY_DOUBLE_MODE )
{
$chunk = round( $chunk, CFILE_DOUBLE_ROUND_DIGITS );
$F = CFILE_DOUBLE_PACK_MODE ;
}
}
else $F = CFILE_TEXT_PACK_MODE ;
$IN = pack( "$F*", $chunk ) ; if ( $nbytes == 0 ) $nbytes = strlen( $IN );
$O = @fwrite( $FH, $IN, $nbytes );
if ( $O === false )
{
$this->bERROR = true ;
$this->error_no = 3.3 ;
}
else $this->bERROR = false ;
return $this->bERROR ;
}
}
private function write_array( $item )
{
if ( is_array( $item ) )
{
$bRET = true ;
foreach( $item AS $key => $chunk )
{
$cast = key( $chunk );
$val = current( $chunk );
$cast_array = ( strpos( $cast, "@", 0 ) !== false ) ? explode( "@", $cast ) : array( $cast, 0 ) ;
$cast_type = strtolower( $cast_array[0] ) ;
$cast_bytes = intval( $cast_array[1] ) ;
$writemode = 0 ;
switch( $cast_type )
{
case "string" :
$val = "$val" ;
$writemode = CFILE_TEXT_MODE ;
if ( is_nan( $cast_bytes ) || $cast_bytes == 0 ) $cast_bytes = strlen( $val );
break ;
case "float" :
$writemode = CFILE_BINARY_FLOAT_MODE ;
if ( is_nan( $cast_bytes ) || $cast_bytes == 0 ) $cast_bytes = CFILE_SIZE_OF_FLOAT ;
break ;
case "double" :
$writemode = CFILE_BINARY_DOUBLE_MODE ;
if ( is_nan( $cast_bytes ) || $cast_bytes == 0 ) $cast_bytes = CFILE_SIZE_OF_DOUBLE ;
break ;
case "int" :
case "integer" :
$writemode = CFILE_BINARY_INT_MODE ;
if ( is_nan( $cast_bytes ) || $cast_bytes == 0 ) $cast_bytes = CFILE_SIZE_OF_INT ;
break ;
default :
$writemode = CFILE_BINARY_INT_MODE ;
if ( is_nan( $cast_bytes ) || $cast_bytes == 0 ) $cast_bytes = CFILE_SIZE_OF_INT ;
break ;
}
$this->write( $val, $cast_bytes, $writemode ) ;
}
}
else
{
$this->bERROR = true ;
$this->error_no = 3.4 ;
return false ;
}
}
function write( $chunk, $nbytes = 0, $writemode = CFILE_BINARY_INT_MODE )
{
if ( is_array( $chunk ) ) $this->write_array( $chunk ) ;
else
{
if ( $this->FILE_HANDLE !== false )
{
if ( !is_numeric( $chunk ) ) $writemode = CFILE_TEXT_MODE ;
else
{
if ( is_int( $chunk ) ) $writemode = CFILE_BINARY_INT_MODE ;
else if ( is_double( $chunk ) ) $writemode = CFILE_BINARY_DOUBLE_MODE ;
else if ( is_float( $chunk ) ) $writemode = CFILE_BINARY_FLOAT_MODE ;
}
if ( $writemode == CFILE_BINARY_INT_MODE )
{
if ( $nbytes == 0 ) $nbytes = CFILE_SIZE_OF_INT ;
return $this->write_binary( $this->FILE_HANDLE, $chunk, $nbytes, CFILE_BINARY_INT_MODE ) ;
}
else if ( $writemode == CFILE_BINARY_FLOAT_MODE )
{
if ( $nbytes == 0 ) $nbytes = CFILE_SIZE_OF_FLOAT ;
return $this->write_binary( $this->FILE_HANDLE, $chunk, $nbytes, CFILE_BINARY_FLOAT_MODE ) ;
}
else if ( $writemode == CFILE_BINARY_DOUBLE_MODE )
{
if ( $nbytes == 0 ) $nbytes = CFILE_SIZE_OF_DOUBLE ;
return $this->write_binary( $this->FILE_HANDLE, $chunk, $nbytes, CFILE_BINARY_DOUBLE_MODE ) ;
}
else if ( $writemode == CFILE_TEXT_MODE )
{
if ( $nbytes == 0 ) $nbytes = ( is_array( $chunk ) ) ? count( $chunk ) : strlen( $chunk ) ;
return $this->write_binary( $this->FILE_HANDLE, $chunk, $nbytes, CFILE_TEXT_MODE ) ;
}
else
{
$this->bERROR = true ;
$this->error_no = 3.2 ;
return false ;
}
}
else
{
$this->bERROR = true ;
$this->error_no = 3.1 ;
return false ;
}
}
}
function close()
{
if ( $this->FILE_HANDLE !== false )
{
$bRET = @fclose( $this->FILE_HANDLE ) ;
if ( $bRET === false )
{
$this->bERROR = true ;
$this->error_no = 4.1 ;
}
else $this->FILE_HANDLE = false ;
}
else
{
$this->bERROR = true ;
$this->error_no = 4.2 ;
$bRET = false ;
}
return $bRET ;
}
function reset()
{
if ( $this->FILE_HANDLE !== false )
{
$bCLOSE = $this->close();
if ( $bCLOSE )
{
$this->FILE_PATH = "" ;
$this->FILE_HANDLE = false ;
$this->FILE_SIZE = 0 ;
$this->bERROR = false ;
$this->error_no = 0 ;
$this->error_msg = "" ;
$this->byte_order = 0 ;
}
return $bCLOSE ;
}
}
////////////////// ADDITIONAL MEMBER FUNCTIONS /////////////////////////////
public function get_pointer_position()
{
return ( $this->FILE_HANDLE !== false ) ? @ftell( $this->FILE_HANDLE ) : false ;
}
public function feof() { return ( $this->FILE_HANDLE !== false ) ? feof( $this->FILE_HANDLE ) : -1 ; }
////////////////// ERROR HANDLING //////////////////////////////////////////
public function is_error() { return $this->bERROR ; }
public function get_error_string()
{
$error_no = intval( $this->error_no ); if ( is_nan( $error_no ) ) $error_no = -1 ;
switch( $error_no )
{
case -1: $this->error_msg = "Error $error_no : unknown" ; break ;
case 0: $this->error_msg = "No error" ; break ;
case 0.1: $this->error_msg = "Error $error_no : reset" ; break ;
case 1.1 : $this->error_msg = "Error $error_no : no filepath" ; break ;
case 1.2 : $this->error_msg = "Error $error_no : filepath does not exists" ; break ;
case 1.3 : $this->error_msg = "Error $error_no : filepath incorrect syntax" ; break ;
case 1.4 : $this->error_msg = "Error $error_no : can't open file" ; break ;
case 2.1 : $this->error_msg = "Error $error_no : no read: file access failure" ; break ;
case 2.2 : $this->error_msg = "Error $error_no : no read: operational error" ; break ;
case 2.3 : $this->error_msg = "Error $error_no : no read: pointer position exceeding file length" ; break ;
case 2.4 : $this->error_msg = "Error $error_no : no read: data input is not of array type" ; break ;
case 2.5 : $this->error_msg = "Error $error_no : no read: some array field was not casted properly" ; break ;
case 3.1 : $this->error_msg = "Error $error_no : no write: file access failure" ; break ;
case 3.2 : $this->error_msg = "Error $error_no : no write: select mode" ; break ;
case 3.3 : $this->error_msg = "Error $error_no : no write: operational error" ; break ;
case 3.4 : $this->error_msg = "Error $error_no : no write: data container is not of array type" ; break ;
case 4.1 : $this->error_msg = "Error $error_no : no close: file access failure" ; break ;
case 4.2 : $this->error_msg = "Error $error_no : no close: operational error" ; break ;
case 5.1 : $this->error_msg = "Error $error_no : no move: file access failure" ; break ;
case 5.2 : $this->error_msg = "Error $error_no : no move: unknown" ; break ;
case 5.3 : $this->error_msg = "Error $error_no : no move: pointer position exceeding file length" ; break ;
default: $this->error_msg = "Error $error_no : unknown" ; break ;
}
return $this->error_msg ;
}
////////////////// STATIC FUNCTIONS ////////////////////////////////////////
public static function reverse_byte_order( $input,
$chunk_length = 1,
$bHEXinput = true,
$bretrieveHEXstring = false,
$pad_to = 2 )
{
if ( $bHEXinput || is_string( $input ) )
{
$v = $input ;
if ( strlen( $v ) % 2 == 1 ) $v = "0$v" ;
// reverse byte read order
$A = str_split( $v, $chunk_length );
$A = array_reverse( $A );
$v = implode( "", $A ) ;
return $v ;
}
else
{
$F = "" ;
if ( is_numeric( $input ) )
{
if ( is_double( $input ) ) $F = "d*" ;
else if ( is_int( $input ) ) $F = "i*" ;
else $F = "a*" ; // it might be a string containing numbers only
}
else $F = "a*" ;
$packedINPUT = pack( "$F", $input );
$RET = unpack( "H*", $packedINPUT );
$v = $RET[1] ;
// no reversion for trailing zeros on the right
$temp_v_01 = rtrim( $v, "0" );
$n_trimmed_zeros = strlen( $v ) - strlen( $temp_v_01 ) ;
$temp_v_02 = strrev( $temp_v_01 ).( str_repeat( "0", $n_trimmed_zeros ) ) ;
$v = $temp_v_02 ;
if ( $bretrieveHEXstring && $pad_to > 0 ) return substr( $v, -$pad_to ) ;
else
{
if ( is_int( $input ) ) $F = "i*" ;
else if ( is_double( $input ) ) $F = "d*" ;
else $F = "a*" ;
$I = pack( "H*", $v ) ;
$v = $I ;
$I = unpack( "$F", $v ) ;
return $I[1] ;
}
}
}
public static function swap_nibble( $byte )
{
$low_nibble = 0x0F & $byte ;
$high_nibble = ( 0xF0 & $byte ) / 0x0F ;
return ( ( $low_nibble ) * 0x0F ) | $high_nibble ;
}
public static function get_nbytes( $input, &$nbits = 0 )
{
$nbits = ( $input > 0 ) ? log10( $input ) / log10( 2 ) : 0 ;
$nbytes = $nbits / 8 ;
if ( fmod( $nbits, 8 ) == 0 ) $nbytes++ ;
return ceil( $nbytes );
}
public static function float_to_hex( $f ) { $f = (float)$f ; $v = pack( "f*", $f ); $v = unpack( "h*", $v ); return $v[1] ; }
public static function hex_to_float( $h ) { $v = pack( "h*", $h ); $f = unpack( "f*", $v ); return $f[1] ; }
public static function double_to_hex( $d ) { $d = (double)$d ; $v = pack( "d*", $d ); $v = unpack( "h*", $v ); return $v[1] ; }
public static function hex_to_double( $h ) { $v = pack( "h*", $h ); $d = unpack( "d*", $v ); return $d[1] ; }
}
?> |