| package com.fasterxml.jackson.core.format; |
| |
| import java.io.*; |
| |
| import com.fasterxml.jackson.core.JsonFactory; |
| |
| /** |
| * Interface used to expose beginning of a data file to data format |
| * detection code. |
| */ |
| public interface InputAccessor |
| { |
| /** |
| * Method to call to check if more input is available. |
| * Since this may result in more content to be read (at least |
| * one more byte), a {@link IOException} may get thrown. |
| */ |
| boolean hasMoreBytes() throws IOException; |
| |
| /** |
| * Returns next byte available, if any; if no more bytes are |
| * available, will throw {@link java.io.EOFException}. |
| */ |
| byte nextByte() throws IOException; |
| |
| /** |
| * Method that can be called to reset accessor to read from beginning |
| * of input. |
| */ |
| void reset(); |
| |
| /* |
| /********************************************************** |
| /* Standard implementation |
| /********************************************************** |
| */ |
| |
| /** |
| * Basic implementation that reads data from given |
| * {@link InputStream} and buffers it as necessary. |
| */ |
| class Std implements InputAccessor |
| { |
| protected final InputStream _in; |
| |
| protected final byte[] _buffer; |
| |
| protected final int _bufferedStart; |
| |
| /** |
| * End of valid bytes in the buffer (points to one past last valid) |
| */ |
| protected int _bufferedEnd; |
| |
| /** |
| * Pointer to next available buffered byte in {@link #_buffer}. |
| */ |
| protected int _ptr; |
| |
| /** |
| * Constructor used when content to check is available via |
| * input stream and must be read. |
| */ |
| public Std(InputStream in, byte[] buffer) |
| { |
| _in = in; |
| _buffer = buffer; |
| _bufferedStart = 0; |
| _ptr = 0; |
| _bufferedEnd = 0; |
| } |
| |
| /** |
| * Constructor used when the full input (or at least enough leading bytes |
| * of full input) is available. |
| */ |
| public Std(byte[] inputDocument) |
| { |
| _in = null; |
| _buffer = inputDocument; |
| // we have it all: |
| _bufferedStart = 0; |
| _bufferedEnd = inputDocument.length; |
| } |
| |
| /** |
| * Constructor used when the full input (or at least enough leading bytes |
| * of full input) is available. |
| * |
| * @since 2.1 |
| */ |
| public Std(byte[] inputDocument, int start, int len) |
| { |
| _in = null; |
| _buffer = inputDocument; |
| _ptr = start; |
| _bufferedStart = start; |
| _bufferedEnd = start+len; |
| } |
| |
| @Override |
| public boolean hasMoreBytes() throws IOException |
| { |
| if (_ptr < _bufferedEnd) { // already got more |
| return true; |
| } |
| if (_in == null) { // nowhere to read from |
| return false; |
| } |
| int amount = _buffer.length - _ptr; |
| if (amount < 1) { // can not load any more |
| return false; |
| } |
| int count = _in.read(_buffer, _ptr, amount); |
| if (count <= 0) { // EOF |
| return false; |
| } |
| _bufferedEnd += count; |
| return true; |
| } |
| |
| @Override |
| public byte nextByte() throws IOException |
| { |
| // should we just try loading more automatically? |
| if (_ptr >= _bufferedEnd) { |
| if (!hasMoreBytes()) { |
| throw new EOFException("Failed auto-detect: could not read more than "+_ptr+" bytes (max buffer size: "+_buffer.length+")"); |
| } |
| } |
| return _buffer[_ptr++]; |
| } |
| |
| @Override |
| public void reset() { |
| _ptr = _bufferedStart; |
| } |
| |
| /* |
| /********************************************************** |
| /* Extended API for DataFormatDetector/Matcher |
| /********************************************************** |
| */ |
| |
| public DataFormatMatcher createMatcher(JsonFactory match, MatchStrength matchStrength) |
| { |
| return new DataFormatMatcher(_in, _buffer, _bufferedStart, (_bufferedEnd - _bufferedStart), |
| match, matchStrength); |
| } |
| } |
| } |