• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdecore
 

tdecore

  • tdecore
  • network
tdesocketbuffer.cpp
1/*
2 * Copyright (C) 2003 Thiago Macieira <thiago.macieira@kdemail.net>
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 <config.h>
26
27#include <assert.h>
28#include <string.h>
29
30#include "tdesocketbase.h"
31#include "tdesocketbuffer_p.h"
32
33using namespace KNetwork;
34using namespace KNetwork::Internal;
35
36TDESocketBuffer::TDESocketBuffer(TQ_LONG size)
37 : m_mutex(true), m_offset(0), m_size(size), m_length(0)
38{
39}
40
41TDESocketBuffer::TDESocketBuffer(const TDESocketBuffer& other)
42 : TDEIOBufferBase(other), m_mutex(true)
43{
44 *this = other;
45}
46
47TDESocketBuffer::~TDESocketBuffer()
48{
49 // TQValueList takes care of deallocating memory
50}
51
52TDESocketBuffer& TDESocketBuffer::operator=(const TDESocketBuffer& other)
53{
54 TQMutexLocker locker1(&m_mutex);
55 TQMutexLocker locker2(&other.m_mutex);
56
57 TDEIOBufferBase::operator=(other);
58
59 m_list = other.m_list; // copy-on-write
60 m_offset = other.m_offset;
61 m_size = other.m_size;
62 m_length = other.m_length;
63
64 return *this;
65}
66
67bool TDESocketBuffer::canReadLine() const
68{
69 TQMutexLocker locker(&m_mutex);
70
71 TQValueListConstIterator<TQByteArray> it = m_list.constBegin(),
72 end = m_list.constEnd();
73 TQIODevice::Offset offset = m_offset;
74
75 // walk the buffer
76 for ( ; it != end; ++it)
77 {
78 if ((*it).find('\n', offset) != -1)
79 return true;
80 if ((*it).find('\r', offset) != -1)
81 return true;
82 offset = 0;
83 }
84
85 return false; // not found
86}
87
88TQCString TDESocketBuffer::readLine()
89{
90 if (!canReadLine())
91 return TQCString(); // empty
92
93 TQMutexLocker locker(&m_mutex);
94
95 // find the offset of the newline in the buffer
96 int newline = 0;
97 TQValueListConstIterator<TQByteArray> it = m_list.constBegin(),
98 end = m_list.constEnd();
99 TQIODevice::Offset offset = m_offset;
100
101 // walk the buffer
102 for ( ; it != end; ++it)
103 {
104 int posnl = (*it).find('\n', offset);
105 if (posnl == -1)
106 {
107 // not found in this one
108 newline += (*it).size();
109 offset = 0;
110 continue;
111 }
112
113 // we found it
114 newline += posnl;
115 break;
116 }
117
118 TQCString result(newline + 2 - m_offset);
119 consumeBuffer(result.data(), newline + 1 - m_offset);
120 return result;
121}
122
123TQ_LONG TDESocketBuffer::length() const
124{
125 return m_length;
126}
127
128TQ_LONG TDESocketBuffer::size() const
129{
130 return m_size;
131}
132
133bool TDESocketBuffer::setSize(TQ_LONG 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 TQMutexLocker 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
150TQ_LONG TDESocketBuffer::feedBuffer(const char *data, TQ_LONG 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 TQMutexLocker 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 TQByteArray a(len);
164 a.duplicate(data, len);
165 m_list.append(a);
166
167 m_length += len;
168 return len;
169}
170
171TQ_LONG TDESocketBuffer::consumeBuffer(char *destbuffer, TQ_LONG maxlen, bool discard)
172{
173 if (maxlen == 0 || isEmpty())
174 return 0;
175
176 TQValueListIterator<TQByteArray> it = m_list.begin(),
177 end = m_list.end();
178 TQIODevice::Offset offset = m_offset;
179 TQ_LONG copied = 0;
180
181 // walk the buffer
182 while (it != end && maxlen)
183 {
184 // calculate how much we'll copy
185 size_t to_copy = (*it).size() - offset;
186 if (to_copy > (size_t)maxlen)
187 to_copy = maxlen;
188
189 // do the copying
190 if (destbuffer)
191 memcpy(destbuffer + copied, (*it).data() + offset, to_copy);
192 maxlen -= to_copy;
193 copied += to_copy;
194
195 if ((*it).size() - offset > to_copy)
196 {
197 // we did not copy everything
198 offset += to_copy;
199 break;
200 }
201 else
202 {
203 // we copied everything
204 // discard this element;
205 offset = 0;
206 if (discard)
207 it = m_list.remove(it);
208 else
209 ++it;
210 }
211 }
212
213 if (discard)
214 {
215 m_offset = offset;
216 m_length -= copied;
217 assert(m_length >= 0);
218 }
219
220 return copied;
221}
222
223void TDESocketBuffer::clear()
224{
225 TQMutexLocker locker(&m_mutex);
226 m_list.clear();
227 m_offset = 0;
228 m_length = 0;
229}
230
231TQ_LONG TDESocketBuffer::sendTo(KActiveSocketBase* dev, TQ_LONG len)
232{
233 if (len == 0 || isEmpty())
234 return 0;
235
236 TQMutexLocker locker(&m_mutex);
237
238 TQValueListIterator<TQByteArray> it = m_list.begin(),
239 end = m_list.end();
240 TQIODevice::Offset offset = m_offset;
241 TQ_LONG written = 0;
242
243 // walk the buffer
244 while (it != end && (len || len == -1))
245 {
246 // we have to write each element up to len bytes
247 // but since we can have several very small buffers, we can make things
248 // better by concatenating a few of them into a big buffer
249 // question is: how big should that buffer be? 2 kB should be enough
250
251 TQ_ULONG bufsize = 1460;
252 if ((len != -1) && ((TQ_ULONG)len < bufsize)) {
253 bufsize = len;
254 }
255 TQByteArray buf(bufsize);
256 TQ_LONG count = 0;
257
258 while (it != end && count + ((*it).size() - offset) <= bufsize)
259 {
260 memcpy(buf.data() + count, (*it).data() + offset, (*it).size() - offset);
261 count += (*it).size() - offset;
262 offset = 0;
263 ++it;
264 }
265
266 // see if we can still fit more
267 if ((TQ_ULONG)count < bufsize && it != end)
268 {
269 // getting here means this buffer (*it) is larger than
270 // (bufsize - count) (even for count == 0).
271 memcpy(buf.data() + count, (*it).data() + offset, bufsize - count);
272 offset += bufsize - count;
273 count = bufsize;
274 }
275
276 // now try to write those bytes
277 TQ_LONG wrote = dev->writeBlock(buf, count);
278
279 if (wrote == -1)
280 // error?
281 break;
282
283 written += wrote;
284 if (wrote != count)
285 // can't fit more?
286 break;
287 }
288
289 // discard data that has been written
290 // this updates m_length too
291 if (written)
292 consumeBuffer(0L, written);
293
294 return written;
295}
296
297TQ_LONG TDESocketBuffer::receiveFrom(KActiveSocketBase* dev, TQ_LONG len)
298{
299 if (len == 0 || isFull())
300 return 0;
301
302 TQMutexLocker locker(&m_mutex);
303
304 if (len == -1)
305 len = dev->bytesAvailable();
306 if (len <= 0)
307 // error or closing socket
308 return len;
309
310 // see if we can read that much
311 if (m_size != -1 && len > (m_size - m_length))
312 len = m_size - m_length;
313
314 // here, len contains just as many bytes as we're supposed to read
315
316 // now do the reading
317 TQByteArray a(len);
318 len = dev->readBlock(a.data(), len);
319
320 if (len == -1)
321 // error?
322 return -1;
323
324 // success
325 // resize the buffer and add it
326 a.truncate(len);
327 m_list.append(a);
328 m_length += len;
329 return len;
330}
KNetwork::KActiveSocketBase
Abstract class for active sockets.
Definition: tdesocketbase.h:444
KNetwork::KActiveSocketBase::bytesAvailable
virtual TQ_LONG bytesAvailable() const =0
Returns the number of bytes available for reading without blocking.
KNetwork::KActiveSocketBase::readBlock
virtual TQ_LONG readBlock(char *data, TQ_ULONG len)=0
Reads data from the socket.
KNetwork::KActiveSocketBase::writeBlock
virtual TQ_LONG writeBlock(const char *data, TQ_ULONG len)=0
Writes the given data to the socket.
TDEIOBufferBase
base for I/O buffer implementation
Definition: tdeiobuffer.h:46
TDEIOBufferBase::operator=
TDEIOBufferBase & operator=(const TDEIOBufferBase &)
Assignment operator.
Definition: tdeiobuffer.h:69
KNetwork
A namespace to store all networking-related (socket) classes.
Definition: kbufferedsocket.h:36
TDEStdAccel::end
const TDEShortcut & end()
Goto end of the document.
Definition: tdestdaccel.cpp:289

tdecore

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

tdecore

Skip menu "tdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.9.4
This website is maintained by Timothy Pearson.