KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mckoi > util > PagedInputStream


1 /**
2  * com.mckoi.util.PagedInputStream 18 Feb 2003
3  *
4  * Mckoi SQL Database ( http://www.mckoi.com/database )
5  * Copyright (C) 2000, 2001, 2002 Diehl and Associates, Inc.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * Version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License Version 2 for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * Version 2 along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  *
20  * Change Log:
21  *
22  *
23  */

24
25 package com.mckoi.util;
26
27 import java.io.InputStream JavaDoc;
28 import java.io.IOException JavaDoc;
29
30 /**
31  * An implementation of InputStream that reads data from an underlying
32  * representation in fixed sized pages. This object maintains a single buffer
33  * that is the size of a page. This implementation supports 'skip' and
34  * buffered access to the data.
35  * <p>
36  * The only method that needs to be implemented is the 'readPageContent'
37  * method.
38  *
39  * @author Tobias Downer
40  */

41
42 public abstract class PagedInputStream extends InputStream JavaDoc {
43
44   /**
45    * The size of the buffer page.
46    */

47   private final int BUFFER_SIZE;
48   
49   /**
50    * The current position in the stream.
51    */

52   private long position;
53
54   /**
55    * The total size of the underlying dataset.
56    */

57   private long size;
58   
59   /**
60    * The start buffer position.
61    */

62   private long buffer_pos;
63   
64   /**
65    * The buffer.
66    */

67   private final byte[] buf;
68
69   /**
70    * Last marked position.
71    */

72   private long mark_position;
73   
74   /**
75    * Constructs the input stream.
76    *
77    * @param page_size the size of the pages when accessing the underlying
78    * stream.
79    * @param total_size the total size of the underlying data set.
80    */

81   public PagedInputStream(int page_size, long total_size) {
82     this.BUFFER_SIZE = page_size;
83     this.position = 0;
84     this.size = total_size;
85     this.mark_position = 0;
86     this.buf = new byte[BUFFER_SIZE];
87     buffer_pos = -1;
88   }
89
90   /**
91    * Reads the page at the given offset in the underlying data into the given
92    * byte[] array. The 'pos' variable given is guarenteed to be a multiple of
93    * buffer_size. For example, the first access will be to pos = 0, the
94    * second access to pos = BUFFER_SIZE, the third access to pos =
95    * BUFFER_SIZE * 2, etc. 'length' will always be either BUFFER_SIZE or a
96    * value smaller than BUFFER_SIZE if the page containing the end of the
97    * stream is read.
98    */

99   protected abstract void readPageContent(byte[] buf, long pos, int length)
100                                                             throws IOException JavaDoc;
101   
102   /**
103    * Fills the buffer with data from the blob at the given position. A buffer
104    * may be partially filled if the end is reached.
105    */

106   private void fillBuffer(long pos) throws IOException JavaDoc {
107     final long read_pos = (pos / BUFFER_SIZE) * BUFFER_SIZE;
108     int to_read = (int) Math.min((long) BUFFER_SIZE, (size - read_pos));
109     if (to_read > 0) {
110       readPageContent(buf, read_pos, to_read);
111       buffer_pos = read_pos;
112     }
113   }
114
115   // ---------- Implemented from InputStream ----------
116

117   public int read() throws IOException JavaDoc {
118     if (position >= size) {
119       return -1;
120     }
121
122     if (buffer_pos == -1) {
123       fillBuffer(position);
124     }
125     
126     int p = (int) (position - buffer_pos);
127     int v = ((int) buf[p]) & 0x0FF;
128     
129     ++position;
130     // Fill the next part of the buffer?
131
if (p + 1 >= BUFFER_SIZE) {
132       fillBuffer(buffer_pos + BUFFER_SIZE);
133     }
134
135     return v;
136   }
137
138   public int read(byte[] read_buf, int off, int len) throws IOException JavaDoc {
139     if (len <= 0) {
140       return 0;
141     }
142
143     if (buffer_pos == -1) {
144       fillBuffer(position);
145     }
146
147     int p = (int) (position - buffer_pos);
148     long buffer_end = Math.min(buffer_pos + BUFFER_SIZE, size);
149     int to_read = (int) Math.min((long) len, buffer_end - position);
150     if (to_read <= 0) {
151       return -1;
152     }
153     int has_read = 0;
154     while (to_read > 0) {
155       System.arraycopy(buf, p, read_buf, off, to_read);
156       has_read += to_read;
157       p += to_read;
158       off += to_read;
159       len -= to_read;
160       position += to_read;
161       if (p >= BUFFER_SIZE) {
162         fillBuffer(buffer_pos + BUFFER_SIZE);
163         p -= BUFFER_SIZE;
164       }
165       buffer_end = Math.min(buffer_pos + BUFFER_SIZE, size);
166       to_read = (int) Math.min((long) len, buffer_end - position);
167     }
168     return has_read;
169   }
170
171   public long skip(long n) throws IOException JavaDoc {
172     long act_skip = Math.min(n, size - position);
173     
174     if (n < 0) {
175       throw new IOException JavaDoc("Negative skip");
176     }
177     position += act_skip;
178     if (buffer_pos == -1 || (position - buffer_pos) > BUFFER_SIZE) {
179       fillBuffer((position / BUFFER_SIZE) * BUFFER_SIZE);
180     }
181     
182     return act_skip;
183   }
184
185   public int available() throws IOException JavaDoc {
186     return (int) Math.min((long) Integer.MAX_VALUE, (size - position));
187   }
188
189   public void close() throws IOException JavaDoc {
190   }
191
192   public void mark(int limit) {
193     mark_position = position;
194   }
195
196   public void reset() {
197     position = mark_position;
198     long fill_pos = (position / BUFFER_SIZE) * BUFFER_SIZE;
199     if (fill_pos != buffer_pos) {
200       try {
201         fillBuffer(fill_pos);
202       }
203       catch (IOException JavaDoc e) {
204         throw new Error JavaDoc(e.getMessage());
205       }
206     }
207   }
208
209   public boolean markSupported() {
210     return true;
211   }
212
213 }
214
215
Popular Tags