22
22
23
23
import org .jruby .Ruby ;
24
24
import org .jruby .RubyArray ;
25
- import org .jruby .RubyBoolean ;
26
25
import org .jruby .RubyClass ;
27
26
import org .jruby .RubyObject ;
28
27
import org .jruby .RubyString ;
@@ -41,12 +40,10 @@ public class BufferedTokenizerExt extends RubyObject {
41
40
freeze (RubyUtil .RUBY .getCurrentContext ());
42
41
43
42
private @ SuppressWarnings ("rawtypes" ) RubyArray input = RubyUtil .RUBY .newArray ();
44
- private StringBuilder headToken = new StringBuilder ();
45
43
private RubyString delimiter = NEW_LINE ;
46
44
private int sizeLimit ;
47
45
private boolean hasSizeLimit ;
48
46
private int inputSize ;
49
- private boolean bufferFullErrorNotified = false ;
50
47
51
48
public BufferedTokenizerExt (final Ruby runtime , final RubyClass metaClass ) {
52
49
super (runtime , metaClass );
@@ -69,6 +66,7 @@ public IRubyObject init(final ThreadContext context, IRubyObject[] args) {
69
66
* Extract takes an arbitrary string of input data and returns an array of
70
67
* tokenized entities, provided there were any available to extract. This
71
68
* makes for easy processing of datagrams using a pattern like:
69
+ *
72
70
* {@code tokenizer.extract(data).map { |entity| Decode(entity) }.each do}
73
71
*
74
72
* @param context ThreadContext
@@ -79,63 +77,22 @@ public IRubyObject init(final ThreadContext context, IRubyObject[] args) {
79
77
@ SuppressWarnings ("rawtypes" )
80
78
public RubyArray extract (final ThreadContext context , IRubyObject data ) {
81
79
final RubyArray entities = data .convertToString ().split (delimiter , -1 );
82
- if (!bufferFullErrorNotified ) {
83
- input .clear ();
84
- input .addAll (entities );
85
- } else {
86
- // after a full buffer signal
87
- if (input .isEmpty ()) {
88
- // after a buffer full error, the remaining part of the line, till next delimiter,
89
- // has to be consumed, unless the input buffer doesn't still contain fragments of
90
- // subsequent tokens.
91
- entities .shift (context );
92
- input .addAll (entities );
93
- } else {
94
- // merge last of the input with first of incoming data segment
95
- if (!entities .isEmpty ()) {
96
- RubyString last = ((RubyString ) input .pop (context ));
97
- RubyString nextFirst = ((RubyString ) entities .shift (context ));
98
- entities .unshift (last .concat (nextFirst ));
99
- input .addAll (entities );
100
- }
101
- }
102
- }
103
-
104
80
if (hasSizeLimit ) {
105
- if (bufferFullErrorNotified ) {
106
- bufferFullErrorNotified = false ;
107
- if (input .isEmpty ()) {
108
- return RubyUtil .RUBY .newArray ();
109
- }
110
- }
111
- final int entitiesSize = ((RubyString ) input .first ()).size ();
81
+ final int entitiesSize = ((RubyString ) entities .first ()).size ();
112
82
if (inputSize + entitiesSize > sizeLimit ) {
113
- bufferFullErrorNotified = true ;
114
- headToken = new StringBuilder ();
115
- inputSize = 0 ;
116
- input .shift (context ); // consume the token fragment that generates the buffer full
117
83
throw new IllegalStateException ("input buffer full" );
118
84
}
119
85
this .inputSize = inputSize + entitiesSize ;
120
86
}
121
-
122
- if (input .getLength () < 2 ) {
123
- // this is a specialization case which avoid adding and removing from input accumulator
124
- // when it contains just one element
125
- headToken .append (input .shift (context )); // remove head
87
+ input .append (entities .shift (context ));
88
+ if (entities .isEmpty ()) {
126
89
return RubyUtil .RUBY .newArray ();
127
90
}
128
-
129
- if (headToken .length () > 0 ) {
130
- // if there is a pending token part, merge it with the first token segment present
131
- // in the accumulator, and clean the pending token part.
132
- headToken .append (input .shift (context )); // append buffer to first element and
133
- input .unshift (RubyUtil .toRubyObject (headToken .toString ())); // reinsert it into the array
134
- headToken = new StringBuilder ();
135
- }
136
- headToken .append (input .pop (context )); // put the leftovers in headToken for later
137
- inputSize = headToken .length ();
138
- return input ;
91
+ entities .unshift (input .join (context ));
92
+ input .clear ();
93
+ input .append (entities .pop (context ));
94
+ inputSize = ((RubyString ) input .first ()).size ();
95
+ return entities ;
139
96
}
140
97
141
98
/**
@@ -147,14 +104,14 @@ public RubyArray extract(final ThreadContext context, IRubyObject data) {
147
104
*/
148
105
@ JRubyMethod
149
106
public IRubyObject flush (final ThreadContext context ) {
150
- final IRubyObject buffer = RubyUtil . toRubyObject ( headToken . toString () );
151
- headToken = new StringBuilder ();
107
+ final IRubyObject buffer = input . join ( context );
108
+ input . clear ();
152
109
return buffer ;
153
110
}
154
111
155
112
@ JRubyMethod (name = "empty?" )
156
113
public IRubyObject isEmpty (final ThreadContext context ) {
157
- return RubyBoolean . newBoolean ( context . runtime , headToken . toString (). isEmpty () );
114
+ return input . empty_p ( );
158
115
}
159
116
160
117
}
0 commit comments