summaryrefslogtreecommitdiff
path: root/vendor/wikimedia/avro/lib/avro/io.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/wikimedia/avro/lib/avro/io.php')
-rw-r--r--vendor/wikimedia/avro/lib/avro/io.php494
1 files changed, 494 insertions, 0 deletions
diff --git a/vendor/wikimedia/avro/lib/avro/io.php b/vendor/wikimedia/avro/lib/avro/io.php
new file mode 100644
index 00000000..239e53d8
--- /dev/null
+++ b/vendor/wikimedia/avro/lib/avro/io.php
@@ -0,0 +1,494 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Avro IO object classes
+ * @package Avro
+ */
+
+/**
+ * Exceptions associated with AvroIO instances.
+ * @package Avro
+ */
+class AvroIOException extends AvroException {}
+
+/**
+ * Barebones IO base class to provide common interface for file and string
+ * access within the Avro classes.
+ *
+ * @package Avro
+ */
+class AvroIO
+{
+
+ /**
+ * @var string general read mode
+ */
+ const READ_MODE = 'r';
+ /**
+ * @var string general write mode.
+ */
+ const WRITE_MODE = 'w';
+
+ /**
+ * @var int set position equal to $offset bytes
+ */
+ const SEEK_CUR = SEEK_CUR;
+ /**
+ * @var int set position to current index + $offset bytes
+ */
+ const SEEK_SET = SEEK_SET;
+ /**
+ * @var int set position to end of file + $offset bytes
+ */
+ const SEEK_END = SEEK_END;
+
+ /**
+ * Read $len bytes from AvroIO instance
+ * @var int $len
+ * @return string bytes read
+ */
+ public function read($len)
+ {
+ throw new AvroNotImplementedException('Not implemented');
+ }
+
+ /**
+ * Append bytes to this buffer. (Nothing more is needed to support Avro.)
+ * @param str $arg bytes to write
+ * @returns int count of bytes written.
+ * @throws AvroIOException if $args is not a string value.
+ */
+ public function write($arg)
+ {
+ throw new AvroNotImplementedException('Not implemented');
+ }
+
+ /**
+ * Return byte offset within AvroIO instance
+ * @return int
+ */
+ public function tell()
+ {
+ throw new AvroNotImplementedException('Not implemented');
+ }
+
+ /**
+ * Set the position indicator. The new position, measured in bytes
+ * from the beginning of the file, is obtained by adding $offset to
+ * the position specified by $whence.
+ *
+ * @param int $offset
+ * @param int $whence one of AvroIO::SEEK_SET, AvroIO::SEEK_CUR,
+ * or Avro::SEEK_END
+ * @returns boolean true
+ *
+ * @throws AvroIOException
+ */
+ public function seek($offset, $whence=self::SEEK_SET)
+ {
+ throw new AvroNotImplementedException('Not implemented');
+ }
+
+ /**
+ * Flushes any buffered data to the AvroIO object.
+ * @returns boolean true upon success.
+ */
+ public function flush()
+ {
+ throw new AvroNotImplementedException('Not implemented');
+ }
+
+ /**
+ * Returns whether or not the current position at the end of this AvroIO
+ * instance.
+ *
+ * Note is_eof() is <b>not</b> like eof in C or feof in PHP:
+ * it returns TRUE if the *next* read would be end of file,
+ * rather than if the *most recent* read read end of file.
+ * @returns boolean true if at the end of file, and false otherwise
+ */
+ public function is_eof()
+ {
+ throw new AvroNotImplementedException('Not implemented');
+ }
+
+ /**
+ * Closes this AvroIO instance.
+ */
+ public function close()
+ {
+ throw new AvroNotImplementedException('Not implemented');
+ }
+
+}
+
+/**
+ * AvroIO wrapper for string access
+ * @package Avro
+ */
+class AvroStringIO extends AvroIO
+{
+ /**
+ * @var string
+ */
+ private $string_buffer;
+ /**
+ * @var int current position in string
+ */
+ private $current_index;
+ /**
+ * @var boolean whether or not the string is closed.
+ */
+ private $is_closed;
+
+ /**
+ * @param string $str initial value of AvroStringIO buffer. Regardless
+ * of the initial value, the pointer is set to the
+ * beginning of the buffer.
+ * @throws AvroIOException if a non-string value is passed as $str
+ */
+ public function __construct($str = '')
+ {
+ $this->is_closed = false;
+ $this->string_buffer = '';
+ $this->current_index = 0;
+
+ if (is_string($str))
+ $this->string_buffer .= $str;
+ else
+ throw new AvroIOException(
+ sprintf('constructor argument must be a string: %s', gettype($str)));
+ }
+
+ /**
+ * Append bytes to this buffer.
+ * (Nothing more is needed to support Avro.)
+ * @param str $arg bytes to write
+ * @returns int count of bytes written.
+ * @throws AvroIOException if $args is not a string value.
+ */
+ public function write($arg)
+ {
+ $this->check_closed();
+ if (is_string($arg))
+ return $this->append_str($arg);
+ throw new AvroIOException(
+ sprintf('write argument must be a string: (%s) %s',
+ gettype($arg), var_export($arg, true)));
+ }
+
+ /**
+ * @returns string bytes read from buffer
+ * @todo test for fencepost errors wrt updating current_index
+ */
+ public function read($len)
+ {
+ $this->check_closed();
+ $read='';
+ for($i=$this->current_index; $i<($this->current_index+$len); $i++)
+ $read .= $this->string_buffer[$i];
+ if (strlen($read) < $len)
+ $this->current_index = $this->length();
+ else
+ $this->current_index += $len;
+ return $read;
+ }
+
+ /**
+ * @returns boolean true if successful
+ * @throws AvroIOException if the seek failed.
+ */
+ public function seek($offset, $whence=self::SEEK_SET)
+ {
+ if (!is_int($offset))
+ throw new AvroIOException('Seek offset must be an integer.');
+ // Prevent seeking before BOF
+ switch ($whence)
+ {
+ case self::SEEK_SET:
+ if (0 > $offset)
+ throw new AvroIOException('Cannot seek before beginning of file.');
+ $this->current_index = $offset;
+ break;
+ case self::SEEK_CUR:
+ if (0 > $this->current_index + $whence)
+ throw new AvroIOException('Cannot seek before beginning of file.');
+ $this->current_index += $offset;
+ break;
+ case self::SEEK_END:
+ if (0 > $this->length() + $offset)
+ throw new AvroIOException('Cannot seek before beginning of file.');
+ $this->current_index = $this->length() + $offset;
+ break;
+ default:
+ throw new AvroIOException(sprintf('Invalid seek whence %d', $whence));
+ }
+
+ return true;
+ }
+
+ /**
+ * @returns int
+ * @see AvroIO::tell()
+ */
+ public function tell() { return $this->current_index; }
+
+ /**
+ * @returns boolean
+ * @see AvroIO::is_eof()
+ */
+ public function is_eof()
+ {
+ return ($this->current_index >= $this->length());
+ }
+
+ /**
+ * No-op provided for compatibility with AvroIO interface.
+ * @returns boolean true
+ */
+ public function flush() { return true; }
+
+ /**
+ * Marks this buffer as closed.
+ * @returns boolean true
+ */
+ public function close()
+ {
+ $this->check_closed();
+ $this->is_closed = true;
+ return true;
+ }
+
+ /**
+ * @throws AvroIOException if the buffer is closed.
+ */
+ private function check_closed()
+ {
+ if ($this->is_closed())
+ throw new AvroIOException('Buffer is closed');
+ }
+
+ /**
+ * Appends bytes to this buffer.
+ * @param string $str
+ * @returns integer count of bytes written.
+ */
+ private function append_str($str)
+ {
+ $this->check_closed();
+ $this->string_buffer .= $str;
+ $len = strlen($str);
+ $this->current_index += $len;
+ return $len;
+ }
+
+ /**
+ * Truncates the truncate buffer to 0 bytes and returns the pointer
+ * to the beginning of the buffer.
+ * @returns boolean true
+ */
+ public function truncate()
+ {
+ $this->check_closed();
+ $this->string_buffer = '';
+ $this->current_index = 0;
+ return true;
+ }
+
+ /**
+ * @returns int count of bytes in the buffer
+ * @internal Could probably memoize length for performance, but
+ * no need do this yet.
+ */
+ public function length() { return strlen($this->string_buffer); }
+
+ /**
+ * @returns string
+ */
+ public function __toString() { return $this->string_buffer; }
+
+
+ /**
+ * @returns string
+ * @uses self::__toString()
+ */
+ public function string() { return $this->__toString(); }
+
+ /**
+ * @returns boolean true if this buffer is closed and false
+ * otherwise.
+ */
+ public function is_closed() { return $this->is_closed; }
+}
+
+/**
+ * AvroIO wrapper for PHP file access functions
+ * @package Avro
+ */
+class AvroFile extends AvroIO
+{
+ /**
+ * @var string fopen read mode value. Used internally.
+ */
+ const FOPEN_READ_MODE = 'rb';
+
+ /**
+ * @var string fopen write mode value. Used internally.
+ */
+ const FOPEN_WRITE_MODE = 'wb';
+
+ /**
+ * @var string
+ */
+ private $file_path;
+
+ /**
+ * @var resource file handle for AvroFile instance
+ */
+ private $file_handle;
+
+ public function __construct($file_path, $mode = self::READ_MODE)
+ {
+ /**
+ * XXX: should we check for file existence (in case of reading)
+ * or anything else about the provided file_path argument?
+ */
+ $this->file_path = $file_path;
+ switch ($mode)
+ {
+ case self::WRITE_MODE:
+ $this->file_handle = fopen($this->file_path, self::FOPEN_WRITE_MODE);
+ if (false == $this->file_handle)
+ throw new AvroIOException('Could not open file for writing');
+ break;
+ case self::READ_MODE:
+ $this->file_handle = fopen($this->file_path, self::FOPEN_READ_MODE);
+ if (false == $this->file_handle)
+ throw new AvroIOException('Could not open file for reading');
+ break;
+ default:
+ throw new AvroIOException(
+ sprintf("Only modes '%s' and '%s' allowed. You provided '%s'.",
+ self::READ_MODE, self::WRITE_MODE, $mode));
+ }
+ }
+
+ /**
+ * @returns int count of bytes written
+ * @throws AvroIOException if write failed.
+ */
+ public function write($str)
+ {
+ $len = fwrite($this->file_handle, $str);
+ if (false === $len)
+ throw new AvroIOException(sprintf('Could not write to file'));
+ return $len;
+ }
+
+ /**
+ * @param int $len count of bytes to read.
+ * @returns string bytes read
+ * @throws AvroIOException if length value is negative or if the read failed
+ */
+ public function read($len)
+ {
+ if (0 > $len)
+ throw new AvroIOException(
+ sprintf("Invalid length value passed to read: %d", $len));
+
+ if (0 == $len)
+ return '';
+
+ $bytes = fread($this->file_handle, $len);
+ if (false === $bytes)
+ throw new AvroIOException('Could not read from file');
+ return $bytes;
+ }
+
+ /**
+ * @returns int current position within the file
+ * @throws AvroFileExcpetion if tell failed.
+ */
+ public function tell()
+ {
+ $position = ftell($this->file_handle);
+ if (false === $position)
+ throw new AvroIOException('Could not execute tell on reader');
+ return $position;
+ }
+
+ /**
+ * @param int $offset
+ * @param int $whence
+ * @returns boolean true upon success
+ * @throws AvroIOException if seek failed.
+ * @see AvroIO::seek()
+ */
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ $res = fseek($this->file_handle, $offset, $whence);
+ // Note: does not catch seeking beyond end of file
+ if (-1 === $res)
+ throw new AvroIOException(
+ sprintf("Could not execute seek (offset = %d, whence = %d)",
+ $offset, $whence));
+ return true;
+ }
+
+ /**
+ * Closes the file.
+ * @returns boolean true if successful.
+ * @throws AvroIOException if there was an error closing the file.
+ */
+ public function close()
+ {
+ $res = fclose($this->file_handle);
+ if (false === $res)
+ throw new AvroIOException('Error closing file.');
+ return $res;
+ }
+
+ /**
+ * @returns boolean true if the pointer is at the end of the file,
+ * and false otherwise.
+ * @see AvroIO::is_eof() as behavior differs from feof()
+ */
+ public function is_eof()
+ {
+ $this->read(1);
+ if (feof($this->file_handle))
+ return true;
+ $this->seek(-1, self::SEEK_CUR);
+ return false;
+ }
+
+ /**
+ * @returns boolean true if the flush was successful.
+ * @throws AvroIOException if there was an error flushing the file.
+ */
+ public function flush()
+ {
+ $res = fflush($this->file_handle);
+ if (false === $res)
+ throw new AvroIOException('Could not flush file.');
+ return true;
+ }
+
+}