1<?php 2 3// Protocol Buffers - Google's data interchange format 4// Copyright 2008 Google Inc. All rights reserved. 5// https://developers.google.com/protocol-buffers/ 6// 7// Redistribution and use in source and binary forms, with or without 8// modification, are permitted provided that the following conditions are 9// met: 10// 11// * Redistributions of source code must retain the above copyright 12// notice, this list of conditions and the following disclaimer. 13// * Redistributions in binary form must reproduce the above 14// copyright notice, this list of conditions and the following disclaimer 15// in the documentation and/or other materials provided with the 16// distribution. 17// * Neither the name of Google Inc. nor the names of its 18// contributors may be used to endorse or promote products derived from 19// this software without specific prior written permission. 20// 21// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 33namespace Google\Protobuf\Internal; 34 35class CodedOutputStream 36{ 37 38 private $buffer; 39 private $buffer_size; 40 private $current; 41 42 const MAX_VARINT64_BYTES = 10; 43 44 public function __construct($size) 45 { 46 $this->current = 0; 47 $this->buffer_size = $size; 48 $this->buffer = str_repeat(chr(0), $this->buffer_size); 49 } 50 51 public function getData() 52 { 53 return $this->buffer; 54 } 55 56 public function writeVarint32($value, $trim) 57 { 58 $bytes = str_repeat(chr(0), self::MAX_VARINT64_BYTES); 59 $size = self::writeVarintToArray($value, $bytes, $trim); 60 return $this->writeRaw($bytes, $size); 61 } 62 63 public function writeVarint64($value) 64 { 65 $bytes = str_repeat(chr(0), self::MAX_VARINT64_BYTES); 66 $size = self::writeVarintToArray($value, $bytes); 67 return $this->writeRaw($bytes, $size); 68 } 69 70 public function writeLittleEndian32($value) 71 { 72 $bytes = str_repeat(chr(0), 4); 73 $size = self::writeLittleEndian32ToArray($value, $bytes); 74 return $this->writeRaw($bytes, $size); 75 } 76 77 public function writeLittleEndian64($value) 78 { 79 $bytes = str_repeat(chr(0), 8); 80 $size = self::writeLittleEndian64ToArray($value, $bytes); 81 return $this->writeRaw($bytes, $size); 82 } 83 84 public function writeTag($tag) 85 { 86 return $this->writeVarint32($tag, true); 87 } 88 89 public function writeRaw($data, $size) 90 { 91 if ($this->buffer_size < $size) { 92 trigger_error("Output stream doesn't have enough buffer."); 93 return false; 94 } 95 96 for ($i = 0; $i < $size; $i++) { 97 $this->buffer[$this->current] = $data[$i]; 98 $this->current++; 99 $this->buffer_size--; 100 } 101 return true; 102 } 103 104 public static function writeVarintToArray($value, &$buffer, $trim = false) 105 { 106 $current = 0; 107 108 $high = 0; 109 $low = 0; 110 if (PHP_INT_SIZE == 4) { 111 GPBUtil::divideInt64ToInt32($value, $high, $low, $trim); 112 } else { 113 $low = $value; 114 } 115 116 while (($low >= 0x80 || $low < 0) || $high != 0) { 117 $buffer[$current] = chr($low | 0x80); 118 $value = ($value >> 7) & ~(0x7F << ((PHP_INT_SIZE << 3) - 7)); 119 $carry = ($high & 0x7F) << ((PHP_INT_SIZE << 3) - 7); 120 $high = ($high >> 7) & ~(0x7F << ((PHP_INT_SIZE << 3) - 7)); 121 $low = (($low >> 7) & ~(0x7F << ((PHP_INT_SIZE << 3) - 7)) | $carry); 122 $current++; 123 } 124 $buffer[$current] = chr($low); 125 return $current + 1; 126 } 127 128 private static function writeLittleEndian32ToArray($value, &$buffer) 129 { 130 $buffer[0] = chr($value & 0x000000FF); 131 $buffer[1] = chr(($value >> 8) & 0x000000FF); 132 $buffer[2] = chr(($value >> 16) & 0x000000FF); 133 $buffer[3] = chr(($value >> 24) & 0x000000FF); 134 return 4; 135 } 136 137 private static function writeLittleEndian64ToArray($value, &$buffer) 138 { 139 $high = 0; 140 $low = 0; 141 if (PHP_INT_SIZE == 4) { 142 GPBUtil::divideInt64ToInt32($value, $high, $low); 143 } else { 144 $low = $value & 0xFFFFFFFF; 145 $high = ($value >> 32) & 0xFFFFFFFF; 146 } 147 148 $buffer[0] = chr($low & 0x000000FF); 149 $buffer[1] = chr(($low >> 8) & 0x000000FF); 150 $buffer[2] = chr(($low >> 16) & 0x000000FF); 151 $buffer[3] = chr(($low >> 24) & 0x000000FF); 152 $buffer[4] = chr($high & 0x000000FF); 153 $buffer[5] = chr(($high >> 8) & 0x000000FF); 154 $buffer[6] = chr(($high >> 16) & 0x000000FF); 155 $buffer[7] = chr(($high >> 24) & 0x000000FF); 156 return 8; 157 } 158 159} 160