KDECore
k3socketbuffer.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 "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
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;
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
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;
00086 }
00087
00088 qint64 KSocketBuffer::readLine(char* data, qint64 maxSize)
00089 {
00090 if (!canReadLine())
00091 return qint64(-1);
00092
00093 QMutexLocker locker(&m_mutex);
00094
00095
00096 qint64 newline = 0;
00097 qint64 offset = m_offset;
00098
00099
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
00106 newline += m_list.at(i).size();
00107 offset = 0;
00108 continue;
00109 }
00110
00111
00112 newline += posnl;
00113 break;
00114 }
00115
00116 qint64 bytesToRead = newline + 1 - m_offset;
00117 if (bytesToRead > maxSize)
00118 bytesToRead = 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
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 qint64 KSocketBuffer::feedBuffer(const char *data, qint64 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(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
00180 while (it.hasNext() && maxlen)
00181 {
00182 QByteArray& item = it.next();
00183
00184 size_t to_copy = item.size() - offset;
00185 if (to_copy > maxlen)
00186 to_copy = maxlen;
00187
00188
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
00197 offset += to_copy;
00198 break;
00199 }
00200 else
00201 {
00202
00203
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
00240 while (it.hasNext() && (len || len == -1))
00241 {
00242
00243
00244
00245
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
00262 if (count < bufsize && it.hasNext())
00263 {
00264
00265
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
00273 qint64 wrote = dev->write(buf, count);
00274
00275 if (wrote == -1)
00276
00277 break;
00278
00279 written += wrote;
00280 if (wrote != count)
00281
00282 break;
00283 }
00284
00285
00286
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
00304 return len;
00305
00306
00307 if (m_size != -1 && len > (m_size - m_length))
00308 len = m_size - m_length;
00309
00310
00311
00312
00313 QByteArray a(len, '\0');
00314 len = dev->read(a.data(), len);
00315
00316 if (len == -1)
00317
00318 return -1;
00319
00320
00321
00322 a.truncate(len);
00323 m_list.append(a);
00324 m_length += len;
00325 return len;
00326 }