diff --git a/src/Reader.php b/src/Reader.php
new file mode 100644
index 0000000..ee143c3
--- /dev/null
+++ b/src/Reader.php
@@ -0,0 +1,182 @@
+
+ * @copyright 2006, 2007 The Bearpaw Project Work Group
+ * @copyright 2007, 2008 BEHR Software Systems
+ * @version $Rev$
+ */
+class Reader
+{
+ /**
+ * @var resource The underlying file descriptor.
+ */
+ private $_fd;
+
+ /**
+ * @var integer The file size.
+ */
+ private $_size;
+
+ /**
+ * Opens the file given as a parameter.
+ *
+ * @param string $filename The absolute or relative path to the file.
+ * @throws ReaderException if the file cannot be read.
+ */
+ public function __construct($filename)
+ {
+ if (($this->_fd = fopen($filename, "rb")) === false)
+ throw new ReaderException("Unable to open file:" . $filename);
+
+ fseek($this->_fd, 0, SEEK_END);
+ $this->_size = ftell($this->_fd);
+ fseek($this->_fd, 0);
+ }
+
+ /**
+ * Closes the file.
+ */
+ public function __destruct()
+ {
+ @fclose($this->_fd);
+ }
+
+ /**
+ * Checks whether there is more to be read in the file.
+ *
+ * @return boolean Returns true if the end of the file has not yet
+ * been reached; false otherwise.
+ */
+ public function available()
+ {
+ return $this->getOffset() < $this->_size;
+ }
+
+ /**
+ * Jumps size amount of bytes in the file stream.
+ *
+ * @return void
+ * @throws ReaderException if size attribute is not greater or
+ * equal than zero.
+ */
+ public function skip($size)
+ {
+ if ($size < 0)
+ throw new ReaderException("Invalid argument");
+ fseek($this->_fd, $size, SEEK_CUR);
+ }
+
+ /**
+ * Reads length amount of bytes from the file stream.
+ *
+ * @return string Returns read bytes as a string
+ * @throws ReaderException if length attribute is not greater than
+ * zero.
+ */
+ public function read($length)
+ {
+ if ($length <= 0)
+ throw new ReaderException("Invalid argument");
+ return fread($this->_fd, $length);
+ }
+
+ /**
+ * Returns the current point of operation.
+ *
+ * @return integer Returns the current cursor position.
+ */
+ public function getOffset()
+ {
+ return ftell($this->_fd);
+ }
+
+ /**
+ * Sets the point of operation, ie the cursor offset value.
+ *
+ * @return void
+ */
+ public function setOffset($offset)
+ {
+ fseek($this->_fd, $offset);
+ }
+
+ /**
+ * Returns the file size in bytes.
+ *
+ * @return integer Returns the file size in bytes.
+ */
+ public function getSize()
+ {
+ return $this->_size;
+ }
+
+ /**
+ * Magic function to delegate the call to helper methods of Transform class
+ * to transform read data in another format.
+ *
+ * The read data length is determined from the helper method name. For methods
+ * where arbitrary data lengths are accepted a parameter can be used to
+ * specify the length.
+ *
+ * @param string $method The method to be called.
+ * @param string $params The parameters should the function accept them.
+ * @return mixed
+ * @throws ReaderException if no such transformer is implemented
+ */
+ public function __call($method, $params) {
+ $chunks = array();
+ if (preg_match
+ ("/get([a-z]{3,6})?(\d{1,2})?(?:LE|BE)?/i", $method, $chunks) &&
+ method_exists("Transform", $method)) {
+ return call_user_func
+ (array("Transform", $method),
+ $this->read(preg_match("/String|(?:H|L)Hex/", $chunks[1]) ?
+ (isset($params[0]) ? $params[0] : 1) :
+ ($chunks[1] == "GUID" ? 16 : $chunks[2] / 8)));
+ } else throw new ReaderException("Unknown method: " . $method);
+ }
+}
diff --git a/src/ReaderException.php b/src/ReaderException.php
new file mode 100644
index 0000000..c056049
--- /dev/null
+++ b/src/ReaderException.php
@@ -0,0 +1,46 @@
+
+ * @copyright 2008 BEHR Software Systems
+ * @version $Rev$
+ */
+class ReaderException extends Exception
+{
+}
diff --git a/src/Transform.php b/src/Transform.php
new file mode 100644
index 0000000..aeb91d2
--- /dev/null
+++ b/src/Transform.php
@@ -0,0 +1,282 @@
+
+ * @copyright 2006, 2007 The Bearpaw Project Work Group
+ * @copyright 2007, 2008 BEHR Software Systems
+ * @version $Rev$
+ * @static
+ */
+final class Transform
+{
+ const MACHINE_ENDIAN_ORDER = 0;
+ const LITTLE_ENDIAN_ORDER = 1;
+ const BIG_ENDIAN_ORDER = 2;
+
+ /**
+ * Default private constructor for a static class.
+ */
+ private function __construct() {}
+
+ /**
+ * Returns machine-endian ordered binary data as 64-bit float. PHP does not
+ * support 64-bit integers as the long integer is of 32-bits but using
+ * aritmetic operations it is implicitly converted into floating point which
+ * is of 64-bits long.
+ *
+ * @return integer Returns the resulting 64-bit integer.
+ */
+ public static function getInt64($raw, $order = self::MACHINE_ENDIAN_ORDER)
+ {
+ list(, $lo, $hi) = unpack(($order == 2 ? "L" :
+ ($order == 1 ? "V" : "N")) . "*", $raw);
+ return $hi * 0xffffffff + $lo;
+ }
+
+ /**
+ * Returns little-endian ordered binary data as 64-bit float. PHP does not
+ * support 64-bit integers as the long integer is of 32-bits but using
+ * aritmetic operations it is implicitly converted into floating point which
+ * is of 64-bits long.
+ *
+ * @return integer Returns the resulting 64-bit integer.
+ */
+ public static function getInt64LE($raw)
+ {
+ return ReaderUtils::getInt64($raw, self::LITTLE_ENDIAN_ORDER);
+ }
+
+ /**
+ * Returns big-endian ordered binary data as 64-bit float. PHP does not
+ * support 64-bit integers as the long integer is of 32-bits but using
+ * aritmetic operations it is implicitly converted into floating point which
+ * is of 64-bits long.
+ *
+ * @return integer Returns the resulting 64-bit integer.
+ */
+ public static function getInt64BE($raw)
+ {
+ return ReaderUtils::getInt64($raw, self::BIG_ENDIAN_ORDER);
+ }
+
+ /**
+ * Returns machine-endian ordered binary data as signed 32-bit integer.
+ *
+ * @return integer Returns the resulting signed 32-bit integer.
+ */
+ public static function getInt32($raw)
+ {
+ list(, $int) = unpack("l*", $raw);
+ return $int;
+ }
+
+ /**
+ * Returns machine-endian ordered binary data as unsigned 32-bit integer.
+ *
+ * @return integer Returns the resulting unsigned 32-bit integer.
+ */
+ public static function getUInt32($raw, $order = self::MACHINE_ENDIAN_ORDER)
+ {
+ list(, $int) = unpack(($order == 2 ? "N" :
+ ($order == 1 ? "V" : "L")) . "*", $raw);
+ return $int;
+ }
+
+ /**
+ * Returns little-endian ordered binary data as unsigned 32-bit integer.
+ *
+ * @return integer Returns the resulting unsigned 32-bit integer.
+ */
+ public static function getUInt32LE($raw)
+ {
+ return ReaderUtils::getUInt32($raw, self::LITTLE_ENDIAN_ORDER);
+ }
+
+ /**
+ * Returns big-endian ordered binary data as unsigned 32-bit integer.
+ *
+ * @return integer Returns the resulting unsigned 32-bit integer.
+ */
+ public static function getUInt32BE($raw)
+ {
+ return ReaderUtils::getUInt32($raw, self::BIG_ENDIAN_ORDER);
+ }
+
+ /**
+ * Returns machine endian ordered binary data as signed 16-bit integer.
+ *
+ * @return integer Returns the resulting signed 16-bit integer.
+ */
+ public static function getInt16($raw)
+ {
+ list(, $int) = unpack("s*", $raw);
+ return $int;
+ }
+
+ /**
+ * Returns machine endian ordered binary data as unsigned 16-bit integer.
+ *
+ * @return integer Returns the resulting unsigned 16-bit integer.
+ */
+ public static function getUInt16($raw, $order)
+ {
+ list(, $int) = unpack(($order == 2 ? "n" :
+ ($order == 1 ? "v" : "S")) . "*", $raw);
+ return $int;
+ }
+
+ /**
+ * Returns little-endian ordered binary data as unsigned 16-bit integer.
+ *
+ * @return integer Returns the resulting unsigned 16-bit integer.
+ */
+ public static function getUInt16LE($raw)
+ {
+ return ReaderUtils::getUInt16($raw, self::LITTLE_ENDIAN_ORDER);
+ }
+
+ /**
+ * Returns big-endian ordered binary data as unsigned 16-bit integer.
+ *
+ * @return integer Returns the resulting unsigned 16-bit integer.
+ */
+ public static function getUInt16BE($raw)
+ {
+ return ReaderUtils::getUInt16($raw, self::BIG_ENDIAN_ORDER);
+ }
+
+ /**
+ * Returns binary data as 8-bit integer.
+ *
+ * @return integer Returns the resulting 8-bit integer.
+ */
+ public static function getInt8($raw)
+ {
+ return $raw;
+ }
+
+ /**
+ * Returns binary data as string. Removes terminating zero.
+ *
+ * @return string Returns the resulting string.
+ */
+ public static function getString8($raw)
+ {
+ $string = "";
+ foreach (unpack("C*", $raw) as $char)
+ $string .= pack("c", $char);
+ return rtrim($string, "\0");
+ }
+
+ /**
+ * Returns machine-endian ordered binary data as string.
+ *
+ * @return string Returns the resulting string.
+ */
+ public static function getString16($raw, $order = self::MACHINE_ENDIAN_ORDER)
+ {
+ $string = "";
+ foreach (unpack(($order == 2 ? "n" :
+ ($order == 1 ? "v" : "S")) . "*", $raw) as $char)
+ $string .= pack("S", $char);
+ return rtrim($string, "\0");
+ }
+
+ /**
+ * Returns little-endian ordered binary data as string.
+ *
+ * @return string Returns the resulting string.
+ */
+ public static function getString16LE($raw)
+ {
+ return ReaderUtils::getString16($raw, self::LITTLE_ENDIAN_ORDER);
+ }
+
+ /**
+ * Returns big-endian ordered binary data as string.
+ *
+ * @return string Returns the resulting string.
+ */
+ public static function getString16BE($raw)
+ {
+ return ReaderUtils::getString16($raw, self::BIG_ENDIAN_ORDER);
+ }
+
+ /**
+ * Returns binary data as hexadecimal string having high nibble first.
+ *
+ * @return string Returns the resulting string.
+ */
+ public static function getHHex($raw)
+ {
+ list($hex) = unpack("H*0", $raw);
+ return $hex;
+ }
+
+ /**
+ * Returns binary data as hexadecimal string having low nibble first.
+ *
+ * @return string Returns the resulting string.
+ */
+ public static function getLHex($raw)
+ {
+ list($hex) = unpack("h*0", $raw);
+ return $hex;
+ }
+
+ /**
+ * Returns the little-endian ordered raw data as big-endian ordered
+ * hexadecimal GUID string.
+ *
+ * @return string Returns the raw data in appropriate GUID format.
+ */
+ public static function getGUID($raw)
+ {
+ $C = @unpack("V1V/v2v/N2N", $raw);
+ list($hex) = @unpack("H*0", pack
+ ("NnnNN", $C["V"], $C["v1"], $C["v2"], $C["N1"], $C["N2"]));
+
+ /* Fixes a bug in PHP versions earlier than Jan 25 2006 */
+ if (implode("", unpack("H*", pack("H*", "a"))) == "a00")
+ $hex = substr($hex, 0, -1);
+
+ return preg_replace
+ ("/^(.{8})(.{4})(.{4})(.{4})/", "\\1-\\2-\\3-\\4-", $hex);
+ }
+}