Skip to content
Snippets Groups Projects
Select Git revision
  • 8efb94d67c4fff40b6b3ef526f933001ab1fcf86
  • master default protected
  • v4.5.2
  • v4.5.1
  • v4.5.0
  • v4.4.0
  • v4.3.3
  • v4.3.2
  • v4.3.1
  • v4.3.0
  • v4.2.0
  • v4.1.0
  • v4.0.2
  • v4.0.1
  • v4.0.0
  • v3.4.0
  • v3.3.0
  • v3.2.0
  • v3.1.1
  • v3.1.0
  • v3.0.1
  • v3.0.0
22 results

ByteStream.cpp

Blame
  • ByteStream.cpp 12.58 KiB
    /***************************************************************************
                              ByteStream.cpp  -  description
                                 -------------------
        begin                : Thu Nov 29 2001
        copyright            : (C) 2001-2013 by Andrea Bulgarelli
                                   2013-2914 by Andrea Bulgarelli, Andrea Zoli
        email                : bulgarelli@iasfbo.inaf.it, zoli@iasfbo.inaf.it
     ***************************************************************************/
     
    /***************************************************************************
     *                                                                         *
     *   This program is free software for non commercial purpose              *
     *   and for public research institutes; you can redistribute it and/or    *
     *   modify it under the terms of the GNU General Public License.          *
     *   For commercial purpose see appropriate license terms                  *
     *                                                                         *
     ***************************************************************************/
    
    
    #include "ByteStream.h"
    #include "PacketLibDemo.h"
    #include "PacketException.h"
    #include "Utility.h"
    #include "lz4.h"
    #include "lz4hc.h"
    using namespace PacketLib;
    
    /// Returns a pointer of a field in the list of fields of this part of packet.
    /// \remarks mem_allocation = true indicates that the allocated memory must be released by the destroyer.
    /// \remarks memory_sharing=false In all methods of constructor or set type accepting byte*, it indicates that the swap is applied. 
    /// In all methods of constructor or set type accepting ByteStreamPtr the swap is never applied.
    
    PacketLib::ByteStream::ByteStream(bool bigendian)
    	: stream(0), byteInTheStream(0), bigendian(bigendian)
    {
        mem_allocation_constructor = true;
        setMemoryAllocated(false);
        mem_allocation_constructor = false;
    }
    
    
    PacketLib::ByteStream::ByteStream(dword dim, bool bigendian)
    	: byteInTheStream(dim), bigendian(bigendian)
    {
        mem_allocation_constructor = true;
        stream = (byte*) new byte[dim];
        setMemoryAllocated(true);
        mem_allocation_constructor = false;
    }
    
    
    PacketLib::ByteStream::ByteStream(byte* stream, dword dim, bool bigendian, bool memory_sharing)
    	: stream(stream), byteInTheStream(dim), bigendian(bigendian)
    {
        mem_allocation_constructor = true;
        //if(!memory_sharing)
        //    swapWordIfStreamIsLittleEndian();
        /// \remarks memory_sharing == false means that the object is responsible for the memory
        setMemoryAllocated(!memory_sharing);
        mem_allocation_constructor = false;
    }
    
    PacketLib::ByteStream::ByteStream(ByteStreamPtr b0, dword start, dword end, bool memory_sharing) {
    	mem_allocation_constructor = true;
    	
    	if(end == (dword)-1)
    		end = b0->size();
    	
    	byteInTheStream = end-start;
        this->stream = b0->stream+start;
        this->bigendian = b0->isBigendian();
        //if(!memory_sharing)
        //    swapWordIfStreamIsLittleEndian();
    	
    	setMemoryAllocated(!memory_sharing);
    	mem_allocation_constructor = false;
    }
    
    
    PacketLib::ByteStream::ByteStream(ByteStreamPtr b0, ByteStreamPtr b1, ByteStreamPtr b2)
    {
        mem_allocation_constructor = true;
    
        /// Streams are swapped
        dword dim = 0;
        if(b0 == 0 && b1 == 0 && b2 == 0)
        {
    
            setMemoryAllocated(false);
    
            byteInTheStream  = 0;
            stream = 0;
            mem_allocation_constructor = false;
            return;
        }
        byteInTheStream = (b0!=0?b0->size():0) + (b1!=0?b1->size():0) + (b2!=0?b2->size():0);
        stream = (byte*) new byte[byteInTheStream];
        this->bigendian = (b0!=0?b0->isBigendian():(b1!=0?b1->isBigendian():(b2!=0?b2->isBigendian():false)));
    
    	if(b0 != 0)
    	{
    		memcpy(stream, b0->stream, b0->size());
    		dim += b0->size();
    	}
    	if(b1 != 0)
    	{
    		memcpy(stream+dim, b1->stream, b1->size());
    		dim += b1->size();
    	}
    	if(b2 != 0)
    	{
    		memcpy(stream+dim, b2->stream, b2->size());
    		dim += b2->size();
    	}
        setMemoryAllocated(true);
        mem_allocation_constructor = false;
    }
    
    
    
    PacketLib::ByteStream::~ByteStream()
    {
        if(mem_allocation)
        {
            delete[] stream;
            stream = 0;
        }
    }
    
    ByteStreamPtr PacketLib::ByteStream::compress(enum CompressionAlgorithms algorithmType, byte compressionLevel) {
    	ByteStreamPtr b;
    
    	switch(algorithmType)
    	{
    		case LZ4:
    		{
    			byte* buff = new byte[LZ4_compressBound(size())];
    			int buffsize = LZ4_compressHC2((const char*)stream, (char*)buff, size(), compressionLevel);
    			if(!buffsize)
    			{
    				cout << "LZ4 compression error" << endl;
    				return 0;
    			}
    			b = ByteStreamPtr(new ByteStream((byte*)buff, buffsize, bigendian));
    			break;
    		}
    		case NONE:
    		{
    			b = ByteStreamPtr(new ByteStream(stream, size(), bigendian));
    			break;
    		}
    		default:
    		{
    			return 0;
    		}
    	}
    #ifdef DEBUG
    	cout << "Buffer decompressed size: " << size() << endl;
    	cout << "Buffer compressed size: " << b->size() << endl;
    #endif
    	return b;
    }
    
    ByteStreamPtr PacketLib::ByteStream::decompress(enum CompressionAlgorithms algorithmType, byte compressionLevel, dword dmax) {
    	ByteStreamPtr b;
    
    	UNUSED(compressionLevel);
    
    	switch(algorithmType)
    	{
    		case NONE:
    		{
    			b = stream;
    			break;
    		}
    		case LZ4:
    		{
    			byte* tmpbuff = new byte[dmax];
    			int buffsize = LZ4_decompress_safe((const char*)stream, (char*)tmpbuff, size(), dmax);
    			if(!buffsize)
    			{
    				delete tmpbuff;
    				throw new PacketException("LZ4 decompression error");
    				return 0;
    			}
    			if(buffsize < 0) {
    				delete tmpbuff;
    				throw new PacketException("LZ4 decompression error: the source stream is malformed");
    			}
    			byte* decompbuff = new byte[buffsize];
    			memcpy(decompbuff, tmpbuff, buffsize);
    			b = ByteStreamPtr(new ByteStream(decompbuff, buffsize, bigendian));
    			delete tmpbuff;
    			break;
    		}
    		default:
    		{
    			return 0;
    		}
    	}
    
    #ifdef DEBUG
    	cout << "dmax: " << dmax << endl;
    	cout << "Buffer compressed size: " << size() << endl;
    	cout << "Buffer decompressed size: " << b->size() << endl;
    #endif
    
    	return b;
    }
    
    
    byte PacketLib::ByteStream::getByte( dword byteNumber)
    {
        DEMORET0;
        if(byteNumber <= byteInTheStream)
            return stream[byteNumber];
        else
            return 0;
    }
    
    
    long PacketLib::ByteStream::getValue(dword start, word dim)
    {
        DEMORET0;
        byte b1, b2;
    	
    	if(start >= byteInTheStream)
    		throw PacketException("PacketLib::ByteStream::getValue() start greater than the size of the ByteStream", 0);
    	
        /// only 1 or 2 bytes
        if(dim == 0 || dim > 2)
        	/// error
            return -1;               
        if(bigendian)
        {
            b1 = stream[start];
            if(dim==2)
                b2 = stream[start+1];
            else
                b2 = 0;
        }
        else
        {
            if(dim==1)
            {
                if((start%2) == 0)
                    b2 = stream[start+1];
                else
                    b2 = stream[start-1];
                b1 = 0;
            }
            if(dim==2)
            {
                if((start%2) == 0)
                {
                    /// even value
                    b1=stream[start+1];
                    b2=stream[start];
                }
                else
                {
                    //b1 = (start-1)<0?0:stream[start-1];
                    //b2 = (start+2)>byteInTheStream?0:stream[start+2];
    				b1=(start+1)>=byteInTheStream?0:stream[start+1];
                    b2=stream[start];
                }
            }
        }
        return b2 + b1*256;
    }
    
    
    
    ByteStreamPtr PacketLib::ByteStream::getSubByteStream(dword first, dword last)
    {
        DEMORET0;
        if(first > last)
            return NULL;
        if(last > byteInTheStream)
            return NULL;
        ByteStreamPtr b = ByteStreamPtr(new ByteStream((stream + first), last-first+1, bigendian, true));
        return b;
    }
    
    
    
    ByteStreamPtr PacketLib::ByteStream::getSubByteStreamCopy(dword first, dword last)
    {
        DEMORET0;
        if(first > last)
            return NULL;
        if(last > byteInTheStream)
            return NULL;
        byte* streamtemp = (byte*) new byte[last-first+1];
        for(dword i=0; i<last-first+1; i++)
            streamtemp[i] = stream[first+i];
        return ByteStreamPtr(new ByteStream(streamtemp, last-first+1, bigendian, false));
    }
    
    
    byte* PacketLib::ByteStream::getStream()
    {
        return stream;
    }
    
    
    
    byte* PacketLib::ByteStream::encode()
    {
        //swapWordIfStreamIsLittleEndian();
        return stream;
    }
    
    
    
    void PacketLib::ByteStream::endOutputStream()
    {
        //swapWordIfStreamIsLittleEndian();
    }
    
    
    dword PacketLib::ByteStream::size()
    {
        return byteInTheStream;
    }
    
    
    char* PacketLib::ByteStream::printStreamInHexadecimal()
    {
        return Utility::stringToHexadecimal(stream, byteInTheStream);
    }
    
    
    
    void PacketLib::ByteStream::setStreamCopy(byte* b, dword dim)
    {
        deleteStreamMemory();
    
        byteInTheStream = dim;
        stream = (byte*) new byte[dim];
        for(dword i=0; i<dim; i++)
            stream[i] = b[i];
        //swapWordIfStreamIsLittleEndian();
        setMemoryAllocated(true);
    }
    
    
    
    bool PacketLib::ByteStream::setStream(byte* b, dword dim, bool bigendian, bool memory_sharing)
    {
        deleteStreamMemory();
    
        byteInTheStream = dim;
        this->bigendian = bigendian;
        this->stream = b;
    
        //if(!memory_sharing) swapWordIfStreamIsLittleEndian();
        setMemoryAllocated(!memory_sharing);
        return true;
    }
    
    
    
    bool PacketLib::ByteStream::setStream(ByteStreamPtr b, dword first, dword last)
    {
        if(first > last)
            return false;
        if(last > b->size())
            return false;
    
        deleteStreamMemory();
    
        this->stream = (b->stream + first);
        this->byteInTheStream = last-first+1;
        this->bigendian = b->isBigendian();
    
        setMemoryAllocated(false);
    
        return true;
    }
    
    
    
    bool PacketLib::ByteStream::getMemAllocation()
    {
        return mem_allocation;
    }
    
    
    bool PacketLib::ByteStream::isBigendian() const
    {
        return bigendian;
    }
    
    
    
    void PacketLib::ByteStream::setByte(dword start, word value)
    {
        stream[start] = value;
    }
    
    
    bool PacketLib::ByteStream::setWord(dword start, word value)
    {
        byte b1, b2;
        /// only even positions
        if(start%2 != 0)
            return false;
        /// It must not overtake the stream dimension
        if(start+1 > byteInTheStream)
            return false;
        /// Byte extraction
        /// \param LSByte
        b1 = (byte) value;           
        /// \param MSByte
        b2 = (byte) (value >> 8);
    	
    	if(bigendian)
    	{
            /// Swap
            stream[start] = b2;
            stream[start+1] = b1;
        } else {
    		/// no Swap
            stream[start] = b1;
            stream[start+1] = b2;
    	}
        return true;
    
    }
    
    
    void PacketLib::ByteStream::swapWordIfStreamIsLittleEndian()
    {
        if(!bigendian)
        {
           swapWord();
        }
    }
    
    void PacketLib::ByteStream::swapWordIfStreamIsBigEndian()
    {
        if(bigendian)
        {
           swapWord();
        }
    }
    
    void PacketLib::ByteStream::setMemoryAllocated(bool allocated)
    {
    	mem_allocation = allocated;
    }
    
    void PacketLib::ByteStream::deleteStreamMemory()
    {
        if(!mem_allocation_constructor && mem_allocation)
            delete[] stream;
    }
    
    ByteStreamPtr PacketLib::ByteStream::getPaddedCopy(dword chunkSize, dword padSize)
    {
    	if(byteInTheStream % chunkSize != 0)
    		throw new PacketException("getPadCopy() error. Chunk size must be a divisor of ByteStream::size().");
    
    	dword nChunks = byteInTheStream / chunkSize;
    	dword newChunkSize = chunkSize + padSize;
    
    	ByteStreamPtr sPtr = ByteStreamPtr(new ByteStream(nChunks*(newChunkSize), bigendian));
    	byte* raw = sPtr->getStream();
    
    	for(dword i=0; i<nChunks; i++)
    		memcpy(raw+i*newChunkSize, stream+i*chunkSize, chunkSize);
    
    	return sPtr;
    }
    
    ByteStreamPtr PacketLib::ByteStream::getUnpaddedCopy(dword chunkSize, dword padSize)
    {
    	if(byteInTheStream % chunkSize != 0)
    		throw new PacketException("getUnpadCopy() error. Chunk size must be a divisor of ByteStream::size().");
    	if(chunkSize - padSize <= 0)
    		throw new PacketException("getUnpadCopy() error. Chunk size - pad size gives a value <= 0.");
    
    	dword nChunks = byteInTheStream / chunkSize;
    	dword newChunkSize = chunkSize - padSize;
    
    	ByteStreamPtr sPtr = ByteStreamPtr(new ByteStream(nChunks*(newChunkSize), bigendian));
    	byte* raw = sPtr->getStream();
    
    	for(dword i=0; i<nChunks; i++)
    		memcpy(raw+i*newChunkSize, stream+i*chunkSize, newChunkSize);
    
    	return sPtr;
    }
    
    void PacketLib::ByteStream::swapWord() {
    	dword dim =  byteInTheStream;
    	for(dword i = 0; i< dim; i+=2)
    	{
    		/// For odd dimensions
    		if((dim - i) != 1)
    		{
    			byte btemp = stream[i];
    			stream[i] = stream[i+1];
    			stream[i+1] = btemp;
    		}
    	}
    }
    
    void PacketLib::ByteStream::swapWordForIntel() {
    	swapWordIfStreamIsBigEndian();
    }