File decomp.patch of Package xtandem
diff --git a/src/Makefile_ubuntu b/src/Makefile_ubuntu
index 27521b5..48c1d5b 100644
--- a/src/Makefile_ubuntu
+++ b/src/Makefile_ubuntu
@@ -17,7 +17,7 @@ CXXFLAGS = -w -O2 -DGCC4_3
#ubuntu 64 bit version
#LDFLAGS = -lpthread -lm -L/usr/lib -static -lexpat
-LDFLAGS = -lpthread -L/usr/lib -lm -lexpat
+LDFLAGS = -lpthread -lm -lexpat -lz
SRCS := $(wildcard *.cpp)
OBJS := $(patsubst %.cpp,%.o,$(wildcard *.cpp))
diff --git a/src/base64.cpp b/src/base64.cpp
index aa75eba..069864a 100644
--- a/src/base64.cpp
+++ b/src/base64.cpp
@@ -2,6 +2,7 @@
//#include <math.h>
//#include <stdio.h>
//#include <string.h>
+#include <zlib.h>
#include "stdafx.h"
#include "base64.h"
@@ -90,11 +91,12 @@ inline int getPosition( char buf )
}
-// Returns the total number of bytes decoded
-int b64_decode_mio ( char *dest, char *src, size_t size )
+// Returns the total number of bytes decoded, or -1 if destination buffer overflows or there is a decompression error
+int b64_decode_mio ( char *const dest, const size_t dest_size, char *src, const size_t src_size, bool decomp )
{
char *temp = dest;
- char *end = dest + size;
+ char *const dest_end = dest + dest_size;
+ char *const src_end = src + src_size;
for (;;)
{
@@ -102,11 +104,11 @@ int b64_decode_mio ( char *dest, char *src, size_t size )
int register b;
int t1,t2,t3,t4;
- if (!(t1 = *src++) || !(t2 = *src++) || !(t3 = *src++) || !(t4 = *src++))
- return (int)(temp-dest);
-
- if (t1 == 61 || temp >= end) // if == '='
- return(int)(temp-dest);
+ // Read first and second characters
+ if (src >= src_end || !(t1 = *src++) || t1 == 61) // if == '='
+ break;
+ if (src >= src_end || !(t2 = *src++))
+ break;
if( t1 > 96 ) // [a-z]
a = (t1 - 71);
@@ -119,7 +121,6 @@ int b64_decode_mio ( char *dest, char *src, size_t size )
else // src[0] == '/'
a = 63;
-
if( t2 > 96 ) // [a-z]
b = (t2 - 71);
else if( t2 > 64 ) // [A-Z]
@@ -131,10 +132,14 @@ int b64_decode_mio ( char *dest, char *src, size_t size )
else // src[0] == '/'
b = 63;
+ // Write first byte
+ if (temp >= dest_end) // destination overflow!
+ return -1;
*temp++ = ( a << 2) | ( b >> 4);
- if (t3 == 61 || temp >= end)
- return (int)(temp-dest);;
+ // Read third character (if any)
+ if (src >= src_end || !(t3 = *src++) || t3 == 61)
+ break;
if( t3 > 96 ) // [a-z]
a = (t3 - 71);
@@ -147,10 +152,14 @@ int b64_decode_mio ( char *dest, char *src, size_t size )
else // src[0] == '/'
a = 63;
+ // Write second byte
+ if (temp >= dest_end) // destination overflow!
+ return -1;
*temp++ = ( b << 4) | ( a >> 2);
- if (t4 == 61 || temp >= end)
- return (int)(temp-dest);;
+ // Read fourth character (if any)
+ if (src >= src_end || !(t4 = *src++) || t4 == 61)
+ break;
if( t4 > 96 ) // [a-z]
b = (t4 - 71);
@@ -163,6 +172,26 @@ int b64_decode_mio ( char *dest, char *src, size_t size )
else // src[0] == '/'
b = 63;
+ // Write third byte
+ if (temp >= dest_end) // destination overflow!
+ return -1;
*temp++ = ( a << 6) | ( b );
}
+
+ // Decompress if required
+ if (decomp) {
+ Bytef *decompBuf = (Bytef*)malloc(dest_size);
+ uLongf decompLen = dest_size;
+ int result = uncompress(decompBuf, &decompLen, (Bytef*)dest, (uLong)(temp - dest));
+ if (result == Z_OK) {
+ memcpy(dest, decompBuf, decompLen);
+ temp = dest + decompLen;
+ }
+ free(decompBuf);
+ if (result != Z_OK) // decompression error
+ return -1;
+ }
+
+ // Done
+ return temp - dest;
}
diff --git a/src/base64.h b/src/base64.h
index e7c1bc5..b529dfa 100644
--- a/src/base64.h
+++ b/src/base64.h
@@ -1,5 +1,5 @@
#ifndef BASE64_H
#define BASE64_H
-int b64_decode_mio (char *dest, char *src, size_t size);
+int b64_decode_mio (char *dest, size_t dest_size, char *src, size_t src_size, bool decomp);
#endif /* BASE64_H */
diff --git a/src/saxhandler.cpp b/src/saxhandler.cpp
index 7afcebf..16a92e9 100644
--- a/src/saxhandler.cpp
+++ b/src/saxhandler.cpp
@@ -299,7 +299,7 @@ void SAXSpectraHandler::pushSpectrum()
}
}
-void SAXSpectraHandler::pushPeaks(bool bM /*= true*/, bool bI /*= true*/)
+void SAXSpectraHandler::pushPeaks(bool bM /*= true*/, bool bI /*= true*/, bool decomp /*= false*/)
{
if(bM)
m_vfM.clear();
@@ -340,10 +340,10 @@ void SAXSpectraHandler::pushPeaks(bool bM /*= true*/, bool bI /*= true*/)
}
else{
if (m_bLowPrecision) {
- decode32(bM,bI);
+ decode32(bM,bI,decomp);
}
else {
- decode64(bM,bI);
+ decode64(bM,bI,decomp);
}
}
}
@@ -393,7 +393,7 @@ void SAXSpectraHandler::numDepress(char* indata, size_t indataLength, bool bM /*
}
-void SAXSpectraHandler::decode32(bool bM /*= true*/, bool bI /*= true*/)
+void SAXSpectraHandler::decode32(bool bM /*= true*/, bool bI /*= true*/, bool decomp /*= false*/)
{
// This code block was revised so that it packs floats correctly
// on both 64 and 32 bit machines, by making use of the uint32_t
@@ -407,15 +407,15 @@ void SAXSpectraHandler::decode32(bool bM /*= true*/, bool bI /*= true*/)
if(bI == true) {
setCount++;
}
- size_t size = stringSize * setCount * 3 / 4;
- char* pDecoded = (char *) new char[size];
-
- memset(pDecoded, 0, size);
+ size_t size = m_peaksCount * setCount * sizeof(uint32_t);
+ size_t dest_size = size + 32;
+ char* pDecoded = (char *) new char[dest_size];
+ memset(pDecoded, 0, dest_size);
if(m_peaksCount > 0) {
// Base64 decoding
// By comparing the size of the unpacked data and the expected size
// an additional check of the data file integrity can be performed
- int length = b64_decode_mio( (char*) pDecoded , (char*) pData, stringSize );
+ int length = b64_decode_mio( (char*) pDecoded, dest_size, (char*) pData, stringSize, decomp );
if (!m_strNumpress.empty()){
numDepress((char*) pDecoded, length, bM, bI);
}
@@ -451,7 +451,7 @@ void SAXSpectraHandler::decode32(bool bM /*= true*/, bool bI /*= true*/)
delete[] pDecoded;
}
-void SAXSpectraHandler::decode64(bool bM /*= true*/, bool bI /*= true*/)
+void SAXSpectraHandler::decode64(bool bM /*= true*/, bool bI /*= true*/, bool decomp /*= false*/)
{
// This code block was revised so that it packs floats correctly
// on both 64 and 32 bit machines, by making use of the uint32_t
@@ -465,14 +465,15 @@ void SAXSpectraHandler::decode64(bool bM /*= true*/, bool bI /*= true*/)
if(bI == true) {
setCount++;
}
- size_t size = stringSize * setCount * 3 / 4;
- char* pDecoded = (char *) new char[size];
- memset(pDecoded, 0, size);
+ size_t size = m_peaksCount * setCount * sizeof(uint64_t);
+ size_t dest_size = size + 32;
+ char* pDecoded = (char *) new char[dest_size];
+ memset(pDecoded, 0, dest_size);
if(m_peaksCount > 0) {
// Base64 decoding
// By comparing the size of the unpacked data and the expected size
// an additional check of the data file integrity can be performed
- int length = b64_decode_mio( (char*) pDecoded , (char*) pData, stringSize );
+ int length = b64_decode_mio( (char*) pDecoded, dest_size, (char*) pData, stringSize, decomp );
if (!m_strNumpress.empty()){
numDepress(pDecoded, length, bM, bI);
diff --git a/src/saxhandler.h b/src/saxhandler.h
index 8a076fd..fc66dcc 100644
--- a/src/saxhandler.h
+++ b/src/saxhandler.h
@@ -231,7 +231,7 @@ public:
protected:
void pushSpectrum(); // Load current data into pvSpec, may have to guess charge
void pushSpectrum(int charge); // Load current data into pvSpec with specific charge
- void pushPeaks(bool bM = true, bool bI = true); // Decode m_strData into a peak list
+ void pushPeaks(bool bM = true, bool bI = true, bool decomp = false); // Decode m_strData into a peak list
inline void reset()
{
@@ -247,8 +247,8 @@ private:
int guessCharge(); // Guess the charge based on spectrum peaks
void setDescription(); // Set specCurrent description based on current data
void numDepress(char* indata, size_t indataLength, bool bM /*= true*/, bool bI /*= true*/);
- void decode32(bool bM /*= true*/, bool bI /*= true*/);
- void decode64(bool bM /*= true*/, bool bI /*= true*/);
+ void decode32(bool bM /*= true*/, bool bI /*= true*/, bool decomp /*= false*/);
+ void decode64(bool bM /*= true*/, bool bI /*= true*/, bool decomp /*= false*/);
unsigned long dtohl(uint32_t l, bool bNet); // Convert from data to host long
uint64_t dtohl(uint64_t l, bool bNet);
protected:
diff --git a/src/saxmzmlhandler.cpp b/src/saxmzmlhandler.cpp
index fe9cfd6..9348b62 100644
--- a/src/saxmzmlhandler.cpp
+++ b/src/saxmzmlhandler.cpp
@@ -44,6 +44,7 @@ SAXMzmlHandler::SAXMzmlHandler( vector<mspectrum>& _vS, mspectrumcondition& _sC,
m_bNetworkData = true;
m_bLowPrecision = false;
m_bGaml = false;
+ m_bDecomp = false;
}
SAXMzmlHandler::~SAXMzmlHandler()
@@ -130,6 +131,7 @@ void SAXMzmlHandler::startElement(const XML_Char *el, const XML_Char **attr)
m_peaksCount = atoi(getAttrValue("arrayLength", attr));
}
m_bInData = true;
+ m_bDecomp = false; // reset flag
}
}
@@ -215,8 +217,7 @@ void SAXMzmlHandler::processCVParam(const char* name, const char* accession, con
m_bInmzArrayBinary = false;
}
else if(!strcmp(name, "zlib compression") || !strcmp(accession,"MS:1000574")) {
- cout << "\nFatal error: unsupported CODEC used for mzML peak data (CODEC type=" << name << ").\n";
- exit(-10);
+ m_bDecomp = true;
}
else if(!strcmp(accession, "MS:1002312") || !strcmp(accession, "MS:1002313") || !strcmp(accession, "MS:1002314")) {
m_strNumpress = string(accession);
@@ -227,11 +228,11 @@ void SAXMzmlHandler::processData()
{
if(m_bInmzArrayBinary && m_bInMsLevel2 && m_bInData)
{
- pushPeaks(m_bInmzArrayBinary, m_bInintenArrayBinary);
+ pushPeaks(m_bInmzArrayBinary, m_bInintenArrayBinary, m_bDecomp);
}
else if(m_bInintenArrayBinary && m_bInMsLevel2 && m_bInData)
{
- pushPeaks(m_bInmzArrayBinary, m_bInintenArrayBinary);
+ pushPeaks(m_bInmzArrayBinary, m_bInintenArrayBinary, m_bDecomp);
}
m_strData.clear();
diff --git a/src/saxmzmlhandler.h b/src/saxmzmlhandler.h
index 3c4d121..c11eae9 100644
--- a/src/saxmzmlhandler.h
+++ b/src/saxmzmlhandler.h
@@ -72,6 +72,7 @@ private:
bool m_bInmzArrayBinary;
bool m_bInintenArrayBinary;
bool m_bInData;
+ bool m_bDecomp;
string m_ccurrentRefGroupName;
class cvParam
{
diff --git a/src/saxmzxmlhandler.cpp b/src/saxmzxmlhandler.cpp
index afccebb..fe34ce9 100644
--- a/src/saxmzxmlhandler.cpp
+++ b/src/saxmzxmlhandler.cpp
@@ -25,6 +25,7 @@ SAXMzxmlHandler::SAXMzxmlHandler( vector<mspectrum>& _vS, mspectrumcondition& _s
m_bInMsLevel2 = false;
m_bInPrecursorMz = false;
m_bInPeaks = false;
+ m_bDecomp = false;
//added this (true by default)
m_bNetworkData = false;
}
@@ -58,9 +59,16 @@ void SAXMzxmlHandler::startElement(const XML_Char *el, const XML_Char **attr)
m_bInPeaks = true;
m_bLowPrecision = (strcmp("64", getAttrValue("precision", attr)) != 0);
const char *pcompressionType = getAttrValue("compressionType", attr);
- if(strlen(pcompressionType) != 0 && !strstr(pcompressionType,"none")) {
- cout << "\nFatal error: unsupported CODEC used for mzXML peak data (CODEC type=" << pcompressionType << ").\n";
- exit(-10);
+ m_bDecomp = false; // default to false in case required attribute is missing
+ if(strlen(pcompressionType) != 0) {
+ if (!strcmp(pcompressionType,"none")) {
+ m_bDecomp = false;
+ } else if (strstr(pcompressionType,"zlib")) {
+ m_bDecomp = true;
+ } else {
+ cout << "Non-standard CODEC used for mzXML peak data (CODEC type=" << pcompressionType << "): file cannot be interpreted.\n";
+ exit(-10);
+ }
}
}
else if(isElement("precursorMz", el))
@@ -106,7 +114,7 @@ void SAXMzxmlHandler::processData()
{
if( m_bInPeaks && m_cidLevel == 2)
{
- pushPeaks();
+ pushPeaks(true, true, m_bDecomp);
}
else if (m_bInPrecursorMz)
{
diff --git a/src/saxmzxmlhandler.h b/src/saxmzxmlhandler.h
index e92f441..fb8c857 100644
--- a/src/saxmzxmlhandler.h
+++ b/src/saxmzxmlhandler.h
@@ -56,6 +56,7 @@ private:
bool m_bInMsLevel2;
bool m_bInPrecursorMz;
bool m_bInPeaks;
+ bool m_bDecomp;
};
#endif //SAXMzxmlHandler_H