• 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 
33 using namespace KNetwork;
34 using namespace KNetwork::Internal;
35 
36 TDESocketBuffer::TDESocketBuffer(TQ_LONG size)
37  : m_mutex(true), m_offset(0), m_size(size), m_length(0)
38 {
39 }
40 
41 TDESocketBuffer::TDESocketBuffer(const TDESocketBuffer& other)
42  : TDEIOBufferBase(other), m_mutex(true)
43 {
44  *this = other;
45 }
46 
47 TDESocketBuffer::~TDESocketBuffer()
48 {
49  // TQValueList takes care of deallocating memory
50 }
51 
52 TDESocketBuffer& 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 
67 bool 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 
88 TQCString 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 
123 TQ_LONG TDESocketBuffer::length() const
124 {
125  return m_length;
126 }
127 
128 TQ_LONG TDESocketBuffer::size() const
129 {
130  return m_size;
131 }
132 
133 bool 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 
150 TQ_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 
171 TQ_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 
223 void TDESocketBuffer::clear()
224 {
225  TQMutexLocker locker(&m_mutex);
226  m_list.clear();
227  m_offset = 0;
228  m_length = 0;
229 }
230 
231 TQ_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 
297 TQ_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.1
This website is maintained by Timothy Pearson.