Codebase list jackson-core / 64aa9d2
Implemented #138 Tatu 10 years ago
7 changed file(s) with 126 addition(s) and 36 deletion(s). Raw diff Collapse all Expand all
33 #121: Increase size of low-level byte[]/char[] input/output buffers
44 (from 4k->8k for bytes, 2k->4k for chars)
55 #127: Add `JsonGenerator.writeStartArray(int size)` for binary formats
6 #138: Add support for using `char[]` as input source; optimize handling
7 of `String` input as well.
68 - Refactor `BufferRecycler` to eliminate helper enums
79
810 ------------------------------------------------------------------------
4242 java.io.Serializable // since 2.1 (for Android, mostly)
4343 {
4444 /**
45 * Computed for Jackson 2.3.0 release
46 */
47 private static final long serialVersionUID = 3194418244231611666L;
45 * Computed for Jackson 2.4.0 release
46 */
47 private static final long serialVersionUID = 3306684576057132431L;
4848
4949 /*
5050 /**********************************************************
809809 * @since 2.1
810810 */
811811 public JsonParser createParser(String content) throws IOException, JsonParseException {
812 Reader r = new StringReader(content);
813 // true -> we own the Reader (and must close); not a big deal
814 IOContext ctxt = _createContext(r, true);
815 // [JACKSON-512]: allow wrapping with InputDecorator
816 if (_inputDecorator != null) {
817 r = _inputDecorator.decorate(ctxt, r);
818 }
819 return _createParser(r, ctxt);
812 final int strLen = content.length();
813 // Actually, let's use this for medium-sized content, up to 64kB chunk (32kb char)
814 if (_inputDecorator != null || strLen > 0x8000) {
815 // easier to just wrap in a Reader than extend InputDecorator; or, if content
816 // is too long for us to copy it over
817 return createParser(new StringReader(content));
818 }
819 IOContext ctxt = _createContext(content, true);
820 char[] buf = ctxt.allocTokenBuffer();
821 if (buf.length < strLen) { // sanity check; should never occur
822 buf = new char[strLen];
823 }
824 content.getChars(0, strLen, buf, 0);
825 return _createParser(buf, 0, strLen, ctxt, true);
826 }
827
828 /**
829 * Method for constructing parser for parsing
830 * contents of given char array.
831 *
832 * @since 2.4
833 */
834 public JsonParser createParser(char[] content) throws IOException {
835 return createParser(content, 0, content.length);
836 }
837
838 /**
839 * Method for constructing parser for parsing
840 * contents of given char array.
841 *
842 * @since 2.4
843 */
844 public JsonParser createParser(char[] content, int offset, int len) throws IOException {
845 if (_inputDecorator != null) { // easier to just wrap in a Reader than extend InputDecorator
846 return createParser(new CharArrayReader(content, offset, len));
847 }
848 return _createParser(content, offset, len, _createContext(content, true), false);
820849 }
821850
822851 /*
11981227
11991228 /**
12001229 * Overridable factory method that actually instantiates parser
1230 * using given <code>char[]</code> object for accessing content.
1231 *
1232 * @since 2.4
1233 */
1234 protected JsonParser _createParser(char[] data, int offset, int len, IOContext ctxt,
1235 boolean recyclable) throws IOException {
1236 return new ReaderBasedJsonParser(ctxt, _parserFeatures, null, _objectCodec,
1237 _rootCharSymbols.makeChild(isEnabled(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES),
1238 isEnabled(JsonFactory.Feature.INTERN_FIELD_NAMES)),
1239 data, offset, offset+len,
1240 // false -> caller-provided, not handled by BufferRecycler
1241 recyclable);
1242 }
1243
1244 /**
1245 * Overridable factory method that actually instantiates parser
12011246 * using given {@link Reader} object for reading content
12021247 * passed as raw byte array.
12031248 *<p>
12071252 * interface from sub-class perspective, although not a public
12081253 * method available to users of factory implementations.
12091254 */
1210 protected JsonParser _createParser(byte[] data, int offset, int len, IOContext ctxt) throws IOException, JsonParseException
1255 protected JsonParser _createParser(byte[] data, int offset, int len, IOContext ctxt) throws IOException
12111256 {
12121257 return new ByteSourceJsonBootstrapper(ctxt, data, offset, len).constructParser(_parserFeatures,
12131258 _objectCodec, _rootByteSymbols, _rootCharSymbols,
219219 */
220220 if (canonicalize) {
221221 BytesToNameCanonicalizer can = rootByteSymbols.makeChild(canonicalize, intern);
222 return new UTF8StreamJsonParser(_context, parserFeatures, _in, codec, can, _inputBuffer, _inputPtr, _inputEnd, _bufferRecyclable);
222 return new UTF8StreamJsonParser(_context, parserFeatures, _in, codec, can,
223 _inputBuffer, _inputPtr, _inputEnd, _bufferRecyclable);
223224 }
224225 }
225226 return new ReaderBasedJsonParser(_context, parserFeatures, constructReader(), codec,
4444 */
4545 protected char[] _inputBuffer;
4646
47 /**
48 * Flag that indicates whether the input buffer is recycable (and
49 * needs to be returned to recycler once we are done) or not.
50 *<p>
51 * If it is not, it also means that parser can NOT modify underlying
52 * buffer.
53 */
54 protected boolean _bufferRecyclable;
55
4756 /*
4857 /**********************************************************
4958 /* Configuration
6877 * some access (or skipped to obtain the next token)
6978 */
7079 protected boolean _tokenIncomplete = false;
71
80
7281 /*
7382 /**********************************************************
7483 /* Life-cycle
7584 /**********************************************************
7685 */
7786
87 /**
88 * Method called when caller wants to provide input buffer directly,
89 * and it may or may not be recyclable use standard recycle context.
90 *
91 * @since 2.4
92 */
7893 public ReaderBasedJsonParser(IOContext ctxt, int features, Reader r,
79 ObjectCodec codec, CharsToNameCanonicalizer st)
94 ObjectCodec codec, CharsToNameCanonicalizer st,
95 char[] inputBuffer, int start, int end,
96 boolean bufferRecyclable)
97 {
98 super(ctxt, features);
99 _reader = r;
100 _inputBuffer = inputBuffer;
101 _inputPtr = start;
102 _inputEnd = end;
103 _objectCodec = codec;
104 _symbols = st;
105 _hashSeed = st.hashSeed();
106 _bufferRecyclable = bufferRecyclable;
107 }
108
109 /**
110 * Method called when input comes as a {@link java.io.Reader}, and buffer allocation
111 * can be done using default mechanism.
112 */
113 public ReaderBasedJsonParser(IOContext ctxt, int features, Reader r,
114 ObjectCodec codec, CharsToNameCanonicalizer st)
80115 {
81116 super(ctxt, features);
82117 _reader = r;
83118 _inputBuffer = ctxt.allocTokenBuffer();
119 _inputPtr = 0;
120 _inputEnd = 0;
84121 _objectCodec = codec;
85122 _symbols = st;
86123 _hashSeed = st.hashSeed();
87 }
88
124 _bufferRecyclable = false;
125 }
126
89127 /*
90128 /**********************************************************
91129 /* Base method defs, overrides
165203 super._releaseBuffers();
166204 // merge new symbols, if any
167205 _symbols.release();
168 char[] buf = _inputBuffer;
169 if (buf != null) {
170 _inputBuffer = null;
171 _ioContext.releaseTokenBuffer(buf);
206 // and release buffers, if they are recyclable ones
207 if (_bufferRecyclable) {
208 char[] buf = _inputBuffer;
209 if (buf != null) {
210 _inputBuffer = null;
211 _ioContext.releaseTokenBuffer(buf);
212 }
172213 }
173214 }
174215
1212 public void testCoreVersions() throws Exception
1313 {
1414 assertVersion(new JsonFactory().version());
15 JsonParser jp = new ReaderBasedJsonParser(getIOContext(), 0, null, null,
15 ReaderBasedJsonParser jp = new ReaderBasedJsonParser(getIOContext(), 0, null, null,
1616 CharsToNameCanonicalizer.createRoot());
1717 assertVersion(jp.version());
1818 jp.close();
296296 * correctly; mostly to stress-test underlying segment-based
297297 * text buffer(s).
298298 */
299 public void testLongText() throws Exception
300 {
301 JsonFactory jf = new JsonFactory();
302 // lengths chosen to tease out problems with buffer allocation...
303 _testLongText(jf, 7700);
304 _testLongText(jf, 49000);
305 _testLongText(jf, 96000);
306 }
307
299308 @SuppressWarnings("resource")
300 public void testLongText() throws Exception
301 {
302 final int LEN = 96000;
309 private void _testLongText(JsonFactory jf, int LEN) throws Exception
310 {
303311 StringBuilder sb = new StringBuilder(LEN + 100);
304312 Random r = new Random(99);
305313 while (sb.length() < LEN) {
324332 }
325333 }
326334 final String VALUE = sb.toString();
327
328 JsonFactory jf = new JsonFactory();
329335
330 // Let's use real generator to get json done right
336 // Let's use real generator to get JSON done right
331337 StringWriter sw = new StringWriter(LEN + (LEN >> 2));
332338 JsonGenerator jg = jf.createGenerator(sw);
333339 jg.writeStartObject();
3838 final String jsonStr = input.asJsonString(f);
3939 final byte[] json = jsonStr.getBytes("UTF-8");
4040
41 new ManualReadPerfWithMedia(f, jsonStr).test("Reader", "char[]", json.length);
41 new ManualReadPerfWithMedia(f, jsonStr).test("String", "char[]", json.length);
4242 }
4343
4444 protected void testRead1(int reps) throws Exception
4545 {
46 final String input = _json;
4746 while (--reps >= 0) {
48 JsonParser p = _factory.createParser(input);
47 JsonParser p = _factory.createParser(_json);
4948 _stream(p);
5049 p.close();
5150 }
5352
5453 protected void testRead2(int reps) throws Exception
5554 {
56 final String input = _json;
55 final char[] ch = _json.toCharArray();
5756 while (--reps >= 0) {
58 /*
59 final char[] ch = input.toCharArray();
6057 JsonParser p = _factory.createParser(ch, 0, ch.length);
61 */
62 JsonParser p = _factory.createParser(input);
6358 _stream(p);
6459 p.close();
6560 }