[ Index ]

PHP Cross Reference of PHK Manager

title

Body

[close]

/PHK/ -> PkgFile.php (source)

   1  <?php
   2  //=============================================================================
   3  //
   4  // Copyright Francois Laupretre <phk@tekwire.net>
   5  //
   6  //   Licensed under the Apache License, Version 2.0 (the "License");
   7  //   you may not use this file except in compliance with the License.
   8  //   You may obtain a copy of the License at
   9  //
  10  //       http://www.apache.org/licenses/LICENSE-2.0
  11  //
  12  //   Unless required by applicable law or agreed to in writing, software
  13  //   distributed under the License is distributed on an "AS IS" BASIS,
  14  //   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15  //   See the License for the specific language governing permissions and
  16  //   limitations under the License.
  17  //
  18  //=============================================================================
  19  /**
  20  * @copyright Francois Laupretre <phk@tekwire.net>
  21  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, V 2.0
  22  * @category PHK
  23  * @package PHK
  24  *///==========================================================================
  25  
  26  namespace PHK {
  27  
  28  if (!class_exists('PHK\PkgFile',false))
  29  {
  30  
  31  //=============================================================================
  32  /**
  33  * Contains the code to physically access PHK package files.
  34  *
  35  * API status: Private
  36  * Included in the PHK PHP runtime: Yes
  37  * Implemented in the extension: No
  38  *///==========================================================================
  39  
  40  class PkgFile
  41  {
  42  
  43  private $fp=null;
  44  private $path;
  45  private $size;
  46  private $open_count=0;
  47  private $keep_open_flag;
  48  
  49  //------
  50  // Special case : keep sub-PHKs open (in stream wrapper memory)
  51  
  52  public function __construct($path,$flags)
  53  {
  54  $this->setParams($path,$flags);
  55  
  56  if (($this->size=filesize($path))===false)
  57      throw new \Exception($path.': Cannot get file size');
  58  }
  59  
  60  //------
  61  
  62  public function setParams($path,$flags)
  63  {
  64  $this->path=$path;
  65  
  66  $this->keep_open_flag=\PHK\Mgr::isPhkUri($path);
  67  }
  68  
  69  //---
  70  
  71  public function __sleep()
  72  {
  73  return array('size');
  74  }
  75  
  76  //------
  77  
  78  public function __destruct()
  79  {
  80  $this->reallyClose();
  81  }
  82  
  83  //------
  84  
  85  private function reallyClose()
  86  {
  87  if (!is_null($this->fp))
  88      {
  89      fclose($this->fp);
  90      $this->fp=null;
  91      $this->open_count=0;
  92      }
  93  }
  94  
  95  //------
  96  // Open in read-only mode. Maintains a count for close(), throws exceptions,
  97  // and force 'b' mode (for Windows).
  98  // Called from self or \PHK\PkgFileSpace only
  99  
 100  public function _open()
 101  {
 102  if (is_null($this->fp))
 103      {
 104      if (!($this->fp=fopen($this->path,'rb',false)))    //-- 'b' mode is for Windows
 105          throw new \Exception($this->path.': Cannot open for reading');
 106      $this->open_count=1;
 107      }
 108  else $this->open_count++;
 109  }
 110  
 111  //-----
 112  // fclose() the file pointer. Maintains an open count.
 113  // Called from self or \PHK\PkgFileSpace only
 114  
 115  public function _close()
 116  {
 117  $this->open_count--;
 118  if (($this->open_count <= 0) && (!$this->keep_open_flag)) $this->reallyClose();
 119  }
 120  
 121  //-----
 122  // Same as PHP fread() but reads any size, throws exceptions, and checks size
 123  // I don't use stream_get_contents() because, sometimes, it crashes
 124  // on Windows (detected with PHP 5.1.4).
 125  
 126  private function read($size)
 127  {
 128  $data='';
 129  $nb_chunks=intval($size/8192);
 130  $rest=$size % 8192;
 131  
 132  \PHK\Tools\Util::disableMQR();
 133  while ($nb_chunks > 0)
 134      {
 135      $data .= $this->readChunk(8192);
 136      $nb_chunks--;
 137      }
 138  
 139  if ($rest) $data .= $this->readChunk($rest);
 140  \PHK\Tools\Util::restoreMQR();
 141  
 142  return $data;
 143  }
 144  
 145  //-----
 146  // Read up to 8192 bytes
 147  
 148  private function readChunk($size)
 149  {
 150  $buf=fread($this->fp,$size);
 151  if ($buf===false) throw new \Exception('Cannot read');
 152  if (($bsize=strlen($buf))!=$size)
 153      throw new \Exception("Short read ($bsize/$size)");
 154  return $buf;
 155  }
 156  
 157  //-----
 158  // Reads a block from file.
 159  // Called only from \PHK\PkgFileSpace. So:
 160  //        - we don't need to check bounds,
 161  //        - we don't provide default args,
 162  //        - we are sure that size is > 0
 163  
 164  public function _readBlock($offset,$size)
 165  {
 166  try
 167      {
 168      $this->_open();
 169      if (fseek($this->fp,$offset,SEEK_SET) == -1)
 170          throw new \Exception('Cannot seek');
 171      $buf=$this->read($size);
 172      $this->_close();    // At the end. Everything before can raise an exception
 173      }                // and we don't want to close it twice
 174  catch (\Exception $e)
 175      {
 176      $this->_close();
 177      throw new \Exception($e->getMessage());
 178      }
 179  return $buf;
 180  }
 181  
 182  //------
 183  
 184  public function size()
 185  {
 186  return $this->size;
 187  }
 188  
 189  //------
 190  
 191  public function path()
 192  {
 193  return $this->path;
 194  }
 195  
 196  }    // End of class PHK\PkgFile
 197  //-------------------------
 198  } // End of class_exists
 199  //=============================================================================
 200  
 201  if (!class_exists('PHK\PkgFileSpace',false))
 202  {
 203  //-------------------------
 204  class PkgFileSpace
 205  {
 206  
 207  public $file;    // underlying  \PHK\PkgFile object
 208  private $offset;
 209  private $size;
 210  
 211  //------
 212  // Two possibles syntaxes :
 213  // new \PHK\PkgFileSpace(string $path,int $flags) : creates a first space for a file
 214  // new \PHK\PkgFileSpace(PkgFileSpace $parent, int $offset, int $size) :
 215  //        creates a subspace inside an existing FileSpace.
 216  
 217  public function __construct($arg1,$arg2,$size=null)
 218  {
 219  if (is_string($arg1))
 220      {
 221      $this->file=new \PHK\PkgFile($arg1,$arg2);
 222      $this->offset=0;
 223      $this->size=$this->file->size();
 224      }
 225  else
 226      {
 227      if ((!($arg1 instanceof self))
 228          || (!is_numeric($arg2))
 229          || (!is_numeric($size))
 230          || ($arg2 < 0)
 231          || (($arg2+$size) > $arg1->size))
 232          throw new \Exception("PkgFileSpace: cannot create - invalid arguments");
 233  
 234      $this->file=$arg1->file;
 235      $this->offset=$arg1->offset + $arg2;
 236      $this->size=$size;
 237      }
 238  }
 239  
 240  //------
 241  // Default args so that readBlock() without args returns the whole filespace
 242  
 243  public function readBlock($offset=0,$size=null)
 244  {
 245  //\PHK\Tools\Util::trace("Starting PkgFileSpace::read_block - offset=$offset - size=$size");//TRACE
 246  
 247  if (is_null($size)) $size=$this->size-$offset; // Read up to the end
 248  
 249  if (($offset<0)||($size<0)||($offset+$size>$this->size))
 250      throw new \Exception('PkgFileSpace: Read out of bound');
 251  
 252  if ($size==0) return '';
 253  
 254  $data=$this->file->_readBlock($this->offset+$offset,$size);
 255  
 256  //\PHK\Tools\Util::trace("Ending PkgFileSpace::read_block");//TRACE
 257  return $data;
 258  }
 259  
 260  //------
 261  // Used to force the file to remain open temporarily
 262  
 263  public function open()
 264  {
 265  $this->file->_open();
 266  }
 267  
 268  //------
 269  
 270  public function close()
 271  {
 272  $this->file->_close();
 273  }
 274  
 275  //------
 276  
 277  public function size()
 278  {
 279  return $this->size;
 280  }
 281  
 282  //------
 283  // Returns path of underlying file (can be a PHK URI)
 284  
 285  public function path()
 286  {
 287  return $this->file->path();
 288  }
 289  
 290  //---
 291  } // End of class
 292  //===========================================================================
 293  } // End of class_exists
 294  //===========================================================================
 295  } // End of namespace
 296  //===========================================================================
 297  ?>


Generated: Thu Jun 4 18:33:15 2015 Cross-referenced by PHPXref 0.7.1