]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blobdiff - vendor/wikimedia/avro/lib/avro/io.php
MediaWiki 1.30.2
[autoinstallsdev/mediawiki.git] / vendor / wikimedia / avro / lib / avro / io.php
diff --git a/vendor/wikimedia/avro/lib/avro/io.php b/vendor/wikimedia/avro/lib/avro/io.php
new file mode 100644 (file)
index 0000000..239e53d
--- /dev/null
@@ -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;
+  }
+
+}