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()
19class QPrivateLinearBuffer
20{
21public:
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
118private:
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
139private:
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

source code of qtconnectivity/src/bluetooth/qprivatelinearbuffer_p.h