Remove "endl;" not necessary now
[kdenetwork.git] / kopete / protocols / oscar / liboscar / buffer.cpp
blob1fdb31606f098f88c56edb420f3cf66aeec7711a
1 /***************************************************************************
2 buffer.cpp - description
3 -------------------
4 begin : Thu Jun 6 2002
6 Copyright (c) 2002 by Tom Linsky <twl6@po.cwru.edu>
7 Copyright (c) 2004,2005 by Matt Rogers <mattr@kde.org>
8 Kopete (c) 2002-2005 by the Kopete developers <kopete-devel@kde.org>
10 *************************************************************************
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 *************************************************************************
20 #include "buffer.h"
22 #include <ctype.h>
23 #include <kdebug.h>
26 Buffer::Buffer()
28 mReadPos=0;
31 Buffer::Buffer( const Buffer& other )
33 mBuffer = other.mBuffer;
34 mReadPos = other.mReadPos;
35 mBlockStack = other.mBlockStack;
38 Buffer::Buffer(const char *b, int len)
40 mBuffer = QByteArray::fromRawData( b, len );
41 mReadPos = 0;
44 Buffer::Buffer( const QByteArray& data )
46 mBuffer = data;
47 mReadPos = 0;
51 Buffer::~Buffer()
56 int Buffer::addByte(Oscar::BYTE b)
58 expandBuffer(1);
59 mBuffer[mBuffer.size()-1] = b;
61 return mBuffer.size();
64 int Buffer::addLEByte(Oscar::BYTE b)
66 expandBuffer(1);
67 mBuffer[mBuffer.size()-1] = ((b) & 0xff);
69 return mBuffer.size();
73 int Buffer::addWord(Oscar::WORD w)
75 expandBuffer(2);
76 mBuffer[mBuffer.size()-2] = ((w & 0xff00) >> 8);
77 mBuffer[mBuffer.size()-1] = (w & 0x00ff);
79 return mBuffer.size();
82 int Buffer::addLEWord(Oscar::WORD w)
84 expandBuffer(2);
85 mBuffer[mBuffer.size()-2] = (unsigned char) ((w >> 0) & 0xff);
86 mBuffer[mBuffer.size()-1] = (unsigned char) ((w >> 8) & 0xff);
88 return mBuffer.size();
92 int Buffer::addDWord(Oscar::DWORD dw)
94 expandBuffer(4);
95 mBuffer[mBuffer.size()-4] = (dw & 0xff000000) >> 24;
96 mBuffer[mBuffer.size()-3] = (dw & 0x00ff0000) >> 16;
97 mBuffer[mBuffer.size()-2] = (dw & 0x0000ff00) >> 8;
98 mBuffer[mBuffer.size()-1] = (dw & 0x000000ff);
100 return mBuffer.size();
103 int Buffer::addLEDWord(Oscar::DWORD dw)
105 expandBuffer(4);
106 mBuffer[mBuffer.size()-4] = (unsigned char) ((dw >> 0) & 0xff);
107 mBuffer[mBuffer.size()-3] = (unsigned char) ((dw >> 8) & 0xff);
108 mBuffer[mBuffer.size()-2] = (unsigned char) ((dw >> 16) & 0xff);
109 mBuffer[mBuffer.size()-1] = (unsigned char) ((dw >> 24) & 0xff);
111 return mBuffer.size();
114 int Buffer::addString( const QByteArray& s )
116 mBuffer.append( s );
117 return mBuffer.size();
120 int Buffer::addString(QByteArray s, Oscar::DWORD len)
122 Q_UNUSED( len );
123 return addString( s );
126 int Buffer::addString( const char* s, Oscar::DWORD len )
128 QByteArray qba( s, len );
129 return addString( qba );
132 int Buffer::addString(const unsigned char* s, Oscar::DWORD len)
134 QByteArray qba( (const char*) s, len );
135 return addString( qba );
138 int Buffer::addLEString(const char *s, Oscar::DWORD len)
140 unsigned int pos = mBuffer.size();
141 expandBuffer(len);
142 //concatenate the new string onto the buffer
143 for(unsigned int i=0; i<len; i++)
145 mBuffer[pos+i]=((s[i]) & 0xff);
147 return mBuffer.size();
151 void Buffer::clear()
153 mBuffer.truncate( 0 );
154 mReadPos=0;
157 int Buffer::addTLV( const TLV& t )
159 return addTLV( t.type, t.data );
162 int Buffer::addTLV( Oscar::WORD type, const QByteArray& data )
164 addWord( type );
165 addWord( data.length() );
166 return addString( data );
169 int Buffer::addLETLV( Oscar::WORD type, const QByteArray& data )
171 addLEWord( type );
172 addLEWord( data.length() );
173 return addString( data );
176 Oscar::BYTE Buffer::getByte()
178 Oscar::BYTE thebyte = 0x00;
180 if(mReadPos < mBuffer.size())
182 thebyte = mBuffer[mReadPos];
183 mReadPos++;
185 else
186 kDebug(14150) << "Buffer::getByte(): mBuffer empty";
188 return thebyte;
191 void Buffer::skipBytes( int bytesToSkip )
193 if (mReadPos < mBuffer.size())
194 mReadPos += bytesToSkip;
197 Oscar::BYTE Buffer::getLEByte()
199 Oscar::BYTE b = getByte();
200 return (b & 0xff);
203 Oscar::WORD Buffer::getWord()
205 Oscar::WORD theword, theword2, retword;
206 theword = getByte();
207 theword2 = getByte();
208 retword = (theword << 8) | theword2;
209 return retword;
212 Oscar::WORD Buffer::getLEWord()
214 Oscar::WORD theword1, theword2, retword;
215 theword1 = getLEByte();
216 theword2 = getLEByte();
217 retword = (theword2 << 8) | theword1;
218 return retword;
221 Oscar::DWORD Buffer::getDWord()
223 Oscar::DWORD word1, word2;
224 Oscar::DWORD retdword;
225 word1 = getWord();
226 word2 = getWord();
227 retdword = (word1 << 16) | word2;
228 return retdword;
231 Oscar::DWORD Buffer::getLEDWord()
233 Oscar::DWORD word1, word2, retdword;
234 word1 = getLEWord();
235 word2 = getLEWord();
236 retdword = (word2 << 16) | word1;
237 return retdword;
240 void Buffer::setBuf(char *b, Oscar::WORD len)
242 mBuffer = QByteArray::fromRawData(b, len);
243 mReadPos = 0;
246 QByteArray Buffer::getBlock(Oscar::DWORD len)
248 if ( len > (Oscar::DWORD)(mBuffer.size() - mReadPos) )
250 kDebug(14150) << "Buffer::getBlock(DWORD): mBuffer underflow!!!";
251 len = mBuffer.size() - mReadPos;
254 QByteArray ch;
255 ch.resize( len );
257 for ( Oscar::DWORD i = 0; i < len; i++ )
259 ch[i] = getByte();
262 return ch;
265 QByteArray Buffer::getBBlock(Oscar::WORD len)
267 QByteArray data = QByteArray::fromRawData( mBuffer.data() + mReadPos, len);
268 mReadPos += len;
269 return data;
273 Oscar::WORD *Buffer::getWordBlock(Oscar::WORD len)
275 kDebug(14150) << "of length " << len;
276 Oscar::WORD *ch=new Oscar::WORD[len+1];
277 for (unsigned int i=0; i<len; i++)
279 ch[i]=getWord();
281 ch[len]=0;
282 return ch;
286 QByteArray Buffer::getLEBlock(Oscar::WORD len)
288 QByteArray ch;
289 for (unsigned int i=0;i<len;i++)
290 ch += getLEByte();
292 return ch;
295 int Buffer::addTLV32(Oscar::WORD type, Oscar::DWORD data)
297 addWord(type);
298 addWord(0x0004); //4 Oscar::BYTEs long
299 return addDWord(data);
302 int Buffer::addLETLV32(Oscar::WORD type, Oscar::DWORD data)
304 addLEWord(type);
305 addLEWord(0x0004); //4 Oscar::BYTEs long
306 return addLEDWord(data);
309 int Buffer::addTLV16(Oscar::WORD type, Oscar::WORD data)
311 addWord(type);
312 addWord(0x0002); //2 Oscar::BYTEs long
313 return addWord(data);
316 int Buffer::addLETLV16(Oscar::WORD type, Oscar::WORD data)
318 addLEWord(type);
319 addLEWord(0x0002); //2 Oscar::BYTEs long
320 return addLEWord(data);
323 int Buffer::addTLV8(Oscar::WORD type, Oscar::BYTE data)
325 addWord(type);
326 addWord(0x0001); //1 Oscar::BYTE long
327 return addByte(data);
330 int Buffer::addLETLV8(Oscar::WORD type, Oscar::BYTE data)
332 addLEWord(type);
333 addLEWord(0x0001); //1 Oscar::BYTE long
334 return addLEByte(data);
337 TLV Buffer::getTLV()
339 TLV t;
340 if(bytesAvailable() >= 4)
342 t.type = getWord();
343 t.length = getWord();
344 if ( t )
345 t.data = getBlock( t.length );
346 /*else
347 kDebug(OSCAR_RAW_DEBUG) << "Invalid TLV in buffer";*/
350 //kDebug(OSCAR_RAW_DEBUG) << "TLV data is " << t.data;
351 return t;
354 QList<TLV> Buffer::getTLVList()
356 QList<TLV> ql;
358 while (mReadPos < mBuffer.size())
360 TLV t;
362 t = getTLV();
363 if ( !t )
365 kDebug(14150) << "Invalid TLV found";
366 continue;
369 //kDebug(14150) << "got TLV(" << t.type << ")";
370 ql.append(t);
373 return ql;
376 int Buffer::addChatTLV(Oscar::WORD type, Oscar::WORD exchange,
377 const QString &roomname, Oscar::WORD instance)
379 addWord(type);
380 addWord(0x0005 + roomname.length());
381 addWord(exchange);
382 addByte(roomname.length());
383 addString(roomname.toLatin1()); // TODO: check encoding
385 return addWord(instance);
388 void Buffer::expandBuffer(unsigned int inc)
390 mBuffer.resize(mBuffer.size()+inc);
393 QByteArray Buffer::getLNTS()
395 Oscar::WORD len = getWord();
396 QByteArray qcs;
397 if ( len > 0 )
399 qcs = getBlock(len - 1);
400 skipBytes( 1 );
403 return qcs;
406 QByteArray Buffer::getLELNTS()
408 Oscar::WORD len = getLEWord();
409 QByteArray qcs;
410 if ( len > 0 )
412 qcs = getBlock(len - 1);
413 skipBytes( 1 );
416 return qcs;
419 int Buffer::addLNTS(const char *s)
421 unsigned int len = strlen(s);
423 addLEWord(len+1);
424 if(len > 0)
425 addString(s, len);
426 int ret = addByte(0x00);
427 return ret;
430 int Buffer::addLELNTS(const char *s)
432 unsigned int len = strlen(s);
433 int ret = addLEWord(len+1);
434 if(len > 0)
435 ret = addLEString(s, len);
436 ret = addByte(0x00);
437 return ret;
440 int Buffer::addBSTR(const char * s)
442 unsigned int len = strlen(s);
443 int ret = addWord(len);
444 if(len > 0)
445 ret = addString(s, len);
446 return ret;
449 QByteArray Buffer::getBSTR()
451 Oscar::WORD len = getWord();
452 QByteArray qba( getBlock(len) );
453 return qba;
456 int Buffer::addBUIN(const char * s)
458 unsigned int len = strlen(s);
459 int ret = addByte(len);
460 ret = addString(s, len);
461 return ret;
464 QByteArray Buffer::getBUIN()
466 Oscar::BYTE len = getByte();
467 QByteArray qba( getBlock(len) );
468 return qba;
471 QByteArray Buffer::buffer() const
473 return mBuffer;
476 int Buffer::length() const
478 return mBuffer.size();
481 int Buffer::bytesAvailable() const
483 return (mBuffer.size() - mReadPos);
488 QString Buffer::toString() const
490 // line format:
491 //00 03 00 0b 00 00 90 b8 f5 9f 09 31 31 33 37 38 |;tJ�..........|
493 int i = 0;
494 QString output = "\n";
495 QString hex, ascii;
497 QByteArray::ConstIterator it;
498 for ( it = mBuffer.begin(); it != mBuffer.end(); ++it )
500 i++;
502 unsigned char c = static_cast<unsigned char>(*it);
504 if ( c < 0x10 )
505 hex.append("0");
506 hex.append(QString("%1 ").arg(c, 0, 16));
508 ascii.append(isprint(c) ? c : '.');
510 if (i == 16)
512 output += hex + " |" + ascii + "|\n";
513 i=0;
514 hex.clear();
515 ascii.clear();
519 if(!hex.isEmpty())
520 output += hex.leftJustified(48, ' ') + " |" + ascii.leftJustified(16, ' ') + '|';
521 output.append('\n');
523 return output;
526 QString Buffer::peekBSTR()
528 int lastPos = mReadPos;
529 QByteArray qba = getBSTR();
530 mReadPos = lastPos;
531 return QString( qba );
533 QString Buffer::peekBUIN()
535 int lastPos = mReadPos;
536 QByteArray qba = getBUIN();
537 mReadPos = lastPos;
538 return QString( qba );
542 int Buffer::addGuid( const Guid & g )
544 if (g.isValid())
545 return addString( g.data() );
546 return mBuffer.size();
550 Guid Buffer::getGuid()
552 return Guid(getBBlock(16)); //block or bblock?
555 int Buffer::addLEBlock( const QByteArray& block )
557 int ret = addLEWord( block.length() );
558 if ( block.length() > 0 )
559 ret = addString( block );
561 return ret;
564 QByteArray Buffer::getLEBlock()
566 Oscar::DWORD len = getLEWord();
567 return getBlock( len );
570 int Buffer::addLEDBlock( const QByteArray& block )
572 int ret = addLEDWord( block.length() );
573 if ( block.length() > 0 )
574 ret = addString( block );
576 return ret;
579 QByteArray Buffer::getLEDBlock()
581 Oscar::DWORD len = getLEDWord();
582 return getBlock( len );
585 void Buffer::startBlock( BlockType type, ByteOrder byteOrder )
587 Block block = { type, byteOrder, mBuffer.size() };
588 mBlockStack.push( block );
590 if ( type == BWord )
591 expandBuffer( 2 );
592 else if ( type == BDWord )
593 expandBuffer( 4 );
596 void Buffer::endBlock()
598 Q_ASSERT( mBlockStack.size() > 0 );
599 Block block = mBlockStack.pop();
601 int size = 0;
602 if ( block.type == BWord )
603 size = mBuffer.size() - block.pos - 2;
604 else if ( block.type == BDWord )
605 size = mBuffer.size() - block.pos - 4;
607 if ( block.byteOrder == BigEndian )
609 if ( block.type == BWord )
611 mBuffer[block.pos++] = (unsigned char) (size & 0x0000ff00) >> 8;
612 mBuffer[block.pos++] = (unsigned char) (size & 0x000000ff) >> 0;
614 else if ( block.type == BDWord )
616 mBuffer[block.pos++] = (unsigned char) (size & 0xff000000) >> 24;
617 mBuffer[block.pos++] = (unsigned char) (size & 0x00ff0000) >> 16;
618 mBuffer[block.pos++] = (unsigned char) (size & 0x0000ff00) >> 8;
619 mBuffer[block.pos++] = (unsigned char) (size & 0x000000ff) >> 0;
622 else
624 if ( block.type == BWord )
626 mBuffer[block.pos++] = (unsigned char) ((size >> 0) & 0xff);
627 mBuffer[block.pos++] = (unsigned char) ((size >> 8) & 0xff);
629 else if ( block.type == BDWord )
631 mBuffer[block.pos++] = (unsigned char) ((size >> 0) & 0xff);
632 mBuffer[block.pos++] = (unsigned char) ((size >> 8) & 0xff);
633 mBuffer[block.pos++] = (unsigned char) ((size >> 16) & 0xff);
634 mBuffer[block.pos++] = (unsigned char) ((size >> 24) & 0xff);
639 Buffer::operator QByteArray() const
641 return mBuffer;
643 //kate: tab-width 4; indent-mode csands;