1104c45677660586026a7e74ef8c47d396403d50eMichael Jurka/*
2104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Copyright (C) 2012 The Android Open Source Project
3104c45677660586026a7e74ef8c47d396403d50eMichael Jurka *
4104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Licensed under the Apache License, Version 2.0 (the "License");
5104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * you may not use this file except in compliance with the License.
6104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * You may obtain a copy of the License at
7104c45677660586026a7e74ef8c47d396403d50eMichael Jurka *
8104c45677660586026a7e74ef8c47d396403d50eMichael Jurka *      http://www.apache.org/licenses/LICENSE-2.0
9104c45677660586026a7e74ef8c47d396403d50eMichael Jurka *
10104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * Unless required by applicable law or agreed to in writing, software
11104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * distributed under the License is distributed on an "AS IS" BASIS,
12104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * See the License for the specific language governing permissions and
14104c45677660586026a7e74ef8c47d396403d50eMichael Jurka * limitations under the License.
15104c45677660586026a7e74ef8c47d396403d50eMichael Jurka */
16104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
17104c45677660586026a7e74ef8c47d396403d50eMichael Jurkapackage com.android.gallery3d.exif;
18104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
19104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.io.EOFException;
20104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.io.FilterInputStream;
21104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.io.IOException;
22104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.io.InputStream;
23104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.nio.ByteBuffer;
24104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.nio.ByteOrder;
25104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaimport java.nio.charset.Charset;
26104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
27104c45677660586026a7e74ef8c47d396403d50eMichael Jurkaclass CountedDataInputStream extends FilterInputStream {
28104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
29104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private int mCount = 0;
30104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
31104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    // allocate a byte buffer for a long value;
32104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private final byte mByteArray[] = new byte[8];
33104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    private final ByteBuffer mByteBuffer = ByteBuffer.wrap(mByteArray);
34104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
35104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    protected CountedDataInputStream(InputStream in) {
36104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        super(in);
37104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
38104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
39104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public int getReadByteCount() {
40104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return mCount;
41104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
42104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
43104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    @Override
44104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public int read(byte[] b) throws IOException {
45104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        int r = in.read(b);
46104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mCount += (r >= 0) ? r : 0;
47104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return r;
48104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
49104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
50104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    @Override
51104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public int read(byte[] b, int off, int len) throws IOException {
52104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        int r = in.read(b, off, len);
53104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mCount += (r >= 0) ? r : 0;
54104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return r;
55104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
56104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
57104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    @Override
58104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public int read() throws IOException {
59104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        int r = in.read();
60104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mCount += (r >= 0) ? 1 : 0;
61104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return r;
62104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
63104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
64104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    @Override
65104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public long skip(long length) throws IOException {
66104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        long skip = in.skip(length);
67104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mCount += skip;
68104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return skip;
69104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
70104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
71104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public void skipOrThrow(long length) throws IOException {
72104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (skip(length) != length) throw new EOFException();
73104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
74104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
75104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public void skipTo(long target) throws IOException {
76104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        long cur = mCount;
77104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        long diff = target - cur;
78104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        assert(diff >= 0);
79104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        skipOrThrow(diff);
80104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
81104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
82104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public void readOrThrow(byte[] b, int off, int len) throws IOException {
83104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        int r = read(b, off, len);
84104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        if (r != len) throw new EOFException();
85104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
86104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
87104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public void readOrThrow(byte[] b) throws IOException {
88104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        readOrThrow(b, 0, b.length);
89104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
90104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
91104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public void setByteOrder(ByteOrder order) {
92104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mByteBuffer.order(order);
93104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
94104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
95104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public ByteOrder getByteOrder() {
96104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return mByteBuffer.order();
97104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
98104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
99104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public short readShort() throws IOException {
100104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        readOrThrow(mByteArray, 0 ,2);
101104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mByteBuffer.rewind();
102104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return mByteBuffer.getShort();
103104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
104104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
105104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public int readUnsignedShort() throws IOException {
106104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return readShort() & 0xffff;
107104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
108104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
109104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public int readInt() throws IOException {
110104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        readOrThrow(mByteArray, 0 , 4);
111104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mByteBuffer.rewind();
112104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return mByteBuffer.getInt();
113104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
114104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
115104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public long readUnsignedInt() throws IOException {
116104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return readInt() & 0xffffffffL;
117104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
118104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
119104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public long readLong() throws IOException {
120104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        readOrThrow(mByteArray, 0 , 8);
121104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        mByteBuffer.rewind();
122104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return mByteBuffer.getLong();
123104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
124104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
125104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public String readString(int n) throws IOException {
126104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        byte buf[] = new byte[n];
127104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        readOrThrow(buf);
128104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return new String(buf, "UTF8");
129104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
130104c45677660586026a7e74ef8c47d396403d50eMichael Jurka
131104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    public String readString(int n, Charset charset) throws IOException {
132104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        byte buf[] = new byte[n];
133104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        readOrThrow(buf);
134104c45677660586026a7e74ef8c47d396403d50eMichael Jurka        return new String(buf, charset);
135104c45677660586026a7e74ef8c47d396403d50eMichael Jurka    }
136104c45677660586026a7e74ef8c47d396403d50eMichael Jurka}