Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/esau/ptarmigan/util/CountingInputStream.java


1   package org.esau.ptarmigan.util;
2   
3   import java.io.IOException;
4   import java.io.InputStream;
5   import java.io.FilterInputStream;
6   
7   import org.apache.commons.logging.Log;
8   import org.apache.commons.logging.LogFactory;
9   
10  /**
11   * Counts the number of bytes that pass through it.
12   * <p>
13   * Note that the counter in this filter is independent of the
14   * mark/reset logic.  If you wish to reset the counter when you
15   * reset the mark, you'll have to do so manually with a call
16   * to resetCount().
17   * <p>
18   * Note that this class has its own renamed read() methods.  This
19   * is to insulate a buffered parent class that will read-ahead as
20   * necessary.
21   *
22   * @author Reed Esau
23   * @version $Revision: 1.3 $ $Date: 2002/10/02 05:30:04 $
24   */
25  public class CountingInputStream extends FilterInputStream {
26  
27      static final int NO_LIMIT = -1;
28  
29      private long m_limit;
30      private long m_count;
31  
32      public CountingInputStream( InputStream in ) {
33          this(in, NO_LIMIT);
34      }
35      public CountingInputStream( InputStream in, long limit ) {
36          super(in);
37          m_limit = limit;
38          log.debug("ctor: limit=" + m_limit);
39      }
40  
41      public int readC() throws IOException {
42  
43          //log.debug("readC: m_limit=" + m_limit + " m_count=" + m_count + " remaining=" + getRemaining());
44  
45          if (m_limit != NO_LIMIT) {
46              if (getRemaining() < 1)
47                  return -1;
48          }
49  
50          int by = super.read();
51          if (by != -1)
52              m_count++;
53          return by;
54      }
55  
56      public int readC(byte b[]) throws IOException {
57  
58          //log.debug("readC-b: blen=" + b.length + " m_limit=" + m_limit + " m_count=" + m_count + " remaining=" + getRemaining());
59  
60          int len = b.length;
61  
62          if (m_limit != NO_LIMIT) {
63              long remaining = getRemaining();
64              if (len > remaining)
65                  len = (int)remaining;
66          }
67  
68          int bytes = super.read(b, 0, len);
69          if (bytes != -1)
70              m_count += bytes;
71          return bytes;
72      }
73  
74      public int readC(byte b[], int off, int len) throws IOException {
75  
76          //log.debug("readC-bol: blen=" + b.length + " off=" + off + " len=" + len + " m_limit=" + m_limit + " m_count=" + m_count + " remaining=" + getRemaining());
77  
78          if (m_limit != NO_LIMIT) {
79              long remaining = getRemaining();
80              if (len > remaining)
81                  len = (int)remaining;
82          }
83  
84          int bytes = super.read(b, off, len);
85          if (bytes != -1)
86              m_count += bytes;
87          return bytes;
88      }
89  
90      public long skipC(long n) throws IOException {
91  
92          //log.debug("skipC: n=" + n + " m_limit=" + m_limit + " m_count=" + m_count + " remaining=" + getRemaining());
93  
94          if (m_limit != NO_LIMIT) {
95              long remaining = getRemaining();
96              if (n > remaining)
97                  n = remaining;
98          }
99  
100         long skipped = super.skip(n);
101         if (skipped >= 0)
102             m_count += skipped;
103         return skipped;
104     }
105 
106     /**
107      * The number of bytes that have passed through this stream.
108      */
109     public long getCount() {
110         return m_count;
111     }
112 
113     /**
114      * Start the count at zero
115      */
116     public void resetCount() {
117         //log.debug("resetCount: m_count=" + m_count);
118         m_count = 0L;
119     }
120 
121     public long getLimit() {
122         return m_limit;
123     }
124     public void setLimit(long limit) {
125         m_limit = limit;
126     }
127 
128     public long getRemaining() {
129         return m_limit - m_count;
130     }
131 
132 //
133 // set the file position
134 //
135 
136     static final int BLOCK_SIZE = 128;
137 
138     /**
139      * a substitute for skip, which doesn't seem to want to work
140      * correctly on buffered streams
141      * <p>
142      * TODO: should be 'long' param?
143      */
144     public int fastForward(int n) throws IOException {
145         if (log.isDebugEnabled())
146             log.debug("fastForward: n=" + n + " counter=" + m_count);
147 
148         if (m_limit == NO_LIMIT)
149             return (int)skip(n);     // trivial case (no limit imposed)
150 
151         if (n < 0)
152             throw new IllegalArgumentException("unexpected value " + n);
153 
154         long remaining = getRemaining();
155         if (n > remaining) {
156             log.warn("fastForward: truncating at limit; remaining=" +remaining);
157             n = (int)remaining;
158         }
159 
160         if (n == 0)
161             return 0;           //trivial case
162 
163         int buf_size = n > BLOCK_SIZE ? BLOCK_SIZE : n;
164         byte[] buf = new byte[ buf_size ];
165 
166         int bytes_to_read = n;
167 
168         while (bytes_to_read > 0) {
169             int bytes_read = readC(buf, 0, (bytes_to_read > BLOCK_SIZE
170                                             ? BLOCK_SIZE
171                                             : bytes_to_read));
172             if (bytes_read == -1) {
173                 log.warn("fastForward: failure to consume bytes, bytes_to_read="
174                          + bytes_to_read);
175                 return -1;
176             }
177 
178             bytes_to_read -= bytes_read;
179         }
180         if (log.isDebugEnabled() && bytes_to_read > 0)
181             log.debug("fastForward: bytes_to_read=" + bytes_to_read);
182         return(n - bytes_to_read);
183     }
184 
185     /**
186      * reposition the stream from the last mark point (in case we
187      * read too far)
188      * <p>
189      * TODO: should be 'long' param?
190      *
191      * @return true if rewind was successful; false if we had read beyond the limit of the mark
192      */
193     public boolean rewind(int n) throws IOException {
194 
195         if (markSupported() == false)
196             throw new IOException("mark/reset not supported");
197 
198         if (m_limit == NO_LIMIT) {
199             reset();            // throws if read beyond mark
200             m_count = 0;
201             return true;
202         }
203 
204         if (log.isDebugEnabled())
205             log.debug("rewind: n=" + n + " counter=" + m_count);
206 
207         int diff = (int)(n - m_count);
208         if (diff > 0) {
209             long skipped = fastForward(diff);
210             if (skipped < 0 || skipped != diff) {
211                 throw new IOException("unable to advance");
212             }
213         }
214         else if (diff < 0) {
215             log.debug("rewind: RESET");
216 
217             reset();            // throws if read beyond mark
218             m_count = 0;
219             long skipped = fastForward(n);
220             if (skipped < 0 || skipped != n) {
221                 throw new IOException("unable to advance after rewind");
222             }
223         }
224         //log.debug("rewind: success, counter=" + m_count);
225         return true;
226     }
227 
228     /**
229      * logging object
230      */
231     static Log log = LogFactory.getLog(CountingInputStream.class);
232 }
233 
234