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: */
22: class 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: