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

KDECore

k3socketbuffer.cpp

Go to the documentation of this file.
00001 /*  -*- C++ -*-
00002  *  Copyright (C) 2003 Thiago Macieira <thiago@kde.org>
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 "k3socketbuffer_p.h"
00026 
00027 #include <config.h>
00028 #include <config-network.h>
00029 
00030 #include <assert.h>
00031 #include <string.h>
00032 
00033 #include <QMutableListIterator>
00034 
00035 #include "k3socketbase.h"
00036 
00037 using namespace KNetwork;
00038 using namespace KNetwork::Internal;
00039 
00040 KSocketBuffer::KSocketBuffer(qint64 size)
00041   : m_mutex(QMutex::Recursive), m_offset(0), m_size(size), m_length(0)
00042 {
00043 }
00044 
00045 KSocketBuffer::KSocketBuffer(const KSocketBuffer& other)
00046   : m_mutex(QMutex::Recursive)
00047 {
00048   *this = other;
00049 }
00050 
00051 KSocketBuffer::~KSocketBuffer()
00052 {
00053   // QValueList takes care of deallocating memory
00054 }
00055 
00056 KSocketBuffer& KSocketBuffer::operator=(const KSocketBuffer& other)
00057 {
00058   QMutexLocker locker1(&m_mutex);
00059   QMutexLocker locker2(&other.m_mutex);
00060 
00061   m_list = other.m_list;    // copy-on-write
00062   m_offset = other.m_offset;
00063   m_size = other.m_size;
00064   m_length = other.m_length;
00065 
00066   return *this;
00067 }
00068 
00069 bool KSocketBuffer::canReadLine() const
00070 {
00071   QMutexLocker locker(&m_mutex);
00072 
00073   qint64 offset = m_offset;
00074 
00075   // walk the buffer
00076   for (int i = 0; i < m_list.size(); ++i)
00077     {
00078       if (m_list.at(i).indexOf('\n', offset) != -1)
00079     return true;
00080       if (m_list.at(i).indexOf('\r', offset) != -1)
00081     return true;
00082       offset = 0;
00083     }
00084 
00085   return false;         // not found
00086 }
00087 
00088 qint64 KSocketBuffer::readLine(char* data, qint64 maxSize)
00089 {
00090   if (!canReadLine())
00091     return qint64(-1);      // empty
00092 
00093   QMutexLocker locker(&m_mutex);
00094 
00095   // find the offset of the newline in the buffer
00096   qint64 newline = 0;
00097   qint64 offset = m_offset;
00098 
00099   // walk the buffer
00100   for (int i = 0; i < m_list.size(); ++i)
00101     {
00102       int posnl = m_list.at(i).indexOf('\n', offset);
00103       if (posnl == -1)
00104     {
00105       // not found in this one
00106       newline += m_list.at(i).size();
00107       offset = 0;
00108       continue;
00109     }
00110 
00111       // we found it
00112       newline += posnl;
00113       break;
00114     }
00115 
00116   qint64 bytesToRead = newline + 1 - m_offset;
00117   if (bytesToRead > maxSize)
00118     bytesToRead = maxSize;      // don't read more than maxSize
00119 
00120   return consumeBuffer(data, bytesToRead);
00121 }
00122 
00123 qint64 KSocketBuffer::length() const
00124 {
00125   return m_length;
00126 }
00127 
00128 qint64 KSocketBuffer::size() const
00129 {
00130   return m_size;
00131 }
00132 
00133 bool KSocketBuffer::setSize(qint64 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 qint64 KSocketBuffer::feedBuffer(const char *data, qint64 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(data, len);
00164   m_list.append(a);
00165 
00166   m_length += len;
00167   return len;
00168 }
00169 
00170 qint64 KSocketBuffer::consumeBuffer(char *destbuffer, qint64 maxlen, bool discard)
00171 {
00172   if (maxlen == 0 || isEmpty())
00173     return 0;
00174 
00175   QMutableListIterator<QByteArray> it(m_list);
00176   qint64 offset = m_offset;
00177   qint64 copied = 0;
00178 
00179   // walk the buffer
00180   while (it.hasNext() && maxlen)
00181     {
00182       QByteArray& item = it.next();
00183       // calculate how much we'll copy
00184       size_t to_copy = item.size() - offset;
00185       if (to_copy > maxlen)
00186     to_copy = maxlen;
00187 
00188       // do the copying
00189       if (destbuffer)
00190     memcpy(destbuffer + copied, item.data() + offset, to_copy);
00191       maxlen -= to_copy;
00192       copied += to_copy;
00193 
00194       if (item.size() - offset > to_copy)
00195     {
00196       // we did not copy everything
00197       offset += to_copy;
00198       break;
00199     }
00200       else
00201     {
00202       // we copied everything
00203       // discard this element;
00204       offset = 0;
00205       if (discard)
00206         it.remove();
00207     }
00208     }
00209 
00210   if (discard)
00211     {
00212       m_offset = offset;
00213       m_length -= copied;
00214       assert(m_length >= 0);
00215     }
00216 
00217   return copied;
00218 }
00219 
00220 void KSocketBuffer::clear()
00221 {
00222   QMutexLocker locker(&m_mutex);
00223   m_list.clear();
00224   m_offset = 0;
00225   m_length = 0;
00226 }
00227 
00228 qint64 KSocketBuffer::sendTo(KActiveSocketBase* dev, qint64 len)
00229 {
00230   if (len == 0 || isEmpty())
00231     return 0;
00232 
00233   QMutexLocker locker(&m_mutex);
00234 
00235   QMutableListIterator<QByteArray> it(m_list);
00236   qint64 offset = m_offset;
00237   qint64 written = 0;
00238 
00239   // walk the buffer
00240   while (it.hasNext() && (len || len == -1))
00241     {
00242       // we have to write each element up to len bytes
00243       // but since we can have several very small buffers, we can make things
00244       // better by concatenating a few of them into a big buffer
00245       // question is: how big should that buffer be? 2 kB should be enough
00246 
00247       uint bufsize = 1460;
00248       if (len != -1 && len < bufsize)
00249     bufsize = len;
00250       QByteArray buf(bufsize, '\0');
00251       qint64 count = 0;
00252 
00253       while (it.hasNext() && count + (it.peekNext().size() - offset) <= bufsize)
00254     {
00255       QByteArray& item = it.next();
00256       memcpy(buf.data() + count, item.data() + offset, item.size() - offset);
00257       count += item.size() - offset;
00258       offset = 0;
00259     }
00260 
00261       // see if we can still fit more
00262       if (count < bufsize && it.hasNext())
00263     {
00264       // getting here means this buffer (peekNext) is larger than
00265       // (bufsize - count) (even for count == 0).
00266       QByteArray& item = it.next();
00267       memcpy(buf.data() + count, item.data() + offset, bufsize - count);
00268       offset += bufsize - count;
00269       count = bufsize;
00270     }
00271 
00272       // now try to write those bytes
00273       qint64 wrote = dev->write(buf, count);
00274 
00275       if (wrote == -1)
00276     // error?
00277     break;
00278 
00279       written += wrote;
00280       if (wrote != count)
00281     // can't fit more?
00282     break;
00283     }
00284 
00285   // discard data that has been written
00286   // this updates m_length too
00287   if (written)
00288     consumeBuffer(0L, written);
00289 
00290   return written;
00291 }
00292 
00293 qint64 KSocketBuffer::receiveFrom(KActiveSocketBase* dev, qint64 len)
00294 {
00295   if (len == 0 || isFull())
00296     return 0;
00297 
00298   QMutexLocker locker(&m_mutex);
00299 
00300   if (len == -1)
00301     len = dev->bytesAvailable();
00302   if (len <= 0)
00303     // error or closing socket
00304     return len;
00305 
00306   // see if we can read that much
00307   if (m_size != -1 && len > (m_size - m_length))
00308     len = m_size - m_length;
00309 
00310   // here, len contains just as many bytes as we're supposed to read
00311 
00312   // now do the reading
00313   QByteArray a(len, '\0');
00314   len = dev->read(a.data(), len);
00315 
00316   if (len == -1)
00317     // error?
00318     return -1;
00319 
00320   // success
00321   // resize the buffer and add it
00322   a.truncate(len);
00323   m_list.append(a);
00324   m_length += len;
00325   return len;
00326 }

KDECore

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
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