1<?php 2 3/** 4 * Hoa 5 * 6 * 7 * @license 8 * 9 * New BSD License 10 * 11 * Copyright © 2007-2017, Hoa community. All rights reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions are met: 15 * * Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * * Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * * Neither the name of the Hoa nor the names of its contributors may be 21 * used to endorse or promote products derived from this software without 22 * specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE 28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37namespace Hoa\File\Link; 38 39use Hoa\File; 40use Hoa\Stream; 41 42/** 43 * Class \Hoa\File\Link\ReadWrite. 44 * 45 * File handler. 46 * 47 * @copyright Copyright © 2007-2017 Hoa community 48 * @license New BSD License 49 */ 50class ReadWrite 51 extends Link 52 implements Stream\IStream\In, 53 Stream\IStream\Out 54{ 55 /** 56 * Open a file. 57 * 58 * @param string $streamName Stream name. 59 * @param string $mode Open mode, see the parent::MODE_* constants. 60 * @param string $context Context ID (please, see the 61 * \Hoa\Stream\Context class). 62 * @param bool $wait Differ opening or not. 63 */ 64 public function __construct( 65 $streamName, 66 $mode = parent::MODE_APPEND_READ_WRITE, 67 $context = null, 68 $wait = false 69 ) { 70 parent::__construct($streamName, $mode, $context, $wait); 71 72 return; 73 } 74 75 /** 76 * Open the stream and return the associated resource. 77 * 78 * @param string $streamName Stream name (e.g. path or URL). 79 * @param \Hoa\Stream\Context $context Context. 80 * @return resource 81 * @throws \Hoa\File\Exception\FileDoesNotExist 82 * @throws \Hoa\File\Exception 83 */ 84 protected function &_open($streamName, Stream\Context $context = null) 85 { 86 static $createModes = [ 87 parent::MODE_READ_WRITE, 88 parent::MODE_TRUNCATE_READ_WRITE, 89 parent::MODE_APPEND_READ_WRITE, 90 parent::MODE_CREATE_READ_WRITE 91 ]; 92 93 if (!in_array($this->getMode(), $createModes)) { 94 throw new File\Exception( 95 'Open mode are not supported; given %d. Only %s are supported.', 96 0, 97 [$this->getMode(), implode(', ', $createModes)] 98 ); 99 } 100 101 preg_match('#^(\w+)://#', $streamName, $match); 102 103 if (((isset($match[1]) && $match[1] == 'file') || !isset($match[1])) && 104 !file_exists($streamName) && 105 parent::MODE_READ_WRITE == $this->getMode()) { 106 throw new File\Exception\FileDoesNotExist( 107 'File %s does not exist.', 108 1, 109 $streamName 110 ); 111 } 112 113 $out = parent::_open($streamName, $context); 114 115 return $out; 116 } 117 118 /** 119 * Test for end-of-file. 120 * 121 * @return bool 122 */ 123 public function eof() 124 { 125 return feof($this->getStream()); 126 } 127 128 /** 129 * Read n characters. 130 * 131 * @param int $length Length. 132 * @return string 133 * @throws \Hoa\File\Exception 134 */ 135 public function read($length) 136 { 137 if (0 > $length) { 138 throw new File\Exception( 139 'Length must be greater than 0, given %d.', 140 2, 141 $length 142 ); 143 } 144 145 return fread($this->getStream(), $length); 146 } 147 148 /** 149 * Alias of $this->read(). 150 * 151 * @param int $length Length. 152 * @return string 153 */ 154 public function readString($length) 155 { 156 return $this->read($length); 157 } 158 159 /** 160 * Read a character. 161 * 162 * @return string 163 */ 164 public function readCharacter() 165 { 166 return fgetc($this->getStream()); 167 } 168 169 /** 170 * Read a boolean. 171 * 172 * @return bool 173 */ 174 public function readBoolean() 175 { 176 return (bool) $this->read(1); 177 } 178 179 /** 180 * Read an integer. 181 * 182 * @param int $length Length. 183 * @return int 184 */ 185 public function readInteger($length = 1) 186 { 187 return (int) $this->read($length); 188 } 189 190 /** 191 * Read a float. 192 * 193 * @param int $length Length. 194 * @return float 195 */ 196 public function readFloat($length = 1) 197 { 198 return (float) $this->read($length); 199 } 200 201 /** 202 * Read an array. 203 * Alias of the $this->scanf() method. 204 * 205 * @param string $format Format (see printf's formats). 206 * @return array 207 */ 208 public function readArray($format = null) 209 { 210 return $this->scanf($format); 211 } 212 213 /** 214 * Read a line. 215 * 216 * @return string 217 */ 218 public function readLine() 219 { 220 return fgets($this->getStream()); 221 } 222 223 /** 224 * Read all, i.e. read as much as possible. 225 * 226 * @param int $offset Offset. 227 * @return string 228 */ 229 public function readAll($offset = 0) 230 { 231 return stream_get_contents($this->getStream(), -1, $offset); 232 } 233 234 /** 235 * Parse input from a stream according to a format. 236 * 237 * @param string $format Format (see printf's formats). 238 * @return array 239 */ 240 public function scanf($format) 241 { 242 return fscanf($this->getStream(), $format); 243 } 244 245 /** 246 * Write n characters. 247 * 248 * @param string $string String. 249 * @param int $length Length. 250 * @return mixed 251 * @throws \Hoa\File\Exception 252 */ 253 public function write($string, $length) 254 { 255 if (0 > $length) { 256 throw new File\Exception( 257 'Length must be greater than 0, given %d.', 258 3, 259 $length 260 ); 261 } 262 263 return fwrite($this->getStream(), $string, $length); 264 } 265 266 /** 267 * Write a string. 268 * 269 * @param string $string String. 270 * @return mixed 271 */ 272 public function writeString($string) 273 { 274 $string = (string) $string; 275 276 return $this->write($string, strlen($string)); 277 } 278 279 /** 280 * Write a character. 281 * 282 * @param string $char Character. 283 * @return mixed 284 */ 285 public function writeCharacter($char) 286 { 287 return $this->write((string) $char[0], 1); 288 } 289 290 /** 291 * Write a boolean. 292 * 293 * @param bool $boolean Boolean. 294 * @return mixed 295 */ 296 public function writeBoolean($boolean) 297 { 298 return $this->write((string) (bool) $boolean, 1); 299 } 300 301 /** 302 * Write an integer. 303 * 304 * @param int $integer Integer. 305 * @return mixed 306 */ 307 public function writeInteger($integer) 308 { 309 $integer = (string) (int) $integer; 310 311 return $this->write($integer, strlen($integer)); 312 } 313 314 /** 315 * Write a float. 316 * 317 * @param float $float Float. 318 * @return mixed 319 */ 320 public function writeFloat($float) 321 { 322 $float = (string) (float) $float; 323 324 return $this->write($float, strlen($float)); 325 } 326 327 /** 328 * Write an array. 329 * 330 * @param array $array Array. 331 * @return mixed 332 */ 333 public function writeArray(array $array) 334 { 335 $array = var_export($array, true); 336 337 return $this->write($array, strlen($array)); 338 } 339 340 /** 341 * Write a line. 342 * 343 * @param string $line Line. 344 * @return mixed 345 */ 346 public function writeLine($line) 347 { 348 if (false === $n = strpos($line, "\n")) { 349 return $this->write($line . "\n", strlen($line) + 1); 350 } 351 352 ++$n; 353 354 return $this->write(substr($line, 0, $n), $n); 355 } 356 357 /** 358 * Write all, i.e. as much as possible. 359 * 360 * @param string $string String. 361 * @return mixed 362 */ 363 public function writeAll($string) 364 { 365 return $this->write($string, strlen($string)); 366 } 367 368 /** 369 * Truncate a file to a given length. 370 * 371 * @param int $size Size. 372 * @return bool 373 */ 374 public function truncate($size) 375 { 376 return ftruncate($this->getStream(), $size); 377 } 378} 379