1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef BITSTREAMS_P_H
5#define BITSTREAMS_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists for the convenience
12// of other Qt classes. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtCore/private/qglobal_p.h>
19#include <QtCore/qdebug.h>
20
21#include <type_traits>
22#include <algorithm>
23#include <vector>
24
25QT_BEGIN_NAMESPACE
26
27class QByteArray;
28
29namespace HPack
30{
31
32// BitOStream works with an external buffer,
33// for example, HEADERS frame.
34class Q_AUTOTEST_EXPORT BitOStream
35{
36public:
37 BitOStream(std::vector<uchar> &buffer);
38
39 // Write 'bitLength' bits from the least significant
40 // bits in 'bits' to bitstream:
41 void writeBits(uchar bits, quint8 bitLength);
42 // HPACK data format, we support:
43 // * 32-bit integers
44 // * strings
45 void write(quint32 src);
46 void write(QByteArrayView src, bool compressed);
47
48 quint64 bitLength() const;
49 quint64 byteLength() const;
50 const uchar *begin() const;
51 const uchar *end() const;
52
53 void clear();
54
55private:
56 Q_DISABLE_COPY_MOVE(BitOStream);
57
58 std::vector<uchar> &buffer;
59 quint64 bitsSet;
60};
61
62class Q_AUTOTEST_EXPORT BitIStream
63{
64public:
65 // Error is set by 'read' functions.
66 // 'peek' does not set the error,
67 // since it just peeks some bits
68 // without the notion of wrong/right.
69 // 'read' functions only change 'streamOffset'
70 // on success.
71 enum class Error
72 {
73 NoError,
74 NotEnoughData,
75 CompressionError,
76 InvalidInteger
77 };
78
79 BitIStream();
80 BitIStream(const uchar *f, const uchar *l);
81
82 quint64 bitLength() const;
83 bool hasMoreBits() const;
84
85 // peekBits tries to read 'length' bits from the bitstream into
86 // 'dst' ('length' must be <= sizeof(dst) * 8), packing them
87 // starting from the most significant bit of the most significant
88 // byte. It's a template so that we can use it with different
89 // integer types. Returns the number of bits actually read.
90 // Does not change stream's offset.
91
92 template<class T>
93 quint64 peekBits(quint64 from, quint64 length, T *dstPtr) const
94 {
95 static_assert(std::is_unsigned<T>::value, "peekBits: unsigned integer type expected");
96
97 Q_ASSERT(dstPtr);
98 Q_ASSERT(length <= sizeof(T) * 8);
99
100 if (from >= bitLength() || !length)
101 return 0;
102
103 T &dst = *dstPtr;
104 dst = T();
105 length = std::min(a: length, b: bitLength() - from);
106
107 const uchar *srcByte = first + from / 8;
108 auto bitsToRead = length + from % 8;
109
110 while (bitsToRead > 8) {
111 dst = (dst << 8) | *srcByte;
112 bitsToRead -= 8;
113 ++srcByte;
114 }
115
116 dst <<= bitsToRead;
117 dst |= *srcByte >> (8 - bitsToRead);
118 dst <<= sizeof(T) * 8 - length;
119
120 return length;
121 }
122
123 quint64 streamOffset() const
124 {
125 return offset;
126 }
127
128 bool skipBits(quint64 nBits);
129 bool rewindOffset(quint64 nBits);
130
131 bool read(quint32 *dstPtr);
132 bool read(QByteArray *dstPtr);
133
134 Error error() const;
135
136private:
137 void setError(Error newState);
138
139 const uchar *first;
140 const uchar *last;
141 quint64 offset;
142 Error streamError;
143};
144
145} // namespace HPack
146
147QT_END_NAMESPACE
148
149#endif
150

source code of qtbase/src/network/access/http2/bitstreams_p.h