• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KDECore

ksocketbuffer.cpp

Go to the documentation of this file.
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 "ksocketbase.h"
00031 #include "ksocketbuffer_p.h"
00032 
00033 using namespace KNetwork;
00034 using namespace KNetwork::Internal;
00035 
00036 KSocketBuffer::KSocketBuffer(Q_LONG size)
00037   : m_mutex(true), m_offset(0), m_size(size), m_length(0)
00038 {
00039 }
00040 
00041 KSocketBuffer::KSocketBuffer(const KSocketBuffer& other)
00042   : KIOBufferBase(other), m_mutex(true)
00043 {
00044   *this = other;
00045 }
00046 
00047 KSocketBuffer::~KSocketBuffer()
00048 {
00049   // QValueList takes care of deallocating memory
00050 }
00051 
00052 KSocketBuffer& KSocketBuffer::operator=(const KSocketBuffer& other)
00053 {
00054   QMutexLocker locker1(&m_mutex);
00055   QMutexLocker locker2(&other.m_mutex);
00056 
00057   KIOBufferBase::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 KSocketBuffer::canReadLine() const
00068 {
00069   QMutexLocker locker(&m_mutex);
00070 
00071   QValueListConstIterator<QByteArray> it = m_list.constBegin(),
00072     end = m_list.constEnd();
00073   QIODevice::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 QCString KSocketBuffer::readLine()
00089 {
00090   if (!canReadLine())
00091     return QCString();      // empty
00092 
00093   QMutexLocker locker(&m_mutex);
00094 
00095   // find the offset of the newline in the buffer
00096   int newline = 0;
00097   QValueListConstIterator<QByteArray> it = m_list.constBegin(),
00098     end = m_list.constEnd();
00099   QIODevice::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   QCString result(newline + 2 - m_offset);
00119   consumeBuffer(result.data(), newline + 1 - m_offset);
00120   return result;
00121 }
00122 
00123 Q_LONG KSocketBuffer::length() const
00124 {
00125   return m_length;
00126 }
00127 
00128 Q_LONG KSocketBuffer::size() const
00129 {
00130   return m_size;
00131 }
00132 
00133 bool KSocketBuffer::setSize(Q_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   QMutexLocker 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 Q_LONG KSocketBuffer::feedBuffer(const char *data, Q_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   QMutexLocker 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   QByteArray a(len);
00164   a.duplicate(data, len);
00165   m_list.append(a);
00166 
00167   m_length += len;
00168   return len;
00169 }
00170 
00171 Q_LONG KSocketBuffer::consumeBuffer(char *destbuffer, Q_LONG maxlen, bool discard)
00172 {
00173   if (maxlen == 0 || isEmpty())
00174     return 0;
00175 
00176   QValueListIterator<QByteArray> it = m_list.begin(),
00177     end = m_list.end();
00178   QIODevice::Offset offset = m_offset;
00179   Q_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 > 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 KSocketBuffer::clear()
00224 {
00225   QMutexLocker locker(&m_mutex);
00226   m_list.clear();
00227   m_offset = 0;
00228   m_length = 0;
00229 }
00230 
00231 Q_LONG KSocketBuffer::sendTo(KActiveSocketBase* dev, Q_LONG len)
00232 {
00233   if (len == 0 || isEmpty())
00234     return 0;
00235 
00236   QMutexLocker locker(&m_mutex);
00237   
00238   QValueListIterator<QByteArray> it = m_list.begin(),
00239     end = m_list.end();
00240   QIODevice::Offset offset = m_offset;
00241   Q_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       Q_ULONG bufsize = 1460;
00252       if (len != -1 && len < bufsize)
00253     bufsize = len;
00254       QByteArray buf(bufsize);
00255       Q_LONG count = 0;
00256 
00257       while (it != end && count + ((*it).size() - offset) <= bufsize)
00258     {
00259       memcpy(buf.data() + count, (*it).data() + offset, (*it).size() - offset);
00260       count += (*it).size() - offset;
00261       offset = 0;
00262       ++it;
00263     }
00264 
00265       // see if we can still fit more
00266       if (count < bufsize && it != end)
00267     {
00268       // getting here means this buffer (*it) is larger than
00269       // (bufsize - count) (even for count == 0).
00270       memcpy(buf.data() + count, (*it).data() + offset, bufsize - count);
00271       offset += bufsize - count;
00272       count = bufsize;
00273     }
00274 
00275       // now try to write those bytes
00276       Q_LONG wrote = dev->writeBlock(buf, count);
00277 
00278       if (wrote == -1)
00279     // error?
00280     break;
00281 
00282       written += wrote;
00283       if (wrote != count)
00284     // can't fit more?
00285     break;
00286     }
00287 
00288   // discard data that has been written
00289   // this updates m_length too
00290   if (written)
00291     consumeBuffer(0L, written);
00292 
00293   return written;
00294 }
00295 
00296 Q_LONG KSocketBuffer::receiveFrom(KActiveSocketBase* dev, Q_LONG len)
00297 {
00298   if (len == 0 || isFull())
00299     return 0;
00300 
00301   QMutexLocker locker(&m_mutex);
00302 
00303   if (len == -1)
00304     len = dev->bytesAvailable();
00305   if (len <= 0)
00306     // error or closing socket
00307     return len;
00308 
00309   // see if we can read that much
00310   if (m_size != -1 && len > (m_size - m_length))
00311     len = m_size - m_length;
00312 
00313   // here, len contains just as many bytes as we're supposed to read
00314 
00315   // now do the reading
00316   QByteArray a(len);
00317   len = dev->readBlock(a.data(), len);
00318 
00319   if (len == -1)
00320     // error?
00321     return -1;
00322 
00323   // success
00324   // resize the buffer and add it
00325   a.truncate(len);
00326   m_list.append(a);
00327   m_length += len;
00328   return len;
00329 }

KDECore

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

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal