| # kdecore Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# ksocketbuffer.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 "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 }

This file is part of the documentation for kdecore Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:18:11 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003