1
#ifndef LEOUTPUTSTREAM_H
2
#define LEOUTPUTSTREAM_H
3
4
#include "leinputstream.h"
5
6
class LEOutputStream {
7
private:
8
    QIODevice* output;
9
    QDataStream data;
10
11
    qint8 bitfieldpos;
12
    quint8 bitfield;
13
14
    void writeBits(quint8 n, quint8 v) {
15
        bitfield = v << bitfieldpos | bitfield;
16
        bitfieldpos += n;
17
        if (bitfieldpos == 8) {
18
            data << bitfield;
19
            bitfield = 0;
20
            bitfieldpos = 0;
21
        } else if (bitfieldpos > 8) {
22
            throw IOException("Bitfield does not have enough bits left.");
23
        }
24
    }
25
26
    void checkForLeftOverBits() const {
27
        if (bitfieldpos != 0) {
28
            throw IOException(
29
                "Cannot read this type halfway through a bit operation.");
30
        }
31
    }
32
33
public:
34
35
    LEOutputStream(QIODevice* out) :output(out), data(out) {
36
        bitfield = 0;
37
        bitfieldpos = 0;
38
        data.setByteOrder(QDataStream::LittleEndian);
39
    }
40
41
    void writebit(bool v) {
42
        writeBits(1, (v) ?1 :0);
43
    }
44
45
    void writeuint2(quint8 v) {
46
        writeBits(2, v);
47
    }
48
49
    void writeuint3(quint8 v) {
50
        writeBits(3, v);
51
    }
52
53
    void writeuint4(quint8 v) {
54
        writeBits(4, v);
55
    }
56
57
    void writeuint5(quint8 v) {
58
        writeBits(5, v);
59
    }
60
61
    void writeuint6(quint8 v) {
62
        writeBits(6, v);
63
    }
64
65
    void writeuint7(quint8 v) {
66
        writeBits(7, v);
67
    }
68
69
    void writeuint9(quint16 v) {
70
        data << (quint8) v;
71
        writeBits(1, v >> 8);
72
    }
73
74
    void writeuint12(quint16 v) {
75
        writeBits(4, v);
76
        data << (quint8)(v >> 4);
77
    }
78
79
    void writeuint13(quint16 v) {
80
        writeBits(5, v);
81
        data << (quint8)(v >> 5);
82
    }
83
84
    void writeuint14(quint16 v) {
85
        if (bitfieldpos == 0) {
86
            data << (quint8) v;
87
            writeBits(6, v >> 8);
88
        } else if (bitfieldpos == 2) {
89
            writeBits(6, v);
90
            data << (quint8)(v >> 6);
91
        } else {
92
            throw IOException(
93
                "Cannot write this type halfway through a bit operation.");
94
        }
95
    }
96
97
    void writeuint15(quint16 v) {
98
        // we assume there are 7 bits left
99
        writeBits(7, v);
100
        data << (quint8)(v >> 7);
101
    }
102
103
    void writeuint20(quint32 v) {
104
        if (bitfieldpos == 0) {
105
            data << (quint8) v;
106
            data << (quint8)(v >> 8);
107
            writeBits(4, v >> 16);
108
        } else if (bitfieldpos == 4) {
109
            writeBits(4, v);
110
            data << (quint8)(v >> 4);
111
            data << (quint8)(v >> 12);
112
        } else {
113
            throw IOException(
114
                "Cannot write this type halfway through a bit operation.");
115
        }
116
    }
117
118
    void writeuint30(quint32 v) {
119
        checkForLeftOverBits();
120
        data << (quint8) v;
121
        data << (quint8)(v >> 8);
122
        data << (quint8)(v >> 16);
123
        writeBits(6, v >> 24);
124
    }
125
126
    void writeuint8(quint8 v) {
127
        checkForLeftOverBits();
128
        data << v;
129
    }
130
131
    void writeint16(qint16 v) {
132
        checkForLeftOverBits();
133
        data << v;
134
    }
135
136
    void writeuint16(quint16 v) {
137
        checkForLeftOverBits();
138
        data << v;
139
    }
140
141
    void writeuint32(quint32 v) {
142
        checkForLeftOverBits();
143
        data << v;
144
    }
145
146
    void writeint32(qint32 v) {
147
        checkForLeftOverBits();
148
        data << v;
149
    }
150
151
    void writeBytes(const QByteArray& b) {
152
        int offset = 0;
153
        int todo = b.size();
154
        do {
155
            int nwritten = data.writeRawData(b.data() + offset, todo);
156
            if (nwritten == -1) return; //TODO report error
157
            todo -= nwritten;
158
            offset += nwritten;
159
        } while (todo > 0);
160
    }
161
162
    quint64 getPosition() const { return output->pos(); }
163
};
164
165
#endif