1 /*** 2 * Ambient - A music player for the Android platform 3 Copyright (C) 2007 Martin Vysny 4 5 This program is free software: you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation, either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 package sk.baka.ambient.commons; 20 21 import java.io.IOException; 22 import java.io.InputStream; 23 24 /*** 25 * Counts bytes which are being read. 26 * 27 * @author Martin Vysny 28 */ 29 public abstract class CountingInputStream extends InputStream { 30 @Override 31 public int read() throws IOException { 32 final int result = in.read(); 33 if (result >= 0) { 34 currentPosition++; 35 checkPos(); 36 } 37 return result; 38 } 39 40 private void checkPos() { 41 if (currentPosition >= nextEventPosition) { 42 nextEventPosition += blockLength; 43 countEvent(currentPosition); 44 } 45 } 46 47 @Override 48 public int read(byte[] buffer, int offset, int count) throws IOException { 49 final int result = in.read(buffer, offset, count); 50 if (result > 0) { 51 currentPosition += result; 52 checkPos(); 53 } 54 return result; 55 } 56 57 @Override 58 public int read(byte[] buffer) throws IOException { 59 final int result = in.read(buffer); 60 if (result > 0) { 61 currentPosition += result; 62 checkPos(); 63 } 64 return result; 65 } 66 67 @Override 68 public long skip(long count) throws IOException { 69 final long result = in.skip(count); 70 currentPosition += result; 71 checkPos(); 72 return result; 73 } 74 75 @Override 76 public synchronized void mark(int readlimit) { 77 in.mark(readlimit); 78 markedPosition = currentPosition; 79 } 80 81 private long markedPosition = 0; 82 83 @Override 84 public synchronized void reset() throws IOException { 85 in.reset(); 86 if (!markSupported()) { 87 currentPosition = 0; 88 } else { 89 currentPosition = markedPosition; 90 } 91 } 92 93 /*** 94 * Fire events only when a block of given size (in bytes) has been read. 95 * This prevents firing events after each byte read. 96 */ 97 public final int blockLength; 98 private final InputStream in; 99 100 /*** 101 * Creates new counting stream instance. 102 * 103 * @param in 104 * poll this stream. 105 * @param blockLength 106 * Fire events only when a block of given size (in bytes) has 107 * been read. This prevents firing events after each byte read. 108 */ 109 public CountingInputStream(final InputStream in, final int blockLength) { 110 super(); 111 this.in = in; 112 this.blockLength = blockLength; 113 nextEventPosition = blockLength; 114 } 115 116 private long currentPosition = 0; 117 118 /*** 119 * Returns number of bytes already read. 120 * 121 * @return the number of bytes. 122 */ 123 public long getCurrentPosition() { 124 return currentPosition; 125 } 126 127 private long nextEventPosition; 128 129 /*** 130 * Invoked when the position 131 * 132 * @param currentPosition 133 */ 134 protected abstract void countEvent(final long currentPosition); 135 136 @Override 137 public int available() throws IOException { 138 return in.available(); 139 } 140 141 @Override 142 public void close() throws IOException { 143 in.close(); 144 } 145 146 @Override 147 public boolean markSupported() { 148 return in.markSupported(); 149 } 150 }