99
1010class StreamReader
1111{
12- private $ stream ;
12+ const RET_DONE = true ;
13+ const RET_INCOMPLETE = null ;
1314
14- public function __construct (Stream $ stream )
15+ private $ buffer = '' ;
16+ private $ queue = array ();
17+
18+ public function write ($ data )
1519 {
16- $ this ->stream = $ stream ;
20+ $ this ->buffer .= $ data ;
21+
22+ do {
23+ $ current = reset ($ this ->queue );
24+
25+ if ($ current === false ) {
26+ break ;
27+ }
28+
29+ /* @var $current Closure */
30+
31+ $ ret = $ current ($ this ->buffer );
32+
33+ if ($ ret === self ::RET_INCOMPLETE ) {
34+ // current is incomplete, so wait for further data to arrive
35+ break ;
36+ } else {
37+ // current is done, remove from list and continue with next
38+ array_shift ($ this ->queue );
39+ }
40+ } while (true );
1741 }
1842
1943 public function readBinary ($ structure )
@@ -45,27 +69,16 @@ public function readBinary($structure)
4569 public function readLength ($ bytes )
4670 {
4771 $ deferred = new Deferred ();
48- $ oldsize = $ this ->stream ->bufferSize ;
49- $ this ->stream ->bufferSize = $ bytes ;
50-
51- $ buffer = '' ;
52-
53- $ fn = function ($ data , Stream $ stream ) use (&$ buffer , &$ bytes , $ deferred , $ oldsize , &$ fn ) {
54- $ bytes -= strlen ($ data );
55- $ buffer .= $ data ;
56-
57- $ deferred ->progress ($ data );
5872
59- if ($ bytes === 0 ) {
60- $ stream ->bufferSize = $ oldsize ;
61- $ stream ->removeListener ('data ' , $ fn );
73+ $ this ->readBufferCallback (function (&$ buffer ) use ($ bytes , $ deferred ) {
74+ if (strlen ($ buffer ) >= $ bytes ) {
75+ $ deferred ->resolve (substr ($ buffer , 0 , $ bytes ));
76+ $ buffer = (string )substr ($ buffer , $ bytes );
6277
63- $ deferred ->resolve ($ buffer );
64- } else {
65- $ stream ->bufferSize = $ bytes ;
78+ return StreamReader::RET_DONE ;
6679 }
67- };
68- $ this -> stream -> on ( ' data ' , $ fn );
80+ }) ;
81+
6982 return $ deferred ->promise ();
7083 }
7184
@@ -78,10 +91,6 @@ public function readByte()
7891 });
7992 }
8093
81- public function readNull (){
82- return $ this ->readByteAssert (0x00 );
83- }
84-
8594 public function readByteAssert ($ expect )
8695 {
8796 return $ this ->readByte ()->then (function ($ byte ) use ($ expect ) {
@@ -92,11 +101,6 @@ public function readByteAssert($expect)
92101 });
93102 }
94103
95- public function readChar ()
96- {
97- return $ this ->readLength (1 );
98- }
99-
100104 public function readStringNull ()
101105 {
102106 $ deferred = new Deferred ();
@@ -118,36 +122,26 @@ public function readStringNull()
118122 return $ deferred ->promise ();
119123 }
120124
121- public function readAssert ( $ byteSequence )
125+ public function readBufferCallback ( /* callable */ $ callable )
122126 {
123- $ deferred = new Deferred ();
124- $ pos = 0 ;
127+ if (!is_callable ($ callable )) {
128+ throw new InvalidArgumentException ('Given function must be callable ' );
129+ }
125130
126- $ that = $ this ;
127- $ this ->readLength (strlen ($ byteSequence ))->then (function ($ data ) use ($ deferred ) {
128- $ deferred ->resolve ($ data );
129- }, null , function ($ part ) use ($ byteSequence , &$ pos , $ deferred , $ that ) {
130- $ len = strlen ($ part );
131- $ expect = substr ($ byteSequence , $ pos , $ len );
132-
133- if ($ part === $ expect ) {
134- $ pos += $ len ;
135- } else {
136- $ deferred ->reject (new UnexpectedValueException ('Expected " ' .$ that ->escape ($ expect ).'", but got " ' .$ that ->escape ($ part ).'" ' ));
131+ if ($ this ->queue ) {
132+ $ this ->queue []= $ callable ;
133+ } else {
134+ $ this ->queue = array ($ callable );
135+
136+ if ($ this ->buffer !== '' ) {
137+ // this is the first element in the queue and the buffer is filled => trigger write procedure
138+ $ this ->write ('' );
137139 }
138- });
139- return $ deferred ->promise ();
140+ }
140141 }
141142
142- public function escape ( $ bytes )
143+ public function getBuffer ( )
143144 {
144- $ ret = '' ;
145- for ($ i = 0 , $ l = strlen ($ bytes ); $ i < $ l ; ++$ i ) {
146- if ($ i !== 0 ) {
147- $ ret .= ' ' ;
148- }
149- $ ret .= sprintf ('0x%02X ' , ord ($ bytes [$ i ]));
150- }
151- return $ ret ;
145+ return $ this ->buffer ;
152146 }
153147}
0 commit comments