Files
cpp/include/zbsdtHelper.h
2021-03-16 09:30:56 +01:00

866 lines
28 KiB
C++

///
/// \file zbsdtHelper.h
/// \author Jan Chrin, PSI
/// \date Release: January 2018
/// \version CAFE 1.6
#ifndef ZBSDTHELPER_H
#define ZBSDTHELPER_H
#include <zbsHash.h>
#include <bitshuffle/bitshuffle.h>
namespace CAFE_BSHELPER
{
using boost::multi_index_container;
using namespace boost::multi_index;
bsreadContainer_set bsdt;
std::vector<BSChannel> bsrdV;
//Type maching is as follows:
// int8 [1 byte] to char
// uint8 [1] to unsigned char
// int16 [2] to short
// uint16 [2] to unsigned short
// int32 [4] to long
// uint32 [4] to unsigned long
// int64 [8] to long long
// uint64 [8] to unsigned long long
// float32[4] to float
// float64[8] to double
// bool [1] same as uint8; 0=false, !0 = true
// string to char (Byte order of strings are irrelevant - always big-endian). The String encoding is utf8; from bsread documentation
enum bsdtIndex {BS_INT8=0, BS_UINT8, BS_INT16, BS_UINT16,
BS_INT32, BS_UINT32, BS_INT64, BS_UINT64,
BS_FLOAT32, BS_FLOAT64, BS_BOOL, BS_STRING, BS_CHAR=BS_STRING
};
void bsdtInsert()
{
bsdt.insert(bsreadContainer(BS_INT8, "int8"));
bsdt.insert(bsreadContainer(BS_UINT8, "uint8"));
bsdt.insert(bsreadContainer(BS_INT16, "int16"));
bsdt.insert(bsreadContainer(BS_UINT16, "uint16"));
bsdt.insert(bsreadContainer(BS_INT32, "int32"));
bsdt.insert(bsreadContainer(BS_UINT32, "uint32"));
bsdt.insert(bsreadContainer(BS_INT64, "int64"));
bsdt.insert(bsreadContainer(BS_UINT64, "uint64"));
bsdt.insert(bsreadContainer(BS_FLOAT32,"float32"));
bsdt.insert(bsreadContainer(BS_FLOAT64,"float64"));
bsdt.insert(bsreadContainer(BS_BOOL, "bool"));
bsdt.insert(bsreadContainer(BS_STRING, "string"));
bsdt.insert(bsreadContainer(BS_CHAR, "string"));
}
int getByteSize(unsigned int dt)
{
#define __METHOD__ "getByteSize (unsigned int)"
switch(dt)
{
case BS_INT8:
return sizeof(int8_t);
case BS_UINT8:
case BS_BOOL:
return sizeof(uint8_t);
case BS_INT16:
return sizeof(int16_t);
case BS_UINT16:
return sizeof(uint16_t);
case BS_INT32:
return sizeof(int32_t);
case BS_UINT32:
return sizeof(uint32_t);
case BS_INT64:
return sizeof(int64_t);
case BS_UINT64:
return sizeof(uint64_t);
case BS_FLOAT32:
return sizeof(float);
case BS_FLOAT64:
return sizeof(double);
case BS_STRING: //is also BS_CHAR
return sizeof(char);
default:
std::cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << std::endl;
std::cout << "Enumerated input value " << dt << " is outside allowed band: " << BS_INT8 << " and " << BS_STRING << std::endl;
print_out_by<by_bsID>(bsdt);
std::cout << "Returning byte size of 1" << std::endl;
return 1;
}
#undef __METHOD__
}
int getByteSize(std::string dt)
{
#define __METHOD__ "getByteSize (string)"
bsreadContainer_set_by_name & name_index = bsdt.get<by_bsName> ();
bsreadContainer_set_by_name::iterator it_name;
unsigned int bsdtIndex;
//Find enum of data type
it_name = name_index.find(dt);
if ( (it_name) != name_index.end() )
{
bsdtIndex=(*it_name).by_bsID;
return getByteSize(bsdtIndex);
}
std::cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << std::endl;
std::cout << "string value " << dt << " is not recognized " << std::endl;
print_out_by<by_bsID>(bsdt);
std::cout << "Returning byte size of 1" << std::endl;
return 1;
#undef __METHOD__
}
//Easy show-error-and-bail function.
//void run_screaming(const char *message, const int code) {
// printf("%s\n", message);
// exit(code);
// return;
//}
/**
* \brief Generic function to display bits of a number
* used for testing in zmq stream
*/
void printBits(int const size, void const * const ptr)
{
unsigned char *b= (unsigned char *) ptr;
unsigned char byte;
int i, j;
for (i=size-1; i>=0; i--)
{
for (j=7; j>=0; j--)
{
byte =(b[i]>>j ) &1;
printf("%u", byte);
}
}
puts("");
return;
}
/**
* \brief Returns true if at least one bit within byte is set
* Used to test endianess of timestamp
*/
bool hasMinOneBitSet(int const size, void const * const ptr)
{
unsigned char *b= (unsigned char *) ptr;
unsigned char byte;
bool hasBit = false;
int i, j;
for (i=size-1; i>=0; i--)
{
for (j=7; j>=0; j--)
{
byte =(b[i]>>j ) &1;
if (byte) {
return true;
}
}
}
return false;
}
/**
* \brief Unfolds the two bytes that precede the blob
* See: https://git.psi.ch/sf_daq/ch.psi.daq.dispatcherrest
* and: https://git.psi.ch/sf_daq/bsread_specification
*/
int unfoldPreBlob(const char * data, long &uncompressedSize, int &blockSize)
{
//Check for -ve numbers
uncompressedSize = ( ((data[7] <<0) & 0x7f) | ((data[7]<<0) & 0x80) | (data[6]<<8) | (data[5]<<16) | (data[4]<<24)
| ((long long) data[3]<<32) | ((long long) data[2]<<40) | ((long long) data[1]<<48) | ((long long) data[0]<<56) ) ;
// printBits(2, &uncompressedSize);
//std::cout << "UNCOMPRESSED SIZE / " << uncompressedSizeL << " " << uncompressedSize << std::endl;
//uncompressedSize = ( ((data[7] <<0) & 0x7f) | ((data[7]<<0) & 0x80) | (data[6]<<8) | (data[5]<<16) | (data[4]<<24)
// | ((long long) data[3]<<32) | ((long long) data[2]<<40) | ((long long) data[1]<<48) | ((long long) data[0]<<56) ) ;
//std::cout << "UNCOMPRESSED SIZE // " << uncompressedSize << std::endl;
//All three give equivalent block size
//blockSize= ( (data[11]<<0) | (data[10]<<8) | (data[9]<<16) | (data[8]<<24) );
//std::cout << "BLOCKSIZE " << blockSize << std::endl;
blockSize= ( ((data[11]<<0)) | ((data[11]<<0)& 0x80) | (data[10]<<8) | (data[9]<<16) | (data[8]<<24) );
//std::cout << "BLOCKSIZE / " << blockSize << std::endl;
//blockSize= ( ((data[11]<<0) & 0x7f) | ((data[11]<<0)& 0x80) | (data[10]<<8) | (data[9]<<16) | (data[8]<<24) );
//std::cout << "BLOCKSIZE // " << blockSize << std::endl;
return ICAFE_NORMAL;;
}
/**
* \brief DataBitset Template \n
* CTYPE is the integer type the data type is to be rendered to the client \n
* method unfold() will receive data and then convert to CTYPE
*/
template <class CTYPE> class DataBitset
{
public:
DataBitset () {};
~DataBitset () {};
CTYPE unfold(char * data, size_t start, size_t end, std::string encoding )
{
//std::cout << "encoding=" << encoding << std::endl;
if (encoding=="big")
{
//big endian
for (short n=start; n < end; n++)
{
i = (i << 8) + data[n];
}
}
else
{
//little endian
for (short n = end; n >= start; n--)
{
i = (i << 8) + data[n];
}
}
//std::cout << "Value = " << i << std::endl;
return i;
}
private:
CTYPE i;
};
/**
* \brief IntegerBitset Template \n
* CTYPE is the integer type the data type is to be rendered to the client \n
* method unfold() will receive data and then convert to vector<CTYPE>
*/
template <class CTYPE> class IntegerBitsetV
{
public:
IntegerBitsetV () {};
~IntegerBitsetV () {};
CTYPE unfold(char * data, unsigned int nelem, std::string encoding, std::vector<CTYPE> &valV )
{
valV.clear();
valV.reserve(nelem);
cSize=sizeof(CTYPE);
idx=0;
if (encoding=="big")
{
switch (cSize)
{
case 1:
for (unsigned int i=0; i<nelem; ++i)
{
idx=i*cSize;
iVal= (data[idx+1]<<0) & 0xff;
valV.push_back(iVal);
}
break;
case 2:
for (unsigned int i=0; i<nelem; ++i)
{
idx=i*cSize;
iVal= ( ((data[idx+1]<<0) & 0xff) | ((data[idx]<<8) & 0xffff));
valV.push_back(iVal);
}
break;
case 4:
for (unsigned int i=0; i<nelem; ++i)
{
idx=i*cSize;
iVal= ( ((data[idx+3]<<0) & 0xff ) | ((data[idx+2]<<8) & 0xffff )
| ((data[idx+1]<<16) & 0xffffff) | ((data[idx]<<24) & 0xffffffff) );
valV.push_back(iVal);
}
break;
case 8:
for (unsigned int i=0; i<nelem; ++i)
{
idx=i*cSize;
iVal= ( ((data[idx+7]<<0) & 0xff) | ((data[idx+6]<<8) & 0xffff )
| ((data[idx+5]<<16) & 0xffffff ) | ((data[idx+4]<<24) & 0xffffffff )
| (((long long) data[idx+3]<<32) & 0xffffffffff)
| (((long long) data[idx+2]<<40) & 0xffffffffffff)
| (((long long) data[idx+1]<<48) & 0xffffffffffffff)
| (((long long) data[idx]<<56) & 0xffffffffffffffff) ) ;
valV.push_back(iVal);
}
break;
default:
std::cout << "Cannot process element of size " << cSize << " bytes" << std::endl;
}
}
else //little endian
{
switch (cSize)
{
case 1:
for (unsigned int i=0; i<nelem; ++i)
{
idx=i*cSize;
iVal= (data[idx]<<0) & 0xff;
valV.push_back(iVal);
}
break;
case 2:
for (unsigned int i=0; i<nelem; ++i)
{
idx=i*cSize;
iVal= ( ( (data[idx]<<0) & 0xff ) | ( (data[idx+1]<<8) & 0xffff) );
valV.push_back(iVal);
}
break;
case 4:
for (unsigned int i=0; i<nelem; ++i)
{
idx=i*cSize;
iVal= ( ( (data[idx]<<0) & 0xff) | ( (data[idx+1]<<8) & 0xffff )
| ( (data[idx+2]<<16) & 0xffffff) | ((data[idx+3]<<24) & 0xffffffff ));
valV.push_back(iVal);
}
break;
case 8:
for (unsigned int i=0; i<nelem; ++i)
{
idx=i*cSize;
iVal = ( ( (data[idx]<<0) & 0xFF) | ( (data[idx+1]<<8) & 0xFFFF)
| ((data[idx+2]<<16) & 0xFFFFFF) | ( (data[idx+3]<<24) & 0xFFFFFFFF)
| (((long long) data[idx+4]<<32) & 0xFFFFFFFFFF )
| (((long long) data[idx+5]<<40) & 0xFFFFFFFFFFFF )
| (((long long) data[idx+6]<<48) & 0xFFFFFFFFFFFFFF )
| (((long long) data[idx+7]<<56) & 0xFFFFFFFFFFFFFFFF ) ) ;
valV.push_back(iVal);
}
break;
default:
std::cout << "Cannot process element of size " << cSize << " bytes" << std::endl;
}
}
return valV[0]; //scalar value
}
private:
unsigned int cSize;
unsigned int idx;
CTYPE iVal;
};
/**
* \brief IntegerBitset Template \n
* CTYPE is the integer type the data type is to be rendered to the client \n
* method unfold() will receive data and then convert to CTYPE *
*/
template <class CTYPE> class IntegerBitset
{
public:
IntegerBitset () {};
~IntegerBitset () {};
CTYPE * unfold(char * data, unsigned int nelem, std::string encoding )
{
//std::cout << sizeof(char) << " s+ " << sizeof(short) << " i+ " << sizeof(int) << " l+ " <<sizeof(long) << " ll+ " << sizeof(long long) << std::endl;
cSize=sizeof(CTYPE);
idx=0;
iVal=new CTYPE[nelem];
//std::cout << "cSize " << cSize << std::endl;
//std::cout << "nelem " << nelem << " encoding" << encoding << std::endl;
if (encoding=="big")
{
switch (cSize)
{
case 1:
for (unsigned int i=0; i<nelem; ++i)
{
idx=i*cSize;
iVal[i]= data[idx]<<0 & 0xff;
}
break;
case 2:
for (unsigned int i=0; i<nelem; ++i)
{
idx=i*cSize;
iVal[i]= ( ((data[idx+1]<<0) & 0xff) | ((data[idx]<<8) & 0xffff));
//char is=data[idx]; printBits(1,&is);
//is=data[idx+1]; printBits(1,&is);
//iVal[i]=( (data[idx+1]<<0) | (data[idx]<<8) );
//short ss=iVal[i];
//printBits(2, &ss);
//std::cout << iVal[i] << " [" << i << "] " ;
}
//std::cout << std::endl;
break;
case 4:
for (unsigned int i=0; i<nelem; ++i)
{
idx=i*cSize;
iVal[i]=( ((data[idx+3]<<0) & 0xff ) | ((data[idx+2]<<8) & 0xffff )
| ((data[idx+1]<<16) & 0xffffff) | ((data[idx]<<24) & 0xffffffff) );
}
break;
case 8:
for (unsigned int i=0; i<nelem; ++i)
{
idx=i*cSize;
iVal[i]= ( ((data[idx+7]<<0) & 0xff) | ((data[idx+6]<<8) & 0xffff )
| ((data[idx+5]<<16) & 0xffffff ) | ((data[idx+4]<<24) & 0xffffffff )
| (((long long) data[idx+3]<<32) & 0xffffffffff)
| (((long long) data[idx+2]<<40) & 0xffffffffffff)
| (((long long) data[idx+1]<<48) & 0xffffffffffffff)
| (((long long) data[idx]<<56) & 0xffffffffffffffff) ) ;
}
default:
std::cout << "Cannot process element of size " << cSize << " bytes" << std::endl;
}
}
else //little endian
{
switch (cSize)
{
case 1:
for (unsigned int i=0; i<nelem; ++i)
{
idx=i*cSize;
iVal[i]= (data[idx]<<0) & 0xff;
}
break;
case 2:
for (unsigned int i=0; i<nelem; ++i)
{
idx=i*cSize;
iVal[i]=( ( (data[idx]<<0) & 0xff ) | ( (data[idx+1]<<8) & 0xffff) );
}
break;
case 4:
for (unsigned int i=0; i<nelem; ++i)
{
idx=i*cSize;
iVal[i]=( ( (data[idx]<<0) & 0xff) | ( (data[idx+1]<<8) & 0xffff )
| ( (data[idx+2]<<16) & 0xffffff) | ((data[idx+3]<<24) & 0xffffffff ));
}
break;
case 8:
for (unsigned int i=0; i<nelem; ++i)
{
idx=i*cSize;
iVal[i]=( ( (data[idx]<<0) & 0xFF) | ( (data[idx+1]<<8) & 0xFFFF)
| ((data[idx+2]<<16) & 0xFFFFFF) | ( (data[idx+3]<<24) & 0xFFFFFFFF)
| (((long long) data[idx+4]<<32) & 0xFFFFFFFFFF )
| (((long long) data[idx+5]<<40) & 0xFFFFFFFFFFFF )
| (((long long) data[idx+6]<<48) & 0xFFFFFFFFFFFFFF )
| (((long long) data[idx+7]<<56) & 0xFFFFFFFFFFFFFFFF ) ) ;
}
break;
default:
std::cout << "Cannot process element of size " << cSize << " bytes" << std::endl;
}
}
return iVal;
}
CTYPE unfoldScalar(char * data, std::string encoding )
{
cSize=sizeof(CTYPE);
idx=0;
if (encoding=="big")
{
switch (cSize)
{
case 1:
idx=0;
iValScalar = data[idx]<<0 & 0xff;
break;
case 2:
idx=0;
iValScalar=( ((data[idx+1]<<0) & 0xff) | ((data[idx]<<8) & 0xffff));
break;
case 4:
idx=0;
iValScalar=( ((data[idx+3]<<0) & 0xff) | ((data[idx+2]<<8) & 0xffff)
| ((data[idx+1]<<16) & 0xffffff) | ((data[idx]<<24) & 0xffffffff) );
break;
case 8:
idx=0;
iValScalar=( ((data[idx+7]<<0) & 0xff) | ((data[idx+6]<<8) & 0xffff )
| ((data[idx+5]<<16) & 0xffffff ) | ((data[idx+4]<<24) & 0xffffffff )
| (((long long) data[idx+3]<<32) & 0xffffffffff)
| (((long long) data[idx+2]<<40) & 0xffffffffffff)
| (((long long) data[idx+1]<<48) & 0xffffffffffffff)
| (((long long) data[idx]<<56) & 0xffffffffffffffff) ) ;
break;
default:
std::cout << "Cannot process element of size " << cSize << " bytes" << std::endl;
}
}
else //little endian
{
switch (cSize)
{
case 1:
idx=0;
iValScalar= (data[idx]<<0) & 0xff;
break;
case 2:
idx=0;
iValScalar=( ( (data[idx]<<0) & 0xff ) | ( (data[idx+1]<<8) & 0xffff) );
break;
case 4:
idx=0;
iValScalar=( ( (data[idx]<<0) & 0xff) | ( (data[idx+1]<<8) & 0xffff )
| ( (data[idx+2]<<16) & 0xffffff) | ((data[idx+3]<<24) & 0xffffffff ));
break;
case 8:
idx=0;
iValScalar=( ( (data[idx]<<0) & 0xFF) | ( (data[idx+1]<<8) & 0xFFFF)
| ((data[idx+2]<<16) & 0xFFFFFF) | ( (data[idx+3]<<24) & 0xFFFFFFFF)
| (((long long) data[idx+4]<<32) & 0xFFFFFFFFFF )
| (((long long) data[idx+5]<<40) & 0xFFFFFFFFFFFF )
| (((long long) data[idx+6]<<48) & 0xFFFFFFFFFFFFFF )
| (((long long) data[idx+7]<<56) & 0xFFFFFFFFFFFFFFFF ) ) ;
break;
default:
std::cout << "Cannot process element of size " << cSize << " bytes" << std::endl;
}
}
return iValScalar;
}
private:
unsigned int cSize;
unsigned int idx;
CTYPE * iVal;
CTYPE iValScalar;
};
// big endian
// int uc = ( ( (data[7]<<0) & 0x7f) | ((data[7]<<0) & 0x80) | (data[6]<<8) | (data[5]<<16) | (data[4]<<24) | ((long long) data[3]<<32)
// | ((long long) data[2]<<40) | ((long long) data[1]<<48) | ((long long) data[0]<<56) ) ;
//
// int bs = ( ( (data[11]<<0) & 0x7f) | ((data[11]<<0) & 0x80) | (data[10]<<8) | (data[9]<<16) | (data[8]<<24));
// big endian
// bs = ( ( (regen_buffer[n] <<24) ) | ( (regen_buffer[n+1] <<26) ) | ( (regen_buffer[n+2] <<8) )
// | ( (regen_buffer[n+3] <<0) & 0x7f) | (regen_buffer[n+3] <<0) & 0x80 ) ;
/**
* \brief FloatBitset Template \n
* CTYPE is the float type of the data type to be rendered to the client \n
* method unfold() will receive data and then convert to CTYPE
*/
template <class CTYPE> class FloatBitset
{
public:
FloatBitset () {};
~FloatBitset () {};
CTYPE * unfold(char * data, unsigned int nelem, std::string encoding)
{
cSize=sizeof(CTYPE);
val=new CTYPE[nelem];
//std::cout << "HELPER>H " << nelem << " " << encoding << " cSize " << cSize << std::endl;
if (encoding=="big")
{
for (unsigned int i=0; i<nelem; ++i)
{
start=i*cSize;
end=(i+1)*cSize;
//std::cout << start << " // " << end << std::endl;
inst=0;
for (size_t char_nbr = start; char_nbr < end ; char_nbr++)
{
idx=(nelem*cSize)-1-char_nbr;
//std::cout << inst << " " << idx << std::endl;
bar.c[inst]=data[idx];
++inst;
}
//std::cout << "i= " << i << " " << std::endl;
//std::cout << bar.v << " [" << i << "] " << std::endl;
val[nelem-1-i]=bar.v;
//std::cout << val[nelem-1-i] << " [" << (nelem-1-i) << "] " << std::endl;
}
}
// little endian
else
{
for (unsigned int i=0; i<nelem; ++i)
{
start=i*cSize;
end=(i+1)*cSize;
inst=0;
for (size_t char_nbr = start; char_nbr < end ; char_nbr++)
{
bar.c[inst]=data[char_nbr];
++inst;
}
val[i]=bar.v;
}
}
return val;
}
CTYPE unfoldScalar(char * data, std::string encoding)
{
cSize=sizeof(CTYPE);
if (encoding=="big")
{
start=0;
end=cSize;
inst=0;
for (size_t char_nbr = start; char_nbr < end ; char_nbr++)
{
idx=cSize-1-char_nbr;
bar.c[inst]=data[idx];
++inst;
}
}
// little endian
else
{
start=0;
end=cSize;
inst=0;
for (size_t char_nbr = start; char_nbr < end ; char_nbr++)
{
bar.c[inst]=data[char_nbr];
++inst;
}
}
return bar.v;
};
/*
CTYPE unfold(char * data, size_t start, size_t end, std::string encoding )
{
if (encoding=="big") {
// big endian
for (size_t char_nbr = start; char_nbr < end; char_nbr++) {
bar.c[char_nbr]=data[end-1-char_nbr];
}
} else {
// little endian
for (size_t char_nbr = start; char_nbr < end; char_nbr++) {
bar.c[char_nbr]=data[char_nbr];
}
}
//std::cout << "UNION D " << bar.v << std::endl;
return bar.v;
}
*/
private:
union dUnion
{
char c[sizeof(CTYPE)];
CTYPE v;
} bar;
CTYPE * val;
unsigned int cSize;
int start;
int end;
int inst;
int idx;
};
/**
* \brief FloatBitsetV Template \n
* CTYPE is the float type of the data type to be rendered to the client \n
* method unfold() will receive data and then convert to vector<CTYPE>
*/
template <class CTYPE> class FloatBitsetV
{
public:
FloatBitsetV () {};
~FloatBitsetV () {};
CTYPE unfold(char * data, unsigned int nelem, std::string encoding, std::vector<CTYPE> &valV)
{
//memory already allocated in zbsread.h
//valV.clear();
//valV.reserve(nelem);
cSize=sizeof(CTYPE);
//std::cout << "HELPER_H " << nelem << " " << encoding << " cSize " << cSize << std::endl;
if (encoding=="big")
{
for (unsigned int i=0; i<nelem; ++i)
{
start=i*cSize;
end=(i+1)*cSize;
std::cout << start << " // " << end << std::endl;
inst=0;
for (size_t char_nbr = start; char_nbr < end ; char_nbr++)
{
idx=(nelem*cSize)-1-char_nbr;
bar.c[inst]=data[idx];
++inst;
}
std::cout << bar.v << " [" << (nelem-1-i) << "] " ;
valV[nelem-1-i]=bar.v;
std::cout << valV[nelem-1-i] << " [" << (nelem-1-i) << "] " ;
//valV.push_back(bar.v);
}
}
else // little endian
{
for (unsigned int i=0; i<nelem; ++i)
{
start=i*cSize;
end=(i+1)*cSize;
inst=0;
for (size_t char_nbr = start; char_nbr < end ; char_nbr++)
{
bar.c[inst]=data[char_nbr];
++inst;
}
std::cout << bar.v << " [" << i << "] " ;
valV[i]=bar.v;
//valV.push_back(bar.v);
}
}
std::cout << std::endl;
return valV[0]; //scalar value
}
private:
union dUnion
{
char c[sizeof(CTYPE)];
CTYPE v;
} bar;
unsigned int cSize;
int start;
int end;
int inst;
int idx;
};
/**
* \brief Routine that decompresses the compressed WFs and other data
*/
int bitshuffleDecompress( const char * data, char* & regen_buffer, int sizeData, int dtByteSize)
{
#define __METHOD__ "bitshuffleDecompress"
long uncompressedSize=0;
int blockSize=0;
int localDebug=0;
int sizeBlob = sizeData-BSREAD_PREBLOB_BYTES;
if (sizeBlob <1)
{
std::cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << std::endl;
std::cout << "WARNING: data size " << sizeData << " is less than BSREAD_PREBLOB_BYTES " << BSREAD_PREBLOB_BYTES << std::endl;
std::cout << "This should not happen. Probably we are trying to decompress uncompressed data! " << std::endl;
return ECAFE_BITSHUFF_BADCOUNT;
} //Should not happen
unfoldPreBlob(data, uncompressedSize, blockSize);
//std::cout << "Uncompressed/Block size: " << uncompressedSize << " / " << blockSize << std::endl;
//decompress
int dataNelem=uncompressedSize/dtByteSize;
//use bitshuffle terminology
regen_buffer = (char *) malloc(uncompressedSize);
if (regen_buffer == NULL)
{
std::cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << std::endl;
std::cout << "FAILED TO ALLOC MEM of size: " << uncompressedSize << std::endl;
return ECAFE_BITSHUFF_ALLOCMEM;
}
char * dataBlob = new char[sizeBlob];
int ij=0;
if(localDebug) std::cout << " BSREAD_PREBLOB_BYTES " << BSREAD_PREBLOB_BYTES <<std::endl;
if(localDebug) std::cout << " sizeData " << sizeData <<std::endl;
if(localDebug) std::cout << " sizeBlob " << sizeBlob <<std::endl;
if(localDebug) std::cout << " dataNelem " << dataNelem <<std::endl;
if(localDebug) std::cout << " dtByteSize " << dtByteSize <<std::endl;
for (int char_nbr = BSREAD_PREBLOB_BYTES; char_nbr < sizeData; char_nbr++)
{
dataBlob[ij]=data[char_nbr];
++ij;
}
//Use 0 rather than given block size as is recommended
const int decompressed_size = bshuf_decompress_lz4((const char *) dataBlob, regen_buffer, dataNelem, dtByteSize, 0);
delete [] dataBlob;
if(localDebug) std::cout << " " << " decompressed_size " << decompressed_size << std::endl;
if (decompressed_size < 0)
{
return ECAFE_BITSHUFF_DECOMPRESS;
}
else if (decompressed_size == 0)
{
if(localDebug)std::cout << "0 decompressed size! Should have a positive number for successful deompression?" <<std::endl;
}
else
{
if(localDebug)std::cout << "We successfully decompressed some data!" <<std::endl;
}
// Not only does a positive return value mean success,
// value returned == number of bytes regenerated from compressed_data stream.
// We can use this to realloc() *regen_buffer to free up memory
// Did this at first to remove spurious trailing characters
// BUT AVOID AT ALL COSTS; screws up regen_buffer content!!
/*
regen_buffer = (char *)realloc(regen_buffer, decompressed_size);
if (regen_buffer == NULL) {
std::cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << std::endl;
std::cout << "WARNING with status code: " << ECAFE_BITSHUFF_REALLOCMEM << std::endl;
std::cout << "Failed to reallocate memory for compressed data. Not a show stopper" << std::endl;
}
*/
return ICAFE_NORMAL;
#undef __METHOD__
}
}
#endif