1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.voicemail.impl.mail;
18 
19 import java.io.IOException;
20 import java.io.InputStream;
21 
22 /**
23  * A filtering InputStream that allows single byte "peeks" without consuming the byte. The client of
24  * this stream can call peek() to see the next available byte in the stream and a subsequent read
25  * will still return the peeked byte.
26  */
27 public class PeekableInputStream extends InputStream {
28   private final InputStream in;
29   private boolean peeked;
30   private int peekedByte;
31 
PeekableInputStream(InputStream in)32   public PeekableInputStream(InputStream in) {
33     this.in = in;
34   }
35 
36   @Override
read()37   public int read() throws IOException {
38     if (!peeked) {
39       return in.read();
40     } else {
41       peeked = false;
42       return peekedByte;
43     }
44   }
45 
peek()46   public int peek() throws IOException {
47     if (!peeked) {
48       peekedByte = read();
49       peeked = true;
50     }
51     return peekedByte;
52   }
53 
54   @Override
read(byte[] b, int offset, int length)55   public int read(byte[] b, int offset, int length) throws IOException {
56     if (!peeked) {
57       return in.read(b, offset, length);
58     } else {
59       b[0] = (byte) peekedByte;
60       peeked = false;
61       int r = in.read(b, offset + 1, length - 1);
62       if (r == -1) {
63         return 1;
64       } else {
65         return r + 1;
66       }
67     }
68   }
69 
70   @Override
read(byte[] b)71   public int read(byte[] b) throws IOException {
72     return read(b, 0, b.length);
73   }
74 
75   @Override
toString()76   public String toString() {
77     return String.format(
78         "PeekableInputStream(in=%s, peeked=%b, peekedByte=%d)", in.toString(), peeked, peekedByte);
79   }
80 }
81