001 /*
002 * Copyright (c) Andrey Kuznetsov. All Rights Reserved.
003 *
004 * http://uio.imagero.com
005 *
006 * Redistribution and use in source and binary forms, with or without
007 * modification, are permitted provided that the following conditions are met:
008 *
009 * o Redistributions of source code must retain the above copyright notice,
010 * this list of conditions and the following disclaimer.
011 *
012 * o Redistributions in binary form must reproduce the above copyright notice,
013 * this list of conditions and the following disclaimer in the documentation
014 * and/or other materials provided with the distribution.
015 *
016 * o Neither the name of Andrey Kuznetsov nor the names of
017 * its contributors may be used to endorse or promote products derived
018 * from this software without specific prior written permission.
019 *
020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
021 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
022 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
023 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
024 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
027 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
028 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
029 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
030 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031 */
032 package com.imagero.uio.bio;
033
034 import java.io.IOException;
035 import java.io.InputStream;
036
037 /**
038 * Independent InputStream with shared IOController.
039 *
040 * @author Andrey Kuznetsov
041 */
042 public class IOCInputStream extends InputStream {
043
044 FixedSizeByteBuffer buffer;
045 BufferIndex bufferIndex;
046 BufferPosition bufferPosition;
047 IOController controller;
048
049 StreamPosition streamPosition = new StreamPosition();
050 long offset;
051
052 long mark;
053
054 public IOCInputStream(IOController controller) {
055 this.controller = controller;
056 }
057
058 public IOCInputStream(IOController controller, long offset) {
059 this.controller = controller;
060 this.offset = offset;
061 bufferPosition = new BufferPosition(controller.bufferSize);
062 seek(0);
063 }
064
065 protected void seek(long offset) {
066 streamPosition.pos = offset + this.offset;
067 bufferPosition.pos = (int) ((streamPosition.pos) % controller.bufferSize);
068 }
069
070 private void prepareBufferForReading() {
071 BufferIndex index = controller.getBufferIndex(streamPosition.pos);
072
073 if (!index.equals(bufferIndex) || buffer == null || buffer.buf == null) {
074 bufferIndex = index;
075 try {
076 buffer = controller.getBuffer(streamPosition.pos, true);
077 } catch (IOException ex) {
078 //ignore
079 }
080 }
081 if (buffer != null) {
082 bufferPosition.pos = (int) ((streamPosition.pos) % controller.bufferSize);
083 }
084 }
085
086 public int read() throws IOException {
087 checkBuffer();
088
089 if (buffer != null) {
090 streamPosition.pos++;
091 return buffer.read(bufferPosition);
092 }
093 return -1;
094 }
095
096 public int available() throws IOException {
097 if(buffer != null) {
098 return buffer.availableForReading(bufferPosition);
099 }
100 return 0;
101 }
102
103 private void checkBuffer() {
104 if (bufferPosition.available() <= 0) {
105 prepareBufferForReading();
106 }
107 }
108
109 public long skip(long n) throws IOException {
110 checkBuffer();
111 if (buffer == null) {
112 return 0;
113 }
114 long skp = buffer.skip(n, bufferPosition);
115 streamPosition.pos += skp;
116 return skp;
117 }
118
119 public int read(byte b[]) throws IOException {
120 return read(b, 0, b.length);
121 }
122
123 public int read(byte[] b, int offset, int length) throws IOException {
124 checkBuffer();
125 if (buffer == null) {
126 return -1;
127 }
128 int rc = buffer.read(b, offset, length, bufferPosition);
129 if (rc > 0) {
130 streamPosition.pos += rc;
131 }
132 return rc;
133 }
134
135 public boolean markSupported() {
136 return true;
137 }
138
139 public synchronized void mark(int readlimit) {
140 this.mark = streamPosition.pos;
141 }
142
143 public synchronized void reset() throws IOException {
144 seek(mark);
145 }
146
147 public void close() throws IOException {
148 if (controller != null) {
149 controller = null;
150 }
151 }
152 }