• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<?php
2
3// Protocol Buffers - Google's data interchange format
4// Copyright 2008 Google Inc.  All rights reserved.
5//
6// Use of this source code is governed by a BSD-style
7// license that can be found in the LICENSE file or at
8// https://developers.google.com/open-source/licenses/bsd
9
10namespace Google\Protobuf\Internal;
11
12class CodedOutputStream
13{
14
15    private $buffer;
16    private $buffer_size;
17    private $current;
18
19    const MAX_VARINT64_BYTES = 10;
20
21    public function __construct($size)
22    {
23        $this->current = 0;
24        $this->buffer_size = $size;
25        $this->buffer = str_repeat(chr(0), $this->buffer_size);
26    }
27
28    public function getData()
29    {
30        return $this->buffer;
31    }
32
33    public function writeVarint32($value, $trim)
34    {
35        $bytes = str_repeat(chr(0), self::MAX_VARINT64_BYTES);
36        $size = self::writeVarintToArray($value, $bytes, $trim);
37        return $this->writeRaw($bytes, $size);
38    }
39
40    public function writeVarint64($value)
41    {
42        $bytes = str_repeat(chr(0), self::MAX_VARINT64_BYTES);
43        $size = self::writeVarintToArray($value, $bytes);
44        return $this->writeRaw($bytes, $size);
45    }
46
47    public function writeLittleEndian32($value)
48    {
49        $bytes = str_repeat(chr(0), 4);
50        $size = self::writeLittleEndian32ToArray($value, $bytes);
51        return $this->writeRaw($bytes, $size);
52    }
53
54    public function writeLittleEndian64($value)
55    {
56        $bytes = str_repeat(chr(0), 8);
57        $size = self::writeLittleEndian64ToArray($value, $bytes);
58        return $this->writeRaw($bytes, $size);
59    }
60
61    public function writeTag($tag)
62    {
63        return $this->writeVarint32($tag, true);
64    }
65
66    public function writeRaw($data, $size)
67    {
68        if ($this->buffer_size < $size) {
69            trigger_error("Output stream doesn't have enough buffer.");
70            return false;
71        }
72
73        for ($i = 0; $i < $size; $i++) {
74            $this->buffer[$this->current] = $data[$i];
75            $this->current++;
76            $this->buffer_size--;
77        }
78        return true;
79    }
80
81    public static function writeVarintToArray($value, &$buffer, $trim = false)
82    {
83        $current = 0;
84
85        $high = 0;
86        $low = 0;
87        if (PHP_INT_SIZE == 4) {
88            GPBUtil::divideInt64ToInt32($value, $high, $low, $trim);
89        } else {
90            $low = $value;
91        }
92
93        while (($low >= 0x80 || $low < 0) || $high != 0) {
94            $buffer[$current] = chr($low | 0x80);
95            $value = ($value >> 7) & ~(0x7F << ((PHP_INT_SIZE << 3) - 7));
96            $carry = ($high & 0x7F) << ((PHP_INT_SIZE << 3) - 7);
97            $high = ($high >> 7) & ~(0x7F << ((PHP_INT_SIZE << 3) - 7));
98            $low = (($low >> 7) & ~(0x7F << ((PHP_INT_SIZE << 3) - 7)) | $carry);
99            $current++;
100        }
101        $buffer[$current] = chr($low);
102        return $current + 1;
103    }
104
105    private static function writeLittleEndian32ToArray($value, &$buffer)
106    {
107        $buffer[0] = chr($value & 0x000000FF);
108        $buffer[1] = chr(($value >> 8) & 0x000000FF);
109        $buffer[2] = chr(($value >> 16) & 0x000000FF);
110        $buffer[3] = chr(($value >> 24) & 0x000000FF);
111        return 4;
112    }
113
114    private static function writeLittleEndian64ToArray($value, &$buffer)
115    {
116        $high = 0;
117        $low = 0;
118        if (PHP_INT_SIZE == 4) {
119            GPBUtil::divideInt64ToInt32($value, $high, $low);
120        } else {
121            $low = $value & 0xFFFFFFFF;
122            $high = ($value >> 32) & 0xFFFFFFFF;
123        }
124
125        $buffer[0] = chr($low & 0x000000FF);
126        $buffer[1] = chr(($low >> 8) & 0x000000FF);
127        $buffer[2] = chr(($low >> 16) & 0x000000FF);
128        $buffer[3] = chr(($low >> 24) & 0x000000FF);
129        $buffer[4] = chr($high & 0x000000FF);
130        $buffer[5] = chr(($high >> 8) & 0x000000FF);
131        $buffer[6] = chr(($high >> 16) & 0x000000FF);
132        $buffer[7] = chr(($high >> 24) & 0x000000FF);
133        return 8;
134    }
135
136}
137