1<?php 2 3/** 4 * Copyright (c) 2006- Facebook 5 * Distributed under the Thrift Software License 6 * 7 * See accompanying file LICENSE or visit the Thrift site at: 8 * http://developers.facebook.com/thrift/ 9 * 10 * @package thrift.transport 11 * @author Mark Slee <mcslee@facebook.com> 12 */ 13 14/** 15 * Buffered transport. Stores data to an internal buffer that it doesn't 16 * actually write out until flush is called. For reading, we do a greedy 17 * read and then serve data out of the internal buffer. 18 * 19 * @package thrift.transport 20 * @author Mark Slee <mcslee@facebook.com> 21 */ 22class TBufferedTransport extends TTransport { 23 24 /** 25 * Constructor. Creates a buffered transport around an underlying transport 26 */ 27 public function __construct($transport=null, $rBufSize=512, $wBufSize=512) { 28 $this->transport_ = $transport; 29 $this->rBufSize_ = $rBufSize; 30 $this->wBufSize_ = $wBufSize; 31 } 32 33 /** 34 * The underlying transport 35 * 36 * @var TTransport 37 */ 38 protected $transport_ = null; 39 40 /** 41 * The receive buffer size 42 * 43 * @var int 44 */ 45 protected $rBufSize_ = 512; 46 47 /** 48 * The write buffer size 49 * 50 * @var int 51 */ 52 protected $wBufSize_ = 512; 53 54 /** 55 * The write buffer. 56 * 57 * @var string 58 */ 59 protected $wBuf_ = ''; 60 61 /** 62 * The read buffer. 63 * 64 * @var string 65 */ 66 protected $rBuf_ = ''; 67 68 public function isOpen() { 69 return $this->transport_->isOpen(); 70 } 71 72 public function open() { 73 $this->transport_->open(); 74 } 75 76 public function close() { 77 $this->transport_->close(); 78 } 79 80 public function putBack($data) { 81 if (strlen($this->rBuf_) === 0) { 82 $this->rBuf_ = $data; 83 } else { 84 $this->rBuf_ = ($data . $this->rBuf_); 85 } 86 } 87 88 /** 89 * The reason that we customize readAll here is that the majority of PHP 90 * streams are already internally buffered by PHP. The socket stream, for 91 * example, buffers internally and blocks if you call read with $len greater 92 * than the amount of data available, unlike recv() in C. 93 * 94 * Therefore, use the readAll method of the wrapped transport inside 95 * the buffered readAll. 96 */ 97 public function readAll($len) { 98 $have = strlen($this->rBuf_); 99 if ($have == 0) { 100 $data = $this->transport_->readAll($len); 101 } else if ($have < $len) { 102 $data = $this->rBuf_; 103 $this->rBuf_ = ''; 104 $data .= $this->transport_->readAll($len - $have); 105 } else if ($have == $len) { 106 $data = $this->rBuf_; 107 $this->rBuf_ = ''; 108 } else if ($have > $len) { 109 $data = substr($this->rBuf_, 0, $len); 110 $this->rBuf_ = substr($this->rBuf_, $len); 111 } 112 return $data; 113 } 114 115 public function read($len) { 116 if (strlen($this->rBuf_) === 0) { 117 $this->rBuf_ = $this->transport_->read($this->rBufSize_); 118 } 119 120 if (strlen($this->rBuf_) <= $len) { 121 $ret = $this->rBuf_; 122 $this->rBuf_ = ''; 123 return $ret; 124 } 125 126 $ret = substr($this->rBuf_, 0, $len); 127 $this->rBuf_ = substr($this->rBuf_, $len); 128 return $ret; 129 } 130 131 public function write($buf) { 132 $this->wBuf_ .= $buf; 133 if (strlen($this->wBuf_) >= $this->wBufSize_) { 134 $out = $this->wBuf_; 135 136 // Note that we clear the internal wBuf_ prior to the underlying write 137 // to ensure we're in a sane state (i.e. internal buffer cleaned) 138 // if the underlying write throws up an exception 139 $this->wBuf_ = ''; 140 $this->transport_->write($out); 141 } 142 } 143 144 public function flush() { 145 if (strlen($this->wBuf_) > 0) { 146 $this->transport_->write($this->wBuf_); 147 $this->wBuf_ = ''; 148 } 149 $this->transport_->flush(); 150 } 151 152} 153 154?> 155