~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/corelib/kernel/qinternal.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
 
4
**
 
5
** This file is part of the core module of the Qt Toolkit.
 
6
**
 
7
** This file may be distributed under the terms of the Q Public License
 
8
** as defined by Trolltech AS of Norway and appearing in the file
 
9
** LICENSE.QPL included in the packaging of this file.
 
10
**
 
11
** This file may be distributed and/or modified under the terms of the
 
12
** GNU General Public License version 2 as published by the Free Software
 
13
** Foundation and appearing in the file LICENSE.GPL included in the
 
14
** packaging of this file.
 
15
**
 
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
 
17
**   information about Qt Commercial License Agreements.
 
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
 
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
 
20
**
 
21
** Contact info@trolltech.com if any conditions of this licensing are
 
22
** not clear to you.
 
23
**
 
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
26
**
 
27
****************************************************************************/
 
28
 
 
29
#include "private/qinternal_p.h"
 
30
 
 
31
/*! \internal
 
32
 
 
33
    Creates an empty ring buffer. The buffer will grow in steps of \a
 
34
    growth as data is written to it.
 
35
*/
 
36
QRingBuffer::QRingBuffer(int growth)
 
37
    : basicBlockSize(growth)
 
38
{
 
39
    buffers << QByteArray();
 
40
    clear();
 
41
}
 
42
 
 
43
/*! \internal
 
44
 
 
45
    Returns the number of bytes that can be read in one operation. The
 
46
    data is read from readPointer().
 
47
*/
 
48
int QRingBuffer::nextDataBlockSize() const
 
49
{
 
50
    return (tailBuffer == 0 ? tail : buffers.at(0).size()) - head;
 
51
}
 
52
 
 
53
/*! \internal
 
54
 
 
55
    Returns a pointer to where no more than nextDataBlockSize() bytes
 
56
    of data can be read. Call free() to remove data after reading.
 
57
*/
 
58
char *QRingBuffer::readPointer() const
 
59
{
 
60
    if (buffers.count() == 0)
 
61
        return 0;
 
62
    return const_cast<char *>(buffers[0].data()) + head;
 
63
}
 
64
 
 
65
/*! \internal
 
66
 
 
67
    Removes \a bytes bytes from the front of the buffer. If \a bytes
 
68
    is larger than the size of the buffer, the buffer is cleared.
 
69
*/
 
70
void QRingBuffer::free(int bytes)
 
71
{
 
72
    bufferSize -= bytes;
 
73
    if (bufferSize < 0)
 
74
        bufferSize = 0;
 
75
 
 
76
    for (;;) {
 
77
        int nextBlockSize = nextDataBlockSize();
 
78
        if (bytes < nextBlockSize) {
 
79
            head += bytes;
 
80
            if (head == tail && tailBuffer == 0)
 
81
                head = tail = 0;
 
82
            return;
 
83
        }
 
84
 
 
85
        bytes -= nextBlockSize;
 
86
        if (buffers.count() == 1) {
 
87
            if (buffers.at(0).size() != basicBlockSize)
 
88
                buffers[0].resize(basicBlockSize);
 
89
            head = tail = 0;
 
90
            tailBuffer = 0;
 
91
            return;
 
92
        }
 
93
 
 
94
        buffers.removeAt(0);
 
95
        --tailBuffer;
 
96
        head = 0;
 
97
    }
 
98
}
 
99
 
 
100
/*! \internal
 
101
 
 
102
    Reserves space in the buffer for \a bytes new bytes, and returns a
 
103
    pointer to the first byte.
 
104
*/
 
105
char *QRingBuffer::reserve(int bytes)
 
106
{
 
107
    bufferSize += bytes;
 
108
 
 
109
    // if there is already enough space, simply return.
 
110
    if (tail + bytes <= buffers.at(tailBuffer).size()) {
 
111
        char *writePtr = buffers[tailBuffer].data() + tail;
 
112
        tail += bytes;
 
113
        return writePtr;
 
114
    }
 
115
 
 
116
    // if our buffer isn't half full yet, simply resize it.
 
117
    if (tail < buffers.at(tailBuffer).size() / 2) {
 
118
        buffers[tailBuffer].resize(tail + bytes);
 
119
        char *writePtr = buffers[tailBuffer].data() + tail;
 
120
        tail += bytes;
 
121
        return writePtr;
 
122
    }
 
123
 
 
124
    // shrink this buffer to its current size
 
125
    buffers[tailBuffer].resize(tail);
 
126
 
 
127
    // create a new QByteArray with the right size
 
128
    buffers << QByteArray();
 
129
    ++tailBuffer;
 
130
    buffers[tailBuffer].resize(qMax(basicBlockSize, bytes));
 
131
    tail = bytes;
 
132
    return buffers[tailBuffer].data();
 
133
}
 
134
 
 
135
/*! \internal
 
136
 
 
137
    Removes \a bytes bytes from the end of the buffer. If \a bytes is
 
138
    larger than the buffer size, the buffer is cleared.
 
139
*/
 
140
void QRingBuffer::truncate(int bytes)
 
141
{
 
142
    bufferSize -= bytes;
 
143
    if (bufferSize < 0)
 
144
        bufferSize = 0;
 
145
 
 
146
    for (;;) {
 
147
        // special case: head and tail are in the same buffer
 
148
        if (tailBuffer == 0) {
 
149
            tail -= bytes;
 
150
            if (tail <= head)
 
151
                tail = head = 0;
 
152
            return;
 
153
        }
 
154
 
 
155
        if (bytes <= tail) {
 
156
            tail -= bytes;
 
157
            return;
 
158
        }
 
159
 
 
160
        bytes -= tail;
 
161
        buffers.removeAt(tailBuffer);
 
162
 
 
163
        --tailBuffer;
 
164
        tail = buffers.at(tailBuffer).size();
 
165
    }
 
166
}
 
167
 
 
168
/*! \internal
 
169
 
 
170
    Returns and removes the first character in the buffer. Returns -1
 
171
    if the buffer is empty.
 
172
*/
 
173
int QRingBuffer::getChar()
 
174
{
 
175
    if (isEmpty())
 
176
       return -1;
 
177
    char c = *readPointer();
 
178
    free(1);
 
179
    return c;
 
180
}
 
181
 
 
182
/*! \internal
 
183
 
 
184
    Appends the character \a c to the end of the buffer.
 
185
*/
 
186
void QRingBuffer::putChar(char c)
 
187
{
 
188
    char *ptr = reserve(1);
 
189
    *ptr = c;
 
190
}
 
191
 
 
192
/*! \internal
 
193
 
 
194
    Prepends the character \a c to the front of the buffer.
 
195
*/
 
196
void QRingBuffer::ungetChar(char c)
 
197
{
 
198
    --head;
 
199
    if (head < 0) {
 
200
        buffers.prepend(QByteArray());
 
201
        buffers[0].resize(basicBlockSize);
 
202
        head = basicBlockSize - 1;
 
203
        ++tailBuffer;
 
204
    }
 
205
    buffers[0][head] = c;
 
206
    ++bufferSize;
 
207
}
 
208
 
 
209
/*! \internal
 
210
 
 
211
    Returns the size of the buffer; e.g. the number of bytes
 
212
    currently in use.
 
213
*/
 
214
int QRingBuffer::size() const
 
215
{
 
216
    return bufferSize;
 
217
}
 
218
 
 
219
/*! \internal
 
220
 
 
221
    Removes all data from the buffer and resets its size to 0.
 
222
*/
 
223
void QRingBuffer::clear()
 
224
{
 
225
    QByteArray tmp = buffers[0];
 
226
    buffers.clear();
 
227
    buffers << tmp;
 
228
 
 
229
    if (buffers.at(0).size() != basicBlockSize)
 
230
        buffers[0].resize(basicBlockSize);
 
231
 
 
232
    head = tail = 0;
 
233
    tailBuffer = 0;
 
234
    bufferSize = 0;
 
235
}
 
236
 
 
237
/*! \internal
 
238
 
 
239
    Returns true if the buffer is empty; otherwise returns false.
 
240
*/
 
241
bool QRingBuffer::isEmpty() const
 
242
{
 
243
    return tailBuffer == 0 && tail == 0;
 
244
}
 
245
 
 
246
/*! \internal
 
247
 
 
248
    Returns the index of the first occurrence of the character \a c in
 
249
    the buffer. In no such character is found, -1 is returned.
 
250
*/
 
251
int QRingBuffer::indexOf(char c) const
 
252
{
 
253
    int index = 0;
 
254
    for (int i = 0; i < buffers.size(); ++i) {
 
255
        int start = 0;
 
256
        int end = buffers.at(i).size();
 
257
 
 
258
        if (i == 0)
 
259
            start = head;
 
260
        if (i == tailBuffer)
 
261
            end = tail;
 
262
        const char *ptr = buffers.at(i).data() + start;
 
263
        for (int j = start; j < end; ++j) {
 
264
            if (*ptr++ == c)
 
265
                return index;
 
266
            ++index;
 
267
        }
 
268
    }
 
269
 
 
270
    return -1;
 
271
}
 
272
 
 
273
/*! \internal
 
274
 
 
275
    Reads one line of data (all data up to and including the '\n'
 
276
    character), no longer than \a maxSize - 1 bytes, and stores it in \a
 
277
    data. If the line is too long, maxSize bytes of the line are read.
 
278
    \a data is always terminated by a '\0' byte.
 
279
*/
 
280
int QRingBuffer::readLine(char *data, int maxSize)
 
281
{
 
282
    int index = indexOf('\n');
 
283
    if (index == -1 || maxSize <= 0)
 
284
        return -1;
 
285
 
 
286
    int readSoFar = 0;
 
287
    while (readSoFar < index && readSoFar < maxSize - 1) {
 
288
        int bytesToRead = qMin((index + 1) - readSoFar, nextDataBlockSize());
 
289
        bytesToRead = qMin(bytesToRead, (maxSize - 1) - readSoFar);
 
290
        memcpy(data + readSoFar, readPointer(), bytesToRead);
 
291
        readSoFar += bytesToRead;
 
292
        free(bytesToRead);
 
293
    }
 
294
 
 
295
    // Terminate it.
 
296
    data[readSoFar] = '\0';
 
297
    return readSoFar;
 
298
}
 
299
 
 
300
/*! \internal
 
301
 
 
302
    Returns true if a line can be read from the buffer; otherwise
 
303
    returns false.
 
304
*/
 
305
bool QRingBuffer::canReadLine() const
 
306
{
 
307
    return indexOf('\n') != -1;
 
308
}