• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.core.io;
2 
3 import java.io.*;
4 
5 /**
6  * Simple {@link InputStream} implementation that is used to "unwind" some
7  * data previously read from an input stream; so that as long as some of
8  * that data remains, it's returned; but as long as it's read, we'll
9  * just use data from the underlying original stream.
10  * This is similar to {@link java.io.PushbackInputStream}, but here there's
11  * only one implicit pushback, when instance is constructed.
12  */
13 public final class MergedStream extends InputStream
14 {
15     final private IOContext _ctxt;
16 
17     final private InputStream _in;
18 
19     private byte[] _b;
20 
21     private int _ptr;
22 
23     final private int _end;
24 
MergedStream(IOContext ctxt, InputStream in, byte[] buf, int start, int end)25     public MergedStream(IOContext ctxt, InputStream in, byte[] buf, int start, int end) {
26         _ctxt = ctxt;
27         _in = in;
28         _b = buf;
29         _ptr = start;
30         _end = end;
31     }
32 
33     @Override
available()34     public int available() throws IOException {
35         if (_b != null) {
36             return _end - _ptr;
37         }
38         return _in.available();
39     }
40 
close()41     @Override public void close() throws IOException {
42         _free();
43         _in.close();
44     }
45 
mark(int readlimit)46     @Override public void mark(int readlimit) {
47         if (_b == null) { _in.mark(readlimit); }
48     }
49 
markSupported()50     @Override public boolean markSupported() {
51         // Only supports marks past the initial rewindable section...
52         return (_b == null) && _in.markSupported();
53     }
54 
read()55     @Override public int read() throws IOException {
56         if (_b != null) {
57             int c = _b[_ptr++] & 0xFF;
58             if (_ptr >= _end) {
59                 _free();
60             }
61             return c;
62         }
63         return _in.read();
64     }
65 
read(byte[] b)66     @Override public int read(byte[] b) throws IOException {
67         return read(b, 0, b.length);
68     }
69 
70     @Override
read(byte[] b, int off, int len)71     public int read(byte[] b, int off, int len) throws IOException {
72         if (_b != null) {
73             int avail = _end - _ptr;
74             if (len > avail) {
75                 len = avail;
76             }
77             System.arraycopy(_b, _ptr, b, off, len);
78             _ptr += len;
79             if (_ptr >= _end) {
80                 _free();
81             }
82             return len;
83         }
84         return _in.read(b, off, len);
85     }
86 
87     @Override
reset()88     public void reset() throws IOException {
89         if (_b == null) { _in.reset(); }
90     }
91 
92     @Override
skip(long n)93     public long skip(long n) throws IOException {
94         long count = 0L;
95 
96         if (_b != null) {
97             int amount = _end - _ptr;
98 
99             if (amount > n) { // all in pushed back segment?
100                 _ptr += (int) n;
101                 return n;
102             }
103             _free();
104             count += amount;
105             n -= amount;
106         }
107 
108         if (n > 0) { count += _in.skip(n); }
109         return count;
110     }
111 
_free()112     private void _free() {
113         byte[] buf = _b;
114         if (buf != null) {
115             _b = null;
116             if (_ctxt != null) {
117                 _ctxt.releaseReadIOBuffer(buf);
118             }
119         }
120     }
121 }
122