• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KDECore

  • kdecore
  • network
k3socketbuffer.cpp
Go to the documentation of this file.
1/* -*- C++ -*-
2 * Copyright (C) 2003 Thiago Macieira <thiago@kde.org>
3 *
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#include "k3socketbuffer_p.h"
26
27#include <config.h>
28#include <config-network.h>
29
30#include <assert.h>
31#include <string.h>
32
33#include <QMutableListIterator>
34
35#include "k3socketbase.h"
36
37using namespace KNetwork;
38using namespace KNetwork::Internal;
39
40KSocketBuffer::KSocketBuffer(qint64 size)
41 : m_mutex(QMutex::Recursive), m_offset(0), m_size(size), m_length(0)
42{
43}
44
45KSocketBuffer::KSocketBuffer(const KSocketBuffer& other)
46 : m_mutex(QMutex::Recursive)
47{
48 *this = other;
49}
50
51KSocketBuffer::~KSocketBuffer()
52{
53 // QValueList takes care of deallocating memory
54}
55
56KSocketBuffer& KSocketBuffer::operator=(const KSocketBuffer& other)
57{
58 QMutexLocker locker1(&m_mutex);
59 QMutexLocker locker2(&other.m_mutex);
60
61 m_list = other.m_list; // copy-on-write
62 m_offset = other.m_offset;
63 m_size = other.m_size;
64 m_length = other.m_length;
65
66 return *this;
67}
68
69bool KSocketBuffer::canReadLine() const
70{
71 QMutexLocker locker(&m_mutex);
72
73 qint64 offset = m_offset;
74
75 // walk the buffer
76 for (int i = 0; i < m_list.size(); ++i)
77 {
78 if (m_list.at(i).indexOf('\n', offset) != -1)
79 return true;
80 if (m_list.at(i).indexOf('\r', offset) != -1)
81 return true;
82 offset = 0;
83 }
84
85 return false; // not found
86}
87
88qint64 KSocketBuffer::readLine(char* data, qint64 maxSize)
89{
90 if (!canReadLine())
91 return qint64(-1); // empty
92
93 QMutexLocker locker(&m_mutex);
94
95 // find the offset of the newline in the buffer
96 qint64 newline = 0;
97 qint64 offset = m_offset;
98
99 // walk the buffer
100 for (int i = 0; i < m_list.size(); ++i)
101 {
102 int posnl = m_list.at(i).indexOf('\n', offset);
103 if (posnl == -1)
104 {
105 // not found in this one
106 newline += m_list.at(i).size();
107 offset = 0;
108 continue;
109 }
110
111 // we found it
112 newline += posnl;
113 break;
114 }
115
116 qint64 bytesToRead = newline + 1 - m_offset;
117 if (bytesToRead > maxSize)
118 bytesToRead = maxSize; // don't read more than maxSize
119
120 return consumeBuffer(data, bytesToRead);
121}
122
123qint64 KSocketBuffer::length() const
124{
125 return m_length;
126}
127
128qint64 KSocketBuffer::size() const
129{
130 return m_size;
131}
132
133bool KSocketBuffer::setSize(qint64 size)
134{
135 m_size = size;
136 if (size == -1 || m_length < m_size)
137 return true;
138
139 // size is now smaller than length
140 QMutexLocker locker(&m_mutex);
141
142 // repeat the test
143 if (m_length < m_size)
144 return true;
145
146 // discard from the beginning
147 return (m_length - m_size) == consumeBuffer(0L, m_length - m_size, true);
148}
149
150qint64 KSocketBuffer::feedBuffer(const char *data, qint64 len)
151{
152 if (data == 0L || len == 0)
153 return 0; // nothing to write
154 if (isFull())
155 return -1; // can't write
156
157 QMutexLocker locker(&m_mutex);
158
159 // verify if we can add len bytes
160 if (m_size != -1 && (m_size - m_length) < len)
161 len = m_size - m_length;
162
163 QByteArray a(data, len);
164 m_list.append(a);
165
166 m_length += len;
167 return len;
168}
169
170qint64 KSocketBuffer::consumeBuffer(char *destbuffer, qint64 maxlen, bool discard)
171{
172 if (maxlen == 0 || isEmpty())
173 return 0;
174
175 QMutableListIterator<QByteArray> it(m_list);
176 qint64 offset = m_offset;
177 qint64 copied = 0;
178
179 // walk the buffer
180 while (it.hasNext() && maxlen)
181 {
182 QByteArray& item = it.next();
183 // calculate how much we'll copy
184 qint64 to_copy = item.size() - offset;
185 if (to_copy > maxlen)
186 to_copy = maxlen;
187
188 // do the copying
189 if (destbuffer)
190 memcpy(destbuffer + copied, item.data() + offset, to_copy);
191 maxlen -= to_copy;
192 copied += to_copy;
193
194 if (item.size() - offset > to_copy)
195 {
196 // we did not copy everything
197 offset += to_copy;
198 break;
199 }
200 else
201 {
202 // we copied everything
203 // discard this element;
204 offset = 0;
205 if (discard)
206 it.remove();
207 }
208 }
209
210 if (discard)
211 {
212 m_offset = offset;
213 m_length -= copied;
214 assert(m_length >= 0);
215 }
216
217 return copied;
218}
219
220void KSocketBuffer::clear()
221{
222 QMutexLocker locker(&m_mutex);
223 m_list.clear();
224 m_offset = 0;
225 m_length = 0;
226}
227
228qint64 KSocketBuffer::sendTo(KActiveSocketBase* dev, qint64 len)
229{
230 if (len == 0 || isEmpty())
231 return 0;
232
233 QMutexLocker locker(&m_mutex);
234
235 QMutableListIterator<QByteArray> it(m_list);
236 qint64 offset = m_offset;
237 qint64 written = 0;
238
239 // walk the buffer
240 while (it.hasNext() && (len || len == -1))
241 {
242 // we have to write each element up to len bytes
243 // but since we can have several very small buffers, we can make things
244 // better by concatenating a few of them into a big buffer
245 // question is: how big should that buffer be? 2 kB should be enough
246
247 uint bufsize = 1460;
248 if (len != -1 && len < bufsize)
249 bufsize = len;
250 QByteArray buf(bufsize, '\0');
251 qint64 count = 0;
252
253 while (it.hasNext() && count + (it.peekNext().size() - offset) <= bufsize)
254 {
255 QByteArray& item = it.next();
256 memcpy(buf.data() + count, item.data() + offset, item.size() - offset);
257 count += item.size() - offset;
258 offset = 0;
259 }
260
261 // see if we can still fit more
262 if (count < bufsize && it.hasNext())
263 {
264 // getting here means this buffer (peekNext) is larger than
265 // (bufsize - count) (even for count == 0).
266 QByteArray& item = it.next();
267 memcpy(buf.data() + count, item.data() + offset, bufsize - count);
268 offset += bufsize - count;
269 count = bufsize;
270 }
271
272 // now try to write those bytes
273 qint64 wrote = dev->write(buf, count);
274
275 if (wrote == -1)
276 // error?
277 break;
278
279 written += wrote;
280 if (wrote != count)
281 // can't fit more?
282 break;
283 }
284
285 // discard data that has been written
286 // this updates m_length too
287 if (written)
288 consumeBuffer(0L, written);
289
290 return written;
291}
292
293qint64 KSocketBuffer::receiveFrom(KActiveSocketBase* dev, qint64 len)
294{
295 if (len == 0 || isFull())
296 return 0;
297
298 QMutexLocker locker(&m_mutex);
299
300 if (len == -1)
301 len = dev->bytesAvailable();
302 if (len <= 0)
303 // error or closing socket
304 return len;
305
306 // see if we can read that much
307 if (m_size != -1 && len > (m_size - m_length))
308 len = m_size - m_length;
309
310 // here, len contains just as many bytes as we're supposed to read
311
312 // now do the reading
313 QByteArray a(len, '\0');
314 len = dev->read(a.data(), len);
315
316 if (len == -1)
317 // error?
318 return -1;
319
320 // success
321 // resize the buffer and add it
322 a.truncate(len);
323 m_list.append(a);
324 m_length += len;
325 return len;
326}
KNetwork::Internal::KSocketBuffer
generic socket buffering code
Definition: k3socketbuffer_p.h:49
KNetwork::Internal::KSocketBuffer::KSocketBuffer
KSocketBuffer(qint64 size=-1)
Default constructor.
Definition: k3socketbuffer.cpp:40
KNetwork::Internal::KSocketBuffer::m_offset
qint64 m_offset
offset of the start of data in the first element
Definition: k3socketbuffer_p.h:168
KNetwork::Internal::KSocketBuffer::feedBuffer
qint64 feedBuffer(const char *data, qint64 len)
Adds data to the end of the buffer.
Definition: k3socketbuffer.cpp:150
KNetwork::Internal::KSocketBuffer::clear
void clear()
Clears the buffer.
Definition: k3socketbuffer.cpp:220
KNetwork::Internal::KSocketBuffer::m_length
qint64 m_length
Definition: k3socketbuffer_p.h:171
KNetwork::Internal::KSocketBuffer::m_list
QList< QByteArray > m_list
Definition: k3socketbuffer_p.h:167
KNetwork::Internal::KSocketBuffer::operator=
KSocketBuffer & operator=(const KSocketBuffer &other)
Assignment operator.
Definition: k3socketbuffer.cpp:56
KNetwork::Internal::KSocketBuffer::length
qint64 length() const
Returns the number of bytes in the buffer.
Definition: k3socketbuffer.cpp:123
KNetwork::Internal::KSocketBuffer::canReadLine
bool canReadLine() const
Returns true if a line can be read from the buffer.
Definition: k3socketbuffer.cpp:69
KNetwork::Internal::KSocketBuffer::readLine
qint64 readLine(char *data, qint64 maxSize)
Reads a line from the buffer and discard it from the buffer.
Definition: k3socketbuffer.cpp:88
KNetwork::Internal::KSocketBuffer::consumeBuffer
qint64 consumeBuffer(char *data, qint64 maxlen, bool discard=true)
Consumes data from the beginning of the buffer.
Definition: k3socketbuffer.cpp:170
KNetwork::Internal::KSocketBuffer::size
qint64 size() const
Retrieves the buffer size.
Definition: k3socketbuffer.cpp:128
KNetwork::Internal::KSocketBuffer::m_size
qint64 m_size
the maximum length of the buffer
Definition: k3socketbuffer_p.h:170
KNetwork::Internal::KSocketBuffer::setSize
bool setSize(qint64 size)
Sets the size of the buffer, if allowed.
Definition: k3socketbuffer.cpp:133
KNetwork::Internal::KSocketBuffer::m_mutex
QMutex m_mutex
Definition: k3socketbuffer_p.h:166
KNetwork::Internal::KSocketBuffer::receiveFrom
qint64 receiveFrom(KActiveSocketBase *device, qint64 len=-1)
Tries to receive len bytes of data from the I/O device.
Definition: k3socketbuffer.cpp:293
KNetwork::Internal::KSocketBuffer::isFull
bool isFull() const
Returns true if the buffer is full (i.e., cannot receive more data)
Definition: k3socketbuffer_p.h:117
KNetwork::Internal::KSocketBuffer::isEmpty
bool isEmpty() const
Returns true if the buffer is empty of data.
Definition: k3socketbuffer_p.h:94
KNetwork::Internal::KSocketBuffer::~KSocketBuffer
~KSocketBuffer()
Virtual destructor.
Definition: k3socketbuffer.cpp:51
KNetwork::Internal::KSocketBuffer::sendTo
qint64 sendTo(KActiveSocketBase *device, qint64 len=-1)
Sends at most len bytes of data to the I/O Device.
Definition: k3socketbuffer.cpp:228
KNetwork::KActiveSocketBase
Abstract class for active sockets.
Definition: k3socketbase.h:462
KNetwork::KActiveSocketBase::read
qint64 read(char *data, qint64 maxlen)
Reads data from the socket.
Definition: k3socketbase.cpp:378
KNetwork::KActiveSocketBase::write
qint64 write(const char *data, qint64 len)
Writes the given data to the socket.
Definition: k3socketbase.cpp:404
qint64
k3socketbase.h
k3socketbuffer_p.h
KNetwork::Internal
Definition: k3resolver.h:48
KNetwork
A namespace to store all networking-related (socket) classes.
Definition: k3bufferedsocket.h:35
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

Skip menu "KDECore"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal