|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2001 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.mdr.persistence.btreeimpl.btreestorage; import java.util.*; import java.io.*; import org.netbeans.mdr.persistence.*; /** * A stream composed of segments stored in CachedPages. The pages * are pinned while members of a CachedPageInputStream. When done with * the stream, close it to unpin the pages. */ public class CachedPageInputStream extends java.io.InputStream { /* first page in stream */ private PageDescriptor first; /* last page in stream */ private PageDescriptor last; /* page currently being read from */ private PageDescriptor currentPage; /* current offset in curent page */ private int currentOffset; /* to support mark and reset */ private PageDescriptor markedPage; private int markedOffset; /** Add a page to the stream * @param pg the page to add * @param offst the offset in the page where the stream data begins * @page len length of stream data */ public void addPage(CachedPage pg, int offst, int len) { PageDescriptor newPage = new PageDescriptor(pg, offst, len); if (first == null) { first = last = newPage; currentPage = first; currentOffset = offst; } else { last.next = newPage; last = newPage; } } /** close the stream. This unpins all of the pages from the cache. * @exception IOException if there is an error unpinning the pages. */ public void close() throws IOException { try { unpinAll(); } catch (StorageException ex) { // By the contract of close, we are only allowed to // throw IOExceptions StreamCorruptedException newEx = new StreamCorruptedException(ex.getMessage()); throw newEx; } finally { first = last = currentPage = null; currentOffset = 0; super.close(); } } /** read a byte from the stream * @return The next byte in the stream, or -1 if at EOF. */ public int read() { while (true) { if (currentPage == null) { return -1; } else if (currentOffset < currentPage.end) { int val = (int)currentPage.page.contents[currentOffset++]; return (val & 0xFF); } else { currentPage = currentPage.next; if (currentPage != null) currentOffset = currentPage.start; } } } /** read bytes into an array * @param b up to b.length bytes are read into this array * @return The number of bytes read. If at EOF, -1 is returned */ public int read(byte b[]) { return read(b, 0, b.length); } /** read bytes into an array * @param b up to length bytes are read into this array * @param offset the offset into the array at whch to start storing bytes * @param maximum number of bytes to read * @return The number of bytes read. If at EOF, -1 is returned */ public int read(byte b[], int offset, int length) { int left; int toCopy = length; int byteOffset = offset; while (true) { if (currentPage == null) { return (toCopy == length) ? -1 : (length - toCopy); } else if ((left = currentPage.end - currentOffset) > 0) { int size = Math.min(left, toCopy); System.arraycopy(currentPage.page.contents, currentOffset, b, byteOffset, size); currentOffset += size; byteOffset += size; toCopy -= size; if (toCopy == 0) { return length; } } else { currentPage = currentPage.next; if (currentPage != null) currentOffset = currentPage.start; } } } /** this class supports mark (since it's easy) * @return true, since we support mark */ public boolean markSupported() { return true; } /** mark a spot in the stream, which reset will return to * @param readlimit ignored */ public void mark(int readlimit) { markedPage = currentPage; markedOffset = currentOffset; } /** report how many bytes are still unread * @return number of bytes left in stream */ public int available() { if (currentPage == null) return 0; int total = currentPage.end - currentOffset; for (PageDescriptor p = currentPage.next; p != null; p = p.next) { total += p.end - p.start; } return total; } /** return to where mark was last called, or to the beginning if * mark was never called. */ public void reset() { if (markedPage != null) { currentPage = markedPage; currentOffset = markedOffset; } else { currentPage = first; if (first != null) currentOffset = first.start; else currentOffset = 0; } } /** if the stream was never closed, unpin the pages now */ protected void finalize() throws StorageException { unpinAll(); } /* unpin all of the pages in the array */ private void unpinAll() throws StorageException{ for (PageDescriptor p = first; p != null; p = p.next) { p.page.unpin(); } } /** This class describes each page in the stream. */ static class PageDescriptor { /** The page contianing the data */ CachedPage page; /** The first byte of data in the page */ int start; /** One past the last byte of data in the page */ int end; /** the next page in the stream */ PageDescriptor next; /** Create a new page descriptor * @param pg the page * @param offset where the stream data starts * @param length how mnay bytes of data the page contains */ public PageDescriptor(CachedPage pg, int offset, int length) { page = pg; start = offset; end = offset + length; } } } |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.