KDECore
ksocketbuffer.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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;
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
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;
00086 }
00087
00088 QCString KSocketBuffer::readLine()
00089 {
00090 if (!canReadLine())
00091 return QCString();
00092
00093 QMutexLocker locker(&m_mutex);
00094
00095
00096 int newline = 0;
00097 QValueListConstIterator<QByteArray> it = m_list.constBegin(),
00098 end = m_list.constEnd();
00099 QIODevice::Offset offset = m_offset;
00100
00101
00102 for ( ; it != end; ++it)
00103 {
00104 int posnl = (*it).find('\n', offset);
00105 if (posnl == -1)
00106 {
00107
00108 newline += (*it).size();
00109 offset = 0;
00110 continue;
00111 }
00112
00113
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
00140 QMutexLocker locker(&m_mutex);
00141
00142
00143 if (m_length < m_size)
00144 return true;
00145
00146
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;
00154 if (isFull())
00155 return -1;
00156
00157 QMutexLocker locker(&m_mutex);
00158
00159
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
00182 while (it != end && maxlen)
00183 {
00184
00185 size_t to_copy = (*it).size() - offset;
00186 if (to_copy > maxlen)
00187 to_copy = maxlen;
00188
00189
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
00198 offset += to_copy;
00199 break;
00200 }
00201 else
00202 {
00203
00204
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
00244 while (it != end && (len || len == -1))
00245 {
00246
00247
00248
00249
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
00266 if (count < bufsize && it != end)
00267 {
00268
00269
00270 memcpy(buf.data() + count, (*it).data() + offset, bufsize - count);
00271 offset += bufsize - count;
00272 count = bufsize;
00273 }
00274
00275
00276 Q_LONG wrote = dev->writeBlock(buf, count);
00277
00278 if (wrote == -1)
00279
00280 break;
00281
00282 written += wrote;
00283 if (wrote != count)
00284
00285 break;
00286 }
00287
00288
00289
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
00307 return len;
00308
00309
00310 if (m_size != -1 && len > (m_size - m_length))
00311 len = m_size - m_length;
00312
00313
00314
00315
00316 QByteArray a(len);
00317 len = dev->readBlock(a.data(), len);
00318
00319 if (len == -1)
00320
00321 return -1;
00322
00323
00324
00325 a.truncate(len);
00326 m_list.append(a);
00327 m_length += len;
00328 return len;
00329 }