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