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

tdecore

tdesocketbuffer.cpp

00001 /*  -*- C++ -*-
00002  *  Copyright (C) 2003 Thiago Macieira <thiago.macieira@kdemail.net>
00003  *
00004  *
00005  *  Permission is hereby granted, free of charge, to any person obtaining
00006  *  a copy of this software and associated documentation files (the
00007  *  "Software"), to deal in the Software without restriction, including
00008  *  without limitation the rights to use, copy, modify, merge, publish,
00009  *  distribute, sublicense, and/or sell copies of the Software, and to
00010  *  permit persons to whom the Software is furnished to do so, subject to
00011  *  the following conditions:
00012  *
00013  *  The above copyright notice and this permission notice shall be included 
00014  *  in all copies or substantial portions of the Software.
00015  *
00016  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00017  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00018  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00019  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00020  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00021  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00022  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023  */
00024 
00025 #include <config.h>
00026 
00027 #include <assert.h>
00028 #include <string.h>
00029 
00030 #include "tdesocketbase.h"
00031 #include "tdesocketbuffer_p.h"
00032 
00033 using namespace KNetwork;
00034 using namespace KNetwork::Internal;
00035 
00036 TDESocketBuffer::TDESocketBuffer(TQ_LONG size)
00037   : m_mutex(true), m_offset(0), m_size(size), m_length(0)
00038 {
00039 }
00040 
00041 TDESocketBuffer::TDESocketBuffer(const TDESocketBuffer& other)
00042   : TDEIOBufferBase(other), m_mutex(true)
00043 {
00044   *this = other;
00045 }
00046 
00047 TDESocketBuffer::~TDESocketBuffer()
00048 {
00049   // TQValueList takes care of deallocating memory
00050 }
00051 
00052 TDESocketBuffer& TDESocketBuffer::operator=(const TDESocketBuffer& other)
00053 {
00054   TQMutexLocker locker1(&m_mutex);
00055   TQMutexLocker locker2(&other.m_mutex);
00056 
00057   TDEIOBufferBase::operator=(other);
00058 
00059   m_list = other.m_list;    // copy-on-write
00060   m_offset = other.m_offset;
00061   m_size = other.m_size;
00062   m_length = other.m_length;
00063 
00064   return *this;
00065 }
00066 
00067 bool TDESocketBuffer::canReadLine() const
00068 {
00069   TQMutexLocker locker(&m_mutex);
00070 
00071   TQValueListConstIterator<TQByteArray> it = m_list.constBegin(),
00072     end = m_list.constEnd();
00073   TQIODevice::Offset offset = m_offset;
00074 
00075   // walk the buffer
00076   for ( ; it != end; ++it)
00077     {
00078       if ((*it).find('\n', offset) != -1)
00079     return true;
00080       if ((*it).find('\r', offset) != -1)
00081     return true;
00082       offset = 0;
00083     }
00084 
00085   return false;         // not found
00086 }
00087 
00088 TQCString TDESocketBuffer::readLine()
00089 {
00090   if (!canReadLine())
00091     return TQCString();     // empty
00092 
00093   TQMutexLocker locker(&m_mutex);
00094 
00095   // find the offset of the newline in the buffer
00096   int newline = 0;
00097   TQValueListConstIterator<TQByteArray> it = m_list.constBegin(),
00098     end = m_list.constEnd();
00099   TQIODevice::Offset offset = m_offset;
00100 
00101   // walk the buffer
00102   for ( ; it != end; ++it)
00103     {
00104       int posnl = (*it).find('\n', offset);
00105       if (posnl == -1)
00106     {
00107       // not found in this one
00108       newline += (*it).size();
00109       offset = 0;
00110       continue;
00111     }
00112 
00113       // we found it
00114       newline += posnl;
00115       break;
00116     }
00117 
00118   TQCString result(newline + 2 - m_offset);
00119   consumeBuffer(result.data(), newline + 1 - m_offset);
00120   return result;
00121 }
00122 
00123 TQ_LONG TDESocketBuffer::length() const
00124 {
00125   return m_length;
00126 }
00127 
00128 TQ_LONG TDESocketBuffer::size() const
00129 {
00130   return m_size;
00131 }
00132 
00133 bool TDESocketBuffer::setSize(TQ_LONG size)
00134 {
00135   m_size = size;
00136   if (size == -1 || m_length < m_size)
00137     return true;
00138 
00139   // size is now smaller than length
00140   TQMutexLocker locker(&m_mutex);
00141 
00142   // repeat the test
00143   if (m_length < m_size)
00144     return true;
00145 
00146   // discard from the beginning
00147   return (m_length - m_size) == consumeBuffer(0L, m_length - m_size, true);
00148 }
00149 
00150 TQ_LONG TDESocketBuffer::feedBuffer(const char *data, TQ_LONG len)
00151 {
00152   if (data == 0L || len == 0)
00153     return 0;           // nothing to write
00154   if (isFull())
00155     return -1;          // can't write
00156 
00157   TQMutexLocker locker(&m_mutex);
00158 
00159   // verify if we can add len bytes
00160   if (m_size != -1 && (m_size - m_length) < len)
00161     len = m_size - m_length;
00162 
00163   TQByteArray a(len);
00164   a.duplicate(data, len);
00165   m_list.append(a);
00166 
00167   m_length += len;
00168   return len;
00169 }
00170 
00171 TQ_LONG TDESocketBuffer::consumeBuffer(char *destbuffer, TQ_LONG maxlen, bool discard)
00172 {
00173   if (maxlen == 0 || isEmpty())
00174     return 0;
00175 
00176   TQValueListIterator<TQByteArray> it = m_list.begin(),
00177     end = m_list.end();
00178   TQIODevice::Offset offset = m_offset;
00179   TQ_LONG copied = 0;
00180 
00181   // walk the buffer
00182   while (it != end && maxlen)
00183     {
00184       // calculate how much we'll copy
00185       size_t to_copy = (*it).size() - offset;
00186       if (to_copy > (size_t)maxlen)
00187     to_copy = maxlen;
00188 
00189       // do the copying
00190       if (destbuffer)
00191     memcpy(destbuffer + copied, (*it).data() + offset, to_copy);
00192       maxlen -= to_copy;
00193       copied += to_copy;
00194 
00195       if ((*it).size() - offset > to_copy)
00196     {
00197       // we did not copy everything
00198       offset += to_copy;
00199       break;
00200     }
00201       else
00202     {
00203       // we copied everything
00204       // discard this element;
00205       offset = 0;
00206       if (discard)
00207         it = m_list.remove(it);
00208       else
00209         ++it;
00210     }
00211     }
00212 
00213   if (discard)
00214     {
00215       m_offset = offset;
00216       m_length -= copied;
00217       assert(m_length >= 0);
00218     }
00219 
00220   return copied;
00221 }
00222 
00223 void TDESocketBuffer::clear()
00224 {
00225   TQMutexLocker locker(&m_mutex);
00226   m_list.clear();
00227   m_offset = 0;
00228   m_length = 0;
00229 }
00230 
00231 TQ_LONG TDESocketBuffer::sendTo(KActiveSocketBase* dev, TQ_LONG len)
00232 {
00233   if (len == 0 || isEmpty())
00234     return 0;
00235 
00236   TQMutexLocker locker(&m_mutex);
00237 
00238   TQValueListIterator<TQByteArray> it = m_list.begin(),
00239     end = m_list.end();
00240   TQIODevice::Offset offset = m_offset;
00241   TQ_LONG written = 0;
00242 
00243   // walk the buffer
00244   while (it != end && (len || len == -1))
00245     {
00246       // we have to write each element up to len bytes
00247       // but since we can have several very small buffers, we can make things
00248       // better by concatenating a few of them into a big buffer
00249       // question is: how big should that buffer be? 2 kB should be enough
00250 
00251       TQ_ULONG bufsize = 1460;
00252       if ((len != -1) && ((TQ_ULONG)len < bufsize)) {
00253     bufsize = len;
00254       }
00255       TQByteArray buf(bufsize);
00256       TQ_LONG count = 0;
00257 
00258       while (it != end && count + ((*it).size() - offset) <= bufsize)
00259     {
00260       memcpy(buf.data() + count, (*it).data() + offset, (*it).size() - offset);
00261       count += (*it).size() - offset;
00262       offset = 0;
00263       ++it;
00264     }
00265 
00266       // see if we can still fit more
00267       if ((TQ_ULONG)count < bufsize && it != end)
00268     {
00269       // getting here means this buffer (*it) is larger than
00270       // (bufsize - count) (even for count == 0).
00271       memcpy(buf.data() + count, (*it).data() + offset, bufsize - count);
00272       offset += bufsize - count;
00273       count = bufsize;
00274     }
00275 
00276       // now try to write those bytes
00277       TQ_LONG wrote = dev->tqwriteBlock(buf, count);
00278 
00279       if (wrote == -1)
00280     // error?
00281     break;
00282 
00283       written += wrote;
00284       if (wrote != count)
00285     // can't fit more?
00286     break;
00287     }
00288 
00289   // discard data that has been written
00290   // this updates m_length too
00291   if (written)
00292     consumeBuffer(0L, written);
00293 
00294   return written;
00295 }
00296 
00297 TQ_LONG TDESocketBuffer::receiveFrom(KActiveSocketBase* dev, TQ_LONG len)
00298 {
00299   if (len == 0 || isFull())
00300     return 0;
00301 
00302   TQMutexLocker locker(&m_mutex);
00303 
00304   if (len == -1)
00305     len = dev->bytesAvailable();
00306   if (len <= 0)
00307     // error or closing socket
00308     return len;
00309 
00310   // see if we can read that much
00311   if (m_size != -1 && len > (m_size - m_length))
00312     len = m_size - m_length;
00313 
00314   // here, len contains just as many bytes as we're supposed to read
00315 
00316   // now do the reading
00317   TQByteArray a(len);
00318   len = dev->tqreadBlock(a.data(), len);
00319 
00320   if (len == -1)
00321     // error?
00322     return -1;
00323 
00324   // success
00325   // resize the buffer and add it
00326   a.truncate(len);
00327   m_list.append(a);
00328   m_length += len;
00329   return len;
00330 }

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.6.3
This website is maintained by Timothy Pearson.