1 package com.fasterxml.jackson.core.format; 2 3 import java.io.*; 4 5 import com.fasterxml.jackson.core.JsonFactory; 6 7 /** 8 * Interface used to expose beginning of a data file to data format 9 * detection code. 10 */ 11 public interface InputAccessor 12 { 13 /** 14 * Method to call to check if more input is available. 15 * Since this may result in more content to be read (at least 16 * one more byte), a {@link IOException} may get thrown. 17 */ hasMoreBytes()18 boolean hasMoreBytes() throws IOException; 19 20 /** 21 * Returns next byte available, if any; if no more bytes are 22 * available, will throw {@link java.io.EOFException}. 23 */ nextByte()24 byte nextByte() throws IOException; 25 26 /** 27 * Method that can be called to reset accessor to read from beginning 28 * of input. 29 */ reset()30 void reset(); 31 32 /* 33 /********************************************************** 34 /* Standard implementation 35 /********************************************************** 36 */ 37 38 /** 39 * Basic implementation that reads data from given 40 * {@link InputStream} and buffers it as necessary. 41 */ 42 class Std implements InputAccessor 43 { 44 protected final InputStream _in; 45 46 protected final byte[] _buffer; 47 48 protected final int _bufferedStart; 49 50 /** 51 * End of valid bytes in the buffer (points to one past last valid) 52 */ 53 protected int _bufferedEnd; 54 55 /** 56 * Pointer to next available buffered byte in {@link #_buffer}. 57 */ 58 protected int _ptr; 59 60 /** 61 * Constructor used when content to check is available via 62 * input stream and must be read. 63 */ Std(InputStream in, byte[] buffer)64 public Std(InputStream in, byte[] buffer) 65 { 66 _in = in; 67 _buffer = buffer; 68 _bufferedStart = 0; 69 _ptr = 0; 70 _bufferedEnd = 0; 71 } 72 73 /** 74 * Constructor used when the full input (or at least enough leading bytes 75 * of full input) is available. 76 */ Std(byte[] inputDocument)77 public Std(byte[] inputDocument) { 78 this(inputDocument, 0, inputDocument.length); 79 } 80 81 /** 82 * Constructor used when the full input (or at least enough leading bytes 83 * of full input) is available. 84 * 85 * @since 2.1 86 */ Std(byte[] inputDocument, int start, int len)87 public Std(byte[] inputDocument, int start, int len) 88 { 89 _in = null; 90 _buffer = inputDocument; 91 _ptr = start; 92 _bufferedStart = start; 93 _bufferedEnd = start+len; 94 } 95 96 @Override hasMoreBytes()97 public boolean hasMoreBytes() throws IOException 98 { 99 if (_ptr < _bufferedEnd) { // already got more 100 return true; 101 } 102 if (_in == null) { // nowhere to read from 103 return false; 104 } 105 int amount = _buffer.length - _ptr; 106 if (amount < 1) { // can not load any more 107 return false; 108 } 109 int count = _in.read(_buffer, _ptr, amount); 110 if (count <= 0) { // EOF 111 return false; 112 } 113 _bufferedEnd += count; 114 return true; 115 } 116 117 @Override nextByte()118 public byte nextByte() throws IOException 119 { 120 // should we just try loading more automatically? 121 if (_ptr >= _bufferedEnd) { 122 if (!hasMoreBytes()) { 123 throw new EOFException("Failed auto-detect: could not read more than "+_ptr+" bytes (max buffer size: "+_buffer.length+")"); 124 } 125 } 126 return _buffer[_ptr++]; 127 } 128 129 @Override reset()130 public void reset() { 131 _ptr = _bufferedStart; 132 } 133 134 /* 135 /********************************************************** 136 /* Extended API for DataFormatDetector/Matcher 137 /********************************************************** 138 */ 139 createMatcher(JsonFactory match, MatchStrength matchStrength)140 public DataFormatMatcher createMatcher(JsonFactory match, MatchStrength matchStrength) 141 { 142 return new DataFormatMatcher(_in, _buffer, _bufferedStart, (_bufferedEnd - _bufferedStart), 143 match, matchStrength); 144 } 145 } 146 } 147