summaryrefslogtreecommitdiff
path: root/isoparser/src/main/java/com/coremedia/iso/IsoTypeReader.java
blob: 6d9e86ec994aacce853a0a9cf2dd5532bf7364c6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
 * Copyright 2012 Sebastian Annies, Hamburg
 *
 * Licensed under the Apache License, Version 2.0 (the License);
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an AS IS BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.coremedia.iso;

import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;

public final class IsoTypeReader {


    public static long readUInt32BE(ByteBuffer bb) {
        long ch1 = readUInt8(bb);
        long ch2 = readUInt8(bb);
        long ch3 = readUInt8(bb);
        long ch4 = readUInt8(bb);
        return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0));

    }


    public static long readUInt32(ByteBuffer bb) {
        long i = bb.getInt();
        if (i < 0) {
            i += 1l<<32;
        }
        return i;
    }

    public static int readUInt24(ByteBuffer bb) {
        int result = 0;
        result += readUInt16(bb) << 8;
        result += byte2int(bb.get());
        return result;
    }


    public static int readUInt16(ByteBuffer bb) {
        int result = 0;
        result += byte2int(bb.get()) << 8;
        result += byte2int(bb.get());
        return result;
    }

    public static int readUInt16BE(ByteBuffer bb) {
        int result = 0;
        result += byte2int(bb.get());
        result += byte2int(bb.get()) << 8;
        return result;
    }

    public static int readUInt8(ByteBuffer bb) {
        return byte2int(bb.get());
    }

    public static int byte2int(byte b) {
        return b < 0 ? b + 256 : b;
    }


    /**
     * Reads a zero terminated UTF-8 string.
     *
     * @param byteBuffer the data source
     * @return the string readByte
     * @throws Error in case of an error in the underlying stream
     */
    public static String readString(ByteBuffer byteBuffer) {

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int read;
        while ((read = byteBuffer.get()) != 0) {
            out.write(read);
        }
        return Utf8.convert(out.toByteArray());
    }

    public static String readString(ByteBuffer byteBuffer, int length) {
        byte[] buffer = new byte[length];
        byteBuffer.get(buffer);
        return Utf8.convert(buffer);

    }

    public static long readUInt64(ByteBuffer byteBuffer) {
        long result = 0;
        // thanks to Erik Nicolas for finding a bug! Cast to long is definitivly needed
        result += readUInt32(byteBuffer) << 32;
        if (result < 0) {
            throw new RuntimeException("I don't know how to deal with UInt64! long is not sufficient and I don't want to use BigInt");
        }
        result += readUInt32(byteBuffer);

        return result;
    }

    public static double readFixedPoint1616(ByteBuffer bb) {
        byte[] bytes = new byte[4];
        bb.get(bytes);

        int result = 0;
        result |= ((bytes[0] << 24) & 0xFF000000);
        result |= ((bytes[1] << 16) & 0xFF0000);
        result |= ((bytes[2] << 8) & 0xFF00);
        result |= ((bytes[3]) & 0xFF);
        return ((double) result) / 65536;

    }

    public static float readFixedPoint88(ByteBuffer bb) {
        byte[] bytes = new byte[2];
        bb.get(bytes);
        short result = 0;
        result |= ((bytes[0] << 8) & 0xFF00);
        result |= ((bytes[1]) & 0xFF);
        return ((float) result) / 256;
    }

    public static String readIso639(ByteBuffer bb) {
        int bits = readUInt16(bb);
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < 3; i++) {
            int c = (bits >> (2 - i) * 5) & 0x1f;
            result.append((char) (c + 0x60));
        }
        return result.toString();
    }

    public static String read4cc(ByteBuffer bb) {
        byte[] b = new byte[4];
        bb.get(b);
        return IsoFile.bytesToFourCC(b);
    }

}