/*************************************************************************** buffer.cpp - description ------------------- begin : Sun Mar 10 2002 copyright : (C) 2002 by Vladimir Shutoff email : vovan@shutoff.ru ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include #ifdef WIN32 #include #else #include #endif #include #include "buffer.h" #include "event.h" #include "log.h" using namespace std; using namespace SIM; #ifdef WORDS_BIGENDIAN # define SWAP_S(s) s = ((s&0xFF)<<8) + ((s&0xFF00)>>8); # define SWAP_L(s) s = ((s&0xFF)<<24) + ((s&0xFF00)<<8) + ((s&0xFF0000)>>8) + ((s&0xFF000000)>>24); #else # define SWAP_S(s) # define SWAP_L(s) #endif // Buffer Buffer::Buffer(unsigned size) : QByteArray(size) { init(size); } Buffer::Buffer(const QByteArray &ba) : QByteArray(ba) { init(ba.size()); m_posWrite = ba.size(); } Buffer::Buffer(const QCString &cstr) : QByteArray(cstr.copy()) { uint len = cstr.length(); init(len); m_posWrite = len; } Buffer::~Buffer() { } void Buffer::init(unsigned size) { m_posRead = 0; m_posWrite = 0; m_packetStartPos = 0; m_startSection = 0; resize(size); } void Buffer::incReadPos(int n) { m_posRead += n; if (m_posRead > m_posWrite) m_posRead = m_posWrite; } bool Buffer::add(uint addSize) { return(resize(size()+addSize)); } bool Buffer::resize(uint size) { bool bRet = QByteArray::resize(size); if (m_posWrite > size) m_posWrite = size; if (m_posRead > size) m_posRead = size; return bRet; } void Buffer::setWritePos(unsigned n) { m_posWrite = n; if (m_posRead > m_posWrite) m_posRead = m_posWrite; if (m_posWrite > size()) resize(m_posWrite); } void Buffer::setReadPos(unsigned n) { if (n > m_posWrite) n = m_posWrite; m_posRead = n; } void Buffer::pack(const char *d, unsigned s) { if(s == 0) return; if(m_posWrite+s > size()) resize(m_posWrite+s); if(d) { memcpy(data() + m_posWrite, d, s); } else { memcpy(data() + m_posWrite, "", 1); } m_posWrite += s; } unsigned Buffer::unpack(char *d, unsigned s) { unsigned readn = size() - m_posRead; if (s < readn) readn = s; memcpy(d, data() + m_posRead, readn); m_posRead += readn; return readn; } Buffer &Buffer::operator << (char c) { pack(&c, 1); return *this; } Buffer &Buffer::operator << (const char *str) { if(!str) return *this; pack(str, strlen(str)); return *this; } Buffer &Buffer::operator << (unsigned short c) { c = htons(c); pack((char*)&c, 2); return *this; } Buffer &Buffer::operator << (long c) { /* XXX: * WARNING! BUG HERE. sizeof(long) is not 4 on 64bit platform */ c = htonl(c); pack((char*)&c, 4); return *this; } Buffer &Buffer::operator >> (char &c) { if (unpack(&c, 1) != 1) c = 0; return *this; } Buffer &Buffer::operator >> (unsigned short &c) { if (unpack((char*)&c, 2) != 2) c = 0; c = ntohs(c); return *this; } Buffer &Buffer::operator >> (long &c) { /* XXX: * WARNING! BUG HERE. sizeof(long) is not 4 on 64bit platform */ if (unpack((char*)&c, 4) != 4) c = 0; c = ntohl(c); return *this; } bool Buffer::scan(const char *substr, QCString &res) { char c = *substr; for (unsigned pos = readPos(); pos < writePos(); pos++){ if (*data(pos) != c) continue; const char *sp = substr; for (unsigned pos1 = pos; *sp; pos1++, sp++){ if (pos1 >= writePos()) break; if (*data(pos1) != *sp) break; } if (*sp == 0){ res = ""; if (pos - readPos()){ unpack(res, pos - readPos()); } incReadPos(pos + strlen(substr) - readPos()); return true; } } return false; } void Buffer::packetStart() { m_packetStartPos = writePos(); } static int findStartSection(const Buffer *pBuf, unsigned start) { int idx = start == ~0U ? 0 : start; for ( ; ; ) { if(idx >= (int)pBuf->size()) return -1; idx = pBuf->find( '[', idx); if(idx == -1) return -1; if( idx == 0 || pBuf->at( idx - 1 ) == '\n' ) return idx; idx++; } } static int findEndSection(const Buffer *pBuf, unsigned start) { int idx = start == ~0U ? 0 : start; for ( ; ; ) { if(idx >= (int)pBuf->size()) return -1; idx = pBuf->find( ']', idx); if(idx == -1) return -1; if( idx == (int)pBuf->size() - 1 || pBuf->at( idx + 1 ) == '\n' ) return idx; idx++; } } QCString Buffer::getSection(bool bSkip) { QCString str; unsigned start = m_posRead; unsigned end = m_posRead; if( bSkip ) start = findStartSection(this, m_posRead + 1); if( start == ~0U ) return str; start = findStartSection( this, start ); end = findEndSection( this, start ); if( start == ~0U || end == ~0U ) return str; m_startSection = m_posRead = start; str = QCString( data() + start + 1, end - start ); m_posRead = end + 1; if ( m_posRead < size() ) if ( at(m_posRead) == '\n' ) m_posRead++; if ( m_posRead >= size() ) m_posRead = size() - 1; m_posWrite = findStartSection( this, end ); if( m_posWrite == ~0U ) m_posWrite = size(); return str; } QCString Buffer::getLine() { if (readPos() >= writePos()) return ""; unsigned start = m_posRead; int end = find('\n', start); if(end == -1) end = size(); QCString res = QCString(data() + start, end - start + 1); m_posRead = end + 1; if ( m_posRead < size() ) if ( at(m_posRead) == '\n' ) m_posRead++; return res; } // for Buffer::scan() unsigned Buffer::unpack(QCString &d, unsigned s) { unsigned readn = size() - m_posRead; if (s < readn) readn = s; d = QCString(data() + m_posRead, readn + 1); m_posRead += readn; return readn; } Buffer Buffer::fromBase64(QCString &from) { unsigned n = 0; unsigned tmp2 = 0; Buffer to; int len = from.length(); for (int i = 0; i < len; i++) { char c = from[i]; char res[3]; char tmp = 0; if ((c >= 'A') && (c <= 'Z')) { tmp = (char)(c - 'A'); } else if ((c >= 'a') && (c <= 'z')) { tmp = (char)(26 + (c - 'a')); } else if ((c >= '0') && (c <= 57)) { tmp = (char)(52 + (c - '0')); } else if (c == '+') { tmp = 62; } else if (c == '/') { tmp = 63; } else if ((c == '\r') || (c == '\n')) { continue; } else if (c == '=') { if (n == 3) { res[0] = (char)((tmp2 >> 10) & 0xff); res[1] = (char)((tmp2 >> 2) & 0xff); to.pack(res, 2); } else if (n == 2) { res[0] = (char)((tmp2 >> 4) & 0xff); to.pack(res, 1); } break; } tmp2 = ((tmp2 << 6) | (tmp & 0xff)); n++; if (n == 4) { res[0] = (char)((tmp2 >> 16) & 0xff); res[1] = (char)((tmp2 >> 8) & 0xff); res[2] = (char)(tmp2 & 0xff); to.pack(res, 3); tmp2 = 0; n = 0; } } return to; } static const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" "0123456789+/"; QCString Buffer::toBase64(Buffer &from) { unsigned char b[3]; char res[5]; QCString to; res[4] = '\0'; while (from.readPos() + 3 <= from.size()){ from.unpack((char*)b, 3); unsigned tmp = (b[0] << 16) | (b[1] << 8) | b[2]; res[0] = alphabet[(tmp >> 18) & 0x3F]; res[1] = alphabet[(tmp >> 12) & 0x3F]; res[2] = alphabet[(tmp >> 6) & 0x3F]; res[3] = alphabet[tmp & 0x3F]; to += res; } unsigned rest = from.size() - from.readPos(); if(rest == 2 || rest == 1) { from.unpack((char*)b, rest); unsigned tmp = (b[0] << 16); if(rest == 2) tmp |= (b[1] << 8); res[0] = alphabet[(tmp >> 18) & 0x3F]; res[1] = alphabet[(tmp >> 12) & 0x3F]; res[2] = (rest == 2 ? alphabet[(tmp >> 6) & 0x3F] : '='); res[3] = '='; to += res; } return to; } // for msn unsigned Buffer::unpack(QString &d, unsigned s) { unsigned readn = size() - m_posRead; if (s < readn) readn = s; d = QString::fromUtf8(data() + m_posRead, readn); m_posRead += readn; return readn; }