Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:14:06

0001 #include "LzmaFile.h"
0002 
0003 #include "LzmaDec.h"
0004 #include "Alloc.h"
0005 #include "Types.h"
0006 #include "7zFile.h"
0007 
0008 //#include <sstream>
0009 //#include <string>
0010 #include <cmath>
0011 #include <iostream>
0012 #include <queue>
0013 #include <cstdlib>
0014 using namespace std;
0015 
0016 const char *kCantReadMessage = "Can not read input file";
0017 const char *kCantWriteMessage = "Can not write output file";
0018 const char *kCantAllocateMessage = "Can not allocate memory";
0019 const char *kDataErrorMessage = "Data error";
0020 
0021 static void *SzAlloc(void *, size_t size) { return MyAlloc(size); }
0022 static void SzFree(void *, void *address) { MyFree(address); }
0023 static ISzAlloc g_Alloc = {SzAlloc, SzFree};
0024 
0025 LzmaFile::LzmaFile() {
0026   // fStorage.reserve(10000);
0027   fStartNumber = false;
0028 
0029   fReadSign = true;
0030   fReadMantisseR = true;
0031   fReadMantisseF = false;
0032   fReadExponentSign = false;
0033   fReadExponent = false;
0034 
0035   fNegative = false;
0036   fExponentNegative = false;
0037 
0038   fMantisseR = 0;
0039   fMantisseF = 0;
0040   fMantisseFcount = 0;
0041   fExponent = 0;
0042 }
0043 
0044 SRes LzmaFile::Open(const string &fileName) {
0045   //fStrNumber.str("");
0046   //fStrNumber.clear();
0047 
0048   FileSeqInStream_CreateVTable(&inStream);
0049   File_Construct(&inStream.file);
0050 
0051   if (InFile_Open(&inStream.file, fileName.c_str()) != 0) {
0052     cout << "Cannot open input file: " << fileName << endl;
0053     cout << "First use: \n\t \'lzma --best " << fileName.substr(0, fileName.rfind(".lzma")) << "\'"
0054          << " to create it. " << endl;
0055     exit(1);
0056   }
0057 
0058   ISeqInStream *stream = &inStream.s;
0059 
0060   /* Read and parse header */
0061   /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */
0062   unsigned char header[LZMA_PROPS_SIZE + 8];
0063   RINOK(SeqInStream_Read(stream, header, sizeof(header)));
0064 
0065   unpackSize = 0;
0066   int i = 0;
0067   for (i = 0; i < 8; i++)
0068     unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8);
0069 
0070   LzmaDec_Construct(&state);
0071   RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc));
0072   LzmaDec_Init(&state);
0073 
0074   inPos = 0;
0075   inSize = 0;
0076   outPos = 0;
0077   return SZ_OK;
0078 }
0079 
0080 SRes LzmaFile::ReadNextNumber(double &data) {
0081   if (fStorage.empty()) {
0082     const int ret = DecodeBuffer();
0083     if (ret != SZ_OK) {
0084       cout << "Error in ReadNextNumber  ret=" << ret << endl;
0085       return SZ_ERROR_DATA;
0086     }
0087   }
0088 
0089   data = fStorage.front();
0090   fStorage.pop();
0091   return SZ_OK;
0092 }
0093 
0094 SRes LzmaFile::FillArray(double *data, const int length) {
0095   for (int i = 0; i < length; ++i) {
0096     if (fStorage.empty()) {
0097       const int ret = DecodeBuffer();
0098       if (ret != SZ_OK) {
0099         cout << "Error in FillArray i=" << i << " ret=" << ret << endl;
0100         return SZ_ERROR_DATA;
0101       }
0102     }
0103 
0104     data[i] = fStorage.front();
0105     fStorage.pop();
0106   }
0107 
0108   return SZ_OK;
0109 }
0110 
0111 /*
0112 double 
0113 LzmaFile::strToDouble(const char& p) {
0114 
0115   // init
0116   fR = 0;  
0117   fNegative = false;
0118   
0119   if (*p == '-') {
0120     neg = true;
0121     ++p;
0122   }
0123   while (*p >= '0' && *p <= '9') {
0124     r = (r*10.0) + (*p - '0');
0125     ++p;
0126   }
0127   if (*p == '.') {
0128     double f = 0.0;
0129     int n = 0;
0130     ++p;
0131     while (*p >= '0' && *p <= '9') {
0132       f = (f*10.0) + (*p - '0');
0133       ++p;
0134       ++n;
0135     }
0136     r += f / std::pow(10.0, n);
0137   }
0138   if (neg) {
0139     r = -r;
0140   }
0141   return r;
0142 }
0143 */
0144 
0145 SRes LzmaFile::DecodeBuffer() {
0146   ISeqInStream *stream = &inStream.s;
0147 
0148   const int thereIsSize = (unpackSize != (UInt64)(Int64)-1);
0149 
0150   if (inPos == inSize) {
0151     inSize = IN_BUF_SIZE;
0152     RINOK(stream->Read(stream, inBuf, &inSize));
0153     inPos = 0;
0154   }
0155 
0156   SizeT inProcessed = inSize - inPos;
0157   SizeT outProcessed = OUT_BUF_SIZE - outPos;
0158   ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
0159   ELzmaStatus status;
0160 
0161   if (thereIsSize && outProcessed > unpackSize) {
0162     outProcessed = (SizeT)unpackSize;
0163     finishMode = LZMA_FINISH_END;
0164   }
0165 
0166   SRes res = LzmaDec_DecodeToBuf(&state, outBuf, &outProcessed, inBuf + inPos, &inProcessed, finishMode, &status);
0167   inPos += inProcessed;
0168   unpackSize -= outProcessed;
0169 
0170   const char *strBuf = (const char *)outBuf;
0171 
0172   int countC = 0;
0173   do {
0174     if (countC >= int(outProcessed)) {
0175       // cout << " countC=" << countC
0176       //       << " outProcessed=" << outProcessed
0177       //       << endl;
0178       break;
0179     }
0180 
0181     const char &C = strBuf[countC];
0182     countC++;
0183 
0184     //cout << "\'" << C << "\'" << endl;
0185 
0186     if (C == ' ' || C == '\n') {  // END OF NUMBER
0187 
0188       if (!fStartNumber)
0189         continue;
0190 
0191       //istringstream strToNum(fStrNumber.str().c_str());
0192       //double number = atof(fStrNumber.str().c_str());
0193       //strToNum >> number;
0194 
0195       const double number = (fNegative ? -1 : 1) * (fMantisseR + fMantisseF / pow(10, fMantisseFcount)) *
0196                             pow(10, (fExponentNegative ? -1 : 1) * fExponent);
0197       //cout << " number=" << number << endl;
0198 
0199       fStorage.push(number);
0200 
0201       fStartNumber = false;
0202 
0203       fReadSign = true;
0204       fReadMantisseR = true;
0205       fReadMantisseF = false;
0206       fReadExponentSign = false;
0207       fReadExponent = false;
0208 
0209       fNegative = false;
0210       fExponentNegative = false;
0211 
0212       fMantisseR = 0;
0213       fMantisseF = 0;
0214       fMantisseFcount = 0;
0215       fExponent = 0;
0216 
0217       continue;
0218     }
0219 
0220     fStartNumber = true;
0221     const int num = C - '0';
0222     if (num >= 0 && num <= 9) {
0223       if (fReadMantisseR) {
0224         fReadSign = false;
0225         fMantisseR = fMantisseR * 10 + num;
0226       } else if (fReadMantisseF) {
0227         fReadSign = false;
0228         fMantisseF = fMantisseF * 10 + num;
0229         ++fMantisseFcount;
0230       } else if (fReadExponent) {
0231         fReadExponentSign = false;
0232         fExponent = fExponent * 10 + num;
0233       }
0234 
0235     } else {
0236       switch (C) {
0237         case '-': {
0238           if (fReadSign) {
0239             fNegative = true;
0240             fReadSign = false;
0241             fReadMantisseR = true;
0242           } else if (fReadExponentSign) {
0243             fExponentNegative = true;
0244             fReadExponentSign = false;
0245             fReadExponent = true;
0246           } else {
0247             cout << "LzmaFile: found \'" << C << "\' at wrong position. " << endl;
0248             exit(10);
0249           }
0250         } break;
0251         case '.':
0252           if (!fReadMantisseR) {
0253             cout << "LzmaFile: found \'" << C << "\' at wrong position. " << endl;
0254             exit(10);
0255           }
0256           fReadMantisseR = false;
0257           fReadMantisseF = true;
0258           break;
0259         case 'e':
0260         case 'E':
0261         case 'D':
0262         case 'd':
0263           if (!fReadMantisseR || !fReadMantisseF) {
0264             fReadMantisseR = false;
0265             fReadMantisseF = false;
0266             fReadExponentSign = true;
0267             fReadExponent = true;
0268           }
0269           break;
0270         default:
0271           cout << "LzmaFile: found \'" << C << "\' at wrong position. " << endl;
0272           exit(10);
0273           break;
0274       }
0275     }
0276 
0277   } while (true);
0278 
0279   //strBuf.str("");
0280   //strBuf.clear();
0281 
0282   /*    
0283   if (!strNumber.str().empty()) {
0284     cout << "NACHZUEGLER" << endl;
0285     istringstream strToNum(strNumber.str());
0286     double number;
0287     strToNum >> number;
0288     fStorage.push(number);
0289   }
0290   */
0291 
0292   if (res != SZ_OK || (thereIsSize && unpackSize == 0))
0293     return res;
0294 
0295   if (inProcessed == 0 && outProcessed == 0) {
0296     if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)
0297       return SZ_ERROR_DATA;
0298     return res;
0299   }
0300 
0301   return SZ_OK;
0302 }
0303 
0304 SRes LzmaFile::DecodeAll() {
0305   ISeqInStream *stream = &inStream.s;
0306 
0307   int thereIsSize = (unpackSize != (UInt64)(Int64)-1);
0308 
0309   for (;;) {
0310     if (inPos == inSize) {
0311       inSize = IN_BUF_SIZE;
0312       RINOK(stream->Read(stream, inBuf, &inSize));
0313       inPos = 0;
0314     }
0315 
0316     SizeT inProcessed = inSize - inPos;
0317     SizeT outProcessed = OUT_BUF_SIZE - outPos;
0318     ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
0319     ELzmaStatus status;
0320 
0321     if (thereIsSize && outProcessed > unpackSize) {
0322       outProcessed = (SizeT)unpackSize;
0323       finishMode = LZMA_FINISH_END;
0324     }
0325 
0326     SRes res = LzmaDec_DecodeToBuf(&state, outBuf, &outProcessed, inBuf + inPos, &inProcessed, finishMode, &status);
0327     inPos += inProcessed;
0328     unpackSize -= outProcessed;
0329 
0330     unsigned int k = 0;
0331     for (k = 0; k < outProcessed; ++k) {
0332       printf("%c", outBuf[k]);
0333     }
0334 
0335     if (res != SZ_OK || (thereIsSize && unpackSize == 0))
0336       return res;
0337 
0338     if (inProcessed == 0 && outProcessed == 0) {
0339       if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)
0340         return SZ_ERROR_DATA;
0341       return res;
0342     }
0343 
0344   }  // for loop
0345 
0346   return 0;
0347 }
0348 
0349 SRes LzmaFile::Close() {
0350   LzmaDec_Free(&state, &g_Alloc);
0351   res = File_Close(&inStream.file);
0352   return res;
0353 }