blob: 6c67e263c88f924c6702a327582729365d06afa9 [file] [log] [blame]
Tatu Saloranta81fb43c2017-05-17 18:25:34 -07001package com.fasterxml.jackson.core.json.async;
2
3import java.io.IOException;
4import java.io.OutputStream;
5
6import com.fasterxml.jackson.core.JsonToken;
7import com.fasterxml.jackson.core.async.ByteArrayFeeder;
8import com.fasterxml.jackson.core.async.NonBlockingInputFeeder;
9import com.fasterxml.jackson.core.io.IOContext;
10import com.fasterxml.jackson.core.sym.ByteQuadsCanonicalizer;
11import com.fasterxml.jackson.core.util.VersionUtil;
12
13public class NonBlockingJsonParser
14 extends NonBlockingJsonParserBase
15 implements ByteArrayFeeder
16{
17 /*
18 /**********************************************************************
19 /* Input source config
20 /**********************************************************************
21 */
22
23 /**
24 * This buffer is actually provided via {@link NonBlockingInputFeeder}
25 */
26 protected byte[] _inputBuffer = NO_BYTES;
27
28 /**
29 * In addition to current buffer pointer, and end pointer,
30 * we will also need to know number of bytes originally
31 * contained. This is needed to correctly update location
32 * information when the block has been completed.
33 */
34 protected int _origBufferLen;
35
36 // And from ParserBase:
37// protected int _inputPtr;
38// protected int _inputEnd;
39
40 /*
41 /**********************************************************************
42 /* Life-cycle
43 /**********************************************************************
44 */
45
46 public NonBlockingJsonParser(IOContext ctxt, int parserFeatures,
47 ByteQuadsCanonicalizer sym)
48 {
49 super(ctxt, parserFeatures, sym);
50 }
51
52 /*
53 /**********************************************************************
54 /* AsyncInputFeeder impl
55 /**********************************************************************
56 */
57
58 @Override
59 public ByteArrayFeeder getNonBlockingInputFeeder() {
60 return this;
61 }
62
63 @Override
64 public final boolean needMoreInput() {
65 return (_inputPtr >=_inputEnd) && !_endOfInput;
66 }
67
68 @Override
69 public void feedInput(byte[] buf, int start, int end) throws IOException
70 {
71 // Must not have remaining input
72 if (_inputPtr < _inputEnd) {
73 _reportError("Still have %d undecoded bytes, should not call 'feedInput'", _inputEnd - _inputPtr);
74 }
75 if (end < start) {
76 _reportError("Input end (%d) may not be before start (%d)", end, start);
77 }
78 // and shouldn't have been marked as end-of-input
79 if (_endOfInput) {
80 _reportError("Already closed, can not feed more input");
81 }
82 // Time to update pointers first
83 _currInputProcessed += _origBufferLen;
84
85 // And then update buffer settings
86 _inputBuffer = buf;
87 _inputPtr = start;
88 _inputEnd = end;
89 _origBufferLen = end - start;
90 }
91
92 @Override
93 public void endOfInput() {
94 _endOfInput = true;
95 }
96
97 /*
98 /**********************************************************************
99 /* Abstract methods/overrides from JsonParser
100 /**********************************************************************
101 */
102
103 /* Implementing these methods efficiently for non-blocking cases would
104 * be complicated; so for now let's just use the default non-optimized
105 * implementation
106 */
107
108// public boolean nextFieldName(SerializableString str) throws IOException
109// public String nextTextValue() throws IOException
110// public int nextIntValue(int defaultValue) throws IOException
111// public long nextLongValue(long defaultValue) throws IOException
112// public Boolean nextBooleanValue() throws IOException
113
114 @Override
115 public int releaseBuffered(OutputStream out) throws IOException {
116 int avail = _inputEnd - _inputPtr;
117 if (avail > 0) {
118 out.write(_inputBuffer, _inputPtr, avail);
119 }
120 return avail;
121 }
122
123 /*
124 /**********************************************************************
125 /* Main-level decoding
126 /**********************************************************************
127 */
128
129 @Override
130 public JsonToken nextToken() throws IOException
131 {
132 // First: regardless of where we really are, need at least one more byte;
133 // can simplify some of the checks by short-circuiting right away
134 if (_inputPtr >= _inputEnd) {
135 if (_closed) {
136 return null;
137 }
138 // note: if so, do not even bother changing state
139 if (_endOfInput) { // except for this special case
140 return _eofAsNextToken();
141 }
142 return JsonToken.NOT_AVAILABLE;
143 }
144 // in the middle of tokenization?
145 if (_currToken == JsonToken.NOT_AVAILABLE) {
146 return _finishToken();
147 }
148
149 // No: fresh new token; may or may not have existing one
150 _numTypesValid = NR_UNKNOWN;
151// _tokenInputTotal = _currInputProcessed + _inputPtr;
152 // also: clear any data retained so far
153 _binaryValue = null;
154 int ch = _inputBuffer[_inputPtr++];
155
156 switch (_majorState) {
157 case MAJOR_INITIAL:
158 // TODO: Bootstrapping? BOM?
159
160 case MAJOR_ROOT:
161 return _startValue(ch);
162
163 case MAJOR_OBJECT_FIELD: // field or end-object
164 // expect name
165 return _startFieldName(ch);
166
167 case MAJOR_OBJECT_VALUE:
168 case MAJOR_ARRAY_ELEMENT: // element or end-array
169 return _startValue(ch);
170
171 default:
172 }
173 VersionUtil.throwInternal();
174 return null;
175 }
176
177 /**
178 * Method called when a (scalar) value type has been detected, but not all of
179 * contents have been decoded due to incomplete input available.
180 */
181 protected final JsonToken _finishToken() throws IOException
182 {
183 // NOTE: caller ensures availability of at least one byte
184
185 switch (_minorState) {
186 }
187 return null;
188 }
189
190 /*
191 /**********************************************************************
192 /* Second-level decoding, root level
193 /**********************************************************************
194 */
195
196 /**
197 * Helper method called to detect type of a value token (at any level), and possibly
198 * decode it if contained in input buffer.
199 * Note that possible header has been ruled out by caller and is not checked here.
200 */
201 private final JsonToken _startValue(int ch) throws IOException
202 {
203 return null;
204 }
205
206 /*
207 /**********************************************************************
208 /* Second-level decoding, Name decoding
209 /**********************************************************************
210 */
211
212 /**
213 * Method that handles initial token type recognition for token
214 * that has to be either FIELD_NAME or END_OBJECT.
215 */
216 protected final JsonToken _startFieldName(int ch) throws IOException
217 {
218 return null;
219 }
220}