<?php

class MemoryStream
{
  public $Data;
  public $Position;

  function __construct()
  {
    $this->Data = '';
    $this->Position = 0;
  }

  function __destruct()
  {
  }

  public function ReadBlock($Count)
  {
    $Result = substr($this->Data, $this->Position, $Count);
    $this->Position = $this->Position + $Count;
    return $Result;
  }

  public function ReadByte()
  {
    $Result = $this->Data[$this->Position];
    $this->Position = $this->Position + 1;
    return $Result;
  }

  public function ReadUint()
  {
    $val = unpack('V*', substr($this->Data, $this->Position, 4));
    $this->Position = $this->Position + 4;
    return $val[1];
  }

  public function ReadInt()
  {
    $val = unpack('I*', substr($this->Data, $this->Position, 4));
    $this->Position = $this->Position + 4;
    return $val[1];
  }

  public function ReadFloat()
  {
    $val = unpack('f*', substr($this->Data, $this->Position, 4));
    $this->Position = $this->Position + 4;
    return $val[1];
  }

  public function ReadChar()
  {
    $Result = $this->Data[$this->Position];
    $this->Position = $this->Position + 1;
    return $Result;
  }

  public function ReadLine($EndSymbol = "\r")
  {
    $Length = 0;
    $StartPosition = $this->Position;
    while (!$this->EOF())
    {
      $Char = $this->ReadChar();
      if ($Char == $EndSymbol) break;
    }
    $Result = substr($this->Data, $StartPosition, $this->Position - $StartPosition);
    return $Result;
  }

  public function WriteBlock($Value, $Count)
  {
    $this->Data = substr_replace($this->Data, $Value, $this->Position, $Count);
    $this->Position = $this->Position + $Count;
  }

  public function WriteByte($Value)
  {
    $this->Data[$this->Position] = pack('C*', $Value);
    $this->Position++;
  }

  public function WriteUint($Value)
  {
    $this->WriteBlock(pack('V*', $Value), 4);
  }

  public function WriteInt($Value)
  {
    $this->WriteBlock(pack('I*', $Value), 4);
  }

  public function WriteFloat($Value)
  {
    $this->WriteBlock(pack('f*', $Value), 4);
  }

  public function WriteChar($Value)
  {
    $this->Data[$this->Position] = pack('C*', $Value);
    $this->Position++;
  }

  public function WriteLine($Value)
  {
    $this->WriteBlock($Value."\r\n", strlen($Value) + 2);
  }

  public function SetPosition($Position)
  {
    $this->Position = $Position;
  }

  public function GetPosition()
  {
    return $this->Position;
  }

  public function GetSize()
  {
    return strlen($this->Data);
  }

  public function SetSize($Size)
  {
    return $this->Data = substr($this->Data, 0, $Size);
  }

  public function EOF()
  {
    return $this->Position >= strlen($this->Data);
  }
}
