1 | // Copyright (C) 2016 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 QPRIVATELINEARBUFFER_P_H |
5 | #define QPRIVATELINEARBUFFER_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 purely as an |
12 | // implementation detail. This header file may change from version to |
13 | // version without notice, or even be removed. |
14 | // |
15 | // We mean it. |
16 | // |
17 | |
18 | // This is QIODevice's read buffer, optimised for read(), isEmpty() and getChar() |
19 | class QPrivateLinearBuffer |
20 | { |
21 | public: |
22 | QPrivateLinearBuffer() : len(0), first(0), buf(0), capacity(0) { |
23 | } |
24 | ~QPrivateLinearBuffer() { |
25 | delete [] buf; |
26 | } |
27 | void clear() { |
28 | first = buf; |
29 | len = 0; |
30 | } |
31 | qsizetype size() const |
32 | { |
33 | return len; |
34 | } |
35 | bool isEmpty() const { |
36 | return len == 0; |
37 | } |
38 | void skip(qsizetype n) |
39 | { |
40 | if (n >= len) { |
41 | clear(); |
42 | } else { |
43 | len -= n; |
44 | first += n; |
45 | } |
46 | } |
47 | int getChar() { |
48 | if (len == 0) |
49 | return -1; |
50 | int ch = uchar(*first); |
51 | len--; |
52 | first++; |
53 | return ch; |
54 | } |
55 | qsizetype read(char* target, qsizetype size) |
56 | { |
57 | qsizetype r = (std::min)(a: size, b: len); |
58 | memcpy(dest: target, src: first, n: r); |
59 | len -= r; |
60 | first += r; |
61 | return r; |
62 | } |
63 | char* reserve(qsizetype size) |
64 | { |
65 | makeSpace(required: size + len, where: freeSpaceAtEnd); |
66 | char* writePtr = first + len; |
67 | len += size; |
68 | return writePtr; |
69 | } |
70 | void chop(qsizetype size) |
71 | { |
72 | if (size >= len) { |
73 | clear(); |
74 | } else { |
75 | len -= size; |
76 | } |
77 | } |
78 | QByteArray readAll() { |
79 | char* f = first; |
80 | qsizetype l = len; |
81 | clear(); |
82 | return QByteArray(f, l); |
83 | } |
84 | qsizetype readLine(char* target, qsizetype size) |
85 | { |
86 | qsizetype r = (std::min)(a: size, b: len); |
87 | char* eol = static_cast<char*>(memchr(s: first, c: '\n', n: r)); |
88 | if (eol) |
89 | r = 1+(eol-first); |
90 | memcpy(dest: target, src: first, n: r); |
91 | len -= r; |
92 | first += r; |
93 | return r; |
94 | } |
95 | bool canReadLine() const { |
96 | return memchr(s: first, c: '\n', n: len); |
97 | } |
98 | void ungetChar(char c) { |
99 | if (first == buf) { |
100 | // underflow, the existing valid data needs to move to the end of the (potentially bigger) buffer |
101 | makeSpace(required: len+1, where: freeSpaceAtStart); |
102 | } |
103 | first--; |
104 | len++; |
105 | *first = c; |
106 | } |
107 | void ungetBlock(const char* block, qsizetype size) |
108 | { |
109 | if ((first - buf) < size) { |
110 | // underflow, the existing valid data needs to move to the end of the (potentially bigger) buffer |
111 | makeSpace(required: len + size, where: freeSpaceAtStart); |
112 | } |
113 | first -= size; |
114 | len += size; |
115 | memcpy(dest: first, src: block, n: size); |
116 | } |
117 | |
118 | private: |
119 | enum FreeSpacePos {freeSpaceAtStart, freeSpaceAtEnd}; |
120 | void makeSpace(size_t required, FreeSpacePos where) { |
121 | size_t newCapacity = (std::max)(a: capacity, b: size_t(QPRIVATELINEARBUFFER_BUFFERSIZE)); |
122 | while (newCapacity < required) |
123 | newCapacity *= 2; |
124 | const qsizetype moveOffset = (where == freeSpaceAtEnd) ? 0 : qsizetype(newCapacity) - len; |
125 | if (newCapacity > capacity) { |
126 | // allocate more space |
127 | char* newBuf = new char[newCapacity]; |
128 | memmove(dest: newBuf + moveOffset, src: first, n: len); |
129 | delete [] buf; |
130 | buf = newBuf; |
131 | capacity = newCapacity; |
132 | } else { |
133 | // shift any existing data to make space |
134 | memmove(dest: buf + moveOffset, src: first, n: len); |
135 | } |
136 | first = buf + moveOffset; |
137 | } |
138 | |
139 | private: |
140 | // length of the unread data |
141 | qsizetype len; |
142 | // start of the unread data |
143 | char* first; |
144 | // the allocated buffer |
145 | char* buf; |
146 | // allocated buffer size |
147 | size_t capacity; |
148 | }; |
149 | |
150 | #endif // QPRIVATELINEARBUFFER_P_H |
151 | |