<?php

// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd

namespace Google\Protobuf\Internal;

use Google\Protobuf\Internal\Uint64;

class CodedInputStream
{

    private $buffer;
    private $buffer_size_after_limit;
    private $buffer_end;
    private $current;
    private $current_limit;
    private $legitimate_message_end;
    private $recursion_budget;
    private $recursion_limit;
    private $total_bytes_limit;
    private $total_bytes_read;

    const MAX_VARINT_BYTES = 10;
    const DEFAULT_RECURSION_LIMIT = 100;
    const DEFAULT_TOTAL_BYTES_LIMIT = 33554432; // 32 << 20, 32MB

    public function __construct($buffer)
    {
        $start = 0;
        $end = strlen($buffer);
        $this->buffer = $buffer;
        $this->buffer_size_after_limit = 0;
        $this->buffer_end = $end;
        $this->current = $start;
        $this->current_limit = $end;
        $this->legitimate_message_end = false;
        $this->recursion_budget = self::DEFAULT_RECURSION_LIMIT;
        $this->recursion_limit = self::DEFAULT_RECURSION_LIMIT;
        $this->total_bytes_limit = self::DEFAULT_TOTAL_BYTES_LIMIT;
        $this->total_bytes_read = $end - $start;
    }

    private function advance($amount)
    {
        $this->current += $amount;
    }

    public function bufferSize()
    {
        return $this->buffer_end - $this->current;
    }

    public function current()
    {
        return $this->total_bytes_read -
            ($this->buffer_end - $this->current +
            $this->buffer_size_after_limit);
    }

    public function substr($start, $end)
    {
        return substr($this->buffer, $start, $end - $start);
    }

    private function recomputeBufferLimits()
    {
        $this->buffer_end += $this->buffer_size_after_limit;
        $closest_limit = min($this->current_limit, $this->total_bytes_limit);
        if ($closest_limit < $this->total_bytes_read) {
            // The limit position is in the current buffer.  We must adjust the
            // buffer size accordingly.
            $this->buffer_size_after_limit = $this->total_bytes_read -
                $closest_limit;
            $this->buffer_end -= $this->buffer_size_after_limit;
        } else {
            $this->buffer_size_after_limit = 0;
        }
    }

    private function consumedEntireMessage()
    {
        return $this->legitimate_message_end;
    }

    /**
     * Read uint32 into $var. Advance buffer with consumed bytes. If the
     * contained varint is larger than 32 bits, discard the high order bits.
     * @param $var
     */
    public function readVarint32(&$var)
    {
        if (!$this->readVarint64($var)) {
            return false;
        }

        if (PHP_INT_SIZE == 4) {
            $var = bcmod($var, 4294967296);
        } else {
            $var &= 0xFFFFFFFF;
        }

        // Convert large uint32 to int32.
        if ($var > 0x7FFFFFFF) {
            if (PHP_INT_SIZE === 8) {
                $var = $var | (0xFFFFFFFF << 32);
            } else {
                $var = bcsub($var, 4294967296);
            }
        }

        $var = intval($var);
        return true;
    }

    /**
     * Read Uint64 into $var. Advance buffer with consumed bytes.
     * @param $var
     */
    public function readVarint64(&$var)
    {
        $count = 0;

        if (PHP_INT_SIZE == 4) {
            $high = 0;
            $low = 0;
            $b = 0;

            do {
                if ($this->current === $this->buffer_end) {
                    return false;
                }
                if ($count === self::MAX_VARINT_BYTES) {
                    return false;
                }
                $b = ord($this->buffer[$this->current]);
                $bits = 7 * $count;
                if ($bits >= 32) {
                    $high |= (($b & 0x7F) << ($bits - 32));
                } else if ($bits > 25){
                    // $bits is 28 in this case.
                    $low |= (($b & 0x7F) << 28);
                    $high = ($b & 0x7F) >> 4;
                } else {
                    $low |= (($b & 0x7F) << $bits);
                }

                $this->advance(1);
                $count += 1;
            } while ($b & 0x80);

            $var = GPBUtil::combineInt32ToInt64($high, $low);
            if (bccomp($var, 0) < 0) {
                $var = bcadd($var, "18446744073709551616");
            }
        } else {
            $result = 0;
            $shift = 0;

            do {
                if ($this->current === $this->buffer_end) {
                    return false;
                }
                if ($count === self::MAX_VARINT_BYTES) {
                    return false;
                }

                $byte = ord($this->buffer[$this->current]);
                $result |= ($byte & 0x7f) << $shift;
                $shift += 7;
                $this->advance(1);
                $count += 1;
            } while ($byte > 0x7f);

            $var = $result;
        }

        return true;
    }

    /**
     * Read int into $var. If the result is larger than the largest integer, $var
     * will be -1. Advance buffer with consumed bytes.
     * @param $var
     */
    public function readVarintSizeAsInt(&$var)
    {
        if (!$this->readVarint64($var)) {
            return false;
        }
        $var = (int)$var;
        return true;
    }

    /**
     * Read 32-bit unsigned integer to $var. If the buffer has less than 4 bytes,
     * return false. Advance buffer with consumed bytes.
     * @param $var
     */
    public function readLittleEndian32(&$var)
    {
        $data = null;
        if (!$this->readRaw(4, $data)) {
            return false;
        }
        $var = unpack('V', $data);
        $var = $var[1];
        return true;
    }

    /**
     * Read 64-bit unsigned integer to $var. If the buffer has less than 8 bytes,
     * return false. Advance buffer with consumed bytes.
     * @param $var
     */
    public function readLittleEndian64(&$var)
    {
        $data = null;
        if (!$this->readRaw(4, $data)) {
            return false;
        }
        $low = unpack('V', $data)[1];
        if (!$this->readRaw(4, $data)) {
            return false;
        }
        $high = unpack('V', $data)[1];
        if (PHP_INT_SIZE == 4) {
            $var = GPBUtil::combineInt32ToInt64($high, $low);
        } else {
            $var = ($high << 32) | $low;
        }
        return true;
    }

    /**
     * Read tag into $var. Advance buffer with consumed bytes.
     */
    public function readTag()
    {
        if ($this->current === $this->buffer_end) {
            // Make sure that it failed due to EOF, not because we hit
            // total_bytes_limit, which, unlike normal limits, is not a valid
            // place to end a message.
            $current_position = $this->total_bytes_read -
                $this->buffer_size_after_limit;
            if ($current_position >= $this->total_bytes_limit) {
                // Hit total_bytes_limit_.  But if we also hit the normal limit,
                // we're still OK.
                $this->legitimate_message_end =
                    ($this->current_limit === $this->total_bytes_limit);
            } else {
                $this->legitimate_message_end = true;
            }
            return 0;
        }

        $result = 0;
        // The largest tag is 2^29 - 1, which can be represented by int32.
        $success = $this->readVarint32($result);
        if ($success) {
            return $result;
        } else {
            return 0;
        }
    }

    public function readRaw($size, &$buffer)
    {
        $current_buffer_size = 0;
        // size (varint) read from the wire could be negative.
        if ($size < 0 || $this->bufferSize() < $size) {
            return false;
        }

        if ($size === 0) {
          $buffer = "";
        } else {
          $buffer = substr($this->buffer, $this->current, $size);
          $this->advance($size);
        }

        return true;
    }

    /* Places a limit on the number of bytes that the stream may read, starting
     * from the current position.  Once the stream hits this limit, it will act
     * like the end of the input has been reached until popLimit() is called.
     *
     * As the names imply, the stream conceptually has a stack of limits.  The
     * shortest limit on the stack is always enforced, even if it is not the top
     * limit.
     *
     * The value returned by pushLimit() is opaque to the caller, and must be
     * passed unchanged to the corresponding call to popLimit().
     *
     * @param integer $byte_limit
     * @throws \Exception Fail to push limit.
     */
    public function pushLimit($byte_limit)
    {
        // Current position relative to the beginning of the stream.
        $current_position = $this->current();
        $old_limit = $this->current_limit;

        // security: byte_limit is possibly evil, so check for negative values
        // and overflow.
        if ($byte_limit >= 0 &&
            $byte_limit <= PHP_INT_MAX - $current_position &&
            $byte_limit <= $this->current_limit - $current_position) {
            $this->current_limit = $current_position + $byte_limit;
            $this->recomputeBufferLimits();
        } else {
            throw new GPBDecodeException("Fail to push limit.");
        }

        return $old_limit;
    }

    /* The limit passed in is actually the *old* limit, which we returned from
     * PushLimit().
     *
     * @param integer $byte_limit
     */
    public function popLimit($byte_limit)
    {
        $this->current_limit = $byte_limit;
        $this->recomputeBufferLimits();
        // We may no longer be at a legitimate message end.  ReadTag() needs to
        // be called again to find out.
        $this->legitimate_message_end = false;
    }

    public function incrementRecursionDepthAndPushLimit(
        $byte_limit, &$old_limit, &$recursion_budget)
    {
        $old_limit = $this->pushLimit($byte_limit);
        $recursion_budget = --$this->recursion_budget;
    }

    public function decrementRecursionDepthAndPopLimit($byte_limit)
    {
        $result = $this->consumedEntireMessage();
        $this->popLimit($byte_limit);
        ++$this->recursion_budget;
        return $result;
    }

    public function bytesUntilLimit()
    {
        if ($this->current_limit === PHP_INT_MAX) {
            return -1;
        }
        return $this->current_limit - $this->current;
    }
}
